diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2010-12-09 23:11:32 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2010-12-09 23:11:32 +0000 |
commit | bfe5788a00b44cf77cb2bd33e1fa0c35eb02e3f9 (patch) | |
tree | 2fe602075a48360a7c7424fd536dc196c7070613 /lib/Sema/SemaDecl.cpp | |
parent | 7344921b22bebec4f86eb8eb865150b2978b5d2e (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.cpp | 1084 |
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, |