summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp587
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,
OpenPOWER on IntegriCloud