diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
commit | ecb7e5c8afe929ee38155db94de6b084ec32a645 (patch) | |
tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /lib/Sema/SemaDecl.cpp | |
parent | 5044f5c816adfd5cba17f1adee1a10127296d0bf (diff) | |
download | src-ecb7e5c8afe929ee38155db94de6b084ec32a645.tar.gz src-ecb7e5c8afe929ee38155db94de6b084ec32a645.zip |
Notes
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 682 |
1 files changed, 404 insertions, 278 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fbe02894ace5..1fc08ce03197 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -14,7 +14,7 @@ #include "Sema.h" #include "SemaInit.h" #include "Lookup.h" -#include "clang/Analysis/PathSensitive/AnalysisContext.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -135,6 +135,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: + Result.suppressDiagnostics(); return 0; case LookupResult::Ambiguous: @@ -509,9 +510,18 @@ static void RemoveUsingDecls(LookupResult &R) { } static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { + if (D->isInvalidDecl()) + return false; + if (D->isUsed() || D->hasAttr<UnusedAttr>()) return false; - + + // White-list anything that isn't a local variable. + if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) || + !D->getDeclContext()->isFunctionOrMethod()) + return false; + + // Types of valid local variables should be complete, so this should succeed. if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { @@ -523,9 +533,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { } } - return (isa<VarDecl>(D) && !isa<ParmVarDecl>(D) && - !isa<ImplicitParamDecl>(D) && - D->getDeclContext()->isFunctionOrMethod()); + return true; } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { @@ -690,7 +698,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, FT->getArgType(i), /*TInfo=*/0, VarDecl::None, 0)); - New->setParams(Context, Params.data(), Params.size()); + New->setParams(Params.data(), Params.size()); } AddKnownFunctionAttributes(New); @@ -957,6 +965,44 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { return true; } + // If a function is first declared with a calling convention, but is + // later declared or defined without one, the second decl assumes the + // calling convention of the first. + // + // For the new decl, we have to look at the NON-canonical type to tell the + // difference between a function that really doesn't have a calling + // convention and one that is declared cdecl. That's because in + // canonicalization (see ASTContext.cpp), cdecl is canonicalized away + // because it is the default calling convention. + // + // Note also that we DO NOT return at this point, because we still have + // other tests to run. + const FunctionType *OldType = OldQType->getAs<FunctionType>(); + const FunctionType *NewType = New->getType()->getAs<FunctionType>(); + if (OldType->getCallConv() != CC_Default && + NewType->getCallConv() == CC_Default) { + NewQType = Context.getCallConvType(NewQType, OldType->getCallConv()); + New->setType(NewQType); + NewQType = Context.getCanonicalType(NewQType); + } else if (!Context.isSameCallConv(OldType->getCallConv(), + NewType->getCallConv())) { + // Calling conventions really aren't compatible, so complain. + Diag(New->getLocation(), diag::err_cconv_change) + << FunctionType::getNameForCallConv(NewType->getCallConv()) + << (OldType->getCallConv() == CC_Default) + << (OldType->getCallConv() == CC_Default ? "" : + FunctionType::getNameForCallConv(OldType->getCallConv())); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + // FIXME: diagnose the other way around? + if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) { + NewQType = Context.getNoReturnType(NewQType); + New->setType(NewQType); + assert(NewQType.isCanonical()); + } + if (getLangOptions().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: @@ -1061,7 +1107,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { Params.push_back(Param); } - New->setParams(Context, Params.data(), Params.size()); + New->setParams(Params.data(), Params.size()); } return MergeCompatibleFunctionDecls(New, Old); @@ -1297,6 +1343,18 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { Diag(Old->getLocation(), diag::note_previous_definition); } + // C++ doesn't have tentative definitions, so go right ahead and check here. + const VarDecl *Def; + if (getLangOptions().CPlusPlus && + New->isThisDeclarationADefinition() == VarDecl::Definition && + (Def = Old->getDefinition())) { + Diag(New->getLocation(), diag::err_redefinition) + << New->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return; + } + // Keep a chain of previous declarations. New->setPreviousDeclaration(Old); @@ -1855,6 +1913,13 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (!DC->isDependentContext() && RequireCompleteDeclContext(D.getCXXScopeSpec())) return DeclPtrTy(); + + if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) { + Diag(D.getIdentifierLoc(), + diag::err_member_def_undefined_record) + << Name << DC << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + } LookupQualifiedName(Previous, DC); @@ -2322,7 +2387,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getString())); + NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); } // Don't consider existing declarations that are in a different @@ -2359,9 +2424,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // attributes declared post-definition are currently ignored if (Previous.isSingleResult()) { - const VarDecl *Def = 0; - VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl()); - if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) { + VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl()); + if (Def && (Def = Def->getDefinition()) && + Def != NewVD && D.hasAttributes()) { Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); Diag(Def->getLocation(), diag::note_previous_definition); } @@ -2675,7 +2740,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // (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() == cast<CXXRecordDecl>(DC)->getIdentifier()){ + if (Name.getAsIdentifierInfo() && + Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); @@ -2783,6 +2849,28 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } + // 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) + << CodeModificationHint::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) + << CodeModificationHint::CreateRemoval( + D.getDeclSpec().getExplicitSpecLoc()); + } + } + // Filter out previous declarations that don't match the scope. FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); @@ -2822,7 +2910,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getString())); + NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); } // Copy the parameter declarations from the declarator D to the function @@ -2882,7 +2970,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, "Should not need args for typedef of non-prototype fn"); } // Finally, we know we have the right number of parameters, install them. - NewFD->setParams(Context, Params.data(), Params.size()); + NewFD->setParams(Params.data(), Params.size()); // If the declarator is a template-id, translate the parser's template // argument list into our AST format. @@ -2950,7 +3038,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) { // Fake up an access specifier if it's supposed to be a class member. - if (isa<CXXRecordDecl>(NewFD->getDeclContext())) + if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext())) NewFD->setAccess(AS_public); // An out-of-line member function declaration must also be a @@ -3041,6 +3129,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (FunctionTemplate) return FunctionTemplate; + + // Keep track of static, non-inlined function definitions that + // have not been used. We will warn later. + // FIXME: Also include static functions declared but not defined. + if (!NewFD->isInvalidDecl() && IsFunctionDefinition + && !NewFD->isInlined() && NewFD->getLinkage() == InternalLinkage + && !NewFD->isUsed()) + UnusedStaticFuncs.push_back(NewFD); + return NewFD; } @@ -3412,8 +3509,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { AbstractVariableType)) VDecl->setInvalidDecl(); - const VarDecl *Def = 0; - if (VDecl->getDefinition(Def)) { + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); Diag(Def->getLocation(), diag::note_previous_definition); @@ -3473,7 +3570,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // }; // Attach the initializer - VDecl->setInit(Context, Init); + VDecl->setInit(Init); // C++ [class.mem]p4: // A member-declarator can contain a constant-initializer only @@ -3545,23 +3642,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { Init = MaybeCreateCXXExprWithTemporaries(Init); // Attach the initializer to the decl. - VDecl->setInit(Context, Init); - - // If the previous declaration of VDecl was a tentative definition, - // remove it from the set of tentative definitions. - if (VDecl->getPreviousDeclaration() && - VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) { - bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName()); - assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted; - } + VDecl->setInit(Init); if (getLangOptions().CPlusPlus) { // Make sure we mark the destructor as used if necessary. QualType InitType = VDecl->getType(); while (const ArrayType *Array = Context.getAsArrayType(InitType)) InitType = Context.getBaseElementType(Array); - if (InitType->isRecordType()) - FinalizeVarWithDestructor(VDecl, InitType); + if (const RecordType *Record = InitType->getAs<RecordType>()) + FinalizeVarWithDestructor(VDecl, Record); } return; @@ -3578,136 +3667,140 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) { QualType Type = Var->getType(); - // Record tentative definitions. - if (Var->isTentativeDefinition(Context)) { - std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool> - InsertPair = - TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var)); + // C++0x [dcl.spec.auto]p3 + if (TypeContainsUndeducedAuto) { + Diag(Var->getLocation(), diag::err_auto_var_requires_init) + << Var->getDeclName() << Type; + Var->setInvalidDecl(); + return; + } + + switch (Var->isThisDeclarationADefinition()) { + case VarDecl::Definition: + if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) + break; - // Keep the latest definition in the map. If we see 'int i; int i;' we - // want the second one in the map. - InsertPair.first->second = Var; + // We have an out-of-line definition of a static data member + // that has an in-class initializer, so we type-check this like + // a declaration. + // + // Fall through + + case VarDecl::DeclarationOnly: + // It's only a declaration. + + // Block scope. C99 6.7p7: If an identifier for an object is + // declared with no linkage (C99 6.2.2p6), the type for the + // object shall be complete. + if (!Type->isDependentType() && Var->isBlockVarDecl() && + !Var->getLinkage() && !Var->isInvalidDecl() && + RequireCompleteType(Var->getLocation(), Type, + diag::err_typecheck_decl_incomplete_type)) + Var->setInvalidDecl(); - // However, for the list, we don't care about the order, just make sure - // that there are no dupes for a given declaration name. - if (InsertPair.second) - TentativeDefinitionList.push_back(Var->getDeclName()); + // Make sure that the type is not abstract. + if (!Type->isDependentType() && !Var->isInvalidDecl() && + RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) + Var->setInvalidDecl(); + return; + + case VarDecl::TentativeDefinition: + // File scope. C99 6.9.2p2: A declaration of an identifier for an + // object that has file scope without an initializer, and without a + // storage-class specifier or with the storage-class specifier "static", + // constitutes a tentative definition. Note: A tentative definition with + // external linkage is valid (C99 6.2.2p5). + if (!Var->isInvalidDecl()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(Type)) { + if (RequireCompleteType(Var->getLocation(), + ArrayT->getElementType(), + diag::err_illegal_decl_array_incomplete_type)) + Var->setInvalidDecl(); + } else if (Var->getStorageClass() == VarDecl::Static) { + // C99 6.9.2p3: If the declaration of an identifier for an object is + // a tentative definition and has internal linkage (C99 6.2.2p3), the + // declared type shall not be an incomplete type. + // NOTE: code such as the following + // static struct s; + // struct s { int a; }; + // is accepted by gcc. Hence here we issue a warning instead of + // an error and we do not invalidate the static declaration. + // NOTE: to avoid multiple warnings, only check the first declaration. + if (Var->getPreviousDeclaration() == 0) + RequireCompleteType(Var->getLocation(), Type, + diag::ext_typecheck_decl_incomplete_type); + } + } + + // Record the tentative definition; we're done. + if (!Var->isInvalidDecl()) + TentativeDefinitions.push_back(Var); + return; } - // C++ [dcl.init.ref]p3: - // The initializer can be omitted for a reference only in a - // parameter declaration (8.3.5), in the declaration of a - // function return type, in the declaration of a class member - // within its class declaration (9.2), and where the extern - // specifier is explicitly used. - if (Type->isReferenceType() && !Var->hasExternalStorage()) { - Diag(Var->getLocation(), diag::err_reference_var_requires_init) - << Var->getDeclName() - << SourceRange(Var->getLocation(), Var->getLocation()); + // Provide a specific diagnostic for uninitialized variable + // definitions with incomplete array type. + if (Type->isIncompleteArrayType()) { + Diag(Var->getLocation(), + diag::err_typecheck_incomplete_array_needs_initializer); Var->setInvalidDecl(); return; } - // C++0x [dcl.spec.auto]p3 - if (TypeContainsUndeducedAuto) { - Diag(Var->getLocation(), diag::err_auto_var_requires_init) - << Var->getDeclName() << Type; + // Provide a specific diagnostic for uninitialized variable + // definitions with reference type. + if (Type->isReferenceType()) { + Diag(Var->getLocation(), diag::err_reference_var_requires_init) + << Var->getDeclName() + << SourceRange(Var->getLocation(), Var->getLocation()); + Var->setInvalidDecl(); + return; + } + + // Do not attempt to type-check the default initializer for a + // variable with dependent type. + if (Type->isDependentType()) + return; + + if (Var->isInvalidDecl()) + return; + + if (RequireCompleteType(Var->getLocation(), + Context.getBaseElementType(Type), + diag::err_typecheck_decl_incomplete_type)) { Var->setInvalidDecl(); return; } - // An array without size is an incomplete type, and there are no special - // rules in C++ to make such a definition acceptable. - if (getLangOptions().CPlusPlus && Type->isIncompleteArrayType() && - !Var->hasExternalStorage()) { - Diag(Var->getLocation(), - diag::err_typecheck_incomplete_array_needs_initializer); + // The variable can not have an abstract class type. + if (RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { Var->setInvalidDecl(); return; } - // C++ [temp.expl.spec]p15: - // An explicit specialization of a static data member of a template is a - // definition if the declaration includes an initializer; otherwise, it - // is a declaration. - if (Var->isStaticDataMember() && - Var->getInstantiatedFromStaticDataMember() && - Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return; + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); - // C++ [dcl.init]p9: - // If no initializer is specified for an object, and the object - // is of (possibly cv-qualified) non-POD class type (or array - // thereof), the object shall be default-initialized; if the - // object is of const-qualified type, the underlying class type - // shall have a user-declared default constructor. - // - // FIXME: Diagnose the "user-declared default constructor" bit. - if (getLangOptions().CPlusPlus) { - QualType InitType = Type; - if (const ArrayType *Array = Context.getAsArrayType(Type)) - InitType = Context.getBaseElementType(Array); - if ((!Var->hasExternalStorage() && !Var->isExternC()) && - InitType->isRecordType() && !InitType->isDependentType()) { - if (!RequireCompleteType(Var->getLocation(), InitType, - diag::err_invalid_incomplete_type_use)) { - InitializedEntity Entity - = InitializedEntity::InitializeVariable(Var); - InitializationKind Kind - = InitializationKind::CreateDefault(Var->getLocation()); - - InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); - OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, 0, 0)); - if (Init.isInvalid()) - Var->setInvalidDecl(); - else { - Var->setInit(Context, - MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>())); - FinalizeVarWithDestructor(Var, InitType); - } - } else { - Var->setInvalidDecl(); - } - } + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) + Var->setInvalidDecl(); + else { + if (Init.get()) + Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>())); - // The variable can not have an abstract class type. - if (RequireNonAbstractType(Var->getLocation(), Type, - diag::err_abstract_type_in_decl, - AbstractVariableType)) - Var->setInvalidDecl(); + if (getLangOptions().CPlusPlus) + if (const RecordType *Record + = Context.getBaseElementType(Type)->getAs<RecordType>()) + FinalizeVarWithDestructor(Var, Record); } - -#if 0 - // FIXME: Temporarily disabled because we are not properly parsing - // linkage specifications on declarations, e.g., - // - // extern "C" const CGPoint CGPointerZero; - // - // C++ [dcl.init]p9: - // - // If no initializer is specified for an object, and the - // object is of (possibly cv-qualified) non-POD class type (or - // array thereof), the object shall be default-initialized; if - // the object is of const-qualified type, the underlying class - // type shall have a user-declared default - // constructor. Otherwise, if no initializer is specified for - // an object, the object and its subobjects, if any, have an - // indeterminate initial value; if the object or any of its - // subobjects are of const-qualified type, the program is - // ill-formed. - // - // This isn't technically an error in C, so we don't diagnose it. - // - // FIXME: Actually perform the POD/user-defined default - // constructor check. - if (getLangOptions().CPlusPlus && - Context.getCanonicalType(Type).isConstQualified() && - !Var->hasExternalStorage()) - Diag(Var->getLocation(), diag::err_const_var_requires_init) - << Var->getName() - << SourceRange(Var->getLocation(), Var->getLocation()); -#endif } } @@ -3723,77 +3816,6 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i].getAs<Decl>()) Decls.push_back(D); - // Perform semantic analysis that depends on having fully processed both - // the declarator and initializer. - for (unsigned i = 0, e = Decls.size(); i != e; ++i) { - VarDecl *IDecl = dyn_cast<VarDecl>(Decls[i]); - if (!IDecl) - continue; - QualType T = IDecl->getType(); - - // Block scope. C99 6.7p7: If an identifier for an object is declared with - // no linkage (C99 6.2.2p6), the type for the object shall be complete... - if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) { - if (T->isDependentType()) { - // If T is dependent, we should not require a complete type. - // (RequireCompleteType shouldn't be called with dependent types.) - // But we still can at least check if we've got an array of unspecified - // size without an initializer. - if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() && - !IDecl->getInit()) { - Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type) - << T; - IDecl->setInvalidDecl(); - } - } else if (!IDecl->isInvalidDecl()) { - // If T is an incomplete array type with an initializer list that is - // dependent on something, its size has not been fixed. We could attempt - // to fix the size for such arrays, but we would still have to check - // here for initializers containing a C++0x vararg expansion, e.g. - // template <typename... Args> void f(Args... args) { - // int vals[] = { args }; - // } - const IncompleteArrayType *IAT = Context.getAsIncompleteArrayType(T); - Expr *Init = IDecl->getInit(); - if (IAT && Init && - (Init->isTypeDependent() || Init->isValueDependent())) { - // Check that the member type of the array is complete, at least. - if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(), - diag::err_typecheck_decl_incomplete_type)) - IDecl->setInvalidDecl(); - } else if (RequireCompleteType(IDecl->getLocation(), T, - diag::err_typecheck_decl_incomplete_type)) - IDecl->setInvalidDecl(); - } - } - // File scope. C99 6.9.2p2: A declaration of an identifier for an - // object that has file scope without an initializer, and without a - // storage-class specifier or with the storage-class specifier "static", - // constitutes a tentative definition. Note: A tentative definition with - // external linkage is valid (C99 6.2.2p5). - if (IDecl->isTentativeDefinition(Context) && !IDecl->isInvalidDecl()) { - if (const IncompleteArrayType *ArrayT - = Context.getAsIncompleteArrayType(T)) { - if (RequireCompleteType(IDecl->getLocation(), - ArrayT->getElementType(), - diag::err_illegal_decl_array_incomplete_type)) - IDecl->setInvalidDecl(); - } else if (IDecl->getStorageClass() == VarDecl::Static) { - // C99 6.9.2p3: If the declaration of an identifier for an object is - // a tentative definition and has internal linkage (C99 6.2.2p3), the - // declared type shall not be an incomplete type. - // NOTE: code such as the following - // static struct s; - // struct s { int a; }; - // is accepted by gcc. Hence here we issue a warning instead of - // an error and we do not invalidate the static declaration. - // NOTE: to avoid multiple warnings, only check the first declaration. - if (IDecl->getPreviousDeclaration() == 0) - RequireCompleteType(IDecl->getLocation(), T, - diag::ext_typecheck_decl_incomplete_type); - } - } - } return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Decls.data(), Decls.size())); } @@ -3853,6 +3875,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Recover by removing the name II = 0; D.SetIdentifier(0, D.getIdentifierLoc()); + D.setInvalidType(true); } } } @@ -3919,6 +3942,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { return DeclPtrTy::make(New); } +void Sema::ActOnObjCCatchParam(DeclPtrTy D) { + ParmVarDecl *Param = cast<ParmVarDecl>(D.getAs<Decl>()); + Param->setDeclContext(CurContext); +} + void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls) { assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && @@ -4297,8 +4325,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { if (!FD->getAttr<FormatAttr>()) - FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1, - HasVAListArg ? 0 : FormatIdx + 2)); + FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1, + HasVAListArg ? 0 : FormatIdx+2)); } // Mark const if we don't care about errno and that is the only @@ -4311,7 +4339,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } if (Context.BuiltinInfo.isNoReturn(BuiltinID)) - FD->addAttr(::new (Context) NoReturnAttr()); + FD->setType(Context.getNoReturnType(FD->getType())); if (Context.BuiltinInfo.isNoThrow(BuiltinID)) FD->addAttr(::new (Context) NoThrowAttr()); if (Context.BuiltinInfo.isConst(BuiltinID)) @@ -4335,15 +4363,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // FIXME: NSLog and NSLogv should be target specific if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { // FIXME: We known better than our headers. - const_cast<FormatAttr *>(Format)->setType("printf"); + const_cast<FormatAttr *>(Format)->setType(Context, "printf"); } else - FD->addAttr(::new (Context) FormatAttr("printf", 1, + FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1, Name->isStr("NSLogv") ? 0 : 2)); } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { // FIXME: asprintf and vasprintf aren't C99 functions. Should they be // target-specific builtins, perhaps? if (!FD->getAttr<FormatAttr>()) - FD->addAttr(::new (Context) FormatAttr("printf", 2, + FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2, Name->isStr("vasprintf") ? 0 : 3)); } } @@ -4614,7 +4642,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { - if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) { + if (TagDecl *Def = PrevTagDecl->getDefinition()) { // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error // here; we'll catch this in the general case below. @@ -4927,9 +4955,17 @@ RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record, if (Record->isDependentContext() || !Record->isDefinition()) return; - if (Record->isDynamicClass() && !S.Context.getKeyFunction(Record)) - S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, Loc)); + if (Record->isDynamicClass()) { + const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record); + if (!KeyFunction) + S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, + Loc)); + + if ((!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined())) + && Record->getLinkage() == ExternalLinkage) + S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record; + } for (DeclContext::decl_iterator D = Record->decls_begin(), DEnd = Record->decls_end(); D != DEnd; ++D) { @@ -5156,7 +5192,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, NewFD->setInvalidDecl(); } - if (getLangOptions().CPlusPlus) { + if (!InvalidDecl && getLangOptions().CPlusPlus) { CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record); if (!T->isPODType()) @@ -5584,7 +5620,7 @@ void Sema::ActOnFields(Scope* S, // Okay, we successfully defined 'Record'. if (Record) { - Record->completeDefinition(Context); + Record->completeDefinition(); } else { ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); @@ -5628,6 +5664,45 @@ void Sema::ActOnFields(Scope* S, ProcessDeclAttributeList(S, Record, Attr); } +/// \brief Determine whether the given integral value is representable within +/// the given type T. +static bool isRepresentableIntegerValue(ASTContext &Context, + llvm::APSInt &Value, + QualType T) { + assert(T->isIntegralType() && "Integral type required!"); + unsigned BitWidth = Context.getTypeSize(T); + + if (Value.isUnsigned() || Value.isNonNegative()) + return Value.getActiveBits() < BitWidth; + + return Value.getMinSignedBits() <= BitWidth; +} + +// \brief Given an integral type, return the next larger integral type +// (or a NULL type of no such type exists). +static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { + // FIXME: Int128/UInt128 support, which also needs to be introduced into + // enum checking below. + assert(T->isIntegralType() && "Integral type required!"); + const unsigned NumTypes = 4; + QualType SignedIntegralTypes[NumTypes] = { + Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy + }; + QualType UnsignedIntegralTypes[NumTypes] = { + Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, + Context.UnsignedLongLongTy + }; + + unsigned BitWidth = Context.getTypeSize(T); + QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes + : UnsignedIntegralTypes; + for (unsigned I = 0; I != NumTypes; ++I) + if (Context.getTypeSize(Types[I]) > BitWidth) + return Types[I]; + + return QualType(); +} + EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EnumConstantDecl *LastEnumConst, SourceLocation IdLoc, @@ -5635,24 +5710,45 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, ExprArg val) { Expr *Val = (Expr *)val.get(); - llvm::APSInt EnumVal(32); + unsigned IntWidth = Context.Target.getIntWidth(); + llvm::APSInt EnumVal(IntWidth); QualType EltTy; if (Val) { if (Enum->isDependentType()) EltTy = Context.DependentTy; else { - // Make sure to promote the operand type to int. - UsualUnaryConversions(Val); - if (Val != val.get()) { - val.release(); - val = Val; - } - // C99 6.7.2.2p2: Make sure we have an integer constant expression. SourceLocation ExpLoc; if (VerifyIntegerConstantExpression(Val, &EnumVal)) { Val = 0; - } else { + } else { + if (!getLangOptions().CPlusPlus) { + // C99 6.7.2.2p2: + // The expression that defines the value of an enumeration constant + // shall be an integer constant expression that has a value + // representable as an int. + + // Complain if the value is not representable in an int. + if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << Val->getSourceRange() + << EnumVal.isNonNegative(); + else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { + // Force the type of the expression to 'int'. + ImpCastExprToType(Val, Context.IntTy, CastExpr::CK_IntegralCast); + + if (Val != val.get()) { + val.release(); + val = Val; + } + } + } + + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If an initializer is specified for an enumerator, the + // initializing value has the same type as the expression. EltTy = Val->getType(); } } @@ -5661,25 +5757,76 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (!Val) { if (Enum->isDependentType()) EltTy = Context.DependentTy; - else if (LastEnumConst) { + else if (!LastEnumConst) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If no initializer is specified for the first enumerator, the + // initializing value has an unspecified integral type. + // + // GCC uses 'int' for its unspecified integral type, as does + // C99 6.7.2.2p3. + EltTy = Context.IntTy; + } else { // Assign the last value + 1. EnumVal = LastEnumConst->getInitVal(); ++EnumVal; + EltTy = LastEnumConst->getType(); // Check for overflow on increment. - if (EnumVal < LastEnumConst->getInitVal()) - Diag(IdLoc, diag::warn_enum_value_overflow); - - EltTy = LastEnumConst->getType(); - } else { - // First value, set to zero. - EltTy = Context.IntTy; - EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy))); - EnumVal.setIsSigned(true); + if (EnumVal < LastEnumConst->getInitVal()) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // + // - Otherwise the type of the initializing value is the same as + // the type of the initializing value of the preceding enumerator + // unless the incremented value is not representable in that type, + // in which case the type is an unspecified integral type + // sufficient to contain the incremented value. If no such type + // exists, the program is ill-formed. + QualType T = getNextLargerIntegralType(Context, EltTy); + if (T.isNull()) { + // There is no integral type larger enough to represent this + // value. Complain, then allow the value to wrap around. + EnumVal = LastEnumConst->getInitVal(); + EnumVal.zext(EnumVal.getBitWidth() * 2); + Diag(IdLoc, diag::warn_enumerator_too_large) + << EnumVal.toString(10); + } else { + EltTy = T; + } + + // Retrieve the last enumerator's value, extent that type to the + // type that is supposed to be large enough to represent the incremented + // value, then increment. + EnumVal = LastEnumConst->getInitVal(); + EnumVal.setIsSigned(EltTy->isSignedIntegerType()); + EnumVal.zextOrTrunc(Context.getTypeSize(EltTy)); + ++EnumVal; + + // If we're not in C++, diagnose the overflow of enumerator values, + // which in C99 means that the enumerator value is not representable in + // an int (C99 6.7.2.2p2). However, we support GCC's extension that + // permits enumerator values that are representable in some larger + // integral type. + if (!getLangOptions().CPlusPlus && !T.isNull()) + Diag(IdLoc, diag::warn_enum_value_overflow); + } else if (!getLangOptions().CPlusPlus && + !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + // Enforce C99 6.7.2.2p2 even when we compute the next value. + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << 1; + } } } - assert(!EltTy.isNull() && "Enum constant with NULL type"); + if (!Enum->isDependentType()) { + // Make the enumerator value match the signedness and size of the + // enumerator's type. + EnumVal.zextOrTrunc(Context.getTypeSize(EltTy)); + EnumVal.setIsSigned(EltTy->isSignedIntegerType()); + } val.release(); return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, @@ -5759,7 +5906,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(EnumType); } - Enum->completeDefinition(Context, Context.DependentTy, Context.DependentTy); + Enum->completeDefinition(Context.DependentTy, Context.DependentTy); return; } @@ -5783,18 +5930,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>()); if (!ECD) continue; // Already issued a diagnostic. - // If the enum value doesn't fit in an int, emit an extension warning. const llvm::APSInt &InitVal = ECD->getInitVal(); - assert(InitVal.getBitWidth() >= IntWidth && - "Should have promoted value to int"); - if (!getLangOptions().CPlusPlus && InitVal.getBitWidth() > IntWidth) { - llvm::APSInt V(InitVal); - V.trunc(IntWidth); - V.extend(InitVal.getBitWidth()); - if (V != InitVal) - Diag(ECD->getLocation(), diag::ext_enum_value_not_int) - << InitVal.toString(10); - } // Keep track of the size of positive and negative values. if (InitVal.isUnsigned() || InitVal.isNonNegative()) @@ -5856,8 +5992,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); } else { - // If there is no negative value, figure out which of uint, ulong, ulonglong - // fits. + // If there is no negative value, figure out the smallest type that fits + // all of the enumerator values. // If it's packed, check also if it fits a char or a short. if (Packed && NumPositiveBits <= CharWidth) { BestType = Context.UnsignedCharTy; @@ -5870,30 +6006,26 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } else if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; BestWidth = IntWidth; - BestPromotionType = (NumPositiveBits == BestWidth - ? Context.UnsignedIntTy : Context.IntTy); + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedIntTy : Context.IntTy; } else if (NumPositiveBits <= (BestWidth = Context.Target.getLongWidth())) { BestType = Context.UnsignedLongTy; - BestPromotionType = (NumPositiveBits == BestWidth - ? Context.UnsignedLongTy : Context.LongTy); + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? 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); + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? 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) { @@ -5906,23 +6038,17 @@ 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 (!getLangOptions().CPlusPlus && ECD->getType() == Context.IntTy) - continue; // Determine whether the value fits into an int. llvm::APSInt InitVal = ECD->getInitVal(); - bool FitsInInt; - if (InitVal.isUnsigned() || !InitVal.isNegative()) - FitsInInt = InitVal.getActiveBits() < IntWidth; - else - FitsInInt = InitVal.getMinSignedBits() <= IntWidth; // If it fits into an integer type, force it. Otherwise force it to match // the enum decl type. QualType NewTy; unsigned NewWidth; bool NewSign; - if (FitsInInt && !getLangOptions().CPlusPlus) { + if (!getLangOptions().CPlusPlus && + isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { NewTy = Context.IntTy; NewWidth = IntWidth; NewSign = true; @@ -5960,7 +6086,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(NewTy); } - Enum->completeDefinition(Context, BestType, BestPromotionType); + Enum->completeDefinition(BestType, BestPromotionType); } Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, |