From fec54013fcd0eb72642741584ca04c1bc292bef8 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 3 Aug 2009 20:12:06 +0000 Subject: [PATCH] Refactor methods on DeclSpec to take a diagnostic& parameter, and reflect this elsewhere. Very slightly decouples DeclSpec users from knowing the exact diagnostics to report, and makes it easier to provide different diagnostics in some places. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77990 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Parse/DeclSpec.h | 45 ++++--- include/clang/Parse/Parser.h | 3 +- lib/Parse/DeclSpec.cpp | 61 +++++---- lib/Parse/ParseDecl.cpp | 222 +++++++++++++++++++-------------- lib/Parse/ParseDeclCXX.cpp | 12 +- lib/Parse/ParseExprCXX.cpp | 36 +++--- lib/Parse/Parser.cpp | 8 +- lib/Sema/SemaDecl.cpp | 12 +- 8 files changed, 242 insertions(+), 157 deletions(-) diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 467254b4d5..ae1876689a 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -267,27 +267,44 @@ public: void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); } void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); } - /// These methods set the specified attribute of the DeclSpec, but return true - /// and ignore the request if invalid (e.g. "extern" then "auto" is - /// specified). The name of the previous specifier is returned in prevspec. - bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec); - bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec); - bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec); - bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec); - bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec); + /// These methods set the specified attribute of the DeclSpec and + /// return false if there was no error. If an error occurs (for + /// example, if we tried to set "auto" on a spec with "extern" + /// already set), they return true and set PrevSpec and DiagID + /// such that + /// Diag(Loc, DiagID) << PrevSpec; + /// will yield a useful result. + /// + /// TODO: use a more general approach that still allows these + /// diagnostics to be ignored when desired. + bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, - void *Rep = 0, bool Owned = false); + unsigned &DiagID, void *Rep = 0, bool Owned = false); bool SetTypeSpecError(); void UpdateTypeRep(void *Rep) { TypeRep = Rep; } bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, - const LangOptions &Lang); + unsigned &DiagID, const LangOptions &Lang); - bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec); - bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec); - bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec); + bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); - bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec); + bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); + bool isFriendSpecified() const { return Friend_specified; } SourceLocation getFriendSpecLoc() const { return FriendLoc; } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index dc6a577771..b1eb4da277 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -923,8 +923,9 @@ private: void ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none); - bool ParseOptionalTypeSpecifier(DeclSpec &DS, int &isInvalid, + bool ParseOptionalTypeSpecifier(DeclSpec &DS, bool &isInvalid, const char *&PrevSpec, + unsigned &DiagID, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); void ParseSpecifierQualifierList(DeclSpec &DS); diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index 216847a7e1..80078660b6 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -105,8 +105,12 @@ unsigned DeclSpec::getParsedSpecifiers() const { return Res; } -template static bool BadSpecifier(T TPrev, const char *&PrevSpec) { +template static bool BadSpecifier(T TNew, T TPrev, + const char *&PrevSpec, + unsigned &DiagID) { PrevSpec = DeclSpec::getSpecifierName(TPrev); + DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec + : diag::err_invalid_decl_spec_combination); return true; } @@ -193,9 +197,10 @@ const char *DeclSpec::getSpecifierName(TQ T) { } bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, - const char *&PrevSpec) { + const char *&PrevSpec, + unsigned &DiagID) { if (StorageClassSpec != SCS_unspecified) - return BadSpecifier((SCS)StorageClassSpec, PrevSpec); + return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID); StorageClassSpec = S; StorageClassSpecLoc = Loc; assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield"); @@ -203,9 +208,11 @@ bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, } bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, - const char *&PrevSpec) { + const char *&PrevSpec, + unsigned &DiagID) { if (SCS_thread_specified) { PrevSpec = "__thread"; + DiagID = diag::ext_duplicate_declspec; return true; } SCS_thread_specified = true; @@ -218,39 +225,46 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, /// and ignore the request if invalid (e.g. "extern" then "auto" is /// specified). bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, - const char *&PrevSpec) { + const char *&PrevSpec, + unsigned &DiagID) { if (TypeSpecWidth != TSW_unspecified && // Allow turning long -> long long. (W != TSW_longlong || TypeSpecWidth != TSW_long)) - return BadSpecifier((TSW)TypeSpecWidth, PrevSpec); + return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); TypeSpecWidth = W; TSWLoc = Loc; return false; } bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, - const char *&PrevSpec) { + const char *&PrevSpec, + unsigned &DiagID) { if (TypeSpecComplex != TSC_unspecified) - return BadSpecifier((TSC)TypeSpecComplex, PrevSpec); + return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID); TypeSpecComplex = C; TSCLoc = Loc; return false; } bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, - const char *&PrevSpec) { + const char *&PrevSpec, + unsigned &DiagID) { if (TypeSpecSign != TSS_unspecified) - return BadSpecifier((TSS)TypeSpecSign, PrevSpec); + return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID); TypeSpecSign = S; TSSLoc = Loc; return false; } bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, - const char *&PrevSpec, void *Rep, - bool Owned) { - if (TypeSpecType != TST_unspecified) - return BadSpecifier((TST)TypeSpecType, PrevSpec); + const char *&PrevSpec, + unsigned &DiagID, + void *Rep, bool Owned) { + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } TypeSpecType = T; TypeRep = Rep; TSTLoc = Loc; @@ -266,10 +280,10 @@ bool DeclSpec::SetTypeSpecError() { } bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, - const LangOptions &Lang) { + unsigned &DiagID, const LangOptions &Lang) { // Duplicates turn into warnings pre-C99. if ((TypeQualifiers & T) && !Lang.C99) - return BadSpecifier(T, PrevSpec); + return BadSpecifier(T, T, PrevSpec, DiagID); TypeQualifiers |= T; switch (T) { @@ -281,33 +295,38 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, return false; } -bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec){ +bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { // 'inline inline' is ok. FS_inline_specified = true; FS_inlineLoc = Loc; return false; } -bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec){ +bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { // 'virtual virtual' is ok. FS_virtual_specified = true; FS_virtualLoc = Loc; return false; } -bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec){ +bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { // 'explicit explicit' is ok. FS_explicit_specified = true; FS_explicitLoc = Loc; return false; } -bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec) { +bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { if (Friend_specified) { PrevSpec = "friend"; + DiagID = diag::ext_duplicate_declspec; return true; } - + Friend_specified = true; FriendLoc = Loc; return false; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 1365282ee1..42ef7e6c29 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -673,7 +673,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R; const char *PrevSpec; - DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec); + unsigned DiagID; + DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID); DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); @@ -710,8 +711,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS) { DS.SetRangeStart(Tok.getLocation()); while (1) { - int isInvalid = false; + bool isInvalid = false; const char *PrevSpec = 0; + unsigned DiagID = 0; + SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { @@ -777,7 +780,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ConsumeToken(); // The C++ scope. isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - TypeRep); + DiagID, TypeRep); if (isInvalid) break; @@ -790,7 +793,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::annot_typename: { if (Tok.getAnnotationValue()) isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - Tok.getAnnotationValue()); + DiagID, Tok.getAnnotationValue()); else DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); @@ -846,7 +849,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - TypeRep); + DiagID, TypeRep); if (isInvalid) break; @@ -913,112 +916,138 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // storage-class-specifier case tok::kw_typedef: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec, + DiagID); break; case tok::kw_extern: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "extern"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec, + DiagID); break; case tok::kw___private_extern__: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc, - PrevSpec); + PrevSpec, DiagID); break; case tok::kw_static: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "static"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec, + DiagID); break; case tok::kw_auto: if (getLang().CPlusPlus0x) - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, + DiagID); else - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, + DiagID); break; case tok::kw_register: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec, + DiagID); break; case tok::kw_mutable: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec, + DiagID); break; case tok::kw___thread: - isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec)*2; + isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID); break; // function-specifier case tok::kw_inline: - isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec); + isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID); break; case tok::kw_virtual: - isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec); + isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID); break; case tok::kw_explicit: - isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec); + isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID); break; // friend case tok::kw_friend: - isInvalid = DS.SetFriendSpec(Loc, PrevSpec); + isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); break; - + // type-specifier case tok::kw_short: - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, + DiagID); break; case tok::kw_long: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long) - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, + DiagID); else - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, + DiagID); break; case tok::kw_signed: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, + DiagID); break; case tok::kw_unsigned: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, + DiagID); break; case tok::kw__Complex: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec, + DiagID); break; case tok::kw__Imaginary: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec, + DiagID); break; case tok::kw_void: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, + DiagID); break; case tok::kw_char: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, + DiagID); break; case tok::kw_int: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, + DiagID); break; case tok::kw_float: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, + DiagID); break; case tok::kw_double: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, + DiagID); break; case tok::kw_wchar_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, + DiagID); break; case tok::kw_char16_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, + DiagID); break; case tok::kw_char32_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, + DiagID); break; case tok::kw_bool: case tok::kw__Bool: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal32: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal64: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal128: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, + DiagID); break; // class-specifier: @@ -1039,15 +1068,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // cv-qualifier: case tok::kw_const: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec,getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_volatile: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_restrict: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, + getLang()); break; // C++ typename-specifier: @@ -1087,12 +1117,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } } - // If the specifier combination wasn't legal, issue a diagnostic. + // If the specifier wasn't legal, issue a diagnostic. if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); - // Pick between error or extwarn. - unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination - : diag::ext_duplicate_declspec; + assert(DiagID); Diag(Tok, DiagID) << PrevSpec; } DS.SetRangeEnd(Tok.getLocation()); @@ -1143,8 +1171,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// [OBJC] class-name objc-protocol-refs[opt] [TODO] /// [OBJC] typedef-name objc-protocol-refs[opt] [TODO] /// [C++0x] 'decltype' ( expression ) -bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, +bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, const char *&PrevSpec, + unsigned &DiagID, const ParsedTemplateInfo &TemplateInfo) { SourceLocation Loc = Tok.getLocation(); @@ -1154,7 +1183,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) - return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo); + return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, + TemplateInfo); // Otherwise, not a type specifier. return false; case tok::coloncolon: // ::foo::bar @@ -1165,7 +1195,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) - return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo); + return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, + TemplateInfo); // Otherwise, not a type specifier. return false; @@ -1173,7 +1204,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, case tok::annot_typename: { if (Tok.getAnnotationValue()) isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - Tok.getAnnotationValue()); + DiagID, Tok.getAnnotationValue()); else DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); @@ -1196,62 +1227,70 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, } case tok::kw_short: - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID); break; case tok::kw_long: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long) - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, + DiagID); else - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, + DiagID); break; case tok::kw_signed: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); break; case tok::kw_unsigned: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, + DiagID); break; case tok::kw__Complex: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec, + DiagID); break; case tok::kw__Imaginary: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec, + DiagID); break; case tok::kw_void: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID); break; case tok::kw_char: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID); break; case tok::kw_int: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; case tok::kw_float: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); break; case tok::kw_double: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID); break; case tok::kw_wchar_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID); break; case tok::kw_char16_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID); break; case tok::kw_char32_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID); break; case tok::kw_bool: case tok::kw__Bool: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); break; case tok::kw__Decimal32: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal64: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal128: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, + DiagID); break; // class-specifier: @@ -1273,15 +1312,15 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, // cv-qualifier: case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, - getLang())*2; + DiagID, getLang()); break; case tok::kw_volatile: isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, - getLang())*2; + DiagID, getLang()); break; case tok::kw_restrict: isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, - getLang())*2; + DiagID, getLang()); break; // GNU typeof support. @@ -1299,7 +1338,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, if (!getLang().CPlusPlus0x) return false; - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID); break; case tok::kw___ptr64: case tok::kw___w64: @@ -1318,8 +1357,6 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); // Pick between error or extwarn. - unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination - : diag::ext_duplicate_declspec; Diag(Tok, DiagID) << PrevSpec; } DS.SetRangeEnd(Tok.getLocation()); @@ -1595,9 +1632,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // TODO: semantic analysis on the declspec for enums. const char *PrevSpec = 0; - if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, + unsigned DiagID; + if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, DiagID, TagDecl.getAs(), Owned)) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + Diag(StartLoc, DiagID) << PrevSpec; } /// ParseEnumBody - Parse a {} enclosed enumerator-list. @@ -1883,22 +1921,23 @@ bool Parser::isDeclarationSpecifier() { /// void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) { while (1) { - int isInvalid = false; + bool isInvalid = false; const char *PrevSpec = 0; + unsigned DiagID = 0; SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { case tok::kw_const: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_volatile: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_restrict: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw___w64: case tok::kw___ptr64: @@ -1927,9 +1966,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) { // If the specifier combination wasn't legal, issue a diagnostic. if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); - // Pick between error or extwarn. - unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination - : diag::ext_duplicate_declspec; Diag(Tok, DiagID) << PrevSpec; } ConsumeToken(); @@ -2831,10 +2867,11 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { } const char *PrevSpec = 0; + unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, - CastTy)) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + DiagID, CastTy)) + Diag(StartLoc, DiagID) << PrevSpec; return; } @@ -2845,8 +2882,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { } const char *PrevSpec = 0; + unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec, - Operand.release())) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + DiagID, Operand.release())) + Diag(StartLoc, DiagID) << PrevSpec; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 176cb35889..c0df8a59f7 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -410,10 +410,11 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { return; const char *PrevSpec = 0; + unsigned DiagID; // Check for duplicate type specifiers (e.g. "int decltype(a)"). if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, - Result.release())) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + DiagID, Result.release())) + Diag(StartLoc, DiagID) << PrevSpec; } /// ParseClassName - Parse a C++ class-name, which names a class. Note @@ -716,15 +717,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Diag(Tok, diag::err_expected_lbrace); } - const char *PrevSpec = 0; if (TagOrTempResult.isInvalid()) { DS.SetTypeSpecError(); return; } - if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, + const char *PrevSpec = 0; + unsigned DiagID; + if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, DiagID, TagOrTempResult.get().getAs(), Owned)) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + Diag(StartLoc, DiagID) << PrevSpec; if (DS.isFriendSpecified()) Actions.ActOnFriendDecl(CurScope, DS.getFriendSpecLoc(), diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index b3c38f4ec8..91b4d4d5a9 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -610,6 +610,7 @@ Parser::OwningExprResult Parser::ParseCXXCondition() { void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetRangeStart(Tok.getLocation()); const char *PrevSpec; + unsigned DiagID; SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { @@ -622,50 +623,50 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { // type-name case tok::annot_typename: { - DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, + DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, Tok.getAnnotationValue()); break; } // builtin types case tok::kw_short: - DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); + DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID); break; case tok::kw_long: - DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); + DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID); break; case tok::kw_signed: - DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); + DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); break; case tok::kw_unsigned: - DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); + DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID); break; case tok::kw_void: - DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID); break; case tok::kw_char: - DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID); break; case tok::kw_int: - DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; case tok::kw_float: - DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); break; case tok::kw_double: - DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID); break; case tok::kw_wchar_t: - DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID); break; case tok::kw_char16_t: - DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID); break; case tok::kw_char32_t: - DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID); break; case tok::kw_bool: - DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); + DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); break; // GNU typeof support. @@ -696,15 +697,16 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { DS.SetRangeStart(Tok.getLocation()); const char *PrevSpec = 0; - int isInvalid = 0; + unsigned DiagID; + bool isInvalid = 0; // Parse one or more of the type specifiers. - if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) { + if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) { Diag(Tok, diag::err_operator_missing_type_specifier); return true; } - while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ; + while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ; return false; } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index ad68f93beb..1a082db434 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -522,8 +522,9 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { return DeclGroupPtrTy(); } const char *PrevSpec = 0; - if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec)) - Diag(AtLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + unsigned DiagID; + if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID)) + Diag(AtLoc, DiagID) << PrevSpec; DeclPtrTy TheDecl; if (Tok.isObjCAtKeyword(tok::objc_protocol)) @@ -619,9 +620,10 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D, // declaration-specifiers are completely optional in the grammar. if (getLang().ImplicitInt && D.getDeclSpec().isEmpty()) { const char *PrevSpec; + unsigned DiagID; D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int, D.getIdentifierLoc(), - PrevSpec); + PrevSpec, DiagID); D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 90a1744c88..503cd1e17b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1394,6 +1394,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, bool Invalid = false; if (getLangOptions().CPlusPlus) { const char* PrevSpec = 0; + unsigned DiagID; // C++ [class.union]p3: // Anonymous unions declared in a named namespace or in the // global namespace shall be declared static. @@ -1405,7 +1406,8 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; // Recover by adding 'static'. - DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), PrevSpec); + DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); } // C++ [class.union]p3: // A storage class is not allowed in a declaration of an @@ -1418,7 +1420,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Recover by removing the storage specifier. DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(), - PrevSpec); + PrevSpec, DiagID); } // C++ [class.union]p2: @@ -3434,8 +3436,9 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, // type. DeclSpec DS; const char* PrevSpec; // unused + unsigned DiagID; // unused DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, - PrevSpec); + PrevSpec, DiagID); Declarator ParamD(DS, Declarator::KNRTypeListContext); ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc); FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD); @@ -3688,7 +3691,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // Set a Declarator for the implicit definition: int foo(); const char *Dummy; DeclSpec DS; - bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy); + unsigned DiagID; + bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); Error = Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); Declarator D(DS, Declarator::BlockContext);