]> granicus.if.org Git - clang/commitdiff
[Sema] Fix a bug in enable_if condition instantiation.
authorGeorge Burgess IV <george.burgess.iv@gmail.com>
Thu, 17 Nov 2016 01:33:54 +0000 (01:33 +0000)
committerGeorge Burgess IV <george.burgess.iv@gmail.com>
Thu, 17 Nov 2016 01:33:54 +0000 (01:33 +0000)
During template instantiation, we currently fall back to just calling
Sema::SubstExpr for enable_if attributes that aren't value-dependent or
type-dependent. Since Sema::SubstExpr strips off any implicit casts
we've added to an expression, it's possible that this behavior will
leave us with an enable_if condition that's just a DeclRefExpr.
Conditions like that deeply confuse Sema::CheckEnableIf.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@287187 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/enable_if.cpp

index e80c75d298d5a760b2792b7fa47c5c1124c84cc9..ae5f5ded890594e20a095338077af2e1d515f98b 100644 (file)
@@ -179,7 +179,7 @@ static void instantiateDependentEnableIfAttr(
       return;
     Cond = Result.getAs<Expr>();
   }
-  if (A->getCond()->isTypeDependent() && !Cond->isTypeDependent()) {
+  if (!Cond->isTypeDependent()) {
     ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
     if (Converted.isInvalid())
       return;
@@ -332,8 +332,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
       continue;
     }
 
-    const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr);
-    if (EnableIf && EnableIf->getCond()->isValueDependent()) {
+    if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) {
       instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
                                        New);
       continue;
index e265b410ac8e2149bbd7b43b99e57e3277472e99..0f8fc9b2652abbb0635f4dc8a13d0bd83cf984a3 100644 (file)
@@ -450,3 +450,17 @@ namespace member_loc {
       .bar(); // expected-error{{no matching member function}}
   }
 }
+
+// Prior bug: we wouldn't properly convert conditions to bools when
+// instantiating templates in some cases.
+namespace template_instantiation {
+template <typename T>
+struct Foo {
+  void bar(int a) __attribute__((enable_if(a, ""))); // expected-note{{disabled}}
+};
+
+void runFoo() {
+  Foo<double>().bar(0); // expected-error{{no matching}}
+  Foo<double>().bar(1);
+}
+}