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
4158dd22
Commit
4158dd22
authored
Jul 16, 2021
by
Stefan Gränitz
Browse files
[WIP] Experimental support for single-use C++14 generic lambdas
parent
d0f84139
Changes
7
Hide whitespace changes
Inline
Side-by-side
ClangVisitor.cpp
View file @
4158dd22
...
...
@@ -577,6 +577,33 @@ exp_node FramacVisitor::make_initializer_list(
}
exp_node
FramacVisitor
::
make_lambda_expr
(
const
clang
::
LambdaExpr
*
lam
)
{
if
(
const
clang
::
FunctionTemplateDecl
*
meths
=
lam
->
getDependentCallOperator
())
{
for
(
const
clang
::
FunctionDecl
*
meth
:
meths
->
specializations
())
{
qual_type
lam_rt
=
makeDefaultExternalNameType
(
meth
->
getReturnTypeSourceRange
().
getBegin
(),
meth
->
getReturnType
());
/* arg_decl */
list
lam_args
=
NULL
;
auto
args
=
meth
->
parameters
();
for
(
auto
it
=
args
.
rbegin
();
it
<
args
.
rend
();
it
++
)
{
std
::
string
name
=
(
*
it
)
->
getNameAsString
();
qual_type
arg_type
=
makeDefaultExternalNameType
(
(
*
it
)
->
getLocation
(),
(
*
it
)
->
getOriginalType
());
location
l
=
makeLocation
((
*
it
)
->
getSourceRange
());
lam_args
=
cons_container
(
arg_decl_cons
(
arg_type
,
copy_string
(
name
),
l
),
lam_args
);
}
/* closure */
list
lam_closure
=
_clangUtils
->
make_capture_list
(
lam
->
captures
());
/* statement */
list
lam_body
=
makeCodeBlock
(
meth
->
getBody
(),
meth
->
getDeclContext
(),
meth
);
return
exp_node_LambdaExpr
(
lam_rt
,
lam_args
,
lam_closure
,
lam_body
);
}
}
const
clang
::
CXXMethodDecl
*
lam_meth
=
lam
->
getCallOperator
();
qual_type
lam_rt
=
makeDefaultExternalNameType
(
...
...
Clang_utils.cpp
View file @
4158dd22
...
...
@@ -164,10 +164,11 @@ compare_typ(typ t1, typ t2) {
result
=
compare_qualified_name
(
t1
->
cons_typ
.
Named
.
name
,
t2
->
cons_typ
.
Named
.
name
);
break
;
case
LAMBDA
:
result
=
compare_signature
(
t1
->
cons_typ
.
Lambda
.
proto
,
t2
->
cons_typ
.
Lambda
.
proto
);
case
LAMBDA
:
{
auto
get_signature
=
[](
typ
t
)
{
return
(
signature
)
t
->
cons_typ
.
Lambda
.
proto
->
element
.
container
;
};
result
=
compare_signature
(
get_signature
(
t1
),
get_signature
(
t2
));
if
(
result
==
0
)
{
/* capture */
list
l1
=
t1
->
cons_typ
.
Lambda
.
closure
;
/* capture */
list
l2
=
t2
->
cons_typ
.
Lambda
.
closure
;
...
...
@@ -184,6 +185,7 @@ compare_typ(typ t1, typ t2) {
}
}
break
;
}
default:
break
;
}
...
...
@@ -1410,6 +1412,11 @@ bool Clang_utils::is_lambda(const clang::RecordDecl* rec) const {
return
cxx_rec
&&
cxx_rec
->
isLambda
();
}
bool
Clang_utils
::
is_generic_lambda
(
const
clang
::
RecordDecl
*
rec
)
const
{
auto
*
cxx_rec
=
llvm
::
dyn_cast
<
const
clang
::
CXXRecordDecl
>
(
rec
);
return
cxx_rec
&&
cxx_rec
->
isGenericLambda
();
}
/* capture */
list
Clang_utils
::
make_capture_list
(
clang
::
CXXRecordDecl
::
capture_const_range
captures
)
const
{
list
lam_closure
=
NULL
;
...
...
@@ -1450,11 +1457,27 @@ typ Clang_utils::make_lambda_type(
{
auto
cxx_rec
=
llvm
::
dyn_cast
<
const
clang
::
CXXRecordDecl
>
(
record
);
auto
oper
=
cxx_rec
->
getLambdaCallOperator
();
auto
sig
=
makeSignature
(
*
oper
);
auto
sig
=
cons_container
(
makeSignature
(
*
oper
)
,
nullptr
)
;
auto
cap
=
make_capture_list
(
cxx_rec
->
captures
());
return
typ_Lambda
(
sig
,
cap
);
}
typ
Clang_utils
::
make_generic_lambda_type
(
clang
::
SourceLocation
const
&
loc
,
clang
::
RecordDecl
const
*
record
,
VirtualDeclRegistration
*
declRegistration
)
const
{
auto
*
cxx_rec
=
llvm
::
dyn_cast
<
const
clang
::
CXXRecordDecl
>
(
record
);
clang
::
FunctionTemplateDecl
*
oper
=
cxx_rec
->
getDependentLambdaCallOperator
();
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
);
}
typ
Clang_utils
::
makePlainType
(
clang
::
SourceLocation
const
&
loc
,
...
...
@@ -1649,6 +1672,8 @@ Clang_utils::makePlainType(
const
clang
::
RecordType
*
recordType
=
static_cast
<
clang
::
RecordType
const
*>
(
type
);
const
clang
::
RecordDecl
*
record
=
recordType
->
getDecl
();
if
(
is_generic_lambda
(
record
))
return
make_generic_lambda_type
(
loc
,
record
,
declRegistration
);
if
(
is_lambda
(
record
))
return
make_lambda_type
(
loc
,
record
,
declRegistration
);
if
(
declRegistration
&&
declRegistration
->
doesRegisterDecl
())
...
...
Clang_utils.h
View file @
4158dd22
...
...
@@ -664,6 +664,7 @@ public:
bool
lvalHasRefType
(
clang
::
Expr
const
*
expr
)
const
;
bool
is_lambda
(
clang
::
RecordDecl
const
*
record
)
const
;
bool
is_generic_lambda
(
const
clang
::
RecordDecl
*
rec
)
const
;
/*capture*/
list
make_capture_list
(
clang
::
CXXRecordDecl
::
capture_const_range
captures
)
const
;
...
...
@@ -672,6 +673,10 @@ public:
clang
::
SourceLocation
const
&
loc
,
clang
::
RecordDecl
const
*
record
,
VirtualDeclRegistration
*
declRegistration
=
NULL
)
const
;
typ
make_generic_lambda_type
(
clang
::
SourceLocation
const
&
loc
,
clang
::
RecordDecl
const
*
record
,
VirtualDeclRegistration
*
declRegistration
=
nullptr
)
const
;
typ
makeBuiltinType
(
clang
::
SourceLocation
const
&
loc
,
clang
::
BuiltinType
const
*
typ
)
const
;
typ
makeBuiltinTypeNoLoc
(
clang
::
BuiltinType
const
*
typ
)
const
...
...
cxx_utils.ml
View file @
4158dd22
...
...
@@ -410,7 +410,7 @@ let force_ptr_to_const p =
let
make_lambda_type
result
args
closure
=
let
parameter
=
List
.
map
(
fun
x
->
x
.
arg_type
)
args
in
Lambda
({
result
;
parameter
;
variadic
=
false
}
,
closure
)
Lambda
(
[
{
result
;
parameter
;
variadic
=
false
}
]
,
closure
)
let
plain_obj_ptr
t
=
Pointer
(
PDataPointer
t
)
...
...
fclang_datatype.ml
View file @
4158dd22
...
...
@@ -183,13 +183,7 @@ and pretty_type fmt typ =
->
Format
.
fprintf
fmt
"union %a"
pretty_qualified_name
(
name
,
tc
)
|
Named
(
qname
,
_
)
->
pretty_qualified_name
fmt
(
qname
,
TStandard
)
|
Lambda
(
proto
,
cap
)
->
let
pp_sep
fmt
()
=
Format
.
pp_print_string
fmt
", "
in
Format
.
fprintf
fmt
"lambda %a [%a]-> %a"
(
Format
.
pp_print_list
~
pp_sep
pretty_qual_type
)
proto
.
parameter
(
Format
.
pp_print_list
~
pp_sep
pretty_capture
)
cap
pretty_qual_type
proto
.
result
|
Lambda
(
protos
,
cap
)
->
pretty_generic_lambda
fmt
protos
cap
and
pretty_capture
fmt
cap
=
match
cap
with
...
...
@@ -208,6 +202,19 @@ and pretty_qual_type fmt { qualifier = specs; plain_type = typ} =
Format
.
fprintf
fmt
"%a (%a)"
(
Pretty_utils
.
pp_list
~
sep
:
" "
pretty_specifier
)
specs
pretty_type
typ
and
pretty_lambda
fmt
proto
cap
=
let
pp_sep
fmt
()
=
Format
.
pp_print_string
fmt
", "
in
Format
.
fprintf
fmt
"lambda %a [%a]-> %a"
(
Format
.
pp_print_list
~
pp_sep
pretty_qual_type
)
proto
.
parameter
(
Format
.
pp_print_list
~
pp_sep
pretty_capture
)
cap
pretty_qual_type
proto
.
result
and
pretty_generic_lambda
fmt
protos
cap
=
match
protos
with
|
[]
->
()
|
p
::
ps
->
pretty_lambda
fmt
p
cap
;
pretty_generic_lambda
fmt
ps
cap
module
Template_parameter
=
Datatype
.
Make_with_collections
(
...
...
intermediate_format.ast
View file @
4158dd22
...
...
@@ -168,7 +168,7 @@ type typ =
(* body.ckind should be CUnion *)
| Named { name: qualified_name; is_extern_c_name : bool; } (* typedef *)
| Lambda {
proto : signature;
proto : signature
list
;
closure: capture list;
} (* a lambda object of the given signature.
Note that normally each anonymous lambda object should give rise
...
...
mangling.ml
View file @
4158dd22
...
...
@@ -203,10 +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
(
proto
,
cap
)
->
|
Lambda
(
proto
s
,
cap
)
->
(* 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
proto
=
(
match
protos
with
|
p
::
_
->
p
|
[]
->
Frama_Clang_option
.
not_yet_implemented
"Initializer list without Compound initialization"
)
in
"Ul"
^
mangle_parameter
proto
.
parameter
^
"EUc"
^
mangle_captures
cap
^
"E_"
(* not translated yet
| ArrayType(t,(DYN_SIZE | NO_SIZE)) ->
...
...
Write
Preview
Supports
Markdown
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