diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index c64a01b73a4a9..290da00061162 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -763,13 +763,17 @@ class Parser : public CodeCompletionHandler { } /// getTypeAnnotation - Read a parsed type out of an annotation token. - static ParsedType getTypeAnnotation(const Token &Tok) { + static TypeResult getTypeAnnotation(const Token &Tok) { + if (!Tok.getAnnotationValue()) + return TypeError(); return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue()); } private: - static void setTypeAnnotation(Token &Tok, ParsedType T) { - Tok.setAnnotationValue(T.getAsOpaquePtr()); + static void setTypeAnnotation(Token &Tok, TypeResult T) { + assert((T.isInvalid() || T.get()) && + "produced a valid-but-null type annotation?"); + Tok.setAnnotationValue(T.isInvalid() ? nullptr : T.get().getAsOpaquePtr()); } static NamedDecl *getNonTypeAnnotation(const Token &Tok) { diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 5a6bedcd6f59d..78010b7bb46e6 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -667,6 +667,13 @@ class DeclSpec { bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, ParsedType Rep, const PrintingPolicy &Policy); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, TypeResult Rep, + const PrintingPolicy &Policy) { + if (Rep.isInvalid()) + return SetTypeSpecError(); + return SetTypeSpecType(T, Loc, PrevSpec, DiagID, Rep.get(), Policy); + } bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, Decl *Rep, bool Owned, const PrintingPolicy &Policy); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 95706fb999c4d..e60d1f68fba56 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3217,16 +3217,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (Next.is(tok::annot_typename)) { DS.getTypeSpecScope() = SS; ConsumeAnnotationToken(); // The C++ scope. - if (Tok.getAnnotationValue()) { - ParsedType T = getTypeAnnotation(Tok); - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, - Tok.getAnnotationEndLoc(), - PrevSpec, DiagID, T, Policy); - if (isInvalid) - break; - } - else - DS.SetTypeSpecError(); + TypeResult T = getTypeAnnotation(Tok); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, + Tok.getAnnotationEndLoc(), + PrevSpec, DiagID, T, Policy); + if (isInvalid) + break; DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeAnnotationToken(); // The typename } @@ -3294,13 +3290,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.hasTypeSpecifier() && DS.hasTagDefinition()) goto DoneWithDeclSpec; - if (Tok.getAnnotationValue()) { - ParsedType T = getTypeAnnotation(Tok); - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - DiagID, T, Policy); - } else - DS.SetTypeSpecError(); - + TypeResult T = getTypeAnnotation(Tok); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, + DiagID, T, Policy); if (isInvalid) break; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 98918efaf2957..710632379ace9 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1151,13 +1151,10 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); - ParsedType Type = getTypeAnnotation(Tok); + TypeResult Type = getTypeAnnotation(Tok); EndLocation = Tok.getAnnotationEndLoc(); ConsumeAnnotationToken(); - - if (Type) - return Type; - return true; + return Type; } // Fall through to produce an error below. @@ -1204,7 +1201,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Retrieve the type from the annotation token, consume that token, and // return. EndLocation = Tok.getAnnotationEndLoc(); - ParsedType Type = getTypeAnnotation(Tok); + TypeResult Type = getTypeAnnotation(Tok); ConsumeAnnotationToken(); return Type; } @@ -3510,7 +3507,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // : declype(...) DeclSpec DS(AttrFactory); // : template_name<...> - ParsedType TemplateTypeTy; + TypeResult TemplateTypeTy; if (Tok.is(tok::identifier)) { // Get the identifier. This may be a member name or a class name, @@ -3532,8 +3529,6 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); ConsumeAnnotationToken(); - if (!TemplateTypeTy) - return true; } else { Diag(Tok, diag::err_expected_member_or_base_name); return true; @@ -3552,8 +3547,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation EllipsisLoc; TryConsumeToken(tok::ellipsis, EllipsisLoc); + if (TemplateTypeTy.isInvalid()) + return true; return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy, DS, IdLoc, + TemplateTypeTy.get(), DS, IdLoc, InitList.get(), EllipsisLoc); } else if(Tok.is(tok::l_paren)) { BalancedDelimiterTracker T(*this, tok::l_paren); @@ -3563,8 +3560,10 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { ExprVector ArgExprs; CommaLocsTy CommaLocs; auto RunSignatureHelp = [&] { + if (TemplateTypeTy.isInvalid()) + return QualType(); QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp( - getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II, + getCurScope(), ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II, T.getOpenLocation()); CalledSignatureHelp = true; return PreferredType; @@ -3585,12 +3584,17 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation EllipsisLoc; TryConsumeToken(tok::ellipsis, EllipsisLoc); + if (TemplateTypeTy.isInvalid()) + return true; return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy, DS, IdLoc, + TemplateTypeTy.get(), DS, IdLoc, T.getOpenLocation(), ArgExprs, T.getCloseLocation(), EllipsisLoc); } + if (TemplateTypeTy.isInvalid()) + return true; + if (getLangOpts().CPlusPlus11) return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace; else diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 80592671dcd0f..9a0f94ae7be57 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1455,7 +1455,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, break; case tok::annot_typename: if (isStartOfObjCClassMessageMissingOpenBracket()) { - ParsedType Type = getTypeAnnotation(Tok); + TypeResult Type = getTypeAnnotation(Tok); // Fake up a Declarator to use with ActOnTypeName. DeclSpec DS(AttrFactory); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 4389c8777c6da..c5e895d090a55 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -2147,12 +2147,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { // type-name case tok::annot_typename: { - if (getTypeAnnotation(Tok)) - DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, - getTypeAnnotation(Tok), Policy); - else - DS.SetTypeSpecError(); - + DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, + getTypeAnnotation(Tok), Policy); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeAnnotationToken(); diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index f0a2a482f063a..10252b08a8d16 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -2978,7 +2978,7 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { InMessageExpression) return false; - ParsedType Type; + TypeResult Type; if (Tok.is(tok::annot_typename)) Type = getTypeAnnotation(Tok); @@ -2988,7 +2988,8 @@ bool Parser::isStartOfObjCClassMessageMissingOpenBracket() { else return false; - if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) { + // FIXME: Should not be querying properties of types from the parser. + if (Type.isUsable() && Type.get().get()->isObjCObjectOrInterfaceType()) { const Token &AfterNext = GetLookAheadToken(2); if (AfterNext.isOneOf(tok::colon, tok::r_square)) { if (Tok.is(tok::identifier)) diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index d383839d9231e..5025ea5c85feb 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1321,7 +1321,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, LAngleLoc, TemplateArgsPtr, RAngleLoc); Tok.setKind(tok::annot_typename); - setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get()); + setTypeAnnotation(Tok, Type); if (SS.isNotEmpty()) Tok.setLocation(SS.getBeginLoc()); else if (TemplateKWLoc.isValid()) @@ -1398,7 +1398,7 @@ void Parser::AnnotateTemplateIdTokenAsType(CXXScopeSpec &SS, /*IsCtorOrDtorName*/ false, IsClassName); // Create the new "type" annotation token. Tok.setKind(tok::annot_typename); - setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get()); + setTypeAnnotation(Tok, Type); if (SS.isNotEmpty()) // it was a C++ qualified type name. Tok.setLocation(SS.getBeginLoc()); // End location stays the same diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index a33e40b8768d7..e9dbd50c3ac10 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1902,7 +1902,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { SourceLocation EndLoc = Tok.getLastLoc(); Tok.setKind(tok::annot_typename); - setTypeAnnotation(Tok, Ty.isInvalid() ? nullptr : Ty.get()); + setTypeAnnotation(Tok, Ty); Tok.setAnnotationEndLoc(EndLoc); Tok.setLocation(TypenameLoc); PP.AnnotateCachedTokens(Tok); diff --git a/clang/test/Parser/cxx-class.cpp b/clang/test/Parser/cxx-class.cpp index ec56d4bee8dda..576c6d7e8b976 100644 --- a/clang/test/Parser/cxx-class.cpp +++ b/clang/test/Parser/cxx-class.cpp @@ -298,6 +298,11 @@ namespace ArrayMemberAccess { } } +namespace UndeclaredBaseTemplate { + template struct imp; + template struct is_member_function_pointer : undeclared::member> {}; // expected-error {{unknown template name 'undeclared'}} +} + // PR11109 must appear at the end of the source file class pr11109r3 { // expected-note{{to match this '{'}} public // expected-error{{expected ':'}} expected-error{{expected '}'}} expected-error{{expected ';' after class}}