From 478f547ceb290b0c00f90f8f0bc3b09355334a3d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 14 Oct 2019 21:53:03 +0000 Subject: PR43080: Do not build context-sensitive expressions during name classification. Summary: We don't know what context to use until the classification result is consumed by the parser, which could happen in a different semantic context. So don't build the expression that results from name classification until we get to that point and can handle it properly. This covers everything except C++ implicit class member access, which is a little awkward to handle properly in the face of the protected member access check. But it at least fixes all the currently-filed instances of PR43080. Reviewers: efriedma Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D68896 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374826 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/TokenKinds.def | 5 ++ include/clang/Parse/Parser.h | 19 +++++++- include/clang/Sema/Sema.h | 95 +++++++++++++++++++++++++++++++------- 3 files changed, 100 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 0a8d27ec2e..94fe1ba63a 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -728,6 +728,11 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly ANNOTATION(template_id) // annotation for a C++ template-id that names a // function template specialization (not a type), // e.g., "std::swap" +ANNOTATION(non_type) // annotation for a single non-type declaration +ANNOTATION(non_type_undeclared) // annotation for an undeclared identifier that + // was assumed to be an ADL-only function name +ANNOTATION(non_type_dependent) // annotation for an assumed non-type member of + // a dependent base class ANNOTATION(primary_expr) // annotation for a primary expression ANNOTATION(decltype) // annotation for a decltype expression, // e.g., "decltype(foo.bar())" diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 920921f693..52d159062c 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -766,6 +766,22 @@ private: Tok.setAnnotationValue(T.getAsOpaquePtr()); } + static NamedDecl *getNonTypeAnnotation(const Token &Tok) { + return static_cast(Tok.getAnnotationValue()); + } + + static void setNonTypeAnnotation(Token &Tok, NamedDecl *ND) { + Tok.setAnnotationValue(ND); + } + + static IdentifierInfo *getIdentifierAnnotation(const Token &Tok) { + return static_cast(Tok.getAnnotationValue()); + } + + static void setIdentifierAnnotation(Token &Tok, IdentifierInfo *ND) { + Tok.setAnnotationValue(ND); + } + /// Read an already-translated primary expression out of an annotation /// token. static ExprResult getExprAnnotation(const Token &Tok) { @@ -799,8 +815,7 @@ private: /// Annotation was successful. ANK_Success }; - AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = nullptr); + AnnotatedNameKind TryAnnotateName(CorrectionCandidateCallback *CCC = nullptr); /// Push a tok::annot_cxxscope token onto the token stream. void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b8b59fdf93..0403df4ba7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1855,29 +1855,52 @@ public: /// Describes the result of the name lookup and resolution performed /// by \c ClassifyName(). enum NameClassificationKind { + /// This name is not a type or template in this context, but might be + /// something else. NC_Unknown, + /// Classification failed; an error has been produced. NC_Error, + /// The name has been typo-corrected to a keyword. NC_Keyword, + /// The name was classified as a type. NC_Type, - NC_Expression, - NC_NestedNameSpecifier, + /// The name was classified as a specific non-type, non-template + /// declaration. ActOnNameClassifiedAsNonType should be called to + /// convert the declaration to an expression. + NC_NonType, + /// The name was classified as an ADL-only function name. + /// ActOnNameClassifiedAsUndeclaredNonType should be called to convert the + /// result to an expression. + NC_UndeclaredNonType, + /// The name denotes a member of a dependent type that could not be + /// resolved. ActOnNameClassifiedAsDependentNonType should be called to + /// convert the result to an expression. + NC_DependentNonType, + /// The name was classified as a non-type, and an expression representing + /// that name has been formed. + NC_ContextIndependentExpr, + /// The name was classified as a template whose specializations are types. NC_TypeTemplate, + /// The name was classified as a variable template name. NC_VarTemplate, + /// The name was classified as a function template name. NC_FunctionTemplate, + /// The name was classified as an ADL-only function template name. NC_UndeclaredTemplate, }; class NameClassification { NameClassificationKind Kind; - ExprResult Expr; - TemplateName Template; - ParsedType Type; + union { + ExprResult Expr; + NamedDecl *NonTypeDecl; + TemplateName Template; + ParsedType Type; + }; explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {} public: - NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {} - NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {} NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {} @@ -1890,8 +1913,24 @@ public: return NameClassification(NC_Unknown); } - static NameClassification NestedNameSpecifier() { - return NameClassification(NC_NestedNameSpecifier); + static NameClassification ContextIndependentExpr(ExprResult E) { + NameClassification Result(NC_ContextIndependentExpr); + Result.Expr = E; + return Result; + } + + static NameClassification NonType(NamedDecl *D) { + NameClassification Result(NC_NonType); + Result.NonTypeDecl = D; + return Result; + } + + static NameClassification UndeclaredNonType() { + return NameClassification(NC_UndeclaredNonType); + } + + static NameClassification DependentNonType() { + return NameClassification(NC_DependentNonType); } static NameClassification TypeTemplate(TemplateName Name) { @@ -1920,14 +1959,19 @@ public: NameClassificationKind getKind() const { return Kind; } + ExprResult getExpression() const { + assert(Kind == NC_ContextIndependentExpr); + return Expr; + } + ParsedType getType() const { assert(Kind == NC_Type); return Type; } - ExprResult getExpression() const { - assert(Kind == NC_Expression); - return Expr; + NamedDecl *getNonTypeDecl() const { + assert(Kind == NC_NonType); + return NonTypeDecl; } TemplateName getTemplateName() const { @@ -1971,17 +2015,29 @@ public: /// \param NextToken The token following the identifier. Used to help /// disambiguate the name. /// - /// \param IsAddressOfOperand True if this name is the operand of a unary - /// address of ('&') expression, assuming it is classified as an - /// expression. - /// /// \param CCC The correction callback, if typo correction is desired. NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc, const Token &NextToken, - bool IsAddressOfOperand, CorrectionCandidateCallback *CCC = nullptr); + /// Act on the result of classifying a name as an undeclared (ADL-only) + /// non-type declaration. + ExprResult ActOnNameClassifiedAsUndeclaredNonType(IdentifierInfo *Name, + SourceLocation NameLoc); + /// Act on the result of classifying a name as an undeclared member of a + /// dependent base class. + ExprResult ActOnNameClassifiedAsDependentNonType(const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool IsAddressOfOperand); + /// Act on the result of classifying a name as a specific non-type + /// declaration. + ExprResult ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS, + NamedDecl *Found, + SourceLocation NameLoc, + const Token &NextToken); + /// Describes the detailed kind of a template name. Used in diagnostics. enum class TemplateNameKindForDiagnostics { ClassTemplate, @@ -3407,6 +3463,7 @@ public: LookupNameKind NameKind, RedeclarationKind Redecl = NotForRedeclaration); + bool LookupBuiltin(LookupResult &R); bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false); bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, @@ -4389,6 +4446,10 @@ public: TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, ArrayRef Args = None, TypoExpr **Out = nullptr); + DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II); + ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV); + ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, IdentifierInfo *II, bool AllowBuiltinCreation=false); -- cgit v1.2.1