summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-14 21:53:03 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-14 21:53:03 +0000
commit478f547ceb290b0c00f90f8f0bc3b09355334a3d (patch)
tree64a363c4a88eb494e97fb5ed87d3cfea81eac611 /include
parent0b01e8d1d5cf0784779f3e607259381faeb9db5f (diff)
downloadclang-478f547ceb290b0c00f90f8f0bc3b09355334a3d.tar.gz
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
Diffstat (limited to 'include')
-rw-r--r--include/clang/Basic/TokenKinds.def5
-rw-r--r--include/clang/Parse/Parser.h19
-rw-r--r--include/clang/Sema/Sema.h95
3 files changed, 100 insertions, 19 deletions
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<int>"
+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<NamedDecl*>(Tok.getAnnotationValue());
+ }
+
+ static void setNonTypeAnnotation(Token &Tok, NamedDecl *ND) {
+ Tok.setAnnotationValue(ND);
+ }
+
+ static IdentifierInfo *getIdentifierAnnotation(const Token &Tok) {
+ return static_cast<IdentifierInfo*>(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<Expr *> 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);