The attached patch improves our handling of value dependent expressions in
attribute((enable_if)), both in the condition expression and at the call
site. Fixes PR20988.

Please review!

Nick
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp	(revision 223753)
+++ lib/AST/ExprConstant.cpp	(working copy)
@@ -9072,7 +9072,8 @@
   ArgVector ArgValues(Args.size());
   for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
        I != E; ++I) {
-    if (!Evaluate(ArgValues[I - Args.begin()], Info, *I))
+    if ((*I)->isValueDependent() ||
+        !Evaluate(ArgValues[I - Args.begin()], Info, *I))
       // If evaluation fails, throw away the argument entirely.
       ArgValues[I - Args.begin()] = APValue();
     if (Info.EvalStatus.HasSideEffects)
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp	(revision 223753)
+++ lib/Sema/SemaOverload.cpp	(working copy)
@@ -5789,6 +5789,7 @@
   // Convert the arguments.
   SmallVector<Expr *, 16> ConvertedArgs;
   bool InitializationFailed = false;
+  bool ContainsValueDependentExpr = false;
   for (unsigned i = 0, e = Args.size(); i != e; ++i) {
     if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
         !cast<CXXMethodDecl>(Function)->isStatic() &&
@@ -5801,6 +5802,7 @@
         InitializationFailed = true;
         break;
       }
+      ContainsValueDependentExpr |= R.get()->isValueDependent();
       ConvertedArgs.push_back(R.get());
     } else {
       ExprResult R =
@@ -5813,6 +5815,7 @@
         InitializationFailed = true;
         break;
       }
+      ContainsValueDependentExpr |= R.get()->isValueDependent();
       ConvertedArgs.push_back(R.get());
     }
   }
@@ -5823,9 +5826,16 @@
   for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
     APValue Result;
     EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
+    if (EIA->getCond()->isValueDependent()) {
+      // Don't even try now, we'll examine it after instantiation.
+      continue;
+    }
+
     if (!EIA->getCond()->EvaluateWithSubstitution(
-            Result, Context, Function, llvm::makeArrayRef(ConvertedArgs)) ||
-        !Result.isInt() || !Result.getInt().getBoolValue()) {
+            Result, Context, Function, llvm::makeArrayRef(ConvertedArgs))) {
+      if (!ContainsValueDependentExpr)
+        return EIA;
+    } else if (!Result.isInt() || !Result.getInt().getBoolValue()) {
       return EIA;
     }
   }
Index: test/SemaCXX/enable_if.cpp
===================================================================
--- test/SemaCXX/enable_if.cpp	(revision 223753)
+++ test/SemaCXX/enable_if.cpp	(working copy)
@@ -77,3 +77,44 @@
   typedep(1);
   typedep(n);  // expected-note{{in instantiation of function template specialization 'typedep<Nothing>' requested here}}
 }
+
+template <typename T> class C {
+  void f() __attribute__((enable_if(T::expr == 0, ""))) {}
+  void g() { f(); }
+};
+
+int fn3(bool b) __attribute__((enable_if(b, "")));
+template <class T> void test3() {
+  fn3(sizeof(T) == 1);
+}
+
+// FIXME: issue an error (without instantiation) because h(T()) is not
+// convertible to bool, because return types aren't overloadable.
+void h(int);
+template <typename T> void outer() {
+  void local_function() __attribute__((enable_if(h(T()), "")));
+  local_function();
+};
+
+namespace PR20988 {
+  struct Integer {
+    Integer(int);
+  };
+
+  int fn1(const Integer &) __attribute__((enable_if(true, "")));
+  template <class T> void test1() {
+    int &expr = T::expr();
+    fn1(expr);
+  }
+
+  int fn2(const Integer &) __attribute__((enable_if(false, "")));  // expected-note{{candidate disabled}}
+  template <class T> void test2() {
+    int &expr = T::expr();
+    fn2(expr);  // expected-error{{no matching function for call to 'fn2'}}
+  }
+
+  int fn3(bool b) __attribute__((enable_if(b, "")));
+  template <class T> void test3() {
+    fn3(sizeof(T) == 1);
+  }
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to