From bbef15e5c22ef1c0a4fe90e7270a2c9459f20ea4 Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Wed, 6 Jan 2016 21:11:18 +0000 Subject: [PATCH] Improve conditional checking during template instantiation. When the condition in an if statement, while statement, or for loop is created during template instantiation, it calls MakeFullExpr with only the condition expression. However, when these conditions are created for non-templated code in the Parser, an additional SourceLocation is passed to MakeFullExpr. The impact of this was that non-dependent templated code could produce diagnostics that the same code outside templates would not. Adding the missing SourceLocation makes diagnostics consistent between templated and non-templated code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256976 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/TreeTransform.h | 8 ++-- test/SemaCXX/conversion.cpp | 89 +++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index e0a9653eb9..e97a262638 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6128,7 +6128,7 @@ TreeTransform::TransformIfStmt(IfStmt *S) { } } - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get())); + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get(), S->getIfLoc())); if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) return StmtError(); @@ -6223,7 +6223,8 @@ TreeTransform::TransformWhileStmt(WhileStmt *S) { } } - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get())); + Sema::FullExprArg FullCond( + getSema().MakeFullExpr(Cond.get(), S->getWhileLoc())); if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) return StmtError(); @@ -6307,7 +6308,8 @@ TreeTransform::TransformForStmt(ForStmt *S) { } } - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get())); + Sema::FullExprArg FullCond( + getSema().MakeFullExpr(Cond.get(), S->getForLoc())); if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) return StmtError(); diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index b8f0e076a2..fe449c8ccb 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -77,30 +77,8 @@ void test3() { // CHECK: note: expanded from macro 'FINIT' #define FINIT int a3 = NULL; FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}} - - // we don't catch the case of #define FOO NULL ... int i = FOO; but that seems a bit narrow anyway - // and avoiding that helps us skip these cases: -#define NULL_COND(cond) ((cond) ? &a : NULL) - bool bl2 = NULL_COND(true); // don't warn on NULL conversion through the conditional operator across a macro boundary - if (NULL_COND(true)) - ; - while (NULL_COND(true)) - ; - for (; NULL_COND(true); ) - ; - do ; - while(NULL_COND(true)); - -#define NULL_WRAPPER NULL_COND(false) - if (NULL_WRAPPER) - ; - while (NULL_WRAPPER) - ; - for (; NULL_WRAPPER;) - ; - do - ; - while (NULL_WRAPPER); + // we don't catch the case of #define FOO NULL ... int i = FOO; but that + // seems a bit narrow anyway and avoiding that helps us skip other cases. int *ip = NULL; int (*fp)() = NULL; @@ -157,3 +135,66 @@ namespace test7 { return nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} } } + +namespace test8 { + #define NULL_COND(cond) ((cond) ? &num : NULL) + #define NULL_WRAPPER NULL_COND(false) + + // don't warn on NULL conversion through the conditional operator across a + // macro boundary + void macro() { + int num; + bool b = NULL_COND(true); + if (NULL_COND(true)) {} + while (NULL_COND(true)) {} + for (;NULL_COND(true);) {} + do {} while (NULL_COND(true)); + + if (NULL_WRAPPER) {} + while (NULL_WRAPPER) {} + for (;NULL_WRAPPER;) {} + do {} while (NULL_WRAPPER); + } + + // Identical to the previous function except with a template argument. + // This ensures that template instantiation does not introduce any new + // warnings. + template + void template_and_macro() { + int num; + bool b = NULL_COND(true); + if (NULL_COND(true)) {} + while (NULL_COND(true)) {} + for (;NULL_COND(true);) {} + do {} while (NULL_COND(true)); + + if (NULL_WRAPPER) {} + while (NULL_WRAPPER) {} + for (;NULL_WRAPPER;) {} + do {} while (NULL_WRAPPER); + } + + // Identical to the previous function except the template argument affects + // the conditional statement. + template + void template_and_macro2() { + X num; + bool b = NULL_COND(true); + if (NULL_COND(true)) {} + while (NULL_COND(true)) {} + for (;NULL_COND(true);) {} + do {} while (NULL_COND(true)); + + if (NULL_WRAPPER) {} + while (NULL_WRAPPER) {} + for (;NULL_WRAPPER;) {} + do {} while (NULL_WRAPPER); + } + + void run() { + template_and_macro(); + template_and_macro(); + template_and_macro2(); + template_and_macro2(); + } +} -- 2.40.0