diff options
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 587 |
1 files changed, 369 insertions, 218 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 520d7de..14d2377 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "SemaInit.h" #include "Lookup.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" @@ -229,7 +230,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { LookupName(R, S, false); R.suppressDiagnostics(); if (R.getResultKind() == LookupResult::Found) - if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsSingleDecl(Context))) { + if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { switch (TD->getTagKind()) { case TagDecl::TK_struct: return DeclSpec::TST_struct; case TagDecl::TK_union: return DeclSpec::TST_union; @@ -379,7 +380,9 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // scope. if ((isa<FunctionTemplateDecl>(D) && cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->isOutOfLine()) || - (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isOutOfLine()) || + (isa<FunctionDecl>(D) && + (cast<FunctionDecl>(D)->isFunctionTemplateSpecialization() || + cast<FunctionDecl>(D)->isOutOfLine())) || (isa<VarDecl>(D) && cast<VarDecl>(D)->isOutOfLine())) return; @@ -588,7 +591,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, FunctionDecl *New = FunctionDecl::Create(Context, Context.getTranslationUnitDecl(), - Loc, II, R, /*DInfo=*/0, + Loc, II, R, /*TInfo=*/0, FunctionDecl::Extern, false, /*hasPrototype=*/true); New->setImplicit(); @@ -599,7 +602,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, llvm::SmallVector<ParmVarDecl*, 16> Params; for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, - FT->getArgType(i), /*DInfo=*/0, + FT->getArgType(i), /*TInfo=*/0, VarDecl::None, 0)); New->setParams(Context, Params.data(), Params.size()); } @@ -762,6 +765,24 @@ struct GNUCompatibleParamWarning { QualType PromotedType; }; + +/// getSpecialMember - get the special member enum for a method. +static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx, + const CXXMethodDecl *MD) { + if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { + if (Ctor->isDefaultConstructor()) + return Sema::CXXDefaultConstructor; + if (Ctor->isCopyConstructor(Ctx)) + return Sema::CXXCopyConstructor; + } + + if (isa<CXXDestructorDecl>(MD)) + return Sema::CXXDestructor; + + assert(MD->isCopyAssignment() && "Must have copy assignment operator"); + return Sema::CXXCopyAssignment; +} + /// MergeFunctionDecl - We just parsed a function 'New' from /// declarator D which has the same name and scope as a previous /// declaration 'Old'. Figure out how to resolve this situation, @@ -782,6 +803,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { else Old = dyn_cast<FunctionDecl>(OldD); if (!Old) { + if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) { + Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); + Diag(Shadow->getTargetDecl()->getLocation(), + diag::note_using_decl_target); + Diag(Shadow->getUsingDecl()->getLocation(), + diag::note_using_decl) << 0; + return true; + } + Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); Diag(OldD->getLocation(), diag::note_previous_definition); @@ -827,33 +857,45 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); - if (OldMethod && NewMethod && !NewMethod->getFriendObjectKind() && - NewMethod->getLexicalDeclContext()->isRecord()) { - // -- Member function declarations with the same name and the - // same parameter types cannot be overloaded if any of them - // is a static member function declaration. - if (OldMethod->isStatic() || NewMethod->isStatic()) { - Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); + if (OldMethod && NewMethod) { + if (!NewMethod->getFriendObjectKind() && + NewMethod->getLexicalDeclContext()->isRecord()) { + // -- Member function declarations with the same name and the + // same parameter types cannot be overloaded if any of them + // is a static member function declaration. + if (OldMethod->isStatic() || NewMethod->isStatic()) { + Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; + } + + // C++ [class.mem]p1: + // [...] A member shall not be declared twice in the + // member-specification, except that a nested class or member + // class template can be declared and then later defined. + unsigned NewDiag; + if (isa<CXXConstructorDecl>(OldMethod)) + NewDiag = diag::err_constructor_redeclared; + else if (isa<CXXDestructorDecl>(NewMethod)) + NewDiag = diag::err_destructor_redeclared; + else if (isa<CXXConversionDecl>(NewMethod)) + NewDiag = diag::err_conv_function_redeclared; + else + NewDiag = diag::err_member_redeclared; + + Diag(New->getLocation(), NewDiag); Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); - return true; + } else { + if (OldMethod->isImplicit()) { + Diag(NewMethod->getLocation(), + diag::err_definition_of_implicitly_declared_member) + << New << getSpecialMember(Context, OldMethod); + + Diag(OldMethod->getLocation(), + diag::note_previous_implicit_declaration); + return true; + } } - - // C++ [class.mem]p1: - // [...] A member shall not be declared twice in the - // member-specification, except that a nested class or member - // class template can be declared and then later defined. - unsigned NewDiag; - if (isa<CXXConstructorDecl>(OldMethod)) - NewDiag = diag::err_constructor_redeclared; - else if (isa<CXXDestructorDecl>(NewMethod)) - NewDiag = diag::err_destructor_redeclared; - else if (isa<CXXConversionDecl>(NewMethod)) - NewDiag = diag::err_conv_function_redeclared; - else - NewDiag = diag::err_member_redeclared; - - Diag(New->getLocation(), NewDiag); - Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); } // (C++98 8.3.5p3): @@ -894,7 +936,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { ParamType != ParamEnd; ++ParamType) { ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(), 0, - *ParamType, /*DInfo=*/0, + *ParamType, /*TInfo=*/0, VarDecl::None, 0); Param->setImplicit(); Params.push_back(Param); @@ -1057,10 +1099,11 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { if (getLangOptions().CPlusPlus) { if (Context.hasSameType(New->getType(), Old->getType())) MergedT = New->getType(); - // C++ [basic.types]p7: - // [...] The declared type of an array object might be an array of - // unknown size and therefore be incomplete at one point in a - // translation unit and complete later on; [...] + // C++ [basic.link]p10: + // [...] the types specified by all declarations referring to a given + // object or function shall be identical, except that declarations for an + // array object can specify array types that differ by the presence or + // absence of a major array bound (8.3.4). else if (Old->getType()->isIncompleteArrayType() && New->getType()->isArrayType()) { CanQual<ArrayType> OldArray @@ -1069,6 +1112,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); if (OldArray->getElementType() == NewArray->getElementType()) MergedT = New->getType(); + } else if (Old->getType()->isArrayType() && + New->getType()->isIncompleteArrayType()) { + CanQual<ArrayType> OldArray + = Context.getCanonicalType(Old->getType())->getAs<ArrayType>(); + CanQual<ArrayType> NewArray + = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); + if (OldArray->getElementType() == NewArray->getElementType()) + MergedT = Old->getType(); } } else { MergedT = Context.mergeTypes(New->getType(), Old->getType()); @@ -1202,6 +1253,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { HasFakeEdge = true; continue; } + if (isa<AsmStmt>(S)) { + HasFakeEdge = true; + HasLiveReturn = true; + continue; + } bool NoReturnEdge = false; if (CallExpr *C = dyn_cast<CallExpr>(S)) { Expr *CEE = C->getCallee()->IgnoreParenCasts(); @@ -1209,11 +1265,10 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { NoReturnEdge = true; HasFakeEdge = true; } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (FD->hasAttr<NoReturnAttr>()) { - NoReturnEdge = true; - HasFakeEdge = true; - } + ValueDecl *VD = DRE->getDecl(); + if (VD->hasAttr<NoReturnAttr>()) { + NoReturnEdge = true; + HasFakeEdge = true; } } } @@ -1648,9 +1703,9 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Mock up a declarator. Declarator Dc(DS, Declarator::TypeNameContext); - DeclaratorInfo *DInfo = 0; - GetTypeForDeclarator(Dc, S, &DInfo); - assert(DInfo && "couldn't build declarator info for anonymous struct/union"); + TypeSourceInfo *TInfo = 0; + GetTypeForDeclarator(Dc, S, &TInfo); + assert(TInfo && "couldn't build declarator info for anonymous struct/union"); // Create a declaration for this anonymous struct/union. NamedDecl *Anon = 0; @@ -1658,7 +1713,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), - DInfo, + TInfo, /*BitWidth=*/0, /*Mutable=*/false); Anon->setAccess(AS_public); if (getLangOptions().CPlusPlus) @@ -1685,7 +1740,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Anon = VarDecl::Create(Context, Owner, Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), - DInfo, + TInfo, SC); } Anon->setImplicit(); @@ -1765,13 +1820,8 @@ DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { case UnqualifiedId::IK_TemplateId: { TemplateName TName - = TemplateName::getFromVoidPointer(Name.TemplateId->Template); - if (TemplateDecl *Template = TName.getAsTemplateDecl()) - return Template->getDeclName(); - if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl()) - return Ovl->getDeclName(); - - return DeclarationName(); + = TemplateName::getFromVoidPointer(Name.TemplateId->Template); + return Context.getNameForTemplate(TName); } } @@ -1851,8 +1901,8 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, DeclContext *DC; NamedDecl *New; - DeclaratorInfo *DInfo = 0; - QualType R = GetTypeForDeclarator(D, S, &DInfo); + TypeSourceInfo *TInfo = 0; + QualType R = GetTypeForDeclarator(D, S, &TInfo); LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, ForRedeclaration); @@ -1982,13 +2032,13 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, return DeclPtrTy(); } - New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, Previous, Redeclaration); + New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration); } else if (R->isFunctionType()) { - New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, Previous, + New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), IsFunctionDefinition, Redeclaration); } else { - New = ActOnVariableDeclarator(S, D, DC, R, DInfo, Previous, + New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), Redeclaration); } @@ -1998,9 +2048,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. - if (Name && !(Redeclaration && New->isInvalidDecl()) && - !(isa<FunctionDecl>(New) && - cast<FunctionDecl>(New)->isFunctionTemplateSpecialization())) + if (Name && !(Redeclaration && New->isInvalidDecl())) PushOnScopeChains(New, S); return DeclPtrTy::make(New); @@ -2104,7 +2152,7 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, DeclaratorInfo *DInfo, + QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { @@ -2125,7 +2173,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); - TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, DInfo); + TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo); if (!NewTD) return 0; // Handle attributes prior to checking for duplicates in MergeVarDecl @@ -2151,7 +2199,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative); if (!FixedTy.isNull()) { Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); - NewTD->setTypeDeclaratorInfo(Context.getTrivialDeclaratorInfo(FixedTy)); + NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); } else { if (SizeIsNegative) Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); @@ -2244,7 +2292,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, NamedDecl* Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, DeclaratorInfo *DInfo, + QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &Redeclaration) { @@ -2302,7 +2350,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << CodeModificationHint::CreateRemoval( - SourceRange(D.getDeclSpec().getStorageClassSpecLoc())); + D.getDeclSpec().getStorageClassSpecLoc()); } else if (SC == VarDecl::None) SC = VarDecl::Static; } @@ -2346,7 +2394,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, } NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), - II, R, DInfo, SC); + II, R, TInfo, SC); if (D.isInvalidType()) NewVD->setInvalidDecl(); @@ -2449,12 +2497,6 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, return NewVD->setInvalidDecl(); } - // The variable can not have an abstract class type. - if (RequireNonAbstractType(NewVD->getLocation(), T, - diag::err_abstract_type_in_decl, - AbstractVariableType)) - return NewVD->setInvalidDecl(); - // Emit an error if an address space was applied to decl with local storage. // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. @@ -2596,7 +2638,7 @@ void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { if (!CheckOverridingFunctionReturnType(MD, OldMD) && !CheckOverridingFunctionExceptionSpec(MD, OldMD) && !CheckOverridingFunctionAttributes(MD, OldMD)) - MD->addOverriddenMethod(OldMD); + MD->addOverriddenMethod(OldMD->getCanonicalDecl()); } } } @@ -2604,7 +2646,7 @@ void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { NamedDecl* Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, - QualType R, DeclaratorInfo *DInfo, + QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, bool &Redeclaration) { @@ -2686,7 +2728,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create the new declaration NewFD = CXXConstructorDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, DInfo, + D.getIdentifierLoc(), Name, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { @@ -2707,7 +2749,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Create a FunctionDecl to satisfy the function definition parsing // code path. NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(), - Name, R, DInfo, SC, isInline, + Name, R, TInfo, SC, isInline, /*hasPrototype=*/true); D.setInvalidType(); } @@ -2720,7 +2762,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, CheckConversionDeclarator(D, R, SC); NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, DInfo, + D.getIdentifierLoc(), Name, R, TInfo, isInline, isExplicit); isVirtualOkay = true; @@ -2754,7 +2796,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // This is a C++ method declaration. NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC), - D.getIdentifierLoc(), Name, R, DInfo, + D.getIdentifierLoc(), Name, R, TInfo, isStatic, isInline); isVirtualOkay = !isStatic; @@ -2772,7 +2814,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(), - Name, R, DInfo, SC, isInline, HasPrototype); + Name, R, TInfo, SC, isInline, HasPrototype); } if (D.isInvalidType()) @@ -2830,18 +2872,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // 'virtual' was specified outside of the class. Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_out_of_class) << CodeModificationHint::CreateRemoval( - SourceRange(D.getDeclSpec().getVirtualSpecLoc())); + D.getDeclSpec().getVirtualSpecLoc()); } else { // Okay: Add virtual to the method. - cast<CXXMethodDecl>(NewFD)->setVirtualAsWritten(true); CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC); - CurClass->setAggregate(false); - CurClass->setPOD(false); - CurClass->setEmpty(false); - CurClass->setPolymorphic(true); - CurClass->setHasTrivialConstructor(false); - CurClass->setHasTrivialCopyConstructor(false); - CurClass->setHasTrivialCopyAssignment(false); + CurClass->setMethodAsVirtual(NewFD); } } @@ -2865,9 +2900,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewFD->setAccess(AS_public); } - if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) - AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD); - if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) { // C++ [class.static]p1: @@ -2880,7 +2912,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << CodeModificationHint::CreateRemoval( - SourceRange(D.getDeclSpec().getStorageClassSpecLoc())); + D.getDeclSpec().getStorageClassSpecLoc()); } // Handle GNU asm-label extension (encoded as an attribute). @@ -2937,7 +2969,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, AE = FT->arg_type_end(); AI != AE; ++AI) { ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, SourceLocation(), 0, - *AI, /*DInfo=*/0, + *AI, /*TInfo=*/0, VarDecl::None, 0); Param->setImplicit(); Params.push_back(Param); @@ -2996,7 +3028,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Perform semantic checking on the function declaration. bool OverloadableAttrRequired = false; // FIXME: HACK! - CheckFunctionDeclaration(NewFD, Previous, isExplicitSpecialization, + CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, Redeclaration, /*FIXME:*/OverloadableAttrRequired); assert((NewFD->isInvalidDecl() || !Redeclaration || @@ -3118,7 +3150,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, /// an explicit specialization of the previous declaration. /// /// This sets NewFD->isInvalidDecl() to true if there was an error. -void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, +void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsExplicitSpecialization, bool &Redeclaration, @@ -3156,34 +3188,47 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, // there's no more work to do here; we'll just add the new // function to the scope. - if (!getLangOptions().CPlusPlus && - AllowOverloadingOfFunction(Previous, Context)) { - OverloadableAttrRequired = true; - - // Functions marked "overloadable" must have a prototype (that - // we can't get through declaration merging). - if (!NewFD->getType()->getAs<FunctionProtoType>()) { - Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype) - << NewFD; - Redeclaration = true; + NamedDecl *OldDecl = 0; + if (!AllowOverloadingOfFunction(Previous, Context)) { + Redeclaration = true; + OldDecl = Previous.getFoundDecl(); + } else { + if (!getLangOptions().CPlusPlus) { + OverloadableAttrRequired = true; + + // Functions marked "overloadable" must have a prototype (that + // we can't get through declaration merging). + if (!NewFD->getType()->getAs<FunctionProtoType>()) { + Diag(NewFD->getLocation(), + diag::err_attribute_overloadable_no_prototype) + << NewFD; + Redeclaration = true; - // Turn this into a variadic function with no parameters. - QualType R = Context.getFunctionType( - NewFD->getType()->getAs<FunctionType>()->getResultType(), - 0, 0, true, 0); - NewFD->setType(R); - return NewFD->setInvalidDecl(); + // Turn this into a variadic function with no parameters. + QualType R = Context.getFunctionType( + NewFD->getType()->getAs<FunctionType>()->getResultType(), + 0, 0, true, 0); + NewFD->setType(R); + return NewFD->setInvalidDecl(); + } } - } - NamedDecl *OldDecl = 0; - if (!Previous.empty()) { - if (!AllowOverloadingOfFunction(Previous, Context)) { + switch (CheckOverload(NewFD, Previous, OldDecl)) { + case Ovl_Match: Redeclaration = true; - OldDecl = Previous.getFoundDecl(); - } else if (!IsOverload(NewFD, Previous, OldDecl)) { - if (!isUsingDecl(OldDecl)) - Redeclaration = true; + if (isa<UsingShadowDecl>(OldDecl) && CurContext->isRecord()) { + HideUsingShadowDecl(S, cast<UsingShadowDecl>(OldDecl)); + Redeclaration = false; + } + break; + + case Ovl_NonFunction: + Redeclaration = true; + break; + + case Ovl_Overload: + Redeclaration = false; + break; } } @@ -3243,8 +3288,6 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, Diag(NewFD->getLocation(), diag::err_destructor_name); return NewFD->setInvalidDecl(); } - - CheckDestructor(Destructor); } Record->setUserDeclaredDestructor(true); @@ -3257,8 +3300,22 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, // FIXME: C++0x: don't do this for "= default" destructors Record->setHasTrivialDestructor(false); } else if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>(NewFD)) + = dyn_cast<CXXConversionDecl>(NewFD)) { ActOnConversionDeclarator(Conversion); + } + + // Find any virtual functions that this function overrides. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) { + if (!Method->isFunctionTemplateSpecialization() && + !Method->getDescribedFunctionTemplate()) + AddOverriddenMethods(Method->getParent(), Method); + } + + // Additional checks for the destructor; make sure we do this after we + // figure out whether the destructor is virtual. + if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD)) + if (!Destructor->getParent()->isDependentType()) + CheckDestructor(Destructor); // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && @@ -3392,18 +3449,9 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { IntegerLiteral *IL; Expr *Init = static_cast<Expr *>(init.get()); if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 && - Context.getCanonicalType(IL->getType()) == Context.IntTy) { - if (Method->isVirtualAsWritten()) { - Method->setPure(); - - // A class is abstract if at least one function is pure virtual. - cast<CXXRecordDecl>(CurContext)->setAbstract(true); - } else if (!Method->isInvalidDecl()) { - Diag(Method->getLocation(), diag::err_non_virtual_pure) - << Method->getDeclName() << Init->getSourceRange(); - Method->setInvalidDecl(); - } - } else { + Context.getCanonicalType(IL->getType()) == Context.IntTy) + CheckPureMethod(Method, Init->getSourceRange()); + else { Diag(Method->getLocation(), diag::err_member_function_initialization) << Method->getDeclName() << Init->getSourceRange(); Method->setInvalidDecl(); @@ -3436,6 +3484,12 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { return; } + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); + const VarDecl *Def = 0; if (VDecl->getDefinition(Def)) { Diag(VDecl->getLocation(), diag::err_redefinition) @@ -3458,8 +3512,36 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); VDecl->setInvalidDecl(); } else if (!VDecl->isInvalidDecl()) { - if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(), - VDecl->getDeclName(), DirectInit)) + if (VDecl->getType()->isReferenceType() + || isa<InitListExpr>(Init)) { + InitializedEntity Entity + = InitializedEntity::InitializeVariable(VDecl); + + // FIXME: Poor source location information. + InitializationKind Kind + = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(), + SourceLocation(), + SourceLocation()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + SourceLocation()); + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + if (InitSeq) { + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&Init, 1), + &DclT); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs<Expr>(); + } else { + InitSeq.Diagnose(*this, Entity, Kind, &Init, 1); + VDecl->setInvalidDecl(); + return; + } + } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(), + VDecl->getDeclName(), DirectInit)) VDecl->setInvalidDecl(); // C++ 3.6.2p2, allow dynamic initialization of static initializers. @@ -3649,7 +3731,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, SourceRange(Var->getLocation(), Var->getLocation()), Var->getDeclName(), - IK_Default, + InitializationKind::CreateDefault(Var->getLocation()), ConstructorArgs); // FIXME: Location info for the variable initialization? @@ -3668,6 +3750,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, Var->setInvalidDecl(); } } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) + Var->setInvalidDecl(); } #if 0 @@ -3817,9 +3905,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); - DeclaratorInfo *DInfo = 0; + TypeSourceInfo *TInfo = 0; TagDecl *OwnedDecl = 0; - QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, &OwnedDecl); + QualType parmDeclType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl); if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { // C++ [dcl.fct]p6: @@ -3862,7 +3950,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ParmVarDecl *New = ParmVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), II, - T, DInfo, StorageClass, 0); + T, TInfo, StorageClass, 0); if (D.isInvalidType()) New->setInvalidDecl(); @@ -3960,6 +4048,50 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, return ActOnStartOfFunctionDef(FnBodyScope, DP); } +static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { + // Don't warn about invalid declarations. + if (FD->isInvalidDecl()) + return false; + + // Or declarations that aren't global. + if (!FD->isGlobal()) + return false; + + // Don't warn about C++ member functions. + if (isa<CXXMethodDecl>(FD)) + return false; + + // Don't warn about 'main'. + if (FD->isMain()) + return false; + + // Don't warn about inline functions. + if (FD->isInlineSpecified()) + return false; + + // Don't warn about function templates. + if (FD->getDescribedFunctionTemplate()) + return false; + + // Don't warn about function template specializations. + if (FD->isFunctionTemplateSpecialization()) + return false; + + bool MissingPrototype = true; + for (const FunctionDecl *Prev = FD->getPreviousDeclaration(); + Prev; Prev = Prev->getPreviousDeclaration()) { + // Ignore any declarations that occur in function or method + // scope, because they aren't visible from the header. + if (Prev->getDeclContext()->isFunctionOrMethod()) + continue; + + MissingPrototype = !Prev->getType()->isFunctionProtoType(); + break; + } + + return MissingPrototype; +} + Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -4005,23 +4137,8 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // prototype declaration. This warning is issued even if the // definition itself provides a prototype. The aim is to detect // global functions that fail to be declared in header files. - if (!FD->isInvalidDecl() && FD->isGlobal() && !isa<CXXMethodDecl>(FD) && - !FD->isMain()) { - bool MissingPrototype = true; - for (const FunctionDecl *Prev = FD->getPreviousDeclaration(); - Prev; Prev = Prev->getPreviousDeclaration()) { - // Ignore any declarations that occur in function or method - // scope, because they aren't visible from the header. - if (Prev->getDeclContext()->isFunctionOrMethod()) - continue; - - MissingPrototype = !Prev->getType()->isFunctionProtoType(); - break; - } - - if (MissingPrototype) - Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; - } + if (ShouldWarnAboutMissingPrototype(FD)) + Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; if (FnBodyScope) PushDeclContext(FnBodyScope, FD); @@ -4090,11 +4207,8 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, if (!FD->isInvalidDecl()) DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); - // C++ [basic.def.odr]p2: - // [...] A virtual member function is used if it is not pure. [...] if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) - if (Method->isVirtual() && !Method->isPure()) - MarkDeclarationReferenced(Method->getLocation(), Method); + MaybeMarkVirtualMembersReferenced(Method->getLocation(), Method); assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { @@ -4301,20 +4415,20 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, - DeclaratorInfo *DInfo) { + TypeSourceInfo *TInfo) { assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); - if (!DInfo) { + if (!TInfo) { assert(D.isInvalidType() && "no declarator info for valid type"); - DInfo = Context.getTrivialDeclaratorInfo(T); + TInfo = Context.getTrivialTypeSourceInfo(T); } // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, D.getIdentifierLoc(), D.getIdentifier(), - DInfo); + TInfo); if (const TagType *TT = T->getAs<TagType>()) { TagDecl *TD = TT->getDecl(); @@ -4621,8 +4735,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Previous.clear(); } } - } else if (TUK == TUK_Reference && SS.isEmpty() && Name && - (Kind != TagDecl::TK_enum || !getLangOptions().CPlusPlus)) { + } else if (TUK == TUK_Reference && SS.isEmpty() && Name) { // C++ [basic.scope.pdecl]p5: // -- for an elaborated-type-specifier of the form // @@ -4640,6 +4753,11 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // C99 6.7.2.3p8 has a similar (but not identical!) provision for // C structs and unions. // + // It is an error in C++ to declare (rather than define) an enum + // type, including via an elaborated type specifier. We'll + // diagnose that later; for now, declare the enum in the same + // scope as we would have picked for any other tag type. + // // GNU C also supports this behavior as part of its incomplete // enum types extension, while GNU C++ does not. // @@ -4739,10 +4857,7 @@ CreateNewDecl: LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName, ForRedeclaration); LookupName(Lookup, S); - TypedefDecl *PrevTypedef = 0; - if (NamedDecl *Prev = Lookup.getAsSingleDecl(Context)) - PrevTypedef = dyn_cast<TypedefDecl>(Prev); - + TypedefDecl *PrevTypedef = Lookup.getAsSingle<TypedefDecl>(); NamedDecl *PrevTypedefNamed = PrevTypedef; if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) && Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) != @@ -4947,8 +5062,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, SourceLocation Loc = DeclStart; if (II) Loc = D.getIdentifierLoc(); - DeclaratorInfo *DInfo = 0; - QualType T = GetTypeForDeclarator(D, S, &DInfo); + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeForDeclarator(D, S, &TInfo); if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); @@ -4974,7 +5089,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); SourceLocation TSSL = D.getSourceRange().getBegin(); FieldDecl *NewFD - = CheckFieldDecl(II, T, DInfo, Record, Loc, Mutable, BitWidth, TSSL, + = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, TSSL, AS, PrevDecl, &D); if (NewFD->isInvalidDecl() && PrevDecl) { // Don't introduce NewFD into scope; there's already something @@ -4998,7 +5113,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, /// /// \todo The Declarator argument is a hack. It will be removed once FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, - DeclaratorInfo *DInfo, + TypeSourceInfo *TInfo, RecordDecl *Record, SourceLocation Loc, bool Mutable, Expr *BitWidth, SourceLocation TSSL, @@ -5015,9 +5130,14 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, T = Context.IntTy; } + QualType EltTy = Context.getBaseElementType(T); + if (!EltTy->isDependentType() && + RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) + InvalidDecl = true; + // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. - if (T->isVariablyModifiedType()) { + if (!InvalidDecl && T->isVariablyModifiedType()) { bool SizeIsNegative; QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative); @@ -5034,20 +5154,22 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } // Fields can not have abstract class types - if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl, - AbstractFieldType)) + if (!InvalidDecl && RequireNonAbstractType(Loc, T, + diag::err_abstract_type_in_decl, + AbstractFieldType)) InvalidDecl = true; bool ZeroWidth = false; // If this is declared as a bit-field, check the bit-field. - if (BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { + if (!InvalidDecl && BitWidth && + VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { InvalidDecl = true; DeleteExpr(BitWidth); BitWidth = 0; ZeroWidth = false; } - FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, DInfo, + FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo, BitWidth, Mutable); if (InvalidDecl) NewFD->setInvalidDecl(); @@ -5059,8 +5181,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } if (getLangOptions().CPlusPlus) { - QualType EltTy = Context.getBaseElementType(T); - CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record); if (!T->isPODType()) @@ -5296,8 +5416,8 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, // FIXME: Unnamed fields can be handled in various different ways, for // example, unnamed unions inject all members into the struct namespace! - DeclaratorInfo *DInfo = 0; - QualType T = GetTypeForDeclarator(D, S, &DInfo); + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeForDeclarator(D, S, &TInfo); if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 @@ -5340,7 +5460,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, // Construct the decl. ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, Loc, II, T, - DInfo, ac, (Expr *)BitfieldWidth); + TInfo, ac, (Expr *)BitfieldWidth); if (II) { NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, @@ -5403,8 +5523,10 @@ void Sema::ActOnFields(Scope* S, // If the field is already invalid for some reason, don't emit more // diagnostics about it. - if (FD->isInvalidDecl()) + if (FD->isInvalidDecl()) { + EnclosingDecl->setInvalidDecl(); continue; + } // C99 6.7.2.1p2: // A structure or union shall not contain a member with @@ -5540,7 +5662,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, llvm::APSInt EnumVal(32); QualType EltTy; if (Val) { - if (Val->isTypeDependent()) + if (Enum->isDependentType()) EltTy = Context.DependentTy; else { // Make sure to promote the operand type to int. @@ -5552,8 +5674,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // C99 6.7.2.2p2: Make sure we have an integer constant expression. SourceLocation ExpLoc; - if (!Val->isValueDependent() && - VerifyIntegerConstantExpression(Val, &EnumVal)) { + if (VerifyIntegerConstantExpression(Val, &EnumVal)) { Val = 0; } else { EltTy = Val->getType(); @@ -5562,7 +5683,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, } if (!Val) { - if (LastEnumConst) { + if (Enum->isDependentType()) + EltTy = Context.DependentTy; + else if (LastEnumConst) { // Assign the last value + 1. EnumVal = LastEnumConst->getInitVal(); ++EnumVal; @@ -5576,6 +5699,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // First value, set to zero. EltTy = Context.IntTy; EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy))); + EnumVal.setIsSigned(true); } } @@ -5647,6 +5771,19 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, if (Attr) ProcessDeclAttributeList(S, Enum, Attr); + if (Enum->isDependentType()) { + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = + cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>()); + if (!ECD) continue; + + ECD->setType(EnumType); + } + + Enum->completeDefinition(Context, Context.DependentTy, Context.DependentTy); + return; + } + // TODO: If the result value doesn't fit in an int, it must be a long or long // long value. ISO C does not support this, but GCC does as an extension, // emit a warning. @@ -5698,6 +5835,17 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, QualType BestType; unsigned BestWidth; + // C++0x N3000 [conv.prom]p3: + // An rvalue of an unscoped enumeration type whose underlying + // type is not fixed can be converted to an rvalue of the first + // of the following types that can represent all the values of + // the enumeration: int, unsigned int, long int, unsigned long + // int, long long int, or unsigned long long int. + // C99 6.4.4.3p2: + // An identifier declared as an enumeration constant has type int. + // The C99 rule is modified by a gcc extension + QualType BestPromotionType; + bool Packed = Enum->getAttr<PackedAttr>() ? true : false; if (NumNegativeBits) { @@ -5705,22 +5853,21 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // int/long/longlong) that fits. // If it's packed, check also if it fits a char or a short. if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) { - BestType = Context.SignedCharTy; - BestWidth = CharWidth; + BestType = Context.SignedCharTy; + BestWidth = CharWidth; } else if (Packed && NumNegativeBits <= ShortWidth && NumPositiveBits < ShortWidth) { - BestType = Context.ShortTy; - BestWidth = ShortWidth; - } - else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { + BestType = Context.ShortTy; + BestWidth = ShortWidth; + } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { BestType = Context.IntTy; BestWidth = IntWidth; } else { BestWidth = Context.Target.getLongWidth(); - if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) + if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) { BestType = Context.LongTy; - else { + } else { BestWidth = Context.Target.getLongLongWidth(); if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) @@ -5728,31 +5875,46 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, BestType = Context.LongLongTy; } } + BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); } else { // If there is no negative value, figure out which of uint, ulong, ulonglong // fits. // If it's packed, check also if it fits a char or a short. if (Packed && NumPositiveBits <= CharWidth) { - BestType = Context.UnsignedCharTy; - BestWidth = CharWidth; + BestType = Context.UnsignedCharTy; + BestPromotionType = Context.IntTy; + BestWidth = CharWidth; } else if (Packed && NumPositiveBits <= ShortWidth) { - BestType = Context.UnsignedShortTy; - BestWidth = ShortWidth; - } - else if (NumPositiveBits <= IntWidth) { + BestType = Context.UnsignedShortTy; + BestPromotionType = Context.IntTy; + BestWidth = ShortWidth; + } else if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; BestWidth = IntWidth; + BestPromotionType = (NumPositiveBits == BestWidth + ? Context.UnsignedIntTy : Context.IntTy); } else if (NumPositiveBits <= (BestWidth = Context.Target.getLongWidth())) { BestType = Context.UnsignedLongTy; + BestPromotionType = (NumPositiveBits == BestWidth + ? Context.UnsignedLongTy : Context.LongTy); } else { BestWidth = Context.Target.getLongLongWidth(); assert(NumPositiveBits <= BestWidth && "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; + BestPromotionType = (NumPositiveBits == BestWidth + ? Context.UnsignedLongLongTy : Context.LongLongTy); } } + // If we're in C and the promotion type is larger than an int, just + // use the underlying type, which is generally the unsigned integer + // type of the same rank as the promotion type. This is how the gcc + // extension works. + if (!getLangOptions().CPlusPlus && BestPromotionType != Context.IntTy) + BestPromotionType = BestType; + // Loop over all of the enumerator constants, changing their types to match // the type of the enum if needed. for (unsigned i = 0; i != NumElements; ++i) { @@ -5765,19 +5927,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // enumerator value fits in an int, type it as an int, otherwise type it the // same as the enumerator decl itself. This means that in "enum { X = 1U }" // that X has type 'int', not 'unsigned'. - if (ECD->getType() == Context.IntTy) { - // Make sure the init value is signed. - llvm::APSInt IV = ECD->getInitVal(); - IV.setIsSigned(true); - ECD->setInitVal(IV); - - if (getLangOptions().CPlusPlus) - // C++ [dcl.enum]p4: Following the closing brace of an - // enum-specifier, each enumerator has the type of its - // enumeration. - ECD->setType(EnumType); - continue; // Already int type. - } + if (!getLangOptions().CPlusPlus && ECD->getType() == Context.IntTy) + continue; // Determine whether the value fits into an int. llvm::APSInt InitVal = ECD->getInitVal(); @@ -5792,7 +5943,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, QualType NewTy; unsigned NewWidth; bool NewSign; - if (FitsInInt) { + if (FitsInInt && !getLangOptions().CPlusPlus) { NewTy = Context.IntTy; NewWidth = IntWidth; NewSign = true; @@ -5830,7 +5981,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(NewTy); } - Enum->completeDefinition(Context, BestType); + Enum->completeDefinition(Context, BestType, BestPromotionType); } Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, |