aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2010-12-09 23:11:32 +0000
committerFariborz Jahanian <fjahanian@apple.com>2010-12-09 23:11:32 +0000
commitbfe5788a00b44cf77cb2bd33e1fa0c35eb02e3f9 (patch)
tree2fe602075a48360a7c7424fd536dc196c7070613 /lib/Sema/SemaDecl.cpp
parent7344921b22bebec4f86eb8eb865150b2978b5d2e (diff)
Refactored/cleanedup ActOnFunctionDeclarator
and ActOnVariableDeclarator No functionality change. // rdar://8751949 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121427 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp1084
1 files changed, 563 insertions, 521 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2924c7b8d6..faf3b7382d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2861,82 +2861,93 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
D.setInvalidType();
}
}
- if (DC->isRecord() && !CurContext->isRecord()) {
- // This is an out-of-line definition of a static data member.
+
+ bool isExplicitSpecialization;
+ VarDecl *NewVD;
+ if (!getLangOptions().CPlusPlus) {
+ NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+ II, R, TInfo, SC, SCAsWritten);
+
+ if (D.isInvalidType())
+ NewVD->setInvalidDecl();
+ } else {
+ if (DC->isRecord() && !CurContext->isRecord()) {
+ // This is an out-of-line definition of a static data member.
+ if (SC == SC_Static) {
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_static_out_of_line)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ } else if (SC == SC_None)
+ SC = SC_Static;
+ }
if (SC == SC_Static) {
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
- diag::err_static_out_of_line)
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
- } else if (SC == SC_None)
- SC = SC_Static;
- }
- if (SC == SC_Static) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
- if (RD->isLocalClass())
- Diag(D.getIdentifierLoc(),
- diag::err_static_data_member_not_allowed_in_local_class)
- << Name << RD->getDeclName();
-
- // C++ [class.union]p1: If a union contains a static data member,
- // the program is ill-formed.
- //
- // We also disallow static data members in anonymous structs.
- if (CurContext->isRecord() && (RD->isUnion() || !RD->getDeclName()))
- Diag(D.getIdentifierLoc(),
- diag::err_static_data_member_not_allowed_in_union_or_anon_struct)
- << Name << RD->isUnion();
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ if (RD->isLocalClass())
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_local_class)
+ << Name << RD->getDeclName();
+
+ // C++ [class.union]p1: If a union contains a static data member,
+ // the program is ill-formed.
+ //
+ // We also disallow static data members in anonymous structs.
+ if (CurContext->isRecord() && (RD->isUnion() || !RD->getDeclName()))
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_union_or_anon_struct)
+ << Name << RD->isUnion();
+ }
}
- }
- // Match up the template parameter lists with the scope specifier, then
- // determine whether we have a template or a template specialization.
- bool isExplicitSpecialization = false;
- unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
- bool Invalid = false;
- if (TemplateParameterList *TemplateParams
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
+ isExplicitSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
+ bool Invalid = false;
+ if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
- D.getDeclSpec().getSourceRange().getBegin(),
+ D.getDeclSpec().getSourceRange().getBegin(),
D.getCXXScopeSpec(),
TemplateParamLists.get(),
TemplateParamLists.size(),
/*never a friend*/ false,
isExplicitSpecialization,
Invalid)) {
- // All but one template parameter lists have been matching.
- --NumMatchedTemplateParamLists;
-
- if (TemplateParams->size() > 0) {
- // There is no such thing as a variable template.
- Diag(D.getIdentifierLoc(), diag::err_template_variable)
- << II
- << SourceRange(TemplateParams->getTemplateLoc(),
- TemplateParams->getRAngleLoc());
- return 0;
- } else {
- // There is an extraneous 'template<>' for this variable. Complain
- // about it, but allow the declaration of the variable.
- Diag(TemplateParams->getTemplateLoc(),
- diag::err_template_variable_noparams)
- << II
- << SourceRange(TemplateParams->getTemplateLoc(),
- TemplateParams->getRAngleLoc());
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
+ if (TemplateParams->size() > 0) {
+ // There is no such thing as a variable template.
+ Diag(D.getIdentifierLoc(), diag::err_template_variable)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+ return 0;
+ } else {
+ // There is an extraneous 'template<>' for this variable. Complain
+ // about it, but allow the declaration of the variable.
+ Diag(TemplateParams->getTemplateLoc(),
+ diag::err_template_variable_noparams)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
- isExplicitSpecialization = true;
+ isExplicitSpecialization = true;
+ }
}
- }
- VarDecl *NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
- II, R, TInfo, SC, SCAsWritten);
+ NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+ II, R, TInfo, SC, SCAsWritten);
- if (D.isInvalidType() || Invalid)
- NewVD->setInvalidDecl();
+ if (D.isInvalidType() || Invalid)
+ NewVD->setInvalidDecl();
- SetNestedNameSpecifier(NewVD, D);
+ SetNestedNameSpecifier(NewVD, D);
- if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
- NewVD->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
- TemplateParamLists.release());
+ if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
+ NewVD->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ TemplateParamLists.release());
+ }
}
if (D.getDeclSpec().isThreadSpecified()) {
@@ -2972,33 +2983,57 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// declaration has linkage).
FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage());
- // Merge the decl with the existing one if appropriate.
- if (!Previous.empty()) {
- if (Previous.isSingleResult() &&
- isa<FieldDecl>(Previous.getFoundDecl()) &&
- D.getCXXScopeSpec().isSet()) {
- // The user tried to define a non-static data member
- // out-of-line (C++ [dcl.meaning]p1).
- Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
+ if (!getLangOptions().CPlusPlus)
+ CheckVariableDeclaration(NewVD, Previous, Redeclaration);
+ else {
+ // Merge the decl with the existing one if appropriate.
+ if (!Previous.empty()) {
+ if (Previous.isSingleResult() &&
+ isa<FieldDecl>(Previous.getFoundDecl()) &&
+ D.getCXXScopeSpec().isSet()) {
+ // The user tried to define a non-static data member
+ // out-of-line (C++ [dcl.meaning]p1).
+ Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
+ << D.getCXXScopeSpec().getRange();
+ Previous.clear();
+ NewVD->setInvalidDecl();
+ }
+ } else if (D.getCXXScopeSpec().isSet()) {
+ // No previous declaration in the qualifying scope.
+ Diag(D.getIdentifierLoc(), diag::err_no_member)
+ << Name << computeDeclContext(D.getCXXScopeSpec(), true)
<< D.getCXXScopeSpec().getRange();
- Previous.clear();
NewVD->setInvalidDecl();
}
- } else if (D.getCXXScopeSpec().isSet()) {
- // No previous declaration in the qualifying scope.
- Diag(D.getIdentifierLoc(), diag::err_no_member)
- << Name << computeDeclContext(D.getCXXScopeSpec(), true)
- << D.getCXXScopeSpec().getRange();
- NewVD->setInvalidDecl();
- }
-
- CheckVariableDeclaration(NewVD, Previous, Redeclaration);
- // This is an explicit specialization of a static data member. Check it.
- if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
- CheckMemberSpecialization(NewVD, Previous))
- NewVD->setInvalidDecl();
+ CheckVariableDeclaration(NewVD, Previous, Redeclaration);
+ // This is an explicit specialization of a static data member. Check it.
+ if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+ CheckMemberSpecialization(NewVD, Previous))
+ NewVD->setInvalidDecl();
+ // For variables declared as __block which require copy construction,
+ // must capture copy initialization expression here.
+ if (!NewVD->isInvalidDecl() && NewVD->hasAttr<BlocksAttr>()) {
+ QualType T = NewVD->getType();
+ if (!T->isDependentType() && !T->isReferenceType() &&
+ T->getAs<RecordType>() && !T->isUnionType()) {
+ Expr *E = new (Context) DeclRefExpr(NewVD, T,
+ VK_LValue, SourceLocation());
+ ExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeBlock(NewVD->getLocation(),
+ T, false),
+ SourceLocation(),
+ Owned(E));
+ if (!Res.isInvalid()) {
+ Res = MaybeCreateExprWithCleanups(Res);
+ Expr *Init = Res.takeAs<Expr>();
+ Context.setBlockVarCopyInits(NewVD, Init);
+ }
+ }
+ }
+ }
+
// attributes declared post-definition are currently ignored
// FIXME: This should be handled in attribute merging, not
// here.
@@ -3021,28 +3056,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// member, set the visibility of this variable.
if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
AddPushedVisibilityAttribute(NewVD);
-
-
- // For variables declared as __block which require copy construction,
- // must capture copy initialization expression here.
- if (getLangOptions().CPlusPlus && NewVD->hasAttr<BlocksAttr>()) {
- QualType T = NewVD->getType();
- if (!T->isDependentType() && !T->isReferenceType() &&
- T->getAs<RecordType>() && !T->isUnionType()) {
- Expr *E = new (Context) DeclRefExpr(NewVD, T,
- VK_LValue, SourceLocation());
- ExprResult Res = PerformCopyInitialization(
- InitializedEntity::InitializeBlock(NewVD->getLocation(),
- T, false),
- SourceLocation(),
- Owned(E));
- if (!Res.isInvalid()) {
- Res = MaybeCreateExprWithCleanups(Res);
- Expr *Init = Res.takeAs<Expr>();
- Context.setBlockVarCopyInits(NewVD, Init);
- }
- }
- }
+
MarkUnusedFileScopedDecl(NewVD);
return NewVD;
@@ -3417,160 +3431,175 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- bool isFriend = D.getDeclSpec().isFriendSpecified();
- bool isInline = D.getDeclSpec().isInlineSpecified();
- bool isVirtual = D.getDeclSpec().isVirtualSpecified();
- bool isExplicit = D.getDeclSpec().isExplicitSpecified();
-
- DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
- FunctionDecl::StorageClass SCAsWritten
- = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
-
- // Check that the return type is not an abstract class type.
- // For record types, this is done by the AbstractClassUsageDiagnoser once
- // the class has been completely parsed.
- if (!DC->isRecord() &&
- RequireNonAbstractType(D.getIdentifierLoc(),
- R->getAs<FunctionType>()->getResultType(),
- diag::err_abstract_type_in_decl,
- AbstractReturnType))
- D.setInvalidType();
-
// Do not allow returning a objc interface by-value.
if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) {
Diag(D.getIdentifierLoc(),
diag::err_object_cannot_be_passed_returned_by_value) << 0
- << R->getAs<FunctionType>()->getResultType();
+ << R->getAs<FunctionType>()->getResultType();
D.setInvalidType();
}
-
- bool isVirtualOkay = false;
+
FunctionDecl *NewFD;
-
- if (isFriend) {
- // C++ [class.friend]p5
- // A function can be defined in a friend declaration of a
- // class . . . . Such a function is implicitly inline.
- isInline |= IsFunctionDefinition;
- }
-
- if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
- // This is a C++ constructor declaration.
- assert(DC->isRecord() &&
- "Constructors can only be declared in a member context");
-
- R = CheckConstructorDeclarator(D, R, SC);
-
- // Create the new declaration
- NewFD = CXXConstructorDecl::Create(Context,
- cast<CXXRecordDecl>(DC),
- NameInfo, R, TInfo,
- isExplicit, isInline,
- /*isImplicitlyDeclared=*/false);
- } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
- // This is a C++ destructor declaration.
- if (DC->isRecord()) {
- R = CheckDestructorDeclarator(D, R, SC);
-
- NewFD = CXXDestructorDecl::Create(Context,
- cast<CXXRecordDecl>(DC),
- NameInfo, R, TInfo,
- isInline,
- /*isImplicitlyDeclared=*/false);
- isVirtualOkay = true;
- } else {
- Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
-
- // Create a FunctionDecl to satisfy the function definition parsing
- // code path.
- NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
- Name, R, TInfo, SC, SCAsWritten, isInline,
- /*hasPrototype=*/true);
- D.setInvalidType();
- }
- } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
- if (!DC->isRecord()) {
- Diag(D.getIdentifierLoc(),
- diag::err_conv_function_not_member);
- return 0;
- }
-
- CheckConversionDeclarator(D, R, SC);
- NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
- NameInfo, R, TInfo,
- isInline, isExplicit);
-
- isVirtualOkay = true;
- } else if (DC->isRecord()) {
- // If the of the function is the same as the name of the record, then this
- // must be an invalid constructor that has a return type.
- // (The parser checks for a return type and makes the declarator a
- // constructor if it has no return type).
- // must have an invalid constructor that has a return type
- if (Name.getAsIdentifierInfo() &&
- Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
- Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
- << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
- << SourceRange(D.getIdentifierLoc());
- return 0;
- }
-
- bool isStatic = SC == SC_Static;
-
- // [class.free]p1:
- // Any allocation function for a class T is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_New ||
- Name.getCXXOverloadedOperator() == OO_Array_New)
- isStatic = true;
-
- // [class.free]p6 Any deallocation function for a class X is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_Delete ||
- Name.getCXXOverloadedOperator() == OO_Array_Delete)
- isStatic = true;
-
- // This is a C++ method declaration.
- NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
- NameInfo, R, TInfo,
- isStatic, SCAsWritten, isInline);
-
- isVirtualOkay = !isStatic;
- } else {
+ bool isFriend, isVirtual, isExplicit, isVirtualOkay;
+ bool isInline = D.getDeclSpec().isInlineSpecified();
+ DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
+ FunctionDecl::StorageClass SCAsWritten
+ = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
+ FunctionTemplateDecl *FunctionTemplate;
+ bool isExplicitSpecialization, isFunctionTemplateSpecialization;
+ unsigned NumMatchedTemplateParamLists;
+
+ if (!getLangOptions().CPlusPlus) {
// Determine whether the function was written with a
// prototype. This true when:
- // - we're in C++ (where every function has a prototype),
// - there is a prototype in the declarator, or
// - the type R of the function is some kind of typedef or other reference
// to a type name (which eventually refers to a function type).
bool HasPrototype =
- getLangOptions().CPlusPlus ||
- (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) ||
- (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
-
+ (D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) ||
+ (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
+
NewFD = FunctionDecl::Create(Context, DC,
NameInfo, R, TInfo, SC, SCAsWritten, isInline,
HasPrototype);
- }
+ if (D.isInvalidType())
+ NewFD->setInvalidDecl();
+
+ // Set the lexical context.
+ NewFD->setLexicalDeclContext(CurContext);
+ // Filter out previous declarations that don't match the scope.
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+ } else {
+ isFriend = D.getDeclSpec().isFriendSpecified();
+ isVirtual = D.getDeclSpec().isVirtualSpecified();
+ isExplicit = D.getDeclSpec().isExplicitSpecified();
+ isVirtualOkay = false;
+
+ // Check that the return type is not an abstract class type.
+ // For record types, this is done by the AbstractClassUsageDiagnoser once
+ // the class has been completely parsed.
+ if (!DC->isRecord() &&
+ RequireNonAbstractType(D.getIdentifierLoc(),
+ R->getAs<FunctionType>()->getResultType(),
+ diag::err_abstract_type_in_decl,
+ AbstractReturnType))
+ D.setInvalidType();
- if (D.isInvalidType())
- NewFD->setInvalidDecl();
- SetNestedNameSpecifier(NewFD, D);
+ if (isFriend) {
+ // C++ [class.friend]p5
+ // A function can be defined in a friend declaration of a
+ // class . . . . Such a function is implicitly inline.
+ isInline |= IsFunctionDefinition;
+ }
+
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
+ // This is a C++ constructor declaration.
+ assert(DC->isRecord() &&
+ "Constructors can only be declared in a member context");
+
+ R = CheckConstructorDeclarator(D, R, SC);
+
+ // Create the new declaration
+ NewFD = CXXConstructorDecl::Create(Context,
+ cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isExplicit, isInline,
+ /*isImplicitlyDeclared=*/false);
+ } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
+ // This is a C++ destructor declaration.
+ if (DC->isRecord()) {
+ R = CheckDestructorDeclarator(D, R, SC);
+
+ NewFD = CXXDestructorDecl::Create(Context,
+ cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isInline,
+ /*isImplicitlyDeclared=*/false);
+ isVirtualOkay = true;
+ } else {
+ Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
- // Set the lexical context. If the declarator has a C++
- // scope specifier, or is the object of a friend declaration, the
- // lexical context will be different from the semantic context.
- NewFD->setLexicalDeclContext(CurContext);
+ // Create a FunctionDecl to satisfy the function definition parsing
+ // code path.
+ NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
+ Name, R, TInfo, SC, SCAsWritten, isInline,
+ /*hasPrototype=*/true);
+ D.setInvalidType();
+ }
+ } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ if (!DC->isRecord()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_conv_function_not_member);
+ return 0;
+ }
- // Match up the template parameter lists with the scope specifier, then
- // determine whether we have a template or a template specialization.
- FunctionTemplateDecl *FunctionTemplate = 0;
- bool isExplicitSpecialization = false;
- bool isFunctionTemplateSpecialization = false;
- unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
- bool Invalid = false;
- if (TemplateParameterList *TemplateParams
+ CheckConversionDeclarator(D, R, SC);
+ NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isInline, isExplicit);
+
+ isVirtualOkay = true;
+ } else if (DC->isRecord()) {
+ // If the of the function is the same as the name of the record, then this
+ // must be an invalid constructor that has a return type.
+ // (The parser checks for a return type and makes the declarator a
+ // constructor if it has no return type).
+ // must have an invalid constructor that has a return type
+ if (Name.getAsIdentifierInfo() &&
+ Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
+ Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
+ << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
+ << SourceRange(D.getIdentifierLoc());
+ return 0;
+ }
+
+ bool isStatic = SC == SC_Static;
+
+ // [class.free]p1:
+ // Any allocation function for a class T is a static member
+ // (even if not explicitly declared static).
+ if (Name.getCXXOverloadedOperator() == OO_New ||
+ Name.getCXXOverloadedOperator() == OO_Array_New)
+ isStatic = true;
+
+ // [class.free]p6 Any deallocation function for a class X is a static member
+ // (even if not explicitly declared static).
+ if (Name.getCXXOverloadedOperator() == OO_Delete ||
+ Name.getCXXOverloadedOperator() == OO_Array_Delete)
+ isStatic = true;
+
+ // This is a C++ method declaration.
+ NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
+ NameInfo, R, TInfo,
+ isStatic, SCAsWritten, isInline);
+
+ isVirtualOkay = !isStatic;
+ } else {
+ // Determine whether the function was written with a
+ // prototype. This true when:
+ // - we're in C++ (where every function has a prototype),
+ NewFD = FunctionDecl::Create(Context, DC,
+ NameInfo, R, TInfo, SC, SCAsWritten, isInline,
+ true/*HasPrototype*/);
+ }
+ SetNestedNameSpecifier(NewFD, D);
+ FunctionTemplate = 0;
+ isExplicitSpecialization = false;
+ isFunctionTemplateSpecialization = false;
+ NumMatchedTemplateParamLists = TemplateParamLists.size();
+ if (D.isInvalidType())
+ NewFD->setInvalidDecl();
+
+ // Set the lexical context. If the declarator has a C++
+ // scope specifier, or is the object of a friend declaration, the
+ // lexical context will be different from the semantic context.
+ NewFD->setLexicalDeclContext(CurContext);
+
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
+ bool Invalid = false;
+ if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
D.getCXXScopeSpec(),
@@ -3579,139 +3608,140 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isFriend,
isExplicitSpecialization,
Invalid)) {
- // All but one template parameter lists have been matching.
- --NumMatchedTemplateParamLists;
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
- if (TemplateParams->size() > 0) {
- // This is a function template
+ if (TemplateParams->size() > 0) {
+ // This is a function template
- // Check that we can declare a template here.
- if (CheckTemplateDeclScope(S, TemplateParams))
- return 0;
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return 0;
- FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
+ FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
NewFD->getLocation(),
Name, TemplateParams,
NewFD);
- FunctionTemplate->setLexicalDeclContext(CurContext);
- NewFD->setDescribedFunctionTemplate(FunctionTemplate);
- } else {
- // This is a function template specialization.
- isFunctionTemplateSpecialization = true;
-
- // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
- if (isFriend && isFunctionTemplateSpecialization) {
- // We want to remove the "template<>", found here.
- SourceRange RemoveRange = TemplateParams->getSourceRange();
-
- // If we remove the template<> and the name is not a
- // template-id, we're actually silently creating a problem:
- // the friend declaration will refer to an untemplated decl,
- // and clearly the user wants a template specialization. So
- // we need to insert '<>' after the name.
- SourceLocation InsertLoc;
- if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
- InsertLoc = D.getName().getSourceRange().getEnd();
- InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+ FunctionTemplate->setLexicalDeclContext(CurContext);
+ NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+ } else {
+ // This is a function template specialization.
+ isFunctionTemplateSpecialization = true;
+
+ // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
+ if (isFriend && isFunctionTemplateSpecialization) {
+ // We want to remove the "template<>", found here.
+ SourceRange RemoveRange = TemplateParams->getSourceRange();
+
+ // If we remove the template<> and the name is not a
+ // template-id, we're actually silently creating a problem:
+ // the friend declaration will refer to an untemplated decl,
+ // and clearly the user wants a template specialization. So
+ // we need to insert '<>' after the name.
+ SourceLocation InsertLoc;
+ if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ InsertLoc = D.getName().getSourceRange().getEnd();
+ InsertLoc = PP.getLocForEndOfToken(InsertLoc);
+ }
+
+ Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
+ << Name << RemoveRange
+ << FixItHint::CreateRemoval(RemoveRange)
+ << FixItHint::CreateInsertion(InsertLoc, "<>");
+ }
+ }
}
- Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
- << Name << RemoveRange
- << FixItHint::CreateRemoval(RemoveRange)
- << FixItHint::CreateInsertion(InsertLoc, "<>");
- }
+ if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
+ NewFD->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ TemplateParamLists.release());
}
- }
-
- if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
- NewFD->setTemplateParameterListsInfo(Context,
- NumMatchedTemplateParamLists,
- TemplateParamLists.release());
- }
- if (Invalid) {
- NewFD->setInvalidDecl();
- if (FunctionTemplate)
- FunctionTemplate->setInvalidDecl();
- }
+ if (Invalid) {
+ NewFD->setInvalidDecl();
+ if (FunctionTemplate)
+ FunctionTemplate->setInvalidDecl();
+ }
- // C++ [dcl.fct.spec]p5:
- // The virtual specifier shall only be used in declarations of
- // nonstatic class member functions that appear within a
- // member-specification of a class declaration; see 10.3.
- //
- if (isVirtual && !NewFD->isInvalidDecl()) {
- if (!isVirtualOkay) {
- Diag(D.getDeclSpec().getVirtualSpecLoc(),
- diag::err_virtual_non_function);
- } else if (!CurContext->isRecord()) {
- // 'virtual' was specified outside of the class.
- Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_out_of_class)
- << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
- } else {
- // Okay: Add virtual to the method.
- NewFD->setVirtualAsWritten(true);
+ // C++ [dcl.fct.spec]p5:
+ // The virtual specifier shall only be used in declarations of
+ // nonstatic class member functions that appear within a
+ // member-specification of a class declaration; see 10.3.
+ //
+ if (isVirtual && !NewFD->isInvalidDecl()) {
+ if (!isVirtualOkay) {
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ diag::err_virtual_non_function);
+ } else if (!CurContext->isRecord()) {
+ // 'virtual' was specified outside of the class.
+ Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_out_of_class)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc());
+ } else {
+ // Okay: Add virtual to the method.
+ NewFD->setVirtualAsWritten(true);
+ }
}
- }
- // C++ [dcl.fct.spec]p3:
- // The inline specifier shall not appear on a block scope function declaration.
- if (isInline && !NewFD->isInvalidDecl() && getLangOptions().CPlusPlus) {
- if (CurContext->isFunctionOrMethod()) {
- // 'inline' is not allowed on block scope function declaration.
- Diag(D.getDeclSpec().getInlineSpecLoc(),
- diag::err_inline_declaration_block_scope) << Name
- << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+ // C++ [dcl.fct.spec]p3:
+ // The inline specifier shall not appear on a block scope function declaration.
+ if (isInline && !NewFD->isInvalidDecl()) {
+ if (CurContext->isFunctionOrMethod()) {
+ // 'inline' is not allowed on block scope function declaration.
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_inline_declaration_block_scope) << Name
+ << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+ }
}
- }
- // C++ [dcl.fct.spec]p6:
- // The explicit specifier shall be used only in the declaration of a
- // constructor or conversion function within its class definition; see 12.3.1
- // and 12.3.2.
- if (isExplicit && !NewFD->isInvalidDecl()) {
- if (!CurContext->isRecord()) {
- // 'explicit' was specified outside of the class.
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
- diag::err_explicit_out_of_class)
- << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
- } else if (!isa<CXXConstructorDecl>(NewFD) &&
- !isa<CXXConversionDecl>(NewFD)) {
- // 'explicit' was specified on a function that wasn't a constructor
- // or conversion function.
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
- diag::err_explicit_non_ctor_or_conv_function)
- << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
- }
- }
-
- // Filter out previous declarations that don't match the scope.
- FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
-
- if (isFriend) {
- // For now, claim that the objects have no previous declaration.
- if (FunctionTemplate) {
- FunctionTemplate->setObjectOfFriendDecl(false);
- FunctionTemplate->setAccess(AS_public);
+ // C++ [dcl.fct.spec]p6:
+ // The explicit specifier shall be used only in the declaration of a
+ // constructor or conversion function within its class definition; see 12.3.1
+ // and 12.3.2.
+ if (isExplicit && !NewFD->isInvalidDecl()) {
+ if (!CurContext->isRecord()) {
+ // 'explicit' was specified outside of the class.
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_out_of_class)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
+ } else if (!isa<CXXConstructorDecl>(NewFD) &&
+ !isa<CXXConversionDecl>(NewFD)) {
+ // 'explicit' was specified on a function that wasn't a constructor
+ // or conversion function.
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_non_ctor_or_conv_function)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc());
+ }
+ }
+
+ // Filter out previous declarations that don't match the scope.
+ FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+
+ if (isFriend) {
+ // For now, claim that the objects have no previous declaration.
+ if (FunctionTemplate) {
+ FunctionTemplate->setObjectOfFriendDecl(false);
+ FunctionTemplate->setAccess(AS_public);
+ }
+ NewFD->setObjectOfFriendDecl(false);
+ NewFD->setAccess(AS_public);
}
- NewFD->setObjectOfFriendDecl(false);
- NewFD->setAccess(AS_public);
- }
- if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
- !CurContext->isRecord()) {
- // C++ [class.static]p1:
- // A data or function member of a class may be declared static
- // in a class definition, in which case it is a static member of
- // the class.
+ if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
+ !CurContext->isRecord()) {
+ // C++ [class.static]p1:
+ // A data or function member of a class may be declared static
+ // in a class definition, in which case it is a static member of
+ // the class.
- // Complain about the 'static' specifier if it's on an out-of-line
- // member function definition.
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
- diag::err_static_out_of_line)
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ // Complain about the 'static' specifier if it's on an out-of-line
+ // member function definition.
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::err_static_out_of_line)
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+ }
}
-
+
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
@@ -3778,180 +3808,192 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Finally, we know we have the right number of parameters, install them.
NewFD->setParams(Params.data(), Params.size());
- // If the declarator is a template-id, translate the parser's template
- // argument list into our AST format.
- bool HasExplicitTemplateArgs = false;
- TemplateArgumentListInfo TemplateArgs;
- if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
- TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
- TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
- TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
- ASTTemplateArgsPtr TemplateArgsPtr(*this,
- TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- translateTemplateArguments(TemplateArgsPtr,
- TemplateArgs);
- TemplateArgsPtr.release();
+ bool OverloadableAttrRequired=false; // FIXME: HACK!
+ if (!getLangOptions().CPlusPlus) {
+ // Perform semantic checking on the function declaration.
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,