Author: Pranav Kant Date: 2024-04-26T00:18:08Z New Revision: 0c6e1ca1c704a3a0fb53ae54f7e3723736f477c7
URL: https://github.com/llvm/llvm-project/commit/0c6e1ca1c704a3a0fb53ae54f7e3723736f477c7 DIFF: https://github.com/llvm/llvm-project/commit/0c6e1ca1c704a3a0fb53ae54f7e3723736f477c7.diff LOG: Revert "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (#84050)" This reverts commit a8fd0d029dca7d17eee72d0445223c2fe1ee7758. Added: Modified: clang-tools-extra/clangd/unittests/FindTargetTests.cpp clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp clang/docs/ReleaseNotes.rst clang/include/clang/Sema/Lookup.h clang/include/clang/Sema/Sema.h clang/lib/AST/Expr.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Sema/HLSLExternalSemaSource.cpp clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaExprMember.cpp clang/lib/Sema/SemaLookup.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/TreeTransform.h clang/test/AST/HLSL/this-reference-template.hlsl clang/test/CXX/drs/dr2xx.cpp clang/test/CXX/drs/dr3xx.cpp clang/test/CXX/temp/temp.res/temp.local/p3.cpp clang/test/CodeGenCXX/mangle.cpp clang/test/Index/annotate-nested-name-specifier.cpp clang/test/SemaCXX/member-expr.cpp clang/test/SemaTemplate/instantiate-function-1.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Removed: clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp ################################################################################ diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 94437857cecca6..799a549ff0816e 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -854,7 +854,7 @@ TEST_F(TargetDeclTest, DependentExprs) { } }; )cpp"; - EXPECT_DECLS("MemberExpr", "void foo()"); + EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()"); // Similar to above but base expression involves a function call. Code = R"cpp( @@ -872,7 +872,7 @@ TEST_F(TargetDeclTest, DependentExprs) { } }; )cpp"; - EXPECT_DECLS("MemberExpr", "void foo()"); + EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()"); // Similar to above but uses a function pointer. Code = R"cpp( @@ -891,7 +891,7 @@ TEST_F(TargetDeclTest, DependentExprs) { } }; )cpp"; - EXPECT_DECLS("MemberExpr", "void foo()"); + EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()"); // Base expression involves a member access into this. Code = R"cpp( @@ -962,7 +962,7 @@ TEST_F(TargetDeclTest, DependentExprs) { void Foo() { this->[[find]](); } }; )cpp"; - EXPECT_DECLS("MemberExpr", "void find()"); + EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()"); } TEST_F(TargetDeclTest, DependentTypes) { diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index 30b9b1902aa9c7..4156921d83edf8 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -621,7 +621,7 @@ sizeof...($TemplateParameter[[Elements]]); struct $Class_def[[Foo]] { int $Field_decl[[Waldo]]; void $Method_def[[bar]]() { - $Class[[Foo]]().$Field[[Waldo]]; + $Class[[Foo]]().$Field_dependentName[[Waldo]]; } template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]] void $Method_def[[bar1]]() { diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp index ae61b17ca14d20..574efe7bd91478 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp @@ -309,8 +309,6 @@ struct HeapArray { // Ok, since destruc HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok other._data = nullptr; // Ok - // CHECK-NOTES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'std::nullptr_t' - // FIXME: This warning is emitted because an ImplicitCastExpr for the NullToPointer conversion isn't created for dependent types. other.size = 0; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp index 4abb9c8555970e..559031cf4d9bda 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp @@ -260,8 +260,6 @@ template <class T> struct Template { Template() = default; Template(const Template &Other) : Field(Other.Field) {} - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' - // CHECK-FIXES: Template(const Template &Other) = default; Template &operator=(const Template &Other); void foo(const T &t); int Field; @@ -271,12 +269,8 @@ Template<T> &Template<T>::operator=(const Template<T> &Other) { Field = Other.Field; return *this; } -// CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default' -// CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default; - Template<int> T1; - // Dependent types. template <class T> struct DT1 { @@ -290,9 +284,6 @@ DT1<T> &DT1<T>::operator=(const DT1<T> &Other) { Field = Other.Field; return *this; } -// CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default' -// CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default; - DT1<int> Dt1; template <class T> @@ -312,9 +303,6 @@ DT2<T> &DT2<T>::operator=(const DT2<T> &Other) { struct T { typedef int TT; }; -// CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default' -// CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default; - DT2<T> Dt2; // Default arguments. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 00c684e773a2e0..f5e5d3a2e6ea36 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -385,18 +385,6 @@ Improvements to Clang's diagnostics - Clang now diagnoses requires expressions with explicit object parameters. -- Clang now looks up members of the current instantiation in the template definition context - if the current instantiation has no dependent base classes. - - .. code-block:: c++ - - template<typename T> - struct A { - int f() { - return this->x; // error: no member named 'x' in 'A<T>' - } - }; - Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h index b0a08a05ac6a0a..0db5b847038ffd 100644 --- a/clang/include/clang/Sema/Lookup.h +++ b/clang/include/clang/Sema/Lookup.h @@ -499,9 +499,7 @@ class LookupResult { /// Note that while no result was found in the current instantiation, /// there were dependent base classes that could not be searched. void setNotFoundInCurrentInstantiation() { - assert((ResultKind == NotFound || - ResultKind == NotFoundInCurrentInstantiation) && - Decls.empty()); + assert(ResultKind == NotFound && Decls.empty()); ResultKind = NotFoundInCurrentInstantiation; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index aa182b15e66ecc..1ca523ec88c2f9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7472,7 +7472,7 @@ class Sema final : public SemaBase { bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, CXXScopeSpec &SS); bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, - QualType ObjectType, bool AllowBuiltinCreation = false, + bool AllowBuiltinCreation = false, bool EnteringContext = false); ObjCProtocolDecl *LookupProtocol( IdentifierInfo *II, SourceLocation IdLoc, @@ -8881,13 +8881,11 @@ class Sema final : public SemaBase { /// functions (but no function templates). FoundFunctions, }; - - bool - LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, - QualType ObjectType, bool EnteringContext, - RequiredTemplateKind RequiredTemplate = SourceLocation(), - AssumedTemplateKind *ATK = nullptr, - bool AllowTypoCorrection = true); + bool LookupTemplateName( + LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, + bool EnteringContext, bool &MemberOfUnknownSpecialization, + RequiredTemplateKind RequiredTemplate = SourceLocation(), + AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true); TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword, diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index d2e40be59d6f3b..63dcdb919c7117 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -103,7 +103,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments( } } else if (const auto *ME = dyn_cast<MemberExpr>(E)) { if (!ME->isArrow()) { - assert(ME->getBase()->getType()->getAsRecordDecl()); + assert(ME->getBase()->getType()->isRecordType()); if (const auto *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) { if (!Field->isBitField() && !Field->getType()->isReferenceType()) { E = ME->getBase(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 53a33fa4add54e..05ad5ecbfaa0cf 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2998,7 +2998,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, << TokenName << TagName << getLangOpts().CPlusPlus << FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName); - if (Actions.LookupName(R, getCurScope())) { + if (Actions.LookupParsedName(R, getCurScope(), SS)) { for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index bb283c54b3d29c..1a1febf7a35241 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -126,15 +126,12 @@ struct BuiltinTypeDeclBuilder { static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S, StringRef Name) { + CXXScopeSpec SS; IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier); DeclarationNameInfo NameInfo = DeclarationNameInfo(DeclarationName(&II), SourceLocation()); LookupResult R(S, NameInfo, Sema::LookupOrdinaryName); - // AllowBuiltinCreation is false but LookupDirect will create - // the builtin when searching the global scope anyways... - S.LookupName(R, S.getCurScope()); - // FIXME: If the builtin function was user-declared in global scope, - // this assert *will* fail. Should this call LookupBuiltin instead? + S.LookupParsedName(R, S.getCurScope(), &SS, false); assert(R.isSingleResult() && "Since this is a builtin it should always resolve!"); auto *VD = cast<ValueDecl>(R.getFoundDecl()); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index a83b1e8afadbc6..a5dd158808f26b 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -837,7 +837,7 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, IdentifierInfo *Name = IdTok.getIdentifierInfo(); LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); - LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true); + LookupParsedName(Lookup, curScope, nullptr, true); if (Lookup.empty()) { Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4e275dc15fbb4e..e0745fe9a45367 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -832,7 +832,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, IdentifierInfo *&Name, SourceLocation NameLoc) { LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName); - SemaRef.LookupParsedName(R, S, &SS, /*ObjectType=*/QualType()); + SemaRef.LookupParsedName(R, S, &SS); if (TagDecl *Tag = R.getAsSingle<TagDecl>()) { StringRef FixItTagName; switch (Tag->getTagKind()) { @@ -869,7 +869,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, // Replace lookup results with just the tag decl. Result.clear(Sema::LookupTagName); - SemaRef.LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType()); + SemaRef.LookupParsedName(Result, S, &SS); return true; } @@ -896,8 +896,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, } LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); - LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType(), - /*AllowBuiltinCreation=*/!CurMethod); + LookupParsedName(Result, S, &SS, !CurMethod); if (SS.isInvalid()) return NameClassification::Error(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 4d5836720a651f..abdbc9d8830c03 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4517,7 +4517,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, DS.getBeginLoc(), DS.getEllipsisLoc()); } else { LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); - LookupParsedName(R, S, &SS, /*ObjectType=*/QualType()); + LookupParsedName(R, S, &SS); TypeDecl *TyD = R.getAsSingle<TypeDecl>(); if (!TyD) { @@ -12262,7 +12262,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, // Lookup namespace name. LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); - LookupParsedName(R, S, &SS, /*ObjectType=*/QualType()); + LookupParsedName(R, S, &SS); if (R.isAmbiguous()) return nullptr; @@ -13721,7 +13721,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, // Lookup the namespace name. LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); - LookupParsedName(R, S, &SS, /*ObjectType=*/QualType()); + LookupParsedName(R, S, &SS); if (R.isAmbiguous()) return nullptr; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0c37f43f75401b..50f92c496a539a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -673,9 +673,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // expressions of certain types in C++. if (getLangOpts().CPlusPlus && (E->getType() == Context.OverloadTy || - // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied - // to pointer types even if the pointee type is dependent. - (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) + T->isDependentType() || + T->isRecordType())) return E; // The C standard is actually really unclear on this point, and @@ -2752,8 +2751,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) { // See if this is reference to a field of struct. LookupResult R(*this, NameInfo, LookupMemberName); - // LookupName handles a name lookup from within anonymous struct. - if (LookupName(R, S)) { + // LookupParsedName handles a name lookup from within anonymous struct. + if (LookupParsedName(R, S, &SS)) { if (auto *VD = dyn_cast<ValueDecl>(R.getFoundDecl())) { QualType type = VD->getType().getNonReferenceType(); // This will eventually be translated into MemberExpr upon @@ -2774,19 +2773,20 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // lookup to determine that it was a template name in the first place. If // this becomes a performance hit, we can work harder to preserve those // results until we get here but it's likely not worth it. + bool MemberOfUnknownSpecialization; AssumedTemplateKind AssumedTemplate; - if (LookupTemplateName(R, S, SS, /*ObjectType=*/QualType(), - /*EnteringContext=*/false, TemplateKWLoc, + if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, + MemberOfUnknownSpecialization, TemplateKWLoc, &AssumedTemplate)) return ExprError(); - if (R.wasNotFoundInCurrentInstantiation()) + if (MemberOfUnknownSpecialization || + (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); } else { bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl(); - LookupParsedName(R, S, &SS, /*ObjectType=*/QualType(), - /*AllowBuiltinCreation=*/!IvarLookupFollowUp); + LookupParsedName(R, S, &SS, !IvarLookupFollowUp); // If the result might be in a dependent base class, this is a dependent // id-expression. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c1cb03e4ec7ae2..779a41620033dc 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -9157,7 +9157,7 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, // Do the redeclaration lookup in the current scope. LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, RedeclarationKind::NotForRedeclaration); - LookupParsedName(R, S, &SS, /*ObjectType=*/QualType()); + LookupParsedName(R, S, &SS); R.suppressDiagnostics(); switch (R.getResultKind()) { diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 0eeb7b1faa0a22..6e30716b9ae436 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -667,8 +667,8 @@ namespace { // classes, one of its base classes. class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { public: - explicit RecordMemberExprValidatorCCC(QualType RTy) - : Record(RTy->getAsRecordDecl()) { + explicit RecordMemberExprValidatorCCC(const RecordType *RTy) + : Record(RTy->getDecl()) { // Don't add bare keywords to the consumer since they will always fail // validation by virtue of not being associated with any decls. WantTypeSpecifiers = false; @@ -713,36 +713,58 @@ class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { } static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, - Expr *BaseExpr, QualType RTy, + Expr *BaseExpr, + const RecordType *RTy, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, bool HasTemplateArgs, SourceLocation TemplateKWLoc, TypoExpr *&TE) { SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange(); - if (!RTy->isDependentType() && - !SemaRef.isThisOutsideMemberFunctionBody(RTy) && - SemaRef.RequireCompleteType( - OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange)) + RecordDecl *RDecl = RTy->getDecl(); + if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) && + SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0), + diag::err_typecheck_incomplete_tag, + BaseRange)) return true; - // LookupTemplateName/LookupParsedName don't expect these both to exist - // simultaneously. - QualType ObjectType = SS.isSet() ? QualType() : RTy; - if (HasTemplateArgs || TemplateKWLoc.isValid()) - return SemaRef.LookupTemplateName(R, - /*S=*/nullptr, SS, ObjectType, - /*EnteringContext=*/false, TemplateKWLoc); + if (HasTemplateArgs || TemplateKWLoc.isValid()) { + // LookupTemplateName doesn't expect these both to exist simultaneously. + QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0); - SemaRef.LookupParsedName(R, /*S=*/nullptr, &SS, ObjectType); + bool MOUS; + return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS, + TemplateKWLoc); + } + + DeclContext *DC = RDecl; + if (SS.isSet()) { + // If the member name was a qualified-id, look into the + // nested-name-specifier. + DC = SemaRef.computeDeclContext(SS, false); + + if (SemaRef.RequireCompleteDeclContext(SS, DC)) { + SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) + << SS.getRange() << DC; + return true; + } + + assert(DC && "Cannot handle non-computable dependent contexts in lookup"); + + if (!isa<TypeDecl>(DC)) { + SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass) + << DC << SS.getRange(); + return true; + } + } - if (!R.empty() || R.wasNotFoundInCurrentInstantiation()) + // The record definition is complete, now look up the member. + SemaRef.LookupQualifiedName(R, DC, SS); + + if (!R.empty()) return false; DeclarationName Typo = R.getLookupName(); SourceLocation TypoLoc = R.getNameLoc(); - // Recompute the lookup context. - DeclContext *DC = SS.isSet() ? SemaRef.computeDeclContext(SS) - : SemaRef.computeDeclContext(RTy); struct QueryState { Sema &SemaRef; @@ -766,8 +788,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, << Typo << DC << DroppedSpecifier << SS.getRange()); } else { - SemaRef.Diag(TypoLoc, diag::err_no_member) - << Typo << DC << (SS.isSet() ? SS.getRange() : BaseRange); + SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << DC << BaseRange; } }, [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable { @@ -793,25 +814,34 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, Decl *ObjCImpDecl, bool HasTemplateArgs, SourceLocation TemplateKWLoc); -ExprResult Sema::BuildMemberReferenceExpr( - Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, - CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - ActOnMemberAccessExtraArgs *ExtraArgs) { - LookupResult R(*this, NameInfo, LookupMemberName); +ExprResult +Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, + SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, + const Scope *S, + ActOnMemberAccessExtraArgs *ExtraArgs) { + if (BaseType->isDependentType() || + (SS.isSet() && isDependentScopeSpecifier(SS)) || + NameInfo.getName().isDependentName()) + return ActOnDependentMemberExpr(Base, BaseType, + IsArrow, OpLoc, + SS, TemplateKWLoc, FirstQualifierInScope, + NameInfo, TemplateArgs); - if (SS.isInvalid()) - return ExprError(); + LookupResult R(*this, NameInfo, LookupMemberName); // Implicit member accesses. if (!Base) { TypoExpr *TE = nullptr; QualType RecordTy = BaseType; if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType(); - if (LookupMemberExprInRecord(*this, R, nullptr, RecordTy, OpLoc, IsArrow, - SS, TemplateArgs != nullptr, TemplateKWLoc, - TE)) + if (LookupMemberExprInRecord( + *this, R, nullptr, RecordTy->castAs<RecordType>(), OpLoc, IsArrow, + SS, TemplateArgs != nullptr, TemplateKWLoc, TE)) return ExprError(); if (TE) return TE; @@ -1003,12 +1033,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, const Scope *S, bool SuppressQualifierCheck, ActOnMemberAccessExtraArgs *ExtraArgs) { - assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid"); - if (R.wasNotFoundInCurrentInstantiation()) - return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, - TemplateKWLoc, FirstQualifierInScope, - R.getLookupNameInfo(), TemplateArgs); - QualType BaseType = BaseExprType; if (IsArrow) { assert(BaseType->isPointerType()); @@ -1016,11 +1040,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } R.setBaseObjectType(BaseType); - assert((SS.isEmpty() - ? !BaseType->isDependentType() || computeDeclContext(BaseType) - : !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) && - "dependent lookup context that isn't the current instantiation?"); - // C++1z [expr.ref]p2: // For the first option (dot) the first expression shall be a glvalue [...] if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) { @@ -1050,11 +1069,13 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (R.empty()) { // Rederive where we looked up. - DeclContext *DC = - (SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType)); + DeclContext *DC = (SS.isSet() + ? computeDeclContext(SS, false) + : BaseType->castAs<RecordType>()->getDecl()); + if (ExtraArgs) { ExprResult RetryExpr; - if (!IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) { + if (!IsArrow && BaseExpr) { SFINAETrap Trap(*this, true); ParsedType ObjectType; bool MayBePseudoDestructor = false; @@ -1077,12 +1098,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } } - assert(DC); Diag(R.getNameLoc(), diag::err_no_member) - << MemberName << DC - << (SS.isSet() - ? SS.getRange() - : (BaseExpr ? BaseExpr->getSourceRange() : SourceRange())); + << MemberName << DC + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); return ExprError(); } @@ -1312,6 +1330,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, return ExprError(); QualType BaseType = BaseExpr.get()->getType(); + assert(!BaseType->isDependentType()); DeclarationName MemberName = R.getLookupName(); SourceLocation MemberLoc = R.getNameLoc(); @@ -1323,31 +1342,29 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (IsArrow) { if (const PointerType *Ptr = BaseType->getAs<PointerType>()) BaseType = Ptr->getPointeeType(); - else if (!BaseType->isDependentType()) { - if (const ObjCObjectPointerType *Ptr = - BaseType->getAs<ObjCObjectPointerType>()) - BaseType = Ptr->getPointeeType(); - else if (BaseType->isRecordType()) { - // Recover from arrow accesses to records, e.g.: - // struct MyRecord foo; - // foo->bar - // This is actually well-formed in C++ if MyRecord has an - // overloaded operator->, but that should have been dealt with - // by now--or a diagnostic message already issued if a problem - // was encountered while looking for the overloaded operator->. - if (!S.getLangOpts().CPlusPlus) { - S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "."); - } - IsArrow = false; - } else if (BaseType->isFunctionType()) { - goto fail; - } else { - S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) - << BaseType << BaseExpr.get()->getSourceRange(); - return ExprError(); + else if (const ObjCObjectPointerType *Ptr + = BaseType->getAs<ObjCObjectPointerType>()) + BaseType = Ptr->getPointeeType(); + else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now--or a diagnostic message already issued if a problem + // was encountered while looking for the overloaded operator->. + if (!S.getLangOpts().CPlusPlus) { + S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); } + IsArrow = false; + } else if (BaseType->isFunctionType()) { + goto fail; + } else { + S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << BaseExpr.get()->getSourceRange(); + return ExprError(); } } @@ -1367,10 +1384,10 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } // Handle field access to simple records. - if (BaseType->getAsRecordDecl() || BaseType->isDependentType()) { + if (const RecordType *RTy = BaseType->getAs<RecordType>()) { TypoExpr *TE = nullptr; - if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow, - SS, HasTemplateArgs, TemplateKWLoc, TE)) + if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS, + HasTemplateArgs, TemplateKWLoc, TE)) return ExprError(); // Returning valid-but-null is how we indicate to the caller that @@ -1807,6 +1824,13 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, if (Result.isInvalid()) return ExprError(); Base = Result.get(); + if (Base->getType()->isDependentType() || Name.isDependentName() || + isDependentScopeSpecifier(SS)) { + return ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS, + TemplateKWLoc, FirstQualifierInScope, + NameInfo, TemplateArgs); + } + ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; ExprResult Res = BuildMemberReferenceExpr( Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index a537eccc2ebaf0..55af414df39f51 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1282,31 +1282,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { if (DeclContext *DC = PreS->getEntity()) DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); } - // C++23 [temp.dep.general]p2: - // The component name of an unqualified-id is dependent if - // - it is a conversion-function-id whose conversion-type-id - // is dependent, or - // - it is operator= and the current class is a templated entity, or - // - the unqualified-id is the postfix-expression in a dependent call. - if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) { - R.setNotFoundInCurrentInstantiation(); - return false; - } - - // If this is the name of an implicitly-declared special member function, - // go through the scope stack to implicitly declare - if (isImplicitlyDeclaredMemberFunctionName(Name)) { - for (Scope *PreS = S; PreS; PreS = PreS->getParent()) - if (DeclContext *DC = PreS->getEntity()) { - if (DC->isDependentContext() && isa<CXXRecordDecl>(DC) && - Name.getCXXOverloadedOperator() == OO_Equal) { - R.setNotFoundInCurrentInstantiation(); - return false; - } - DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); - } - } // Implicitly declare member functions with the name we're looking for, if in // fact we are in a scope where it matters. @@ -2471,33 +2446,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, } } QL(LookupCtx); - CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); - // FIXME: Per [temp.dep.general]p2, an unqualified name is also dependent - // if it's a dependent conversion-function-id or operator= where the current - // class is a templated entity. This should be handled in LookupName. - if (!InUnqualifiedLookup && !R.isForRedeclaration()) { - // C++23 [temp.dep.type]p5: - // A qualified name is dependent if - // - it is a conversion-function-id whose conversion-type-id - // is dependent, or - // - [...] - // - its lookup context is the current instantiation and it - // is operator=, or - // - [...] - if (DeclarationName Name = R.getLookupName(); - (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) || - (Name.getCXXOverloadedOperator() == OO_Equal && LookupRec && - LookupRec->isDependentContext())) { - R.setNotFoundInCurrentInstantiation(); - return false; - } - } - if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); - if (LookupRec) - R.setNamingClass(LookupRec); + if (isa<CXXRecordDecl>(LookupCtx)) + R.setNamingClass(cast<CXXRecordDecl>(LookupCtx)); return true; } @@ -2519,6 +2471,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. + CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); if (!LookupRec || !LookupRec->getDefinition()) return false; @@ -2765,54 +2718,38 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, - QualType ObjectType, bool AllowBuiltinCreation, - bool EnteringContext) { - // When the scope specifier is invalid, don't even look for anything. - if (SS && SS->isInvalid()) + bool AllowBuiltinCreation, bool EnteringContext) { + if (SS && SS->isInvalid()) { + // When the scope specifier is invalid, don't even look for + // anything. return false; + } - // Determine where to perform name lookup - DeclContext *DC = nullptr; - bool IsDependent = false; - if (!ObjectType.isNull()) { - // This nested-name-specifier occurs in a member access expression, e.g., - // x->B::f, and we are looking into the type of the object. - assert((!SS || SS->isEmpty()) && - "ObjectType and scope specifier cannot coexist"); - DC = computeDeclContext(ObjectType); - IsDependent = !DC && ObjectType->isDependentType(); - assert(((!DC && ObjectType->isDependentType()) || - !ObjectType->isIncompleteType() || !ObjectType->getAs<TagType>() || - ObjectType->castAs<TagType>()->isBeingDefined()) && - "Caller should have completed object type"); - } else if (SS && SS->isNotEmpty()) { - if (NestedNameSpecifier *NNS = SS->getScopeRep(); - NNS->getKind() == NestedNameSpecifier::Super) + if (SS && SS->isSet()) { + NestedNameSpecifier *NNS = SS->getScopeRep(); + if (NNS->getKind() == NestedNameSpecifier::Super) return LookupInSuper(R, NNS->getAsRecordDecl()); - // This nested-name-specifier occurs after another nested-name-specifier, - // so long into the context associated with the prior nested-name-specifier. - if (DC = computeDeclContext(*SS, EnteringContext)) { - // The declaration context must be complete. + + if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { + // We have resolved the scope specifier to a particular declaration + // contex, and will perform name lookup in that context. if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC)) return false; + R.setContextRange(SS->getRange()); + return LookupQualifiedName(R, DC); } - IsDependent = !DC && isDependentScopeSpecifier(*SS); - } else { - // Perform unqualified name lookup starting in the given scope. - return LookupName(R, S, AllowBuiltinCreation); - } - // If we were able to compute a declaration context, perform qualified name - // lookup in that context. - if (DC) - return LookupQualifiedName(R, DC); - else if (IsDependent) // We could not resolve the scope specified to a specific declaration // context, which means that SS refers to an unknown specialization. // Name lookup can't find anything in this case. R.setNotFoundInCurrentInstantiation(); - return false; + R.setContextRange(SS->getRange()); + return false; + } + + // Perform unqualified name lookup starting in the given scope. + return LookupName(R, S, AllowBuiltinCreation); } /// Perform qualified name lookup into all base classes of the given @@ -5081,9 +5018,8 @@ static void LookupPotentialTypoResult(Sema &SemaRef, return; } - SemaRef.LookupParsedName(Res, S, SS, - /*ObjectType=*/QualType(), - /*AllowBuiltinCreation=*/false, EnteringContext); + SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, + EnteringContext); // Fake ivar lookup; this should really be part of // LookupParsedName. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index cf5447f223d450..cee8da495c5495 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3061,9 +3061,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope *CurScope, OpenMPDirectiveKind Kind) { ASTContext &Context = getASTContext(); LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName); - SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, - /*ObjectType=*/QualType(), - /*AllowBuiltinCreation=*/true); + SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, true); if (Lookup.isAmbiguous()) return ExprError(); @@ -7409,8 +7407,7 @@ void SemaOpenMP::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( const IdentifierInfo *BaseII = D.getIdentifier(); LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(), Sema::LookupOrdinaryName); - SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(), - /*ObjectType=*/QualType()); + SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec()); TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); QualType FType = TInfo->getType(); @@ -19314,8 +19311,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, if (S) { LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName); Lookup.suppressDiagnostics(); - while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec, - /*ObjectType=*/QualType())) { + while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec)) { NamedDecl *D = Lookup.getRepresentativeDecl(); do { S = S->getParent(); @@ -22184,8 +22180,7 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName); Lookup.suppressDiagnostics(); if (S) { - while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec, - /*ObjectType=*/QualType())) { + while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec)) { NamedDecl *D = Lookup.getRepresentativeDecl(); while (S && !S->isDeclScope(D)) S = S->getParent(); @@ -23502,9 +23497,7 @@ void SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() { NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName( Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) { LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName); - SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, - /*ObjectType=*/QualType(), - /*AllowBuiltinCreation=*/true); + SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec, true); if (Lookup.isAmbiguous()) return nullptr; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 72bf6370ca821a..bbcb7c33a98579 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -210,11 +210,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S, AssumedTemplateKind AssumedTemplate; LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName); if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, - /*RequiredTemplate=*/SourceLocation(), + MemberOfUnknownSpecialization, SourceLocation(), &AssumedTemplate, /*AllowTypoCorrection=*/!Disambiguation)) return TNK_Non_template; - MemberOfUnknownSpecialization = R.wasNotFoundInCurrentInstantiation(); if (AssumedTemplate != AssumedTemplateKind::None) { TemplateResult = TemplateTy::make(Context.getAssumedTemplateName(TName)); @@ -321,12 +320,15 @@ TemplateNameKind Sema::isTemplateName(Scope *S, bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name, SourceLocation NameLoc, CXXScopeSpec &SS, ParsedTemplateTy *Template /*=nullptr*/) { + bool MemberOfUnknownSpecialization = false; + // We could use redeclaration lookup here, but we don't need to: the // syntactic form of a deduction guide is enough to identify it even // if we can't look up the template name at all. LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName); if (LookupTemplateName(R, S, SS, /*ObjectType*/ QualType(), - /*EnteringContext*/ false)) + /*EnteringContext*/ false, + MemberOfUnknownSpecialization)) return false; if (R.empty()) return false; @@ -372,8 +374,11 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, return true; } -bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS, - QualType ObjectType, bool EnteringContext, +bool Sema::LookupTemplateName(LookupResult &Found, + Scope *S, CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext, + bool &MemberOfUnknownSpecialization, RequiredTemplateKind RequiredTemplate, AssumedTemplateKind *ATK, bool AllowTypoCorrection) { @@ -386,6 +391,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS, Found.setTemplateNameLookup(true); // Determine where to perform name lookup + MemberOfUnknownSpecialization = false; DeclContext *LookupCtx = nullptr; bool IsDependent = false; if (!ObjectType.isNull()) { @@ -542,7 +548,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS, FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup); if (Found.empty()) { if (IsDependent) { - Found.setNotFoundInCurrentInstantiation(); + MemberOfUnknownSpecialization = true; return false; } @@ -5589,9 +5595,11 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, RequireCompleteDeclContext(SS, DC)) return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); + bool MemberOfUnknownSpecialization; LookupResult R(*this, NameInfo, LookupOrdinaryName); if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(), - /*Entering*/ false, TemplateKWLoc)) + /*Entering*/false, MemberOfUnknownSpecialization, + TemplateKWLoc)) return ExprError(); if (R.isAmbiguous()) @@ -5712,13 +5720,14 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S, DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name); LookupResult R(*this, DNI.getName(), Name.getBeginLoc(), LookupOrdinaryName); + bool MOUS; // Tell LookupTemplateName that we require a template so that it diagnoses // cases where it finds a non-template. RequiredTemplateKind RTK = TemplateKWLoc.isValid() ? RequiredTemplateKind(TemplateKWLoc) : TemplateNameIsRequired; - if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, RTK, - /*ATK=*/nullptr, /*AllowTypoCorrection=*/false) && + if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, MOUS, + RTK, nullptr, /*AllowTypoCorrection=*/false) && !R.isAmbiguous()) { if (LookupCtx) Diag(Name.getBeginLoc(), diag::err_no_member) @@ -5807,7 +5816,7 @@ bool Sema::CheckTemplateTypeArgument( if (auto *II = NameInfo.getName().getAsIdentifierInfo()) { LookupResult Result(*this, NameInfo, LookupOrdinaryName); - LookupParsedName(Result, CurScope, &SS, /*ObjectType=*/QualType()); + LookupParsedName(Result, CurScope, &SS); if (Result.getAsSingle<TypeDecl>() || Result.getResultKind() == @@ -11170,8 +11179,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, : TSK_ExplicitInstantiationDeclaration; LookupResult Previous(*this, NameInfo, LookupOrdinaryName); - LookupParsedName(Previous, S, &D.getCXXScopeSpec(), - /*ObjectType=*/QualType()); + LookupParsedName(Previous, S, &D.getCXXScopeSpec()); if (!R->isFunctionType()) { // C++ [temp.explicit]p1: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 28d3d1b79a7424..f47bc219e6fa32 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13217,26 +13217,6 @@ bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old, // Resolve a kind, but don't do any further analysis. If it's // ambiguous, the callee needs to deal with it. R.resolveKind(); - - if (Old->hasTemplateKeyword() && !R.empty()) { - NamedDecl *FoundDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); - getSema().FilterAcceptableTemplateNames(R, - /*AllowFunctionTemplates=*/true, - /*AllowDependent=*/true); - if (R.empty()) { - // If a 'template' keyword was used, a lookup that finds only non-template - // names is an error. - getSema().Diag(R.getNameLoc(), - diag::err_template_kw_refers_to_non_template) - << R.getLookupName() << Old->getQualifierLoc().getSourceRange() - << Old->hasTemplateKeyword() << Old->getTemplateKeywordLoc(); - getSema().Diag(FoundDecl->getLocation(), - diag::note_template_kw_refers_to_non_template) - << R.getLookupName(); - return true; - } - } - return false; } diff --git a/clang/test/AST/HLSL/this-reference-template.hlsl b/clang/test/AST/HLSL/this-reference-template.hlsl index d427e73044b788..60e057986ebf80 100644 --- a/clang/test/AST/HLSL/this-reference-template.hlsl +++ b/clang/test/AST/HLSL/this-reference-template.hlsl @@ -24,7 +24,7 @@ void main() { // CHECK: -CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <line:8:3, line:10:3> line:8:5 getFirst 'K ()' implicit-inline // CHECK-NEXT:-CompoundStmt 0x{{[0-9A-Fa-f]+}} <col:16, line:10:3> // CHECK-NEXT:-ReturnStmt 0x{{[0-9A-Fa-f]+}} <line:9:4, col:16> -// CHECK-NEXT:-MemberExpr 0x{{[0-9A-Fa-f]+}} <col:11, col:16> 'K' lvalue .First 0x{{[0-9A-Fa-f]+}} +// CHECK-NEXT:-CXXDependentScopeMemberExpr 0x{{[0-9A-Fa-f]+}} <col:11, col:16> '<dependent type>' lvalue .First // CHECK-NEXT:-CXXThisExpr 0x{{[0-9A-Fa-f]+}} <col:11> 'Pair<K, V>' lvalue this // CHECK-NEXT:-CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <line:12:3, line:14:3> line:12:5 getSecond 'V ()' implicit-inline // CHECK-NEXT:-CompoundStmt 0x{{[0-9A-Fa-f]+}} <col:17, line:14:3> diff --git a/clang/test/CXX/drs/dr2xx.cpp b/clang/test/CXX/drs/dr2xx.cpp index 2b3131be33057a..5d3e8ce4bea3bc 100644 --- a/clang/test/CXX/drs/dr2xx.cpp +++ b/clang/test/CXX/drs/dr2xx.cpp @@ -561,9 +561,9 @@ namespace cwg244 { // cwg244: 11 B_ptr->B_alias::~B(); B_ptr->B_alias::~B_alias(); B_ptr->cwg244::~B(); - // expected-error@-1 {{no member named '~B' in namespace 'cwg244'}} + // expected-error@-1 {{qualified member access refers to a member in namespace 'cwg244'}} B_ptr->cwg244::~B_alias(); - // expected-error@-1 {{no member named '~B' in namespace 'cwg244'}} + // expected-error@-1 {{qualified member access refers to a member in namespace 'cwg244'}} } template<typename T, typename U> @@ -836,7 +836,7 @@ namespace cwg258 { // cwg258: 2.8 namespace cwg259 { // cwg259: 4 template<typename T> struct A {}; - template struct A<int>; // #cwg259-A-int + template struct A<int>; // #cwg259-A-int template struct A<int>; // expected-error@-1 {{duplicate explicit instantiation of 'A<int>'}} // expected-note@#cwg259-A-int {{previous explicit instantiation is here}} @@ -997,7 +997,7 @@ namespace cwg275 { // cwg275: no // expected-error@-1 {{no function template matches function template specialization 'f'}} } - template <class T> void g(T) {} // #cwg275-g + template <class T> void g(T) {} // #cwg275-g template <> void N::f(char) {} template <> void f(int) {} @@ -1164,7 +1164,7 @@ namespace cwg285 { // cwg285: yes namespace cwg286 { // cwg286: 2.8 template<class T> struct A { class C { - template<class T2> struct B {}; // #cwg286-B + template<class T2> struct B {}; // #cwg286-B }; }; diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp index 94227dc031c6ab..3e9228fe21fb64 100644 --- a/clang/test/CXX/drs/dr3xx.cpp +++ b/clang/test/CXX/drs/dr3xx.cpp @@ -34,7 +34,7 @@ namespace cwg301 { // cwg301: 3.5 bool b = (void(*)(S, S))operator- < (void(*)(S, S))operator-; // cxx98-17-warning@-1 {{ordered comparison of function pointers ('void (*)(S, S)' and 'void (*)(S, S)')}} // cxx20-23-error@-2 {{expected '>'}} - // cxx20-23-note@-3 {{to match this '<'}} + // cxx20-23-note@-3 {{to match this '<'}} bool c = (void(*)(S, S))operator+ < (void(*)(S, S))operator-; // expected-error@-1 {{expected '>'}} // expected-note@-2 {{to match this '<'}} @@ -642,7 +642,7 @@ namespace cwg339 { // cwg339: 2.8 char xxx(int); char (&xxx(float))[2]; - template<class T> A<sizeof(xxx((T)0))> f(T) {} // #cwg339-f + template<class T> A<sizeof(xxx((T)0))> f(T) {} // #cwg339-f void test() { A<1> a = f(0); @@ -828,7 +828,7 @@ namespace cwg352 { // cwg352: 2.8 void g(A::E e) { foo(e, &arg); // expected-error@-1 {{no matching function for call to 'foo'}} - // expected-note@#cwg352-foo {{candidate template ignored: couldn't infer template argument 'R'}} + // expected-note@#cwg352-foo {{candidate template ignored: couldn't infer template argument 'R'}} using A::foo; foo<int, int>(e, &arg); // ok, uses non-template @@ -929,7 +929,7 @@ namespace cwg352 { // cwg352: 2.8 namespace example5 { template<int I> class A {}; - template<int I> void g(A<I+1>); // #cwg352-g + template<int I> void g(A<I+1>); // #cwg352-g template<int I> void f(A<I>, A<I+1>); void h(A<1> a1, A<2> a2) { g(a1); @@ -1256,7 +1256,7 @@ namespace cwg373 { // cwg373: 5 } }; - struct A { struct B {}; }; // #cwg373-A + struct A { struct B {}; }; // #cwg373-A namespace X = A::B; // expected-error@-1 {{expected namespace name}} // expected-note@#cwg373-A {{'A' declared here}} @@ -1608,7 +1608,7 @@ namespace cwg395 { // cwg395: 3.0 // expected-error@-2 {{conversion function cannot have any parameters}} // expected-error@-3 {{cannot specify any part of a return type in the declaration of a conversion function}} // expected-error@-4 {{conversion function cannot convert to a function type}} - + }; struct null1_t { @@ -1721,9 +1721,9 @@ namespace cwg399 { // cwg399: 11 B_ptr->B_alias::~B(); B_ptr->B_alias::~B_alias(); B_ptr->cwg399::~B(); - // expected-error@-1 {{no member named '~B' in namespace 'cwg399'}} + // expected-error@-1 {{qualified member access refers to a member in namespace 'cwg399'}} B_ptr->cwg399::~B_alias(); - // expected-error@-1 {{no member named '~B' in namespace 'cwg399'}} + // expected-error@-1 {{qualified member access refers to a member in namespace 'cwg399'}} } template<typename T, typename U> diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp deleted file mode 100644 index b1d2859be863aa..00000000000000 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ /dev/null @@ -1,456 +0,0 @@ -// RUN: %clang_cc1 -Wno-unused-value -verify %s - -namespace N0 { - struct A { - int x0; - static int y0; - int x1; - static int y1; - - void f0(); - static void g0(); - void f1(); - static void g1(); - - using M0 = int; - using M1 = int; - - struct C0 { }; - struct C1 { }; - }; - - template<typename T> - struct B : A { - int x2; - static int y2; - - void f2(); - static void g2(); - - using M2 = int; - - struct C2 { }; - - using A::x1; - using A::y1; - using A::f1; - using A::g1; - using A::M1; - using A::C1; - - using T::x3; - using T::y3; - using T::f3; - using T::g3; - using typename T::M3; - using typename T::C3; - - void not_instantiated(B *a, B &b) { - // All of the following should be found in the current instantiation. - - new M0; - new B::M0; - new A::M0; - new B::A::M0; - new C0; - new B::C0; - new A::C0; - new B::A::C0; - new M1; - new B::M1; - new A::M1; - new B::A::M1; - new C1; - new B::C1; - new A::C1; - new B::A::C1; - new M2; - new B::M2; - new C2; - new B::C2; - new M3; - new B::M3; - new C3; - new B::C3; - - x0; - B::x0; - A::x0; - B::A::x0; - y0; - B::y0; - A::y0; - B::A::y0; - x1; - B::x1; - A::x1; - B::A::x1; - y1; - B::y1; - A::y1; - B::A::y1; - x2; - B::x2; - y2; - B::y2; - x3; - B::x3; - y3; - B::y3; - - f0(); - B::f0(); - A::f0(); - B::A::f0(); - g0(); - B::g0(); - A::g0(); - B::A::g0(); - f1(); - B::f1(); - A::f1(); - B::A::f1(); - g1(); - B::g1(); - A::g1(); - B::A::g1(); - f2(); - B::f2(); - g2(); - B::g2(); - f3(); - B::f3(); - g3(); - B::g3(); - - this->x0; - this->B::x0; - this->A::x0; - this->B::A::x0; - this->y0; - this->B::y0; - this->A::y0; - this->B::A::y0; - this->x1; - this->B::x1; - this->A::x1; - this->B::A::x1; - this->y1; - this->B::y1; - this->A::y1; - this->B::A::y1; - this->x2; - this->B::x2; - this->y2; - this->B::y2; - this->x3; - this->B::x3; - this->y3; - this->B::y3; - - this->f0(); - this->B::f0(); - this->A::f0(); - this->B::A::f0(); - this->g0(); - this->B::g0(); - this->A::g0(); - this->B::A::g0(); - this->f1(); - this->B::f1(); - this->A::f1(); - this->B::A::f1(); - this->g1(); - this->B::g1(); - this->A::g1(); - this->B::A::g1(); - this->f2(); - this->B::f2(); - this->g2(); - this->B::g2(); - this->f3(); - this->B::f3(); - this->g3(); - this->B::g3(); - - a->x0; - a->B::x0; - a->A::x0; - a->B::A::x0; - a->y0; - a->B::y0; - a->A::y0; - a->B::A::y0; - a->x1; - a->B::x1; - a->A::x1; - a->B::A::x1; - a->y1; - a->B::y1; - a->A::y1; - a->B::A::y1; - a->x2; - a->B::x2; - a->y2; - a->B::y2; - a->x3; - a->B::x3; - a->y3; - a->B::y3; - - a->f0(); - a->B::f0(); - a->A::f0(); - a->B::A::f0(); - a->g0(); - a->B::g0(); - a->A::g0(); - a->B::A::g0(); - a->f1(); - a->B::f1(); - a->A::f1(); - a->B::A::f1(); - a->g1(); - a->B::g1(); - a->A::g1(); - a->B::A::g1(); - a->f2(); - a->B::f2(); - a->g2(); - a->B::g2(); - a->f3(); - a->B::f3(); - a->g3(); - a->B::g3(); - - (*this).x0; - (*this).B::x0; - (*this).A::x0; - (*this).B::A::x0; - (*this).y0; - (*this).B::y0; - (*this).A::y0; - (*this).B::A::y0; - (*this).x1; - (*this).B::x1; - (*this).A::x1; - (*this).B::A::x1; - (*this).y1; - (*this).B::y1; - (*this).A::y1; - (*this).B::A::y1; - (*this).x2; - (*this).B::x2; - (*this).y2; - (*this).B::y2; - (*this).x3; - (*this).B::x3; - (*this).y3; - (*this).B::y3; - - (*this).f0(); - (*this).B::f0(); - (*this).A::f0(); - (*this).B::A::f0(); - (*this).g0(); - (*this).B::g0(); - (*this).A::g0(); - (*this).B::A::g0(); - (*this).f1(); - (*this).B::f1(); - (*this).A::f1(); - (*this).B::A::f1(); - (*this).g1(); - (*this).B::g1(); - (*this).A::g1(); - (*this).B::A::g1(); - (*this).f2(); - (*this).B::f2(); - (*this).g2(); - (*this).B::g2(); - (*this).f3(); - (*this).B::f3(); - (*this).g3(); - (*this).B::g3(); - - b.x0; - b.B::x0; - b.A::x0; - b.B::A::x0; - b.y0; - b.B::y0; - b.A::y0; - b.B::A::y0; - b.x1; - b.B::x1; - b.A::x1; - b.B::A::x1; - b.y1; - b.B::y1; - b.A::y1; - b.B::A::y1; - b.x2; - b.B::x2; - b.y2; - b.B::y2; - b.x3; - b.B::x3; - b.y3; - b.B::y3; - - b.f0(); - b.B::f0(); - b.A::f0(); - b.B::A::f0(); - b.g0(); - b.B::g0(); - b.A::g0(); - b.B::A::g0(); - b.f1(); - b.B::f1(); - b.A::f1(); - b.B::A::f1(); - b.g1(); - b.B::g1(); - b.A::g1(); - b.B::A::g1(); - b.f2(); - b.B::f2(); - b.g2(); - b.B::g2(); - b.f3(); - b.B::f3(); - b.g3(); - b.B::g3(); - - // None of the following should be found in the current instantiation. - - new M4; // expected-error{{unknown type name 'M4'}} - new B::M4; // expected-error{{no type named 'M4' in 'B<T>'}} - new A::M4; // expected-error{{no type named 'M4' in 'N0::A'}} - new B::A::M4; // expected-error{{no type named 'M4' in 'N0::A'}} - - x4; // expected-error{{use of undeclared identifier 'x4'}} - B::x4; // expected-error{{no member named 'x4' in 'B<T>'}} - A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - f4(); // expected-error{{use of undeclared identifier 'f4'}} - B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - - this->x4; // expected-error{{no member named 'x4' in 'B<T>'}} - this->B::x4; // expected-error{{no member named 'x4' in 'B<T>'}} - this->A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - this->B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - this->f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - this->B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - this->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - this->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - - a->x4; // expected-error{{no member named 'x4' in 'B<T>'}} - a->B::x4; // expected-error{{no member named 'x4' in 'B<T>'}} - a->A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - a->B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - a->f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - a->B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - a->A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - a->B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - - // FIXME: An overloaded unary 'operator*' is built for these - // even though the operand is a pointer (to a dependent type). - // Type::isOverloadableType should return false for such cases. - (*this).x4; - (*this).B::x4; - (*this).A::x4; - (*this).B::A::x4; - (*this).f4(); - (*this).B::f4(); - (*this).A::f4(); - (*this).B::A::f4(); - - b.x4; // expected-error{{no member named 'x4' in 'B<T>'}} - b.B::x4; // expected-error{{no member named 'x4' in 'B<T>'}} - b.A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - b.B::A::x4; // expected-error{{no member named 'x4' in 'N0::A'}} - b.f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - b.B::f4(); // expected-error{{no member named 'f4' in 'B<T>'}} - b.A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - b.B::A::f4(); // expected-error{{no member named 'f4' in 'N0::A'}} - } - }; -} // namespace N0 - -namespace N1 { - struct A { - template<int I> - void f(); - }; - - template<typename T> - struct B { - template<int I> - void f(); - - A x; - A g(); - - void not_instantiated(B *a, B &b) { - f<0>(); - this->f<0>(); - a->f<0>(); - // FIXME: This should not require 'template'! - (*this).f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - b.f<0>(); - - x.f<0>(); - this->x.f<0>(); - a->x.f<0>(); - // FIXME: This should not require 'template'! - (*this).x.f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - b.x.f<0>(); - - // FIXME: None of these should require 'template'! - g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - this->g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - a->g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - (*this).g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - b.g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} - } - }; -} // namespace N1 - -namespace N2 { - template<typename T> - struct A { - struct B { - using C = A; - - void not_instantiated(A *a, B *b) { - b->x; // expected-error{{no member named 'x' in 'N2::A::B'}} - b->B::x; // expected-error{{no member named 'x' in 'N2::A::B'}} - a->B::C::x; // expected-error{{no member named 'x' in 'A<T>'}} - } - }; - - void not_instantiated(A *a, B *b) { - b->x; - b->B::x; - a->B::C::x; - } - }; -} - -namespace N3 { - struct A { }; - - template<typename T> - struct B : A { - void not_instantiated() { - // Dependent, lookup context is the current instantiation. - this->operator=(*this); - // Not dependent, the lookup context is A (not the current instantiation). - this->A::operator=(*this); - } - }; -} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp index b9b29d22736e23..87589e1e5bcdc8 100644 --- a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp +++ b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp @@ -16,7 +16,8 @@ template <class T> struct Derived: Base<int>, Base<char> { void g(X0 *t) { t->Derived::Base<T>::f(); t->Base<T>::f(); - t->Base::f(); // expected-error{{member 'Base' found in multiple base classes of diff erent types}} + t->Base::f(); // expected-error{{member 'Base' found in multiple base classes of diff erent types}} \ + // expected-error{{no member named 'f' in 'X0'}} } }; diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index d0800af55c87e8..31467d943840e0 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1032,6 +1032,10 @@ namespace test51 { template <typename T> decltype(S1<T>().~S1<T>(), S1<T>().~S1<T>()) fun4() {}; template <typename T> + decltype(S1<int>().~S1<T>()) fun5(){}; + template <template <typename T> class U> + decltype(S1<int>().~U<int>()) fun6(){}; + template <typename T> decltype(E().E::~T()) fun7() {} template <template <typename> class U> decltype(X<int>::Y().U<int>::Y::~Y()) fun8() {} @@ -1043,6 +1047,10 @@ namespace test51 { // CHECK-LABEL: @_ZN6test514fun3I2S1IiEiEEDTcldtcvS1_IT0_E_EdnT_EEv template void fun4<int>(); // CHECK-LABEL: @_ZN6test514fun4IiEEDTcmcldtcv2S1IT_E_Edn2S1IS2_EEcldtcvS3__Edn2S1IS2_EEEv + template void fun5<int>(); + // CHECK-LABEL: @_ZN6test514fun5IiEEDTcldtcv2S1IiE_Edn2S1IT_EEEv + template void fun6<S1>(); + // CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv template void fun7<E>(); // CHECK-LABEL: @_ZN6test514fun7INS_1EEEEDTcldtcvS1__Esr1EEdnT_EEv template void fun8<X>(); diff --git a/clang/test/Index/annotate-nested-name-specifier.cpp b/clang/test/Index/annotate-nested-name-specifier.cpp index 3181497258407f..a7338db6b05b77 100644 --- a/clang/test/Index/annotate-nested-name-specifier.cpp +++ b/clang/test/Index/annotate-nested-name-specifier.cpp @@ -132,7 +132,7 @@ struct X8 { struct X9 : X8 { typedef X8 inherited; - void f() { + void f() { inherited::f(); } }; @@ -299,7 +299,7 @@ struct X9 : X8 { // CHECK: Identifier: "type" [77:16 - 77:20] TypeRef=X4::type:70:13 // CHECK: Punctuation: ">" [77:20 - 77:21] MemberRefExpr= // CHECK: Punctuation: "::" [77:21 - 77:23] MemberRefExpr= -// CHECK: Identifier: "g" [77:23 - 77:24] OverloadedDeclRef= +// CHECK: Identifier: "g" [77:23 - 77:24] MemberRefExpr= // CHECK: Punctuation: "(" [77:24 - 77:25] CallExpr= // CHECK: Identifier: "t" [77:25 - 77:26] DeclRefExpr=t:74:12 // CHECK: Punctuation: ")" [77:26 - 77:27] CallExpr= diff --git a/clang/test/SemaCXX/member-expr.cpp b/clang/test/SemaCXX/member-expr.cpp index 0596e40f6c2f6a..75c9ef0caa2e00 100644 --- a/clang/test/SemaCXX/member-expr.cpp +++ b/clang/test/SemaCXX/member-expr.cpp @@ -40,8 +40,8 @@ namespace C { } void test2(X *xp) { - xp->::i = 7; // expected-error{{'i' is not a member of class 'X'}} - xp->C::i = 7; // expected-error{{'C::i' is not a member of class 'X'}} + xp->::i = 7; // expected-error{{qualified member access refers to a member in the global namespace}} + xp->C::i = 7; // expected-error{{qualified member access refers to a member in namespace 'C'}} } diff --git a/clang/test/SemaTemplate/instantiate-function-1.cpp b/clang/test/SemaTemplate/instantiate-function-1.cpp index a4967264c654b7..ceef2743774805 100644 --- a/clang/test/SemaTemplate/instantiate-function-1.cpp +++ b/clang/test/SemaTemplate/instantiate-function-1.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s template<typename T, typename U> struct X0 { - void f(T x, U y) { + void f(T x, U y) { (void)(x + y); // expected-error{{invalid operands}} } }; @@ -41,7 +41,7 @@ template <typename T> struct X4 { T f() const { return; // expected-error{{non-void function 'f' should return a value}} } - + T g() const { return 1; // expected-error{{void function 'g' should not return a value}} } @@ -64,7 +64,7 @@ template<typename T, typename U, typename V> struct X6 { // IfStmt if (t > 0) return u; - else { + else { if (t < 0) return v; // expected-error{{cannot initialize return object of type}} } @@ -131,12 +131,12 @@ template<typename T> struct Member0 { t; t.f; t->f; - + T* tp; tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}} tp->f; - this->f; // expected-error{{reference to non-static member function must be called}} + this->f; this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}} } }; @@ -239,11 +239,11 @@ namespace PR9880 { static yes_tag check(char[sizeof(&U::luaIndex)]); enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) }; }; - + class SomeClass { public: int luaIndex(lua_State* L); }; - + int i = HasIndexMetamethod<SomeClass>::value; } diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index c08deb903f129b..87774b00956a5a 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1569,9 +1569,8 @@ TEST_P(ASTMatchersTest, IsArrow_MatchesMemberVariablesViaArrow) { matches("class Y { void x() { y; } int y; };", memberExpr(isArrow()))); EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };", memberExpr(isArrow()))); - EXPECT_TRUE( - matches("template <class T> class Y { void x() { this->m; } int m; };", - memberExpr(isArrow()))); + EXPECT_TRUE(matches("template <class T> class Y { void x() { this->m; } };", + cxxDependentScopeMemberExpr(isArrow()))); EXPECT_TRUE( notMatches("template <class T> class Y { void x() { (*this).m; } };", cxxDependentScopeMemberExpr(isArrow()))); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits