Reworked PredefinedExpr representation with internal StringLiteral field for function declaration.
Details
Diff Detail
Event Timeline
lib/AST/Expr.cpp | ||
---|---|---|
633–634 | This existing code is already trying to handle this situation. Did your tests fail without your change? If so, why? (The existing code is wrong for decltype(auto), auto*, and so on, but that is not the case your tests seem to be covering.) |
Coincidentally, I looked at this code the other day. IMO running the mangler twice for FUNCDNAME is silly. Is there a problem with computing the string in Sema and storing it on the PredefinedExpr? It looks like we always have to do this just to build the type.
lib/AST/Expr.cpp | ||
---|---|---|
532 | The best fix (for the immediate issue) would probably be to use the declared type rather than the actual type: use Decl->getTypeSourceInfo()->getType() rather than Decl->getType() here. As Reid points out, we may want to just stash the string into the PredefinedExpr object when we create it, rather than recomputing it each time. | |
634–635 | Remove the existing (broken) handling for this case. | |
test/CodeGenCXX/predefined-expr-cxx14.cpp | ||
4–5 | This test does not seem quite right:
|
Richard, yes, it fails on lines 79, 76, 88
Best regards,
Alexey Bataev
Software Engineer
Intel Compiler Team
16.09.2014 21:07, Richard Smith пишет:
Comment at: lib/AST/Expr.cpp:604
@@ -603,2 +603,3 @@
+ Policy.KeepAutoType = true;if ((isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->getParent()->isLambda()) ||
This existing code is already trying to handle this situation. Did your tests fail without your change? If so, why?
(The existing code is wrong for decltype(auto), auto*, and so on, but that is not the case your tests seem to be covering.)
Reid, I though about it too. I also think it is a better solution. I'll
rework the patch.
Best regards,
Alexey Bataev
Software Engineer
Intel Compiler Team
16.09.2014 22:03, Reid Kleckner пишет:
Coincidentally, I looked at this code the other day. IMO running the mangler twice for FUNCDNAME is silly. Is there a problem with computing the string in Sema and storing it on the PredefinedExpr? It looks like we always have to do this just to build the type.
Comment at: lib/AST/Expr.cpp:501
@@ -500,3 +500,3 @@Decl = Pattern; const FunctionType *AFT = Decl->getType()->getAs<FunctionType>(); const FunctionProtoType *FT = nullptr;
The best fix (for the immediate issue) would probably be to use the declared type rather than the actual type: use Decl->getTypeSourceInfo()->getType() rather than Decl->getType() here.
As Reid points out, we may want to just stash the string into the PredefinedExpr object when we create it, rather than recomputing it each time.
Richard, I'll rework the patch and store string in PredefinedExpr.
Comment at: test/CodeGenCXX/predefined-expr-cxx14.cpp:3-4
@@ +2,4 @@
+
+ CHECK-DAG: private unnamed_addr constant [15 x i8] c"externFunction\00"
+ CHECK-DAG: private unnamed_addr constant [26 x i8] c"auto NS::externFunction()\00"+// CHECK-DAG: private unnamed_addr constant [49 x i8] c"auto functionTemplateExplicitSpecialization(int)\00"
This test does not seem quite right:
- Testing all the different kinds of function declarations here is gaining you zero test coverage. The thing that's relevant here is how we handle the return type, and that does not change between these cases.
- You're missing test coverage for the cases you fixed: decltype(auto) as a return type, and types that contain auto (but are not *exactly* auto).
The test is too big, but it has test cases for , I'll reduce it.
Best regards,
Alexey Bataev
Software Engineer
Intel Compiler Team
16.09.2014 22:48, Richard Smith пишет:
Comment at: lib/AST/Expr.cpp:501
@@ -500,3 +500,3 @@Decl = Pattern; const FunctionType *AFT = Decl->getType()->getAs<FunctionType>(); const FunctionProtoType *FT = nullptr;
The best fix (for the immediate issue) would probably be to use the declared type rather than the actual type: use Decl->getTypeSourceInfo()->getType() rather than Decl->getType() here.
As Reid points out, we may want to just stash the string into the PredefinedExpr object when we create it, rather than recomputing it each time.
Comment at: lib/AST/Expr.cpp:606
@@ -604,3 +605,3 @@cast<CXXMethodDecl>(FD)->getParent()->isLambda()) || (FT && FT->getReturnType()->getAs<AutoType>())) Proto = "auto " + Proto;
Remove the existing (broken) handling for this case.
Comment at: test/CodeGenCXX/predefined-expr-cxx14.cpp:3-4
@@ +2,4 @@
+
+ CHECK-DAG: private unnamed_addr constant [15 x i8] c"externFunction\00"
+ CHECK-DAG: private unnamed_addr constant [26 x i8] c"auto NS::externFunction()\00"+// CHECK-DAG: private unnamed_addr constant [49 x i8] c"auto functionTemplateExplicitSpecialization(int)\00"
This test does not seem quite right:
- Testing all the different kinds of function declarations here is gaining you zero test coverage. The thing that's relevant here is how we handle the return type, and that does not change between these cases.
- You're missing test coverage for the cases you fixed: decltype(auto) as a return type, and types that contain auto (but are not *exactly* auto).
include/clang/AST/Expr.h | ||
---|---|---|
1164 | Please don't move this class to a different place in the file (and likewise in Expr.cpp); it creates history churn and makes the patch hard to review. Instead, you can move the getStringLiteral method definitions out of the class (either to after the definition of StringLiteral or into the .cpp file). | |
1637 | I don't think you need to pass in T here; it can be obtained from the StringLiteral. | |
1658 | Generally, we prefer to make the ASTReader a friend of the class being deserialized rather than adding setters. Please do that here (you should also be able to remove the other setters in the process). | |
lib/AST/ExprConstant.cpp | ||
2654 | C++ guarantees that __func__ has the same address for all evaluations within the same function. It looks like this patch will make them all be treated as distinct objects. | |
lib/AST/StmtProfile.cpp | ||
472 ↗ | (On Diff #13780) | This doesn't seem necessary. |
lib/CodeGen/CGExpr.cpp | ||
2058 | I think we need to emit this with a specific mangled name in order to merge the func objects across translation units if it's used in an inline function. | |
lib/Sema/TreeTransform.h | ||
6976–6980 | This is wrong: unless this is overridden by the derived class, it would just call itself. Instead you should add a RebuildPredefinedExpr function, call it from here, and make it call into Sema to rebuild the PredefinedExpr. | |
test/CodeGenCXX/funcsig.cpp | ||
11 | If this is supposed to be linkonce_odr, you should also check its mangled name. |
FYI: I'm investigating how to deal with the constraint that __func__ is the same object throughout a function; it's not supported by current ABIs, and it's not even clear that it's supportable without *extreme* heroics. On that basis, I think it's fine to continue treating __func__ like a string literal for now (that is, two different __func__s can evaluate to different arrays).
Richard, thanks for the review!
include/clang/AST/Expr.h | ||
---|---|---|
1164 | Ok | |
1637 | Yes, I thought about it too. But decided to make the constructor similar to all others. | |
1658 | Agree, thanks. | |
lib/AST/StmtProfile.cpp | ||
472 ↗ | (On Diff #13780) | Ok |
lib/CodeGen/CGExpr.cpp | ||
2058 | Agree, I'll try to improve it. | |
lib/Sema/TreeTransform.h | ||
6976–6980 | Ok, I'll fix it | |
test/CodeGenCXX/funcsig.cpp | ||
11 | Ok |
include/clang/AST/Expr.h | ||
---|---|---|
1184–1185 | You can delete these and directly set the members from ASTStmtReader. | |
lib/AST/Expr.cpp | ||
468 | You need an llvm_unreachable here to shut up GCC's -Wreturn-type. | |
lib/Sema/SemaExpr.cpp | ||
2969–2973 | Please remove the static local variable for now; we're discussing this on the standard reflectors and the requirement for this may soon be removed. The above doesn't completely fix the ABI problem anyway (if two compilers did this and came up with different strings, they could give __func__ different types). Sorry for the change in direction here. |
Thanks for the cleanup! Looks good with a fix for the func-inside-block-inside-ctor test case.
lib/AST/Expr.cpp | ||
---|---|---|
508 | I believe this will assert in this code: struct A { const char *s; A() { const char *(^b)() = ^() { return __func__; }; s = b(); }; A a; You probably need to handle the ctor / dtor cases separately, as is done in CodeGenModule::getBlockMangledName. Using Ctor_Base and Dtor_Base should be correct. I don't think we should ever emit two different block implementations for the base ctor and complete ctor. =/ | |
lib/CodeGen/CGExpr.cpp | ||
2061 | I think this can be an array of StringRefs to avoid building two tmp strings. | |
lib/CodeGen/CodeGenModule.cpp | ||
2751–2752 ↗ | (On Diff #14221) | This change will cause duplicate string literals to not be merged across TUs on Windows. Just mangle the string literal if the ABI says we should. |
test/CodeGenCXX/ms_wide_predefined_expr.cpp | ||
3 | This test in particular should not change. |
Hi Reid, Thanks for the review!
lib/AST/Expr.cpp | ||
---|---|---|
508 | I'll add this test and fix the code to properly handle it. | |
lib/CodeGen/CGExpr.cpp | ||
2061 | Agree | |
lib/CodeGen/CodeGenModule.cpp | ||
2751–2752 ↗ | (On Diff #14221) | Agree, I'll remove it |
test/CodeGenCXX/ms_wide_predefined_expr.cpp | ||
3 | Agree, will revert it back |
Please don't move this class to a different place in the file (and likewise in Expr.cpp); it creates history churn and makes the patch hard to review. Instead, you can move the getStringLiteral method definitions out of the class (either to after the definition of StringLiteral or into the .cpp file).