diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 63 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 33 |
7 files changed, 95 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 7373331a638..1e37c894eea 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -19,8 +19,8 @@ #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/AST/Decl.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/BitmaskEnum.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitmaskEnum.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DerivedTypes.h" diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index bccf4239c1b..77f2dccfede 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -312,6 +312,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param); std::unique_ptr<CachedTokens> Toks = std::move(LM.DefaultArgs[I].Toks); if (Toks) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Mark the end of the default argument so that we know when to stop when // we parse it later on. Token LastDefaultArgToken = Toks->back(); @@ -384,6 +386,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Parse a delayed exception-specification, if there is one. if (CachedTokens *Toks = LM.ExceptionSpecTokens) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Add the 'stop' token. Token LastExceptionSpecToken = Toks->back(); Token ExceptionSpecEnd; @@ -489,6 +493,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { ++CurTemplateDepthTracker; } + ParenBraceBracketBalancer BalancerRAIIObj(*this); + assert(!LM.Toks.empty() && "Empty body!"); Token LastBodyToken = LM.Toks.back(); Token BodyEnd; @@ -609,6 +615,8 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { if (!MI.Field || MI.Field->isInvalidDecl()) return; + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Append the current token at the end of the new token stream so that it // doesn't get lost. MI.Toks.push_back(Tok); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 4a1280e7f81..de759c8c945 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3009,6 +3009,8 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs, DeclSpec::TST TagType, Decl *TagDecl) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + switch (Tok.getKind()) { case tok::kw___if_exists: case tok::kw___if_not_exists: diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 8d51bc82d39..94e56e9d8a5 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -302,6 +302,59 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { if (OpToken.is(tok::caretcaret)) { return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or)); } + + // If we have a name-shaped expression followed by '<', track it in case we + // later find we're probably supposed to be in a template-id. + ExprResult TemplateName = LHS; + bool DependentTemplateName = false; + if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName( + TemplateName, DependentTemplateName)) { + AngleBracketTracker::Priority Priority = + (DependentTemplateName ? AngleBracketTracker::DependentName + : AngleBracketTracker::PotentialTypo) | + (OpToken.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess + : AngleBracketTracker::NoSpaceBeforeLess); + AngleBrackets.add(*this, TemplateName.get(), OpToken.getLocation(), + Priority); + } + + // If we're potentially in a template-id, we may now be able to determine + // whether we're actually in one or not. + if (auto *Info = AngleBrackets.getCurrent(*this)) { + // If an operator is followed by a type that can be a template argument + // and cannot be an expression, then this is ill-formed, but might be + // intended to be part of a template-id. Likewise if this is <>. + if ((OpToken.isOneOf(tok::less, tok::comma) && + isKnownToBeDeclarationSpecifier()) || + (OpToken.is(tok::less) && + Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater))) { + if (diagnoseUnknownTemplateId(Info->TemplateName, Info->LessLoc)) { + AngleBrackets.clear(*this); + return ExprError(); + } + } + + // If a context that looks like a template-id is followed by '()', then + // this is ill-formed, but might be intended to be a template-id followed + // by '()'. + if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) && + NextToken().is(tok::r_paren)) { + Actions.diagnoseExprIntendedAsTemplateName( + getCurScope(), Info->TemplateName, Info->LessLoc, + OpToken.getLocation()); + AngleBrackets.clear(*this); + return ExprError(); + } + } + + // After a '>' (etc), we're no longer potentially in a construct that's + // intended to be treated as a template-id. + if (OpToken.is(tok::greater) || + (getLangOpts().CPlusPlus11 && + OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater))) + AngleBrackets.clear(*this); + // Bail out when encountering a comma followed by a token which can't // possibly be the start of an expression. For instance: // int f() { return 1, } @@ -313,16 +366,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } - // If a '<' token is followed by a type that can be a template argument and - // cannot be an expression, then this is ill-formed, but might be intended - // to be a template-id. - if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) && - (isKnownToBeDeclarationSpecifier() || - Tok.isOneOf(tok::greater, tok::greatergreater, - tok::greatergreatergreater)) && - diagnoseUnknownTemplateId(LHS, OpToken.getLocation())) - return ExprError(); - // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 12aee8cff3d..a5a340ad22b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1735,6 +1735,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, Sema::ConditionKind CK) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition); cutOffParsing(); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 44406002c0d..8c4a3056ec0 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1621,6 +1621,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { attrs, attrs.Range.getEnd()); ForRange = true; } else if (isForInitDeclaration()) { // for (int X = 4; + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Parse declaration, which eats the ';'. if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8f316024cc6..68a5196f6b8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -508,20 +508,41 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, DeclContext *LookupCtx = nullptr; NamedDecl *Found = nullptr; + bool MissingTemplateKeyword = false; // Figure out what name we looked up. - if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { + if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) { + NameInfo = DRE->getNameInfo(); + SS.Adopt(DRE->getQualifierLoc()); + LookupKind = LookupOrdinaryName; + Found = DRE->getFoundDecl(); + } else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { NameInfo = ME->getMemberNameInfo(); SS.Adopt(ME->getQualifierLoc()); LookupKind = LookupMemberName; LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl(); Found = ME->getMemberDecl(); + } else if (auto *DSDRE = + dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) { + NameInfo = DSDRE->getNameInfo(); + SS.Adopt(DSDRE->getQualifierLoc()); + MissingTemplateKeyword = true; + } else if (auto *DSME = + dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) { + NameInfo = DSME->getMemberNameInfo(); + SS.Adopt(DSME->getQualifierLoc()); + MissingTemplateKeyword = true; } else { - auto *DRE = cast<DeclRefExpr>(TemplateName.get()); - NameInfo = DRE->getNameInfo(); - SS.Adopt(DRE->getQualifierLoc()); - LookupKind = LookupOrdinaryName; - Found = DRE->getFoundDecl(); + llvm_unreachable("unexpected kind of potential template name"); + } + + // If this is a dependent-scope lookup, diagnose that the 'template' keyword + // was missing. + if (MissingTemplateKeyword) { + Diag(NameInfo.getLocStart(), diag::err_template_kw_missing) + << "" << NameInfo.getName().getAsString() + << SourceRange(Less, Greater); + return; } // Try to correct the name by looking for templates and C++ named casts. |