Skip to content

Commit 7e8fe67

Browse files
committedOct 14, 2019
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 llvm-svn: 374826
1 parent 9efbc56 commit 7e8fe67

14 files changed

+417
-178
lines changed
 

‎clang/include/clang/Basic/TokenKinds.def

+5
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,11 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
728728
ANNOTATION(template_id) // annotation for a C++ template-id that names a
729729
// function template specialization (not a type),
730730
// e.g., "std::swap<int>"
731+
ANNOTATION(non_type) // annotation for a single non-type declaration
732+
ANNOTATION(non_type_undeclared) // annotation for an undeclared identifier that
733+
// was assumed to be an ADL-only function name
734+
ANNOTATION(non_type_dependent) // annotation for an assumed non-type member of
735+
// a dependent base class
731736
ANNOTATION(primary_expr) // annotation for a primary expression
732737
ANNOTATION(decltype) // annotation for a decltype expression,
733738
// e.g., "decltype(foo.bar())"

‎clang/include/clang/Parse/Parser.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,22 @@ class Parser : public CodeCompletionHandler {
766766
Tok.setAnnotationValue(T.getAsOpaquePtr());
767767
}
768768

769+
static NamedDecl *getNonTypeAnnotation(const Token &Tok) {
770+
return static_cast<NamedDecl*>(Tok.getAnnotationValue());
771+
}
772+
773+
static void setNonTypeAnnotation(Token &Tok, NamedDecl *ND) {
774+
Tok.setAnnotationValue(ND);
775+
}
776+
777+
static IdentifierInfo *getIdentifierAnnotation(const Token &Tok) {
778+
return static_cast<IdentifierInfo*>(Tok.getAnnotationValue());
779+
}
780+
781+
static void setIdentifierAnnotation(Token &Tok, IdentifierInfo *ND) {
782+
Tok.setAnnotationValue(ND);
783+
}
784+
769785
/// Read an already-translated primary expression out of an annotation
770786
/// token.
771787
static ExprResult getExprAnnotation(const Token &Tok) {
@@ -799,8 +815,7 @@ class Parser : public CodeCompletionHandler {
799815
/// Annotation was successful.
800816
ANK_Success
801817
};
802-
AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand,
803-
CorrectionCandidateCallback *CCC = nullptr);
818+
AnnotatedNameKind TryAnnotateName(CorrectionCandidateCallback *CCC = nullptr);
804819

805820
/// Push a tok::annot_cxxscope token onto the token stream.
806821
void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);

‎clang/include/clang/Sema/Sema.h

+78-17
Original file line numberDiff line numberDiff line change
@@ -1855,29 +1855,52 @@ class Sema {
18551855
/// Describes the result of the name lookup and resolution performed
18561856
/// by \c ClassifyName().
18571857
enum NameClassificationKind {
1858+
/// This name is not a type or template in this context, but might be
1859+
/// something else.
18581860
NC_Unknown,
1861+
/// Classification failed; an error has been produced.
18591862
NC_Error,
1863+
/// The name has been typo-corrected to a keyword.
18601864
NC_Keyword,
1865+
/// The name was classified as a type.
18611866
NC_Type,
1862-
NC_Expression,
1863-
NC_NestedNameSpecifier,
1867+
/// The name was classified as a specific non-type, non-template
1868+
/// declaration. ActOnNameClassifiedAsNonType should be called to
1869+
/// convert the declaration to an expression.
1870+
NC_NonType,
1871+
/// The name was classified as an ADL-only function name.
1872+
/// ActOnNameClassifiedAsUndeclaredNonType should be called to convert the
1873+
/// result to an expression.
1874+
NC_UndeclaredNonType,
1875+
/// The name denotes a member of a dependent type that could not be
1876+
/// resolved. ActOnNameClassifiedAsDependentNonType should be called to
1877+
/// convert the result to an expression.
1878+
NC_DependentNonType,
1879+
/// The name was classified as a non-type, and an expression representing
1880+
/// that name has been formed.
1881+
NC_ContextIndependentExpr,
1882+
/// The name was classified as a template whose specializations are types.
18641883
NC_TypeTemplate,
1884+
/// The name was classified as a variable template name.
18651885
NC_VarTemplate,
1886+
/// The name was classified as a function template name.
18661887
NC_FunctionTemplate,
1888+
/// The name was classified as an ADL-only function template name.
18671889
NC_UndeclaredTemplate,
18681890
};
18691891

18701892
class NameClassification {
18711893
NameClassificationKind Kind;
1872-
ExprResult Expr;
1873-
TemplateName Template;
1874-
ParsedType Type;
1894+
union {
1895+
ExprResult Expr;
1896+
NamedDecl *NonTypeDecl;
1897+
TemplateName Template;
1898+
ParsedType Type;
1899+
};
18751900

18761901
explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {}
18771902

18781903
public:
1879-
NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {}
1880-
18811904
NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {}
18821905

18831906
NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {}
@@ -1890,8 +1913,24 @@ class Sema {
18901913
return NameClassification(NC_Unknown);
18911914
}
18921915

1893-
static NameClassification NestedNameSpecifier() {
1894-
return NameClassification(NC_NestedNameSpecifier);
1916+
static NameClassification ContextIndependentExpr(ExprResult E) {
1917+
NameClassification Result(NC_ContextIndependentExpr);
1918+
Result.Expr = E;
1919+
return Result;
1920+
}
1921+
1922+
static NameClassification NonType(NamedDecl *D) {
1923+
NameClassification Result(NC_NonType);
1924+
Result.NonTypeDecl = D;
1925+
return Result;
1926+
}
1927+
1928+
static NameClassification UndeclaredNonType() {
1929+
return NameClassification(NC_UndeclaredNonType);
1930+
}
1931+
1932+
static NameClassification DependentNonType() {
1933+
return NameClassification(NC_DependentNonType);
18951934
}
18961935

18971936
static NameClassification TypeTemplate(TemplateName Name) {
@@ -1920,14 +1959,19 @@ class Sema {
19201959

19211960
NameClassificationKind getKind() const { return Kind; }
19221961

1962+
ExprResult getExpression() const {
1963+
assert(Kind == NC_ContextIndependentExpr);
1964+
return Expr;
1965+
}
1966+
19231967
ParsedType getType() const {
19241968
assert(Kind == NC_Type);
19251969
return Type;
19261970
}
19271971

1928-
ExprResult getExpression() const {
1929-
assert(Kind == NC_Expression);
1930-
return Expr;
1972+
NamedDecl *getNonTypeDecl() const {
1973+
assert(Kind == NC_NonType);
1974+
return NonTypeDecl;
19311975
}
19321976

19331977
TemplateName getTemplateName() const {
@@ -1971,17 +2015,29 @@ class Sema {
19712015
/// \param NextToken The token following the identifier. Used to help
19722016
/// disambiguate the name.
19732017
///
1974-
/// \param IsAddressOfOperand True if this name is the operand of a unary
1975-
/// address of ('&') expression, assuming it is classified as an
1976-
/// expression.
1977-
///
19782018
/// \param CCC The correction callback, if typo correction is desired.
19792019
NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS,
19802020
IdentifierInfo *&Name, SourceLocation NameLoc,
19812021
const Token &NextToken,
1982-
bool IsAddressOfOperand,
19832022
CorrectionCandidateCallback *CCC = nullptr);
19842023

2024+
/// Act on the result of classifying a name as an undeclared (ADL-only)
2025+
/// non-type declaration.
2026+
ExprResult ActOnNameClassifiedAsUndeclaredNonType(IdentifierInfo *Name,
2027+
SourceLocation NameLoc);
2028+
/// Act on the result of classifying a name as an undeclared member of a
2029+
/// dependent base class.
2030+
ExprResult ActOnNameClassifiedAsDependentNonType(const CXXScopeSpec &SS,
2031+
IdentifierInfo *Name,
2032+
SourceLocation NameLoc,
2033+
bool IsAddressOfOperand);
2034+
/// Act on the result of classifying a name as a specific non-type
2035+
/// declaration.
2036+
ExprResult ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS,
2037+
NamedDecl *Found,
2038+
SourceLocation NameLoc,
2039+
const Token &NextToken);
2040+
19852041
/// Describes the detailed kind of a template name. Used in diagnostics.
19862042
enum class TemplateNameKindForDiagnostics {
19872043
ClassTemplate,
@@ -3407,6 +3463,7 @@ class Sema {
34073463
LookupNameKind NameKind,
34083464
RedeclarationKind Redecl
34093465
= NotForRedeclaration);
3466+
bool LookupBuiltin(LookupResult &R);
34103467
bool LookupName(LookupResult &R, Scope *S,
34113468
bool AllowBuiltinCreation = false);
34123469
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
@@ -4389,6 +4446,10 @@ class Sema {
43894446
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
43904447
ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr);
43914448

4449+
DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
4450+
IdentifierInfo *II);
4451+
ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
4452+
43924453
ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
43934454
IdentifierInfo *II,
43944455
bool AllowBuiltinCreation=false);

‎clang/lib/Parse/ParseDecl.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -2929,28 +2929,29 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
29292929
IdentifierInfo *Name = AfterScope.getIdentifierInfo();
29302930
Sema::NameClassification Classification = Actions.ClassifyName(
29312931
getCurScope(), SS, Name, AfterScope.getLocation(), Next,
2932-
/*IsAddressOfOperand=*/false, /*CCC=*/nullptr);
2932+
/*CCC=*/nullptr);
29332933
switch (Classification.getKind()) {
29342934
case Sema::NC_Error:
29352935
SkipMalformedDecl();
29362936
return true;
29372937

29382938
case Sema::NC_Keyword:
2939-
case Sema::NC_NestedNameSpecifier:
2940-
llvm_unreachable("typo correction and nested name specifiers not "
2941-
"possible here");
2939+
llvm_unreachable("typo correction is not possible here");
29422940

29432941
case Sema::NC_Type:
29442942
case Sema::NC_TypeTemplate:
2943+
case Sema::NC_UndeclaredNonType:
2944+
case Sema::NC_UndeclaredTemplate:
29452945
// Not a previously-declared non-type entity.
29462946
MightBeDeclarator = false;
29472947
break;
29482948

29492949
case Sema::NC_Unknown:
2950-
case Sema::NC_Expression:
2950+
case Sema::NC_NonType:
2951+
case Sema::NC_DependentNonType:
2952+
case Sema::NC_ContextIndependentExpr:
29512953
case Sema::NC_VarTemplate:
29522954
case Sema::NC_FunctionTemplate:
2953-
case Sema::NC_UndeclaredTemplate:
29542955
// Might be a redeclaration of a prior entity.
29552956
break;
29562957
}

‎clang/lib/Parse/ParseExpr.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -840,13 +840,23 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
840840
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
841841

842842
case tok::annot_primary_expr:
843-
assert(Res.get() == nullptr && "Stray primary-expression annotation?");
844843
Res = getExprAnnotation(Tok);
845844
ConsumeAnnotationToken();
846845
if (!Res.isInvalid() && Tok.is(tok::less))
847846
checkPotentialAngleBracket(Res);
848847
break;
849848

849+
case tok::annot_non_type:
850+
case tok::annot_non_type_dependent:
851+
case tok::annot_non_type_undeclared: {
852+
CXXScopeSpec SS;
853+
Token Replacement;
854+
Res = tryParseCXXIdExpression(SS, isAddressOfOperand, Replacement);
855+
assert(!Res.isUnset() &&
856+
"should not perform typo correction on annotation token");
857+
break;
858+
}
859+
850860
case tok::kw___super:
851861
case tok::kw_decltype:
852862
// Annotate the token and tail recurse.

‎clang/lib/Parse/ParseExprCXX.cpp

+57-18
Original file line numberDiff line numberDiff line change
@@ -555,27 +555,66 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
555555
return false;
556556
}
557557

558-
ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand,
558+
ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS,
559+
bool isAddressOfOperand,
559560
Token &Replacement) {
560-
SourceLocation TemplateKWLoc;
561-
UnqualifiedId Name;
562-
if (ParseUnqualifiedId(SS,
563-
/*EnteringContext=*/false,
564-
/*AllowDestructorName=*/false,
565-
/*AllowConstructorName=*/false,
566-
/*AllowDeductionGuide=*/false,
567-
/*ObjectType=*/nullptr, &TemplateKWLoc, Name))
568-
return ExprError();
561+
ExprResult E;
562+
563+
// We may have already annotated this id-expression.
564+
switch (Tok.getKind()) {
565+
case tok::annot_non_type: {
566+
NamedDecl *ND = getNonTypeAnnotation(Tok);
567+
SourceLocation Loc = ConsumeAnnotationToken();
568+
E = Actions.ActOnNameClassifiedAsNonType(getCurScope(), SS, ND, Loc, Tok);
569+
break;
570+
}
571+
572+
case tok::annot_non_type_dependent: {
573+
IdentifierInfo *II = getIdentifierAnnotation(Tok);
574+
SourceLocation Loc = ConsumeAnnotationToken();
575+
576+
// This is only the direct operand of an & operator if it is not
577+
// followed by a postfix-expression suffix.
578+
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
579+
isAddressOfOperand = false;
580+
581+
E = Actions.ActOnNameClassifiedAsDependentNonType(SS, II, Loc,
582+
isAddressOfOperand);
583+
break;
584+
}
569585

570-
// This is only the direct operand of an & operator if it is not
571-
// followed by a postfix-expression suffix.
572-
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
573-
isAddressOfOperand = false;
586+
case tok::annot_non_type_undeclared: {
587+
assert(SS.isEmpty() &&
588+
"undeclared non-type annotation should be unqualified");
589+
IdentifierInfo *II = getIdentifierAnnotation(Tok);
590+
SourceLocation Loc = ConsumeAnnotationToken();
591+
E = Actions.ActOnNameClassifiedAsUndeclaredNonType(II, Loc);
592+
break;
593+
}
594+
595+
default:
596+
SourceLocation TemplateKWLoc;
597+
UnqualifiedId Name;
598+
if (ParseUnqualifiedId(SS,
599+
/*EnteringContext=*/false,
600+
/*AllowDestructorName=*/false,
601+
/*AllowConstructorName=*/false,
602+
/*AllowDeductionGuide=*/false,
603+
/*ObjectType=*/nullptr, &TemplateKWLoc, Name))
604+
return ExprError();
605+
606+
// This is only the direct operand of an & operator if it is not
607+
// followed by a postfix-expression suffix.
608+
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
609+
isAddressOfOperand = false;
610+
611+
E = Actions.ActOnIdExpression(
612+
getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren),
613+
isAddressOfOperand, /*CCC=*/nullptr, /*IsInlineAsmIdentifier=*/false,
614+
&Replacement);
615+
break;
616+
}
574617

575-
ExprResult E = Actions.ActOnIdExpression(
576-
getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren),
577-
isAddressOfOperand, /*CCC=*/nullptr, /*IsInlineAsmIdentifier=*/false,
578-
&Replacement);
579618
if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less))
580619
checkPotentialAngleBracket(E);
581620
return E;

‎clang/lib/Parse/ParseStmt.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
187187
// Try to limit which sets of keywords should be included in typo
188188
// correction based on what the next token is.
189189
StatementFilterCCC CCC(Next);
190-
if (TryAnnotateName(/*IsAddressOfOperand*/ false, &CCC) == ANK_Error) {
190+
if (TryAnnotateName(&CCC) == ANK_Error) {
191191
// Handle errors here by skipping up to the next semicolon or '}', and
192192
// eat the semicolon if that's what stopped us.
193193
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);

‎clang/lib/Parse/ParseTentative.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
13301330
// this is ambiguous. Typo-correct to type and expression keywords and
13311331
// to types and identifiers, in order to try to recover from errors.
13321332
TentativeParseCCC CCC(Next);
1333-
switch (TryAnnotateName(false /* no nested name specifier */, &CCC)) {
1333+
switch (TryAnnotateName(&CCC)) {
13341334
case ANK_Error:
13351335
return TPResult::Error;
13361336
case ANK_TentativeDecl:
@@ -1569,7 +1569,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
15691569
} else {
15701570
// Try to resolve the name. If it doesn't exist, assume it was
15711571
// intended to name a type and keep disambiguating.
1572-
switch (TryAnnotateName(false /* SS is not dependent */)) {
1572+
switch (TryAnnotateName()) {
15731573
case ANK_Error:
15741574
return TPResult::Error;
15751575
case ANK_TentativeDecl:

0 commit comments

Comments
 (0)
Please sign in to comment.