From 004319554cf6044896073b8a305ba9d340ed5f94 Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Thu, 17 Nov 2016 01:33:54 +0000 Subject: [PATCH] [Sema] Fix a bug in enable_if condition instantiation. 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. llvm-svn: 287187 --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 ++--- clang/test/SemaCXX/enable_if.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e80c75d..ae5f5de 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -179,7 +179,7 @@ static void instantiateDependentEnableIfAttr( return; Cond = Result.getAs(); } - 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(TmplAttr); - if (EnableIf && EnableIf->getCond()->isValueDependent()) { + if (const auto *EnableIf = dyn_cast(TmplAttr)) { instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, New); continue; diff --git a/clang/test/SemaCXX/enable_if.cpp b/clang/test/SemaCXX/enable_if.cpp index e265b41..0f8fc9b 100644 --- a/clang/test/SemaCXX/enable_if.cpp +++ b/clang/test/SemaCXX/enable_if.cpp @@ -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 +struct Foo { + void bar(int a) __attribute__((enable_if(a, ""))); // expected-note{{disabled}} +}; + +void runFoo() { + Foo().bar(0); // expected-error{{no matching}} + Foo().bar(1); +} +} -- 2.7.4