diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-03 01:35:08 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-03 01:35:08 +0000 |
commit | 3f9a0566e6793151b99a65ab936220971cf96c1b (patch) | |
tree | 00a3baa8ea3e6a98caaa988a21bdff8bd3d3b3ba /lib | |
parent | cc667e2bd2ed7aaf99bc52c58d127644b8ebbfc8 (diff) |
Introduce a new class, UnqualifiedId, that provides a parsed
representation of a C++ unqualified-id, along with a single parsing
function (Parser::ParseUnqualifiedId) that will parse all of the
various forms of unqualified-id in C++.
Replace the representation of the declarator name in Declarator with
the new UnqualifiedId class, simplifying declarator-id parsing
considerably and providing more source-location information to
Sema. In the future, I hope to migrate all of the other
unqualified-id-parsing code over to this single representation, then
begin to merge actions that are currently only different because we
didn't have a unqualified notion of the name in the parser.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85851 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/DeclSpec.cpp | 25 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 113 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 413 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 71 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 20 |
8 files changed, 529 insertions, 134 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index b8422aad5a..3436900027 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -446,3 +446,28 @@ bool DeclSpec::isMissingDeclaratorOk() { || tst == TST_enum ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef; } + +void UnqualifiedId::clear() { + if (Kind == IK_TemplateId) + TemplateId->Destroy(); + + Kind = IK_Identifier; + Identifier = 0; + StartLocation = SourceLocation(); + EndLocation = SourceLocation(); +} + +void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + SourceLocation SymbolLocations[3]) { + Kind = IK_OperatorFunctionId; + StartLocation = OperatorLoc; + EndLocation = OperatorLoc; + OperatorFunctionId.Operator = Op; + for (unsigned I = 0; I != 3; ++I) { + OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding(); + + if (SymbolLocations[I].isValid()) + EndLocation = SymbolLocations[I]; + } +} diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index b56c33170c..55970c0c8c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2270,97 +2270,46 @@ void Parser::ParseDeclaratorInternal(Declarator &D, void Parser::ParseDirectDeclarator(Declarator &D) { DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec()); - if (getLang().CPlusPlus) { - if (D.mayHaveIdentifier()) { - // ParseDeclaratorInternal might already have parsed the scope. - bool afterCXXScope = D.getCXXScopeSpec().isSet() || - ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0, - true); - if (afterCXXScope) { - // Change the declaration context for name lookup, until this function - // is exited (and the declarator has been parsed). - DeclScopeObj.EnterDeclaratorScope(); - } - - if (Tok.is(tok::identifier)) { - assert(Tok.getIdentifierInfo() && "Not an identifier?"); - - // If this identifier is the name of the current class, it's a - // constructor name. - if (!D.getDeclSpec().hasTypeSpecifier() && - Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) { - CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0; - D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope, SS), - Tok.getLocation()); - // This is a normal identifier. - } else - D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); - ConsumeToken(); - goto PastIdentifier; - } else if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId - = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - - D.setTemplateId(TemplateId); - ConsumeToken(); - goto PastIdentifier; - } else if (Tok.is(tok::kw_operator)) { - SourceLocation OperatorLoc = Tok.getLocation(); - SourceLocation EndLoc; - - // First try the name of an overloaded operator - if (OverloadedOperatorKind Op = TryParseOperatorFunctionId(&EndLoc)) { - D.setOverloadedOperator(Op, OperatorLoc, EndLoc); - } else { - // This must be a conversion function (C++ [class.conv.fct]). - if (TypeTy *ConvType = ParseConversionFunctionId(&EndLoc)) - D.setConversionFunction(ConvType, OperatorLoc, EndLoc); - else { - D.SetIdentifier(0, Tok.getLocation()); - } - } - goto PastIdentifier; - } else if (Tok.is(tok::tilde)) { - // This should be a C++ destructor. - SourceLocation TildeLoc = ConsumeToken(); - if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { - // FIXME: Inaccurate. - SourceLocation NameLoc = Tok.getLocation(); - SourceLocation EndLoc; - CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0; - TypeResult Type = ParseClassName(EndLoc, SS, true); - if (Type.isInvalid()) - D.SetIdentifier(0, TildeLoc); - else - D.setDestructor(Type.get(), TildeLoc, NameLoc); - } else { - Diag(Tok, diag::err_destructor_class_name); - D.SetIdentifier(0, TildeLoc); - } - goto PastIdentifier; - } - - // If we reached this point, token is not identifier and not '~'. - - if (afterCXXScope) { - Diag(Tok, diag::err_expected_unqualified_id); + if (getLang().CPlusPlus && D.mayHaveIdentifier()) { + // ParseDeclaratorInternal might already have parsed the scope. + bool afterCXXScope = D.getCXXScopeSpec().isSet() || + ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0, + true); + if (afterCXXScope) { + // Change the declaration context for name lookup, until this function + // is exited (and the declarator has been parsed). + DeclScopeObj.EnterDeclaratorScope(); + } + + if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) || + Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) { + // We found something that indicates the start of an unqualified-id. + // Parse that unqualified-id. + if (ParseUnqualifiedId(D.getCXXScopeSpec(), + /*EnteringContext=*/true, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(), + D.getName())) { D.SetIdentifier(0, Tok.getLocation()); D.setInvalidType(true); - goto PastIdentifier; + } else { + // Parsed the unqualified-id; update range information and move along. + if (D.getSourceRange().getBegin().isInvalid()) + D.SetRangeBegin(D.getName().getSourceRange().getBegin()); + D.SetRangeEnd(D.getName().getSourceRange().getEnd()); } + goto PastIdentifier; } - } - - // If we reached this point, we are either in C/ObjC or the token didn't - // satisfy any of the C++-specific checks. - if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { + } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { assert(!getLang().CPlusPlus && "There's a C++-specific check for tok::identifier above"); assert(Tok.getIdentifierInfo() && "Not an identifier?"); D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); - } else if (Tok.is(tok::l_paren)) { + goto PastIdentifier; + } + + if (Tok.is(tok::l_paren)) { // direct-declarator: '(' declarator ')' // direct-declarator: '(' attributes declarator ')' // Example: 'char (*X)' or 'int (*XX)(void)' diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 65265afa91..a8e127610c 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -323,6 +323,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, SkipUntil(tok::semi); return DeclPtrTy(); } + // FIXME: what about conversion functions? } else if (Tok.is(tok::identifier)) { // Parse identifier. TargetName = Tok.getIdentifierInfo(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index fa651569f8..dc7974135d 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -14,6 +14,8 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" +#include "llvm/Support/ErrorHandling.h" + using namespace clang; /// \brief Parse global scope or nested-name-specifier if present. @@ -761,6 +763,417 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { return false; } +/// \brief Finish parsing a C++ unqualified-id that is a template-id of +/// some form. +/// +/// This routine is invoked when a '<' is encountered after an identifier or +/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine +/// whether the unqualified-id is actually a template-id. This routine will +/// then parse the template arguments and form the appropriate template-id to +/// return to the caller. +/// +/// \param SS the nested-name-specifier that precedes this template-id, if +/// we're actually parsing a qualified-id. +/// +/// \param Name for constructor and destructor names, this is the actual +/// identifier that may be a template-name. +/// +/// \param NameLoc the location of the class-name in a constructor or +/// destructor. +/// +/// \param EnteringContext whether we're entering the scope of the +/// nested-name-specifier. +/// +/// \param Id as input, describes the template-name or operator-function-id +/// that precedes the '<'. If template arguments were parsed successfully, +/// will be updated with the template-id. +/// +/// \returns true if a parse error occurred, false otherwise. +bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool EnteringContext, + UnqualifiedId &Id) { + assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id"); + + TemplateTy Template; + TemplateNameKind TNK = TNK_Non_template; + switch (Id.getKind()) { + case UnqualifiedId::IK_Identifier: + TNK = Actions.isTemplateName(CurScope, *Id.Identifier, Id.StartLocation, + &SS, /*ObjectType=*/0, EnteringContext, + Template); + break; + + case UnqualifiedId::IK_OperatorFunctionId: { + // FIXME: Temporary hack: warn that we are completely ignoring the + // template arguments for now. + // Parse the enclosed template argument list. + SourceLocation LAngleLoc, RAngleLoc; + TemplateArgList TemplateArgs; + TemplateArgIsTypeList TemplateArgIsType; + TemplateArgLocationList TemplateArgLocations; + if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, + &SS, true, LAngleLoc, + TemplateArgs, + TemplateArgIsType, + TemplateArgLocations, + RAngleLoc)) + return true; + + Diag(Id.StartLocation, diag::warn_operator_template_id_ignores_args) + << SourceRange(LAngleLoc, RAngleLoc); + break; + } + + case UnqualifiedId::IK_ConstructorName: + TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, + &SS, /*ObjectType=*/0, EnteringContext, + Template); + break; + + case UnqualifiedId::IK_DestructorName: + TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, + &SS, /*ObjectType=*/0, EnteringContext, + Template); + break; + + default: + return false; + } + + if (TNK == TNK_Non_template) + return false; + + // Parse the enclosed template argument list. + SourceLocation LAngleLoc, RAngleLoc; + TemplateArgList TemplateArgs; + TemplateArgIsTypeList TemplateArgIsType; + TemplateArgLocationList TemplateArgLocations; + if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, + &SS, true, LAngleLoc, + TemplateArgs, + TemplateArgIsType, + TemplateArgLocations, + RAngleLoc)) + return true; + + if (Id.getKind() == UnqualifiedId::IK_Identifier || + Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) { + // Form a parsed representation of the template-id to be stored in the + // UnqualifiedId. + TemplateIdAnnotation *TemplateId + = TemplateIdAnnotation::Allocate(TemplateArgs.size()); + + if (Id.getKind() == UnqualifiedId::IK_Identifier) { + TemplateId->Name = Id.Identifier; + TemplateId->TemplateNameLoc = Id.StartLocation; + } else { + // FIXME: Handle IK_OperatorFunctionId + } + + TemplateId->Template = Template.getAs<void*>(); + TemplateId->Kind = TNK; + TemplateId->LAngleLoc = LAngleLoc; + TemplateId->RAngleLoc = RAngleLoc; + void **Args = TemplateId->getTemplateArgs(); + bool *ArgIsType = TemplateId->getTemplateArgIsType(); + SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations(); + for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); + Arg != ArgEnd; ++Arg) { + Args[Arg] = TemplateArgs[Arg]; + ArgIsType[Arg] = TemplateArgIsType[Arg]; + ArgLocs[Arg] = TemplateArgLocations[Arg]; + } + + Id.setTemplateId(TemplateId); + return false; + } + + // Bundle the template arguments together. + ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), + TemplateArgIsType.data(), + TemplateArgs.size()); + + // Constructor and destructor names. + Action::TypeResult Type + = Actions.ActOnTemplateIdType(Template, NameLoc, + LAngleLoc, TemplateArgsPtr, + &TemplateArgLocations[0], + RAngleLoc); + if (Type.isInvalid()) + return true; + + if (Id.getKind() == UnqualifiedId::IK_ConstructorName) + Id.setConstructorName(Type.get(), NameLoc, RAngleLoc); + else + Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc); + + return false; +} + +/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the +/// name of an entity. +/// +/// \code +/// unqualified-id: [C++ expr.prim.general] +/// identifier +/// operator-function-id +/// conversion-function-id +/// [C++0x] literal-operator-id [TODO] +/// ~ class-name +/// template-id +/// +/// operator-function-id: [C++ 13.5] +/// 'operator' operator +/// +/// operator: one of +/// new delete new[] delete[] +/// + - * / % ^ & | ~ +/// ! = < > += -= *= /= %= +/// ^= &= |= << >> >>= <<= == != +/// <= >= && || ++ -- , ->* -> +/// () [] +/// +/// conversion-function-id: [C++ 12.3.2] +/// operator conversion-type-id +/// +/// conversion-type-id: +/// type-specifier-seq conversion-declarator[opt] +/// +/// conversion-declarator: +/// ptr-operator conversion-declarator[opt] +/// \endcode +/// +/// \param The nested-name-specifier that preceded this unqualified-id. If +/// non-empty, then we are parsing the unqualified-id of a qualified-id. +/// +/// \param EnteringContext whether we are entering the scope of the +/// nested-name-specifier. +/// +/// \param AllowDestructorName whether we allow parsing of a destructor name. +/// +/// \param AllowConstructorName whether we allow parsing a constructor name. +/// +/// \param Result on a successful parse, contains the parsed unqualified-id. +/// +/// \returns true if parsing fails, false otherwise. +bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, + bool AllowDestructorName, + bool AllowConstructorName, + UnqualifiedId &Result) { + // unqualified-id: + // identifier + // template-id (when it hasn't already been annotated) + if (Tok.is(tok::identifier)) { + // Consume the identifier. + IdentifierInfo *Id = Tok.getIdentifierInfo(); + SourceLocation IdLoc = ConsumeToken(); + + if (AllowConstructorName && + Actions.isCurrentClassName(*Id, CurScope, &SS)) { + // We have parsed a constructor name. + Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope, + &SS, false), + IdLoc, IdLoc); + } else { + // We have parsed an identifier. + Result.setIdentifier(Id, IdLoc); + } + + // If the next token is a '<', we may have a template. + if (Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, + Result); + + return false; + } + + // unqualified-id: + // template-id (already parsed and annotated) + if (Tok.is(tok::annot_template_id)) { + // FIXME: Could this be a constructor name??? + + // We have already parsed a template-id; consume the annotation token as + // our unqualified-id. + Result.setTemplateId( + static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue())); + ConsumeToken(); + return false; + } + + // unqualified-id: + // operator-function-id + // conversion-function-id + if (Tok.is(tok::kw_operator)) { + // Consume the 'operator' keyword. + SourceLocation KeywordLoc = ConsumeToken(); + + // Determine what kind of operator name we have. + unsigned SymbolIdx = 0; + SourceLocation SymbolLocations[3]; + OverloadedOperatorKind Op = OO_None; + switch (Tok.getKind()) { + case tok::kw_new: + case tok::kw_delete: { + bool isNew = Tok.getKind() == tok::kw_new; + // Consume the 'new' or 'delete'. + SymbolLocations[SymbolIdx++] = ConsumeToken(); + if (Tok.is(tok::l_square)) { + // Consume the '['. + SourceLocation LBracketLoc = ConsumeBracket(); + // Consume the ']'. + SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square, + LBracketLoc); + if (RBracketLoc.isInvalid()) + return true; + + SymbolLocations[SymbolIdx++] = LBracketLoc; + SymbolLocations[SymbolIdx++] = RBracketLoc; + Op = isNew? OO_Array_New : OO_Array_Delete; + } else { + Op = isNew? OO_New : OO_Delete; + } + break; + } + + #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + case tok::Token: \ + SymbolLocations[SymbolIdx++] = ConsumeToken(); \ + Op = OO_##Name; \ + break; + #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) + #include "clang/Basic/OperatorKinds.def" + + case tok::l_paren: { + // Consume the '('. + SourceLocation LParenLoc = ConsumeParen(); + // Consume the ')'. + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, + LParenLoc); + if (RParenLoc.isInvalid()) + return true; + + SymbolLocations[SymbolIdx++] = LParenLoc; + SymbolLocations[SymbolIdx++] = RParenLoc; + Op = OO_Call; + break; + } + + case tok::l_square: { + // Consume the '['. + SourceLocation LBracketLoc = ConsumeBracket(); + // Consume the ']'. + SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square, + LBracketLoc); + if (RBracketLoc.isInvalid()) + return true; + + SymbolLocations[SymbolIdx++] = LBracketLoc; + SymbolLocations[SymbolIdx++] = RBracketLoc; + Op = OO_Subscript; + break; + } + + case tok::code_completion: { + // Code completion for the operator name. + Actions.CodeCompleteOperatorName(CurScope); + + // Consume the operator token. + ConsumeToken(); + + // Don't try to parse any further. + return true; + } + + default: + break; + } + + if (Op != OO_None) { + // We have parsed an operator-function-id. + Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations); + + // If the next token is a '<', we may have a template. + if (Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), + EnteringContext, Result); + + return false; + } + + // Parse a conversion-function-id. + // + // conversion-function-id: [C++ 12.3.2] + // operator conversion-type-id + // + // conversion-type-id: + // type-specifier-seq conversion-declarator[opt] + // + // conversion-declarator: + // ptr-operator conversion-declarator[opt] + + // Parse the type-specifier-seq. + DeclSpec DS; + if (ParseCXXTypeSpecifierSeq(DS)) + return true; + + // Parse the conversion-declarator, which is merely a sequence of + // ptr-operators. + Declarator D(DS, Declarator::TypeNameContext); + ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); + + // Finish up the type. + Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D); + if (Ty.isInvalid()) + return true; + + // Note that this is a conversion-function-id. + Result.setConversionFunctionId(KeywordLoc, Ty.get(), + D.getSourceRange().getEnd()); + return false; + } + + if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) { + // C++ [expr.unary.op]p10: + // There is an ambiguity in the unary-expression ~X(), where X is a + // class-name. The ambiguity is resolved in favor of treating ~ as a + // unary complement rather than treating ~X as referring to a destructor. + + // Parse the '~'. + SourceLocation TildeLoc = ConsumeToken(); + + // Parse the class-name. + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_destructor_class_name); + return true; + } + + // Parse the class-name (or template-name in a simple-template-id). + IdentifierInfo *ClassName = Tok.getIdentifierInfo(); + SourceLocation ClassNameLoc = ConsumeToken(); + + // Note that this is a destructor name. + Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc, + CurScope, &SS); + if (!Ty) { + Diag(ClassNameLoc, diag::err_destructor_class_name); + return true; + } + + Result.setDestructorName(TildeLoc, Ty, ClassNameLoc); + + if (Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc, + EnteringContext, Result); + + return false; + } + + Diag(Tok, diag::err_expected_unqualified_id); + return true; +} + /// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded /// operator name (C++ [over.oper]). If successful, returns the /// predefined identifier that corresponds to that overloaded diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 71afe68916..8d00c09f30 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1606,45 +1606,48 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, /// GetNameForDeclarator - Determine the full declaration name for the /// given Declarator. DeclarationName Sema::GetNameForDeclarator(Declarator &D) { - switch (D.getKind()) { - case Declarator::DK_Abstract: - assert(D.getIdentifier() == 0 && "abstract declarators have no name"); - return DeclarationName(); + UnqualifiedId &Name = D.getName(); + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + return DeclarationName(Name.Identifier); - case Declarator::DK_Normal: - assert (D.getIdentifier() != 0 && "normal declarators have an identifier"); - return DeclarationName(D.getIdentifier()); + case UnqualifiedId::IK_OperatorFunctionId: + return Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator); - case Declarator::DK_Constructor: { - QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); + case UnqualifiedId::IK_ConversionFunctionId: { + QualType Ty = GetTypeFromParser(Name.ConversionFunctionId); + if (Ty.isNull()) + return DeclarationName(); + + return Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(Ty)); + } + + case UnqualifiedId::IK_ConstructorName: { + QualType Ty = GetTypeFromParser(Name.ConstructorName); + if (Ty.isNull()) + return DeclarationName(); + return Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Ty)); } - - case Declarator::DK_Destructor: { - QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); + + case UnqualifiedId::IK_DestructorName: { + QualType Ty = GetTypeFromParser(Name.DestructorName); + if (Ty.isNull()) + return DeclarationName(); + return Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(Ty)); } - - case Declarator::DK_Conversion: { - // FIXME: We'd like to keep the non-canonical type for diagnostics! - QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); - return Context.DeclarationNames.getCXXConversionFunctionName( - Context.getCanonicalType(Ty)); - } - - case Declarator::DK_Operator: - assert(D.getIdentifier() == 0 && "operator names have no identifier"); - return Context.DeclarationNames.getCXXOperatorName( - D.getOverloadedOperator()); - case Declarator::DK_TemplateId: { - TemplateName Name - = TemplateName::getFromVoidPointer(D.getTemplateId()->Template); - if (TemplateDecl *Template = Name.getAsTemplateDecl()) + case UnqualifiedId::IK_TemplateId: { + TemplateName TName + = TemplateName::getFromVoidPointer(Name.TemplateId->Template); + if (TemplateDecl *Template = TName.getAsTemplateDecl()) return Template->getDeclName(); - if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) + if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl()) return Ovl->getDeclName(); return DeclarationName(); @@ -2517,7 +2520,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isInline |= IsFunctionDefinition; } - if (D.getKind() == Declarator::DK_Constructor) { + if (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && "Constructors can only be declared in a member context"); @@ -2530,7 +2533,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, D.getIdentifierLoc(), Name, R, DInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); - } else if (D.getKind() == Declarator::DK_Destructor) { + } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { R = CheckDestructorDeclarator(D, SC); @@ -2552,7 +2555,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, /*hasPrototype=*/true); D.setInvalidType(); } - } else if (D.getKind() == Declarator::DK_Conversion) { + } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { if (!DC->isRecord()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member); @@ -2798,8 +2801,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, bool HasExplicitTemplateArgs = false; llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (D.getKind() == Declarator::DK_TemplateId) { - TemplateIdAnnotation *TemplateId = D.getTemplateId(); + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->getTemplateArgIsType(), diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 90aef21637..bc255137fc 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2295,7 +2295,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // (7.1.3); however, a typedef-name that names a class shall not // be used as the identifier in the declarator for a destructor // declaration. - QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType()); + QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); if (isa<TypedefType>(DeclaratorType)) { Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType; @@ -2421,7 +2421,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // C++ [class.conv.fct]p4: // The conversion-type-id shall not represent a function type nor // an array type. - QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType()); + QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId); if (ConvType->isArrayType()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); ConvType = Context.getPointerType(ConvType); @@ -4515,12 +4515,12 @@ Sema::ActOnFriendFunctionDecl(Scope *S, if (DC->isFileContext()) { // This implies that it has to be an operator or function. - if (D.getKind() == Declarator::DK_Constructor || - D.getKind() == Declarator::DK_Destructor || - D.getKind() == Declarator::DK_Conversion) { + if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || + D.getName().getKind() == UnqualifiedId::IK_DestructorName || + D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) { Diag(Loc, diag::err_introducing_special_friend) << - (D.getKind() == Declarator::DK_Constructor ? 0 : - D.getKind() == Declarator::DK_Destructor ? 1 : 2); + (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : + D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); return DeclPtrTy(); } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f7a22d2eb0..7182992d42 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4043,8 +4043,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // argument list into our AST format. bool HasExplicitTemplateArgs = false; llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - if (D.getKind() == Declarator::DK_TemplateId) { - TemplateIdAnnotation *TemplateId = D.getTemplateId(); + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->getTemplateArgIsType(), @@ -4147,7 +4147,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // // C++98 has the same restriction, just worded differently. FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate(); - if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl && + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl && D.getCXXScopeSpec().isSet() && !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) Diag(D.getIdentifierLoc(), diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d2652c9864..94b74fbcd1 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -870,6 +870,11 @@ QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) { QualType QT = QualType::getFromOpaquePtr(Ty); + if (QT.isNull()) { + if (DInfo) *DInfo = 0; + return QualType(); + } + DeclaratorInfo *DI = 0; if (LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) { QT = LIT->getType(); @@ -893,20 +898,19 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // have a type. QualType T; - switch (D.getKind()) { - case Declarator::DK_Abstract: - case Declarator::DK_Normal: - case Declarator::DK_Operator: - case Declarator::DK_TemplateId: + switch (D.getName().getKind()) { + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_TemplateId: T = ConvertDeclSpecToType(D, *this); if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned()) *OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep()); break; - case Declarator::DK_Constructor: - case Declarator::DK_Destructor: - case Declarator::DK_Conversion: + case UnqualifiedId::IK_ConstructorName: + case UnqualifiedId::IK_DestructorName: + case UnqualifiedId::IK_ConversionFunctionId: // Constructors and destructors don't have return types. Use // "void" instead. Conversion operators will check their return // types separately. |