]> granicus.if.org Git - clang/commitdiff
Improve conditional checking during template instantiation.
authorRichard Trieu <rtrieu@google.com>
Wed, 6 Jan 2016 21:11:18 +0000 (21:11 +0000)
committerRichard Trieu <rtrieu@google.com>
Wed, 6 Jan 2016 21:11:18 +0000 (21:11 +0000)
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
test/SemaCXX/conversion.cpp

index e0a9653eb93bc7d78864c9d95b5baf07cf67a1df..e97a26263875b05434122e61f9300776d834ed8b 100644 (file)
@@ -6128,7 +6128,7 @@ TreeTransform<Derived>::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<Derived>::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<Derived>::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();
 
index b8f0e076a2bcc1461ba45654cff1b7d0712a3239..fe449c8ccb4a2e2d8284fa54f3681b0ce4a2275e 100644 (file)
@@ -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 <typename X>
+  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 <typename X>
+  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<int>();
+    template_and_macro<double>();
+    template_and_macro2<int>();
+    template_and_macro2<double>();
+  }
+}