aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/DeclSpec.cpp25
-rw-r--r--lib/Parse/ParseDecl.cpp113
-rw-r--r--lib/Parse/ParseDeclCXX.cpp1
-rw-r--r--lib/Parse/ParseExprCXX.cpp413
-rw-r--r--lib/Sema/SemaDecl.cpp71
-rw-r--r--lib/Sema/SemaDeclCXX.cpp14
-rw-r--r--lib/Sema/SemaTemplate.cpp6
-rw-r--r--lib/Sema/SemaType.cpp20
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.