Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Stefan Gränitz
Frama Clang
Commits
a1d04502
Commit
a1d04502
authored
Aug 21, 2021
by
Stefan Gränitz
Browse files
[wip] Clang-mangled lambda names
parent
a53e073c
Pipeline
#37284
failed with stages
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Clang_utils.cpp
View file @
a1d04502
...
...
@@ -24,8 +24,20 @@
#include "Clang_utils.h"
#include "ClangVisitor.h"
#include <clang/AST/Type.h>
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include <clang/AST/ASTContext.h>
#include <clang/AST/Mangle.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/Basic/DiagnosticDriver.h>
#include <clang/Basic/DiagnosticFrontend.h>
#include <clang/Basic/DiagnosticIDs.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <llvm/Support/Casting.h>
#include <llvm/Support/FormatVariadic.h>
#include <llvm/Support/raw_ostream.h>
extern
"C"
{
...
...
@@ -1451,6 +1463,49 @@ bool Clang_utils::is_generic_lambda(const clang::RecordDecl* rec) const {
return
lam_closure
;
}
// Clang generates rich diagnostics for failures. For now we render them into
// strings and dump them via stderr. Thus, one global static instance is fine.
//clang::DiagnosticsEngine &Clang_utils::get_diagnostics_engine() {
// static std::unique_ptr<clang::DiagnosticsEngine> global_inst = nullptr;
// if (!global_inst)
// global_inst = std::make_unique<clang::DiagnosticsEngine>(
// new clang::DiagnosticIDs, new clang::DiagnosticOptions,
// new clang::TextDiagnosticPrinter(llvm::errs(),
// new clang::DiagnosticOptions));
// return *global_inst;
//}
unsigned
Clang_utils
::
get_lambda_id
(
const
clang
::
CXXRecordDecl
*
inst
)
const
{
const
clang
::
DeclContext
*
scope
=
inst
->
getDeclContext
();
auto
it
=
TrackLambdasByScope
.
find
(
scope
);
if
(
it
==
TrackLambdasByScope
.
end
())
{
TrackLambdasByScope
.
insert
(
std
::
make_pair
(
scope
,
LamInstances_t
{
inst
}));
return
0
;
// first lambda in this scope
}
LamInstances_t
&
insts
=
it
->
second
;
for
(
unsigned
i
=
0
;
i
<
insts
.
size
();
++
i
)
if
(
inst
==
insts
[
i
])
return
i
;
// known lambda in this scope
insts
.
push_back
(
inst
);
return
insts
.
size
()
-
1
;
// new lambda in this scope
}
std
::
string
Clang_utils
::
get_lambda_name
(
const
clang
::
FunctionDecl
*
inst
)
const
{
clang
::
ASTNameGenerator
mangler
(
inst
->
getASTContext
());
std
::
string
first_name
=
mangler
.
getName
(
inst
);
size_t
sep_pos
=
first_name
.
find
(
'$'
);
assert
(
sep_pos
!=
std
::
string
::
npos
&&
"Lambda mangling always employs a dollar separator"
);
return
first_name
.
substr
(
0
,
sep_pos
);
}
std
::
string
Clang_utils
::
get_lambda_name
(
const
clang
::
FunctionTemplateDecl
*
inst
)
const
{
const
clang
::
FunctionDecl
*
first_overload
=
*
inst
->
spec_begin
();
return
get_lambda_name
(
first_overload
);
}
typ
Clang_utils
::
make_lambda_type
(
clang
::
SourceLocation
const
&
loc
,
clang
::
RecordDecl
const
*
record
,
VirtualDeclRegistration
*
declRegistration
)
const
...
...
@@ -1459,7 +1514,12 @@ typ Clang_utils::make_lambda_type(
auto
oper
=
cxx_rec
->
getLambdaCallOperator
();
auto
sig
=
cons_container
(
makeSignature
(
*
oper
),
nullptr
);
auto
cap
=
make_capture_list
(
cxx_rec
->
captures
());
return
typ_Lambda
(
sig
,
cap
);
unsigned
id
=
get_lambda_id
(
cxx_rec
);
std
::
string
base_name
=
get_lambda_name
(
oper
);
LambdaNames
.
push_back
(
llvm
::
formatv
(
"{0}_{1}"
,
base_name
,
id
));
return
typ_Lambda
(
sig
,
cap
,
LambdaNames
.
back
().
c_str
());
}
typ
Clang_utils
::
make_generic_lambda_type
(
...
...
@@ -1468,14 +1528,18 @@ typ Clang_utils::make_generic_lambda_type(
{
auto
*
cxx_rec
=
llvm
::
dyn_cast
<
const
clang
::
CXXRecordDecl
>
(
record
);
clang
::
FunctionTemplateDecl
*
oper
=
cxx_rec
->
getDependentLambdaCallOperator
();
list
sigs
=
nullptr
;
unsigned
id
=
get_lambda_id
(
cxx_rec
);
std
::
string
base_name
=
get_lambda_name
(
oper
);
LambdaNames
.
push_back
(
llvm
::
formatv
(
"{0}_{1}"
,
base_name
,
id
));
list
sigs
=
nullptr
;
for
(
const
clang
::
FunctionDecl
*
function
:
oper
->
specializations
())
sigs
=
cons_container
(
makeSignature
(
*
function
),
sigs
);
assert
(
sigs
&&
"Will unused generic lambdas appear in the AST? Possible."
);
auto
*
cap
=
make_capture_list
(
cxx_rec
->
captures
());
return
typ_Lambda
(
sigs
,
cap
);
return
typ_Lambda
(
sigs
,
cap
,
LambdaNames
.
back
().
c_str
()
);
}
typ
...
...
Clang_utils.h
View file @
a1d04502
...
...
@@ -814,6 +814,13 @@ public:
#endif
}
using
LamInstances_t
=
std
::
vector
<
const
clang
::
CXXRecordDecl
*>
;
using
LamScopes_t
=
std
::
map
<
const
clang
::
DeclContext
*
,
LamInstances_t
>
;
mutable
LamScopes_t
TrackLambdasByScope
;
mutable
std
::
vector
<
std
::
string
>
LambdaNames
;
unsigned
get_lambda_id
(
const
clang
::
CXXRecordDecl
*
inst
)
const
;
std
::
string
get_lambda_name
(
const
clang
::
FunctionDecl
*
inst
)
const
;
std
::
string
get_lambda_name
(
const
clang
::
FunctionTemplateDecl
*
inst
)
const
;
};
class
ForwardList
;
...
...
convert.ml
View file @
a1d04502
...
...
@@ -1713,7 +1713,7 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual =
mk_signature
ovl
.
return_type
params
in
let
signatures
=
List
.
map
make_signature
overloads
in
let
lam_type
=
Lambda
(
signatures
,
closures
)
in
let
lam_type
=
Lambda
(
signatures
,
closures
,
""
)
in
let
lam_name
=
Convert_env
.
temp_name
env
"__fc_lambda_tmp"
in
let
(
env
,
aux
)
=
create_lambda
env
aux
lam_name
lam_type
overloads
closures
in
...
...
fclang_datatype.ml
View file @
a1d04502
...
...
@@ -183,9 +183,9 @@ and pretty_type fmt typ =
->
Format
.
fprintf
fmt
"union %a"
pretty_qualified_name
(
name
,
tc
)
|
Named
(
qname
,
_
)
->
pretty_qualified_name
fmt
(
qname
,
TStandard
)
|
Lambda
(
sigs
,
caps
)
->
pretty_generic_lambda
fmt
sigs
caps
|
Lambda
(
sigs
,
caps
,
mangled
)
->
pretty_generic_lambda
fmt
sigs
caps
mangled
and
pretty_generic_lambda
fmt
signatures
captures
=
and
pretty_generic_lambda
fmt
signatures
captures
mangled
=
let
pretty_capture
fmt
cap
=
match
cap
with
|
Cap_id
(
s
,
typ
,
is_ref
)
->
...
...
@@ -196,7 +196,8 @@ and pretty_generic_lambda fmt signatures captures =
in
let
pretty_lambda
lam
=
let
pp_sep
fmt
()
=
Format
.
pp_print_string
fmt
", "
in
Format
.
fprintf
fmt
"lambda %a [%a]-> %a"
Format
.
fprintf
fmt
"lambda %s %a [%a]-> %a"
mangled
(
Format
.
pp_print_list
~
pp_sep
pretty_capture
)
captures
(
Format
.
pp_print_list
~
pp_sep
pretty_qual_type
)
lam
.
parameter
pretty_qual_type
lam
.
result
...
...
intermediate_format.ast
View file @
a1d04502
...
...
@@ -170,6 +170,7 @@ type typ =
| Lambda {
proto: signature list;
closure: capture list;
mangled: string;
} (* a lambda object of the given signature.
Note that normally each anonymous lambda object should give rise
to a different class. With this representation, we won't distinguish
...
...
mangling.ml
View file @
a1d04502
...
...
@@ -203,14 +203,14 @@ let rec mangle_cc_type = function
|
Named
(
name
,
is_extern_c_name
)
->
if
is_extern_c_name
then
name
.
decl_name
else
mangle_name_optt
name
TStandard
|
Lambda
(
signatures
,
cap
)
->
|
Lambda
(
signatures
,
cap
tures
,
mangled
)
->
(* NB: we depart from standard mangling rules here, in order to have
a contextless mangling, whereas Itanium ABI mangles according to
the number of lambda classes found in each function. *)
let
rec
mangle_all
=
function
|
[]
->
""
|
s
::
sigs
->
mangle_parameter
s
.
parameter
^
mangle_all
sigs
in
"Ul
"
^
mangle_all
signatures
^
"
EUc
"
^
mangle_captures
cap
^
"E_"
mangled
^
"$
"
^
mangle_all
signatures
^
"
_
"
^
mangle_captures
cap
tures
(* not translated yet
| ArrayType(t,(DYN_SIZE | NO_SIZE)) ->
"A_" ^ mangle_cc_type t *)
...
...
tests/basic/lambda_generic.cpp
View file @
a1d04502
...
...
@@ -9,7 +9,8 @@ int test_cxx11_lambda(int cap, int i) {
int
test_cxx14_single_inst
(
int
cap
,
int
i
)
{
auto
lam2
=
[
cap
](
auto
val
)
{
return
cap
-
val
;
};
return
lam2
(
i
);
auto
lam2b
=
[
cap
](
auto
val
)
{
return
cap
-
val
;
};
return
lam2
(
i
)
+
lam2b
(
i
);
}
int
test_cxx14_multi_inst
(
int
cap
,
int
i
,
float
f
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment