From dcf00498c8ad51313911dca77e1414bf90948d07 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 23 Feb 2016 18:55:15 +0000 Subject: [PATCH 1/4] Amends r252104 to evaluate the controlling expression in an unevaluated context. This eliminates false-positive diagnostics about null pointer dereferences (etc) in the controlling expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261669 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit 1dc827614f4762cb4135bfa1ae0b7d628ed8f1a2) --- lib/Sema/SemaExpr.cpp | 11 +++++++---- test/Sema/generic-selection.c | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f003db9ea87..4ff4f781f80 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1365,10 +1365,13 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, // Decay and strip qualifiers for the controlling expression type, and handle // placeholder type replacement. See committee discussion from WG14 DR423. - ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr); - if (R.isInvalid()) - return ExprError(); - ControllingExpr = R.get(); + { + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr); + if (R.isInvalid()) + return ExprError(); + ControllingExpr = R.get(); + } // The controlling expression is an unevaluated operand, so side effects are // likely unintended. diff --git a/test/Sema/generic-selection.c b/test/Sema/generic-selection.c index 0563ec0f4fc..5c02005d0fa 100644 --- a/test/Sema/generic-selection.c +++ b/test/Sema/generic-selection.c @@ -31,4 +31,8 @@ void foo(int n) { const int i = 12; int a9[_Generic(i, int: 1, default: 2) == 1 ? 1 : -1]; + + // This is expected to not trigger any diagnostics because the controlling + // expression is not evaluated. + (void)_Generic(*(int *)0, int: 1); } From b4db5646fcdfbb9aa8f14368eaa6f6a6b8a81d9a Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 24 Feb 2016 21:59:10 +0000 Subject: [PATCH 2/4] PR26237: Fix iterator invalidation bug that occurs if serializing specializations of a template manages to trigger deserialization of more specializations of the same template. No test case provided: this is hard to reliably test due to standard library differences. Patch by Vassil Vassilev! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261781 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit e639f9c8bbde03a63afea2c1b4834c4536b1dbc8) --- lib/Serialization/ASTWriterDecl.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 54bba282ab8..64985a27110 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -191,8 +191,8 @@ namespace clang { return None; } - template - void AddTemplateSpecializations(Decl *D) { + template + void AddTemplateSpecializations(DeclTy *D) { auto *Common = D->getCommonPtr(); // If we have any lazy specializations, and the external AST source is @@ -204,8 +204,6 @@ namespace clang { assert(!Common->LazySpecializations); } - auto &Specializations = Common->Specializations; - auto &&PartialSpecializations = getPartialSpecializations(Common); ArrayRef LazySpecializations; if (auto *LS = Common->LazySpecializations) LazySpecializations = llvm::makeArrayRef(LS + 1, LS[0]); @@ -214,13 +212,15 @@ namespace clang { unsigned I = Record.size(); Record.push_back(0); - for (auto &Entry : Specializations) { - auto *D = getSpecializationDecl(Entry); - assert(D->isCanonicalDecl() && "non-canonical decl in set"); - AddFirstDeclFromEachModule(D, /*IncludeLocal*/true); - } - for (auto &Entry : PartialSpecializations) { - auto *D = getSpecializationDecl(Entry); + // AddFirstDeclFromEachModule might trigger deserialization, invalidating + // *Specializations iterators. + llvm::SmallVector Specs; + for (auto &Entry : Common->Specializations) + Specs.push_back(getSpecializationDecl(Entry)); + for (auto &Entry : getPartialSpecializations(Common)) + Specs.push_back(getSpecializationDecl(Entry)); + + for (auto *D : Specs) { assert(D->isCanonicalDecl() && "non-canonical decl in set"); AddFirstDeclFromEachModule(D, /*IncludeLocal*/true); } From 7176e261d15edb612f1903a23a1f045d35c48b93 Mon Sep 17 00:00:00 2001 From: Faisal Vali Date: Thu, 25 Feb 2016 05:09:30 +0000 Subject: [PATCH 3/4] Twek fix for PR24473 (r261506) - Preserve the template arguments as written (within the DeclRefExpr Node) when creating AST nodes that reference specializations of static data member templates. While we pass the template args through for all non-instance members, they should only be relevant (i.e. non-null) for variable template ids (assertion added for that assumption) Also preserve the FoundDecl that refers to the canonical Decl (the primary VarTemplateDecl for a variable template specialization) that we are referencing in our DeclRefExpr. Not sure why this was not being done for non-variable template-ids. No functionality change - so no tests added. Thanks to Richard Smith for drawing my attention to this! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261823 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit 3f527ef16f0653272bb5102185d9388b308002fd) --- lib/Sema/SemaExprMember.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 207bdc49291..d94f754e3f8 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -1100,6 +1100,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // declaration corresponding to the supplied template arguments // (while emitting diagnostics as necessary) that will be referenced // by this expression. + assert((!TemplateArgs || isa(MemberDecl)) && + "How did we get template arguments here sans a variable template"); if (isa(MemberDecl)) { MemberDecl = getVarTemplateSpecialization( *this, cast(MemberDecl), TemplateArgs, @@ -1107,7 +1109,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (!MemberDecl) return ExprError(); } - return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl); + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl, + FoundDecl, TemplateArgs); } SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) From 4c3d82af3031fc84fb10f3b3c8096848f2ef27e6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 27 Feb 2016 02:36:43 +0000 Subject: [PATCH 4/4] Fix bug in using shadow decl checking: a using shadow decl should not conflict with a prior UsingDecl -- those should not even really be found by the lookup here, except that we use the same lookup results for two different checks, and the other check needs them. This happens to work in *almost all* cases, because either the lookup results list the UsingDecl first (and the NonTag result gets replaced by something else) or because the problematic declaration is a function (which causes us to use different logic to detect conflicts). This can also be triggered from a state only reachable through modules (where the name lookup results can contain multiple UsingDecls in the same scope). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262105 91177308-0d34-0410-b5e6-96231b3b80d8 (cherry picked from commit fceda7d31062da61f20ac369843d390d9ff4fc20) --- lib/Sema/SemaDeclCXX.cpp | 6 ++++++ test/SemaCXX/using-decl-1.cpp | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 48466af92ec..5d1dda0c6be 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7798,6 +7798,12 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); + // We can have UsingDecls in our Previous results because we use the same + // LookupResult for checking whether the UsingDecl itself is a valid + // redeclaration. + if (isa(D)) + continue; + if (IsEquivalentForUsingDecl(Context, D, Target)) { if (UsingShadowDecl *Shadow = dyn_cast(*I)) PrevShadow = Shadow; diff --git a/test/SemaCXX/using-decl-1.cpp b/test/SemaCXX/using-decl-1.cpp index ec45b3109a0..e17612d277c 100644 --- a/test/SemaCXX/using-decl-1.cpp +++ b/test/SemaCXX/using-decl-1.cpp @@ -338,3 +338,26 @@ struct B : A { enum { X = sizeof(field) }; }; } + +namespace tag_vs_var { + namespace N { + struct X {}; + + struct Y {}; + int Y; + + int Z; + } + using N::X; + using N::Y; + using N::Z; + + namespace N { + int X; + + struct Z {}; + } + using N::X; + using N::Y; + using N::Z; +}