summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit9092c3e0fa01f3139b016d05d267a89e3b07747a (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Sema/SemaDecl.cpp
parent4981926bf654fe5a2c3893f24ca44106b217e71e (diff)
downloadFreeBSD-src-9092c3e0fa01f3139b016d05d267a89e3b07747a.zip
FreeBSD-src-9092c3e0fa01f3139b016d05d267a89e3b07747a.tar.gz
Update clang to r84119.
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp2571
1 files changed, 1818 insertions, 753 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1fd5697..606b33f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12,28 +12,34 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
-#include "SemaInherit.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
#include "clang/Parse/DeclSpec.h"
-#include "clang/Basic/TargetInfo.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "llvm/ADT/SmallSet.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
+#include <cstring>
#include <functional>
+#include <queue>
using namespace clang;
/// getDeclName - Return a pretty name for the specified decl if possible, or
-/// an empty string if not. This is used for pretty crash reporting.
+/// an empty string if not. This is used for pretty crash reporting.
std::string Sema::getDeclName(DeclPtrTy d) {
Decl *D = d.getAs<Decl>();
if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(D))
@@ -57,7 +63,8 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
/// If name lookup results in an ambiguity, this routine will complain
/// and then return NULL.
Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, const CXXScopeSpec *SS) {
+ Scope *S, const CXXScopeSpec *SS,
+ bool isClassName) {
// C++ [temp.res]p3:
// A qualified-id that refers to a type and in which the
// nested-name-specifier depends on a template-parameter (14.6.2)
@@ -67,11 +74,20 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
//
// We therefore do not perform any name lookup if the result would
// refer to a member of an unknown specialization.
- if (SS && isUnknownSpecialization(*SS))
- return 0;
+ if (SS && isUnknownSpecialization(*SS)) {
+ if (!isClassName)
+ return 0;
+
+ // We know from the grammar that this name refers to a type, so build a
+ // TypenameType node to describe the type.
+ // FIXME: Record somewhere that this TypenameType node has no "typename"
+ // keyword associated with it.
+ return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
+ II, SS->getRange()).getAsOpaquePtr();
+ }
- LookupResult Result
- = LookupParsedName(S, SS, &II, LookupOrdinaryName, false, false);
+ LookupResult Result;
+ LookupParsedName(Result, S, SS, &II, LookupOrdinaryName, false, false);
NamedDecl *IIDecl = 0;
switch (Result.getKind()) {
@@ -79,15 +95,21 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::FoundOverloaded:
return 0;
- case LookupResult::AmbiguousBaseSubobjectTypes:
- case LookupResult::AmbiguousBaseSubobjects:
- case LookupResult::AmbiguousReference: {
+ case LookupResult::Ambiguous: {
+ // Recover from type-hiding ambiguities by hiding the type. We'll
+ // do the lookup again when looking for an object, and we can
+ // diagnose the error then. If we don't do this, then the error
+ // about hiding the type will be immediately followed by an error
+ // that only makes sense if the identifier was treated like a type.
+ if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding)
+ return 0;
+
// Look to see if we have a type anywhere in the list of results.
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
Res != ResEnd; ++Res) {
if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) {
- if (!IIDecl ||
- (*Res)->getLocation().getRawEncoding() <
+ if (!IIDecl ||
+ (*Res)->getLocation().getRawEncoding() <
IIDecl->getLocation().getRawEncoding())
IIDecl = *Res;
}
@@ -100,7 +122,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// perform this lookup again (e.g., as an object name), which
// will produce the ambiguity, or will complain that it expected
// a type name.
- Result.Destroy();
return 0;
}
@@ -113,17 +134,17 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
}
case LookupResult::Found:
- IIDecl = Result.getAsDecl();
+ IIDecl = Result.getFoundDecl();
break;
}
if (IIDecl) {
QualType T;
-
+
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
// Check whether we can use this type
(void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-
+
if (getLangOptions().CPlusPlus) {
// C++ [temp.local]p2:
// Within the scope of a class template specialization or
@@ -143,7 +164,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
// Check whether we can use this interface.
(void)DiagnoseUseOfDecl(IIDecl, NameLoc);
-
+
T = Context.getObjCInterfaceType(IDecl);
} else
return 0;
@@ -164,9 +185,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
/// where the user forgot to specify the tag.
DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
// Do a tag name lookup in this scope.
- LookupResult R = LookupName(S, &II, LookupTagName, false, false);
+ LookupResult R;
+ LookupName(R, S, &II, LookupTagName, false, false);
if (R.getKind() == LookupResult::Found)
- if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsDecl())) {
+ if (const TagDecl *TD = dyn_cast<TagDecl>(R.getAsSingleDecl(Context))) {
switch (TD->getTagKind()) {
case TagDecl::TK_struct: return DeclSpec::TST_struct;
case TagDecl::TK_union: return DeclSpec::TST_union;
@@ -174,24 +196,60 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
case TagDecl::TK_enum: return DeclSpec::TST_enum;
}
}
-
+
return DeclSpec::TST_unspecified;
}
+bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TypeTy *&SuggestedType) {
+ // We don't have anything to suggest (yet).
+ SuggestedType = 0;
+
+ // FIXME: Should we move the logic that tries to recover from a missing tag
+ // (struct, union, enum) from Parser::ParseImplicitInt here, instead?
+
+ if (!SS)
+ Diag(IILoc, diag::err_unknown_typename) << &II;
+ else if (DeclContext *DC = computeDeclContext(*SS, false))
+ Diag(IILoc, diag::err_typename_nested_not_found)
+ << &II << DC << SS->getRange();
+ else if (isDependentScopeSpecifier(*SS)) {
+ Diag(SS->getRange().getBegin(), diag::err_typename_missing)
+ << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
+ << SourceRange(SS->getRange().getBegin(), IILoc)
+ << CodeModificationHint::CreateInsertion(SS->getRange().getBegin(),
+ "typename ");
+ SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get();
+ } else {
+ assert(SS && SS->isInvalid() &&
+ "Invalid scope specifier has already been diagnosed");
+ }
+
+ return true;
+}
-
+// Determines the context to return to after temporarily entering a
+// context. This depends in an unnecessarily complicated way on the
+// exact ordering of callbacks from the parser.
DeclContext *Sema::getContainingDC(DeclContext *DC) {
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
- // A C++ out-of-line method will return to the file declaration context.
- if (MD->isOutOfLine())
- return MD->getLexicalDeclContext();
-
- // A C++ inline method is parsed *after* the topmost class it was declared
- // in is fully parsed (it's "complete").
- // The parsing of a C++ inline method happens at the declaration context of
- // the topmost (non-nested) class it is lexically declared in.
- assert(isa<CXXRecordDecl>(MD->getParent()) && "C++ method not in Record.");
- DC = MD->getParent();
+
+ // Functions defined inline within classes aren't parsed until we've
+ // finished parsing the top-level class, so the top-level class is
+ // the context we'll need to return to.
+ if (isa<FunctionDecl>(DC)) {
+ DC = DC->getLexicalParent();
+
+ // A function not defined within a class will always return to its
+ // lexical context.
+ if (!isa<CXXRecordDecl>(DC))
+ return DC;
+
+ // A C++ inline method/friend is parsed *after* the topmost class
+ // it was declared in is fully parsed ("complete"); the topmost
+ // class is the context we need to return to.
while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent()))
DC = RD;
@@ -260,103 +318,84 @@ static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) {
}
/// Add this decl to the scope shadowed decl chains.
-void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
+void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
// Move up the scope chain until we find the nearest enclosing
// non-transparent context. The declaration will be introduced into this
// scope.
- while (S->getEntity() &&
+ while (S->getEntity() &&
((DeclContext *)S->getEntity())->isTransparentContext())
S = S->getParent();
- S->AddDecl(DeclPtrTy::make(D));
-
// Add scoped declarations into their context, so that they can be
// found later. Declarations without a context won't be inserted
// into any context.
- CurContext->addDecl(D);
-
- // C++ [basic.scope]p4:
- // -- exactly one declaration shall declare a class name or
- // enumeration name that is not a typedef name and the other
- // declarations shall all refer to the same object or
- // enumerator, or all refer to functions and function templates;
- // in this case the class name or enumeration name is hidden.
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- // We are pushing the name of a tag (enum or class).
- if (CurContext->getLookupContext()
- == TD->getDeclContext()->getLookupContext()) {
- // We're pushing the tag into the current context, which might
- // require some reshuffling in the identifier resolver.
- IdentifierResolver::iterator
- I = IdResolver.begin(TD->getDeclName()),
- IEnd = IdResolver.end();
- if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
- NamedDecl *PrevDecl = *I;
- for (; I != IEnd && isDeclInScope(*I, CurContext, S);
- PrevDecl = *I, ++I) {
- if (TD->declarationReplaces(*I)) {
- // This is a redeclaration. Remove it from the chain and
- // break out, so that we'll add in the shadowed
- // declaration.
- S->RemoveDecl(DeclPtrTy::make(*I));
- if (PrevDecl == *I) {
- IdResolver.RemoveDecl(*I);
- IdResolver.AddDecl(TD);
- return;
- } else {
- IdResolver.RemoveDecl(*I);
- break;
- }
- }
- }
+ if (AddToContext)
+ CurContext->addDecl(D);
- // There is already a declaration with the same name in the same
- // scope, which is not a tag declaration. It must be found
- // before we find the new declaration, so insert the new
- // declaration at the end of the chain.
- IdResolver.AddShadowedDecl(TD, PrevDecl);
-
- return;
- }
- }
- } else if ((isa<FunctionDecl>(D) &&
- AllowOverloadingOfFunction(D, Context)) ||
- isa<FunctionTemplateDecl>(D)) {
- // We are pushing the name of a function or function template,
- // which might be an overloaded name.
- IdentifierResolver::iterator Redecl
- = std::find_if(IdResolver.begin(D->getDeclName()),
- IdResolver.end(),
- std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
- D));
- if (Redecl != IdResolver.end() &&
- S->isDeclScope(DeclPtrTy::make(*Redecl))) {
- // There is already a declaration of a function on our
- // IdResolver chain. Replace it with this declaration.
- S->RemoveDecl(DeclPtrTy::make(*Redecl));
- IdResolver.RemoveDecl(*Redecl);
- }
- } else if (isa<ObjCInterfaceDecl>(D)) {
- // We're pushing an Objective-C interface into the current
- // context. If there is already an alias declaration, remove it first.
- for (IdentifierResolver::iterator
- I = IdResolver.begin(D->getDeclName()), IEnd = IdResolver.end();
- I != IEnd; ++I) {
- if (isa<ObjCCompatibleAliasDecl>(*I)) {
- S->RemoveDecl(DeclPtrTy::make(*I));
- IdResolver.RemoveDecl(*I);
- break;
- }
+ // Out-of-line function and variable definitions should not be pushed into
+ // scope.
+ if ((isa<FunctionTemplateDecl>(D) &&
+ cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->isOutOfLine()) ||
+ (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isOutOfLine()) ||
+ (isa<VarDecl>(D) && cast<VarDecl>(D)->isOutOfLine()))
+ return;
+
+ // If this replaces anything in the current scope,
+ IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
+ IEnd = IdResolver.end();
+ for (; I != IEnd; ++I) {
+ if (S->isDeclScope(DeclPtrTy::make(*I)) && D->declarationReplaces(*I)) {
+ S->RemoveDecl(DeclPtrTy::make(*I));
+ IdResolver.RemoveDecl(*I);
+
+ // Should only need to replace one decl.
+ break;
}
}
+ S->AddDecl(DeclPtrTy::make(D));
IdResolver.AddDecl(D);
}
+bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
+ if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
+ // Look inside the overload set to determine if any of the declarations
+ // are in scope. (Possibly) build a new overload set containing only
+ // those declarations that are in scope.
+ OverloadedFunctionDecl *NewOvl = 0;
+ bool FoundInScope = false;
+ for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+ FEnd = Ovl->function_end();
+ F != FEnd; ++F) {
+ NamedDecl *FD = F->get();
+ if (!isDeclInScope(FD, Ctx, S)) {
+ if (!NewOvl && F != Ovl->function_begin()) {
+ NewOvl = OverloadedFunctionDecl::Create(Context,
+ F->get()->getDeclContext(),
+ F->get()->getDeclName());
+ D = NewOvl;
+ for (OverloadedFunctionDecl::function_iterator
+ First = Ovl->function_begin();
+ First != F; ++First)
+ NewOvl->addOverload(*First);
+ }
+ } else {
+ FoundInScope = true;
+ if (NewOvl)
+ NewOvl->addOverload(*F);
+ }
+ }
+
+ return FoundInScope;
+ }
+
+ return IdResolver.isDeclInScope(D, Ctx, Context, S);
+}
+
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) &&
- "Scope shouldn't contain decls!");
+ "Scope shouldn't contain decls!");
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
@@ -368,6 +407,12 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!D->getDeclName()) continue;
+ // Diagnose unused variables in this scope.
+ if (!D->isUsed() && !D->hasAttr<UnusedAttr>() && isa<VarDecl>(D) &&
+ !isa<ParmVarDecl>(D) && !isa<ImplicitParamDecl>(D) &&
+ D->getDeclContext()->isFunctionOrMethod())
+ Diag(D->getLocation(), diag::warn_unused_variable) << D->getDeclName();
+
// Remove this name from our lexical scope.
IdResolver.RemoveDecl(D);
}
@@ -378,8 +423,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
// The third "scope" argument is 0 since we aren't enabling lazy built-in
// creation from this context.
- NamedDecl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName);
-
+ NamedDecl *IDecl = LookupSingleName(TUScope, Id, LookupOrdinaryName);
+
return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
}
@@ -392,7 +437,7 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
/// struct S6 {
/// enum { BAR } e;
/// };
-///
+///
/// void test_S6() {
/// struct S6 a;
/// a.e = BAR;
@@ -408,7 +453,7 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
/// contain non-field names.
Scope *Sema::getNonFieldDeclScope(Scope *S) {
while (((S->getFlags() & Scope::DeclScope) == 0) ||
- (S->getEntity() &&
+ (S->getEntity() &&
((DeclContext *)S->getEntity())->isTransparentContext()) ||
(S->isClassScope() && !getLangOptions().CPlusPlus))
S = S->getParent();
@@ -418,9 +463,9 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
void Sema::InitBuiltinVaListType() {
if (!Context.getBuiltinVaListType().isNull())
return;
-
+
IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
- NamedDecl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName);
+ NamedDecl *VaDecl = LookupSingleName(TUScope, VaIdent, LookupOrdinaryName);
TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
}
@@ -438,17 +483,23 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
InitBuiltinVaListType();
ASTContext::GetBuiltinTypeError Error;
- QualType R = Context.GetBuiltinType(BID, Error);
+ QualType R = Context.GetBuiltinType(BID, Error);
switch (Error) {
case ASTContext::GE_None:
// Okay
break;
- case ASTContext::GE_Missing_FILE:
+ case ASTContext::GE_Missing_stdio:
if (ForRedeclaration)
Diag(Loc, diag::err_implicit_decl_requires_stdio)
<< Context.BuiltinInfo.GetName(BID);
return 0;
+
+ case ASTContext::GE_Missing_setjmp:
+ if (ForRedeclaration)
+ Diag(Loc, diag::err_implicit_decl_requires_setjmp)
+ << Context.BuiltinInfo.GetName(BID);
+ return 0;
}
if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
@@ -465,7 +516,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
FunctionDecl *New = FunctionDecl::Create(Context,
Context.getTranslationUnitDecl(),
- Loc, II, R,
+ Loc, II, R, /*DInfo=*/0,
FunctionDecl::Extern, false,
/*hasPrototype=*/true);
New->setImplicit();
@@ -476,12 +527,13 @@ 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), VarDecl::None, 0));
+ FT->getArgType(i), /*DInfo=*/0,
+ VarDecl::None, 0));
New->setParams(Context, Params.data(), Params.size());
}
-
- AddKnownFunctionAttributes(New);
-
+
+ AddKnownFunctionAttributes(New);
+
// TUScope is the translation-unit scope to insert this function into.
// FIXME: This is hideous. We need to teach PushOnScopeChains to
// relate Scopes to DeclContexts, and probably eliminate CurContext
@@ -493,18 +545,6 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
return New;
}
-/// GetStdNamespace - This method gets the C++ "std" namespace. This is where
-/// everything from the standard library is defined.
-NamespaceDecl *Sema::GetStdNamespace() {
- if (!StdNamespace) {
- IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std");
- DeclContext *Global = Context.getTranslationUnitDecl();
- Decl *Std = LookupQualifiedName(Global, StdIdent, LookupNamespaceName);
- StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
- }
- return StdNamespace;
-}
-
/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the
/// same name and scope as a previous declaration 'Old'. Figure out
/// how to resolve this situation, merging decls or emitting
@@ -515,25 +555,26 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
// don't bother doing any merging checks.
if (New->isInvalidDecl() || OldD->isInvalidDecl())
return New->setInvalidDecl();
-
- bool objc_types = false;
-
+
// Allow multiple definitions for ObjC built-in typedefs.
// FIXME: Verify the underlying types are equivalent!
if (getLangOptions().ObjC1) {
const IdentifierInfo *TypeID = New->getIdentifier();
switch (TypeID->getLength()) {
default: break;
- case 2:
+ case 2:
if (!TypeID->isStr("id"))
break;
- Context.setObjCIdType(Context.getTypeDeclType(New));
- objc_types = true;
- break;
+ Context.ObjCIdRedefinitionType = New->getUnderlyingType();
+ // Install the built-in type for 'id', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
+ return;
case 5:
if (!TypeID->isStr("Class"))
break;
- Context.setObjCClassType(Context.getTypeDeclType(New));
+ Context.ObjCClassRedefinitionType = New->getUnderlyingType();
+ // Install the built-in type for 'Class', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
return;
case 3:
if (!TypeID->isStr("SEL"))
@@ -551,14 +592,14 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
// Verify the old decl was also a type.
TypeDecl *Old = dyn_cast<TypeDecl>(OldD);
if (!Old) {
- Diag(New->getLocation(), diag::err_redefinition_different_kind)
+ Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
if (OldD->getLocation().isValid())
Diag(OldD->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
- // Determine the "old" type we'll use for checking and diagnostics.
+ // Determine the "old" type we'll use for checking and diagnostics.
QualType OldType;
if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old))
OldType = OldTypedef->getUnderlyingType();
@@ -568,8 +609,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
// If the typedef types are not identical, reject them in all languages and
// with any extensions enabled.
- if (OldType != New->getUnderlyingType() &&
- Context.getCanonicalType(OldType) !=
+ if (OldType != New->getUnderlyingType() &&
+ Context.getCanonicalType(OldType) !=
Context.getCanonicalType(New->getUnderlyingType())) {
Diag(New->getLocation(), diag::err_redefinition_different_typedef)
<< New->getUnderlyingType() << OldType;
@@ -577,8 +618,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
-
- if (objc_types || getLangOptions().Microsoft)
+
+ if (getLangOptions().Microsoft)
return;
// C++ [dcl.typedef]p2:
@@ -602,7 +643,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
(Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
Context.getSourceManager().isInSystemHeader(New->getLocation())))
return;
-
+
Diag(New->getLocation(), diag::warn_redefinition_of_typedef)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
@@ -611,7 +652,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
-static bool
+static bool
DeclHasAttr(const Decl *decl, const Attr *target) {
for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
if (attr->getKind() == target->getKind())
@@ -651,15 +692,15 @@ struct GNUCompatibleParamWarning {
///
/// Returns true if there was an error, false otherwise.
bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
- assert(!isa<OverloadedFunctionDecl>(OldD) &&
+ assert(!isa<OverloadedFunctionDecl>(OldD) &&
"Cannot merge with an overloaded function declaration");
// Verify the old decl was also a function.
FunctionDecl *Old = 0;
- if (FunctionTemplateDecl *OldFunctionTemplate
+ if (FunctionTemplateDecl *OldFunctionTemplate
= dyn_cast<FunctionTemplateDecl>(OldD))
Old = OldFunctionTemplate->getTemplatedDecl();
- else
+ else
Old = dyn_cast<FunctionDecl>(OldD);
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
@@ -675,12 +716,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
PrevDiag = diag::note_previous_definition;
else if (Old->isImplicit())
PrevDiag = diag::note_previous_implicit_declaration;
- else
+ else
PrevDiag = diag::note_previous_declaration;
-
+
QualType OldQType = Context.getCanonicalType(Old->getType());
QualType NewQType = Context.getCanonicalType(New->getType());
-
+
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == FunctionDecl::Static &&
Old->getStorageClass() != FunctionDecl::Static) {
@@ -693,11 +734,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
if (getLangOptions().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
- // -- Function declarations that differ only in the return type
+ // -- Function declarations that differ only in the return type
// cannot be overloaded.
- QualType OldReturnType
+ QualType OldReturnType
= cast<FunctionType>(OldQType.getTypePtr())->getResultType();
- QualType NewReturnType
+ QualType NewReturnType
= cast<FunctionType>(NewQType.getTypePtr())->getResultType();
if (OldReturnType != NewReturnType) {
Diag(New->getLocation(), diag::err_ovl_diff_return_type);
@@ -707,11 +748,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
- if (OldMethod && NewMethod &&
- OldMethod->getLexicalDeclContext() ==
- NewMethod->getLexicalDeclContext()) {
- // -- Member function declarations with the same name and the
- // same parameter types cannot be overloaded if any of them
+ 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);
@@ -732,7 +772,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
NewDiag = diag::err_conv_function_redeclared;
else
NewDiag = diag::err_member_redeclared;
-
+
Diag(New->getLocation(), NewDiag);
Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
}
@@ -750,8 +790,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
// duplicate function decls like "void f(int); void f(enum X);" properly.
if (!getLangOptions().CPlusPlus &&
Context.typesAreCompatible(OldQType, NewQType)) {
- const FunctionType *OldFuncType = OldQType->getAsFunctionType();
- const FunctionType *NewFuncType = NewQType->getAsFunctionType();
+ const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
+ const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
const FunctionProtoType *OldProto = 0;
if (isa<FunctionNoProtoType>(NewFuncType) &&
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) {
@@ -769,20 +809,20 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
// Synthesize a parameter for each argument type.
llvm::SmallVector<ParmVarDecl*, 16> Params;
- for (FunctionProtoType::arg_type_iterator
- ParamType = OldProto->arg_type_begin(),
+ for (FunctionProtoType::arg_type_iterator
+ ParamType = OldProto->arg_type_begin(),
ParamEnd = OldProto->arg_type_end();
ParamType != ParamEnd; ++ParamType) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
SourceLocation(), 0,
- *ParamType, VarDecl::None,
- 0);
+ *ParamType, /*DInfo=*/0,
+ VarDecl::None, 0);
Param->setImplicit();
Params.push_back(Param);
}
New->setParams(Context, Params.data(), Params.size());
- }
+ }
return MergeCompatibleFunctionDecls(New, Old);
}
@@ -800,29 +840,29 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
// C99 6.9.1p8.
if (!getLangOptions().CPlusPlus &&
Old->hasPrototype() && !New->hasPrototype() &&
- New->getType()->getAsFunctionProtoType() &&
+ New->getType()->getAs<FunctionProtoType>() &&
Old->getNumParams() == New->getNumParams()) {
llvm::SmallVector<QualType, 16> ArgTypes;
llvm::SmallVector<GNUCompatibleParamWarning, 16> Warnings;
- const FunctionProtoType *OldProto
- = Old->getType()->getAsFunctionProtoType();
- const FunctionProtoType *NewProto
- = New->getType()->getAsFunctionProtoType();
-
+ const FunctionProtoType *OldProto
+ = Old->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+
// Determine whether this is the GNU C extension.
QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(),
NewProto->getResultType());
bool LooseCompatible = !MergedReturn.isNull();
- for (unsigned Idx = 0, End = Old->getNumParams();
+ for (unsigned Idx = 0, End = Old->getNumParams();
LooseCompatible && Idx != End; ++Idx) {
ParmVarDecl *OldParm = Old->getParamDecl(Idx);
ParmVarDecl *NewParm = New->getParamDecl(Idx);
- if (Context.typesAreCompatible(OldParm->getType(),
+ if (Context.typesAreCompatible(OldParm->getType(),
NewProto->getArgType(Idx))) {
ArgTypes.push_back(NewParm->getType());
} else if (Context.typesAreCompatible(OldParm->getType(),
NewParm->getType())) {
- GNUCompatibleParamWarning Warn
+ GNUCompatibleParamWarning Warn
= { OldParm, NewParm, NewProto->getArgType(Idx) };
Warnings.push_back(Warn);
ArgTypes.push_back(NewParm->getType());
@@ -836,7 +876,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
diag::ext_param_promoted_not_compatible_with_prototype)
<< Warnings[Warn].PromotedType
<< Warnings[Warn].OldParm->getType();
- Diag(Warnings[Warn].OldParm->getLocation(),
+ Diag(Warnings[Warn].OldParm->getLocation(),
diag::note_previous_declaration);
}
@@ -851,7 +891,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
// A function that has already been declared has been redeclared or defined
// with a different type- show appropriate diagnostic
- if (unsigned BuiltinID = Old->getBuiltinID(Context)) {
+ if (unsigned BuiltinID = Old->getBuiltinID()) {
// The user has declared a builtin function with an incompatible
// signature.
if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
@@ -876,7 +916,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
}
/// \brief Completes the merge of two function declarations that are
-/// known to be compatible.
+/// known to be compatible.
///
/// This routine handles the merging of attributes and other
/// properties of function declarations form the old declaration to
@@ -889,25 +929,10 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
MergeAttributes(New, Old, Context);
// Merge the storage class.
- if (Old->getStorageClass() != FunctionDecl::Extern)
+ if (Old->getStorageClass() != FunctionDecl::Extern &&
+ Old->getStorageClass() != FunctionDecl::None)
New->setStorageClass(Old->getStorageClass());
- // Merge "inline"
- if (Old->isInline())
- New->setInline(true);
-
- // If this function declaration by itself qualifies as a C99 inline
- // definition (C99 6.7.4p6), but the previous definition did not,
- // then the function is not a C99 inline definition.
- if (New->isC99InlineDefinition() && !Old->isC99InlineDefinition())
- New->setC99InlineDefinition(false);
- else if (Old->isC99InlineDefinition() && !New->isC99InlineDefinition()) {
- // Mark all preceding definitions as not being C99 inline definitions.
- for (const FunctionDecl *Prev = Old; Prev;
- Prev = Prev->getPreviousDeclaration())
- const_cast<FunctionDecl *>(Prev)->setC99InlineDefinition(false);
- }
-
// Merge "pure" flag.
if (Old->isPure())
New->setPure();
@@ -915,7 +940,7 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
// Merge the "deleted" flag.
if (Old->isDeleted())
New->setDeleted();
-
+
if (getLangOptions().CPlusPlus)
return MergeCXXFunctionDecl(New, Old);
@@ -926,16 +951,16 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
/// and scope as a previous declaration 'Old'. Figure out how to resolve this
/// situation, merging decls or emitting diagnostics as appropriate.
///
-/// Tentative definition rules (C99 6.9.2p2) are checked by
-/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
+/// Tentative definition rules (C99 6.9.2p2) are checked by
+/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
-///
+///
void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
// If either decl is invalid, make sure the new one is marked invalid and
// don't do any other checking.
if (New->isInvalidDecl() || OldD->isInvalidDecl())
return New->setInvalidDecl();
-
+
// Verify the old decl was also a variable.
VarDecl *Old = dyn_cast<VarDecl>(OldD);
if (!Old) {
@@ -952,11 +977,24 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
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; [...]
+ else if (Old->getType()->isIncompleteArrayType() &&
+ New->getType()->isArrayType()) {
+ CanQual<ArrayType> OldArray
+ = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
+ CanQual<ArrayType> NewArray
+ = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
+ if (OldArray->getElementType() == NewArray->getElementType())
+ MergedT = New->getType();
+ }
} else {
MergedT = Context.mergeTypes(New->getType(), Old->getType());
}
if (MergedT.isNull()) {
- Diag(New->getLocation(), diag::err_redefinition_different_type)
+ Diag(New->getLocation(), diag::err_redefinition_different_type)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -970,7 +1008,7 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
- // C99 6.2.2p4:
+ // C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
// identifier is visible,23) if the prior declaration specifies
@@ -989,7 +1027,7 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
}
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
-
+
// FIXME: The test for external storage here seems wrong? We still
// need to check for mismatches.
if (!New->hasExternalStorage() && !New->isFileVarDecl() &&
@@ -1013,6 +1051,214 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
New->setPreviousDeclaration(Old);
}
+/// CheckFallThrough - Check that we don't fall off the end of a
+/// Statement that should return a value.
+///
+/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
+/// MaybeFallThrough iff we might or might not fall off the end and
+/// NeverFallThrough iff we never fall off the end of the statement. We assume
+/// that functions not marked noreturn will return.
+Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
+ llvm::OwningPtr<CFG> cfg (CFG::buildCFG(Root, &Context));
+
+ // FIXME: They should never return 0, fix that, delete this code.
+ if (cfg == 0)
+ return NeverFallThrough;
+ // The CFG leaves in dead things, and we don't want to dead code paths to
+ // confuse us, so we mark all live things first.
+ std::queue<CFGBlock*> workq;
+ llvm::BitVector live(cfg->getNumBlockIDs());
+ // Prep work queue
+ workq.push(&cfg->getEntry());
+ // Solve
+ while (!workq.empty()) {
+ CFGBlock *item = workq.front();
+ workq.pop();
+ live.set(item->getBlockID());
+ for (CFGBlock::succ_iterator I=item->succ_begin(),
+ E=item->succ_end();
+ I != E;
+ ++I) {
+ if ((*I) && !live[(*I)->getBlockID()]) {
+ live.set((*I)->getBlockID());
+ workq.push(*I);
+ }
+ }
+ }
+
+ // Now we know what is live, we check the live precessors of the exit block
+ // and look for fall through paths, being careful to ignore normal returns,
+ // and exceptional paths.
+ bool HasLiveReturn = false;
+ bool HasFakeEdge = false;
+ bool HasPlainEdge = false;
+ for (CFGBlock::succ_iterator I=cfg->getExit().pred_begin(),
+ E = cfg->getExit().pred_end();
+ I != E;
+ ++I) {
+ CFGBlock& B = **I;
+ if (!live[B.getBlockID()])
+ continue;
+ if (B.size() == 0) {
+ // A labeled empty statement, or the entry block...
+ HasPlainEdge = true;
+ continue;
+ }
+ Stmt *S = B[B.size()-1];
+ if (isa<ReturnStmt>(S)) {
+ HasLiveReturn = true;
+ continue;
+ }
+ if (isa<ObjCAtThrowStmt>(S)) {
+ HasFakeEdge = true;
+ continue;
+ }
+ if (isa<CXXThrowExpr>(S)) {
+ HasFakeEdge = true;
+ continue;
+ }
+ bool NoReturnEdge = false;
+ if (CallExpr *C = dyn_cast<CallExpr>(S)) {
+ Expr *CEE = C->getCallee()->IgnoreParenCasts();
+ if (CEE->getType().getNoReturnAttr()) {
+ 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;
+ }
+ }
+ }
+ }
+ // FIXME: Add noreturn message sends.
+ if (NoReturnEdge == false)
+ HasPlainEdge = true;
+ }
+ if (!HasPlainEdge)
+ return NeverFallThrough;
+ if (HasFakeEdge || HasLiveReturn)
+ return MaybeFallThrough;
+ // This says AlwaysFallThrough for calls to functions that are not marked
+ // noreturn, that don't return. If people would like this warning to be more
+ // accurate, such functions should be marked as noreturn.
+ return AlwaysFallThrough;
+}
+
+/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
+/// function that should return a value. Check that we don't fall off the end
+/// of a noreturn function. We assume that functions and blocks not marked
+/// noreturn will return.
+void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
+ // FIXME: Would be nice if we had a better way to control cascading errors,
+ // but for now, avoid them. The problem is that when Parse sees:
+ // int foo() { return a; }
+ // The return is eaten and the Sema code sees just:
+ // int foo() { }
+ // which this code would then warn about.
+ if (getDiagnostics().hasErrorOccurred())
+ return;
+ bool ReturnsVoid = false;
+ bool HasNoReturn = false;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // If the result type of the function is a dependent type, we don't know
+ // whether it will be void or not, so don't
+ if (FD->getResultType()->isDependentType())
+ return;
+ if (FD->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (FD->hasAttr<NoReturnAttr>())
+ HasNoReturn = true;
+ } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (MD->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (MD->hasAttr<NoReturnAttr>())
+ HasNoReturn = true;
+ }
+
+ // Short circuit for compilation speed.
+ if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
+ == Diagnostic::Ignored || ReturnsVoid)
+ && (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
+ == Diagnostic::Ignored || !HasNoReturn)
+ && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
+ == Diagnostic::Ignored || !ReturnsVoid))
+ return;
+ // FIXME: Function try block
+ if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+ switch (CheckFallThrough(Body)) {
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(),diag::warn_maybe_falloff_nonvoid_function);
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::warn_falloff_noreturn_function);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
+ break;
+ case NeverFallThrough:
+ if (ReturnsVoid)
+ Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
+ break;
+ }
+ }
+}
+
+/// CheckFallThroughForBlock - Check that we don't fall off the end of a block
+/// that should return a value. Check that we don't fall off the end of a
+/// noreturn block. We assume that functions and blocks not marked noreturn
+/// will return.
+void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
+ // FIXME: Would be nice if we had a better way to control cascading errors,
+ // but for now, avoid them. The problem is that when Parse sees:
+ // int foo() { return a; }
+ // The return is eaten and the Sema code sees just:
+ // int foo() { }
+ // which this code would then warn about.
+ if (getDiagnostics().hasErrorOccurred())
+ return;
+ bool ReturnsVoid = false;
+ bool HasNoReturn = false;
+ if (const FunctionType *FT = BlockTy->getPointeeType()->getAs<FunctionType>()) {
+ if (FT->getResultType()->isVoidType())
+ ReturnsVoid = true;
+ if (FT->getNoReturnAttr())
+ HasNoReturn = true;
+ }
+
+ // Short circuit for compilation speed.
+ if (ReturnsVoid
+ && !HasNoReturn
+ && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
+ == Diagnostic::Ignored || !ReturnsVoid))
+ return;
+ // FIXME: Funtion try block
+ if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
+ switch (CheckFallThrough(Body)) {
+ case MaybeFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(), diag::err_maybe_falloff_nonvoid_block);
+ break;
+ case AlwaysFallThrough:
+ if (HasNoReturn)
+ Diag(Compound->getRBracLoc(), diag::err_noreturn_block_has_return_expr);
+ else if (!ReturnsVoid)
+ Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
+ break;
+ case NeverFallThrough:
+ if (ReturnsVoid)
+ Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
+ break;
+ }
+ }
+}
+
/// CheckParmsForFunctionDef - Check that the parameters of the given
/// function are appropriate for the definition of a function. This
/// takes care of any checks that cannot be performed on the
@@ -1034,10 +1280,10 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
Param->setInvalidDecl();
HasInvalidParm = true;
}
-
+
// C99 6.9.1p5: If the declarator includes a parameter type list, the
// declaration of each parameter shall include an identifier.
- if (Param->getIdentifier() == 0 &&
+ if (Param->getIdentifier() == 0 &&
!Param->isImplicit() &&
!getLangOptions().CPlusPlus)
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
@@ -1056,17 +1302,31 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
// FIXME: Warn on useless const/volatile
// FIXME: Warn on useless static/extern/typedef/private_extern/mutable
// FIXME: Warn on useless attributes
+ Decl *TagD = 0;
TagDecl *Tag = 0;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
DS.getTypeSpecType() == DeclSpec::TST_struct ||
DS.getTypeSpecType() == DeclSpec::TST_union ||
DS.getTypeSpecType() == DeclSpec::TST_enum) {
- if (!DS.getTypeRep()) // We probably had an error
+ TagD = static_cast<Decl *>(DS.getTypeRep());
+
+ if (!TagD) // We probably had an error
return DeclPtrTy();
- Tag = dyn_cast<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
+ // Note that the above type specs guarantee that the
+ // type rep is a Decl, whereas in many of the others
+ // it's a Type.
+ Tag = dyn_cast<TagDecl>(TagD);
}
+ if (DS.isFriendSpecified()) {
+ // If we're dealing with a class template decl, assume that the
+ // template routines are handling it.
+ if (TagD && isa<ClassTemplateDecl>(TagD))
+ return DeclPtrTy();
+ return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
+ }
+
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
if (!Record->getDeclName() && Record->isDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
@@ -1084,8 +1344,8 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
if (Record->getDeclName() && getLangOptions().Microsoft)
return DeclPtrTy::make(Tag);
}
-
- if (!DS.isMissingDeclaratorOk() &&
+
+ if (!DS.isMissingDeclaratorOk() &&
DS.getTypeSpecType() != DeclSpec::TST_error) {
// Warn about typedefs of enums without names, since this is an
// extension in both Microsoft an GNU.
@@ -1100,7 +1360,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
<< DS.getSourceRange();
return DeclPtrTy();
}
-
+
return DeclPtrTy::make(Tag);
}
@@ -1127,14 +1387,16 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
FEnd = AnonRecord->field_end();
F != FEnd; ++F) {
if ((*F)->getDeclName()) {
- NamedDecl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(),
- LookupOrdinaryName, true);
+ LookupResult R;
+ LookupQualifiedName(R, Owner, (*F)->getDeclName(),
+ LookupOrdinaryName, true);
+ NamedDecl *PrevDecl = R.getAsSingleDecl(Context);
if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
// distinct from the names of any other entity in the
// scope in which the anonymous union is declared.
- unsigned diagKind
+ unsigned diagKind
= AnonRecord->isUnion()? diag::err_anonymous_union_member_redecl
: diag::err_anonymous_struct_member_redecl;
Diag((*F)->getLocation(), diagKind)
@@ -1152,10 +1414,10 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
IdResolver.AddDecl(*F);
}
} else if (const RecordType *InnerRecordType
- = (*F)->getType()->getAsRecordType()) {
+ = (*F)->getType()->getAs<RecordType>()) {
RecordDecl *InnerRecord = InnerRecordType->getDecl();
if (InnerRecord->isAnonymousStructOrUnion())
- Invalid = Invalid ||
+ Invalid = Invalid ||
InjectAnonymousStructOrUnionMembers(S, Owner, InnerRecord);
}
}
@@ -1166,7 +1428,7 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
/// ActOnAnonymousStructOrUnion - Handle the declaration of an
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a GNU C extension; anonymous structures
-/// are a GNU C and GNU C++ extension.
+/// are a GNU C and GNU C++ extension.
Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
RecordDecl *Record) {
DeclContext *Owner = Record->getDeclContext();
@@ -1176,40 +1438,42 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Diag(Record->getLocation(), diag::ext_anonymous_union);
else if (!Record->isUnion())
Diag(Record->getLocation(), diag::ext_anonymous_struct);
-
+
// C and C++ require different kinds of checks for anonymous
// structs/unions.
bool Invalid = false;
if (getLangOptions().CPlusPlus) {
const char* PrevSpec = 0;
+ unsigned DiagID;
// C++ [class.union]p3:
// Anonymous unions declared in a named namespace or in the
// global namespace shall be declared static.
if (DS.getStorageClassSpec() != DeclSpec::SCS_static &&
(isa<TranslationUnitDecl>(Owner) ||
- (isa<NamespaceDecl>(Owner) &&
+ (isa<NamespaceDecl>(Owner) &&
cast<NamespaceDecl>(Owner)->getDeclName()))) {
Diag(Record->getLocation(), diag::err_anonymous_union_not_static);
Invalid = true;
// Recover by adding 'static'.
- DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), PrevSpec);
- }
+ DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(),
+ PrevSpec, DiagID);
+ }
// C++ [class.union]p3:
// A storage class is not allowed in a declaration of an
// anonymous union in a class scope.
else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
isa<RecordDecl>(Owner)) {
- Diag(DS.getStorageClassSpecLoc(),
+ Diag(DS.getStorageClassSpecLoc(),
diag::err_anonymous_union_with_storage_spec);
Invalid = true;
// Recover by removing the storage specifier.
DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(),
- PrevSpec);
+ PrevSpec, DiagID);
}
- // C++ [class.union]p2:
+ // C++ [class.union]p2:
// The member-specification of an anonymous union shall only
// define non-static data members. [Note: nested types and
// functions cannot be declared within an anonymous union. ]
@@ -1255,7 +1519,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Invalid = true;
}
}
- }
+ }
if (!Record->isUnion() && !Owner->isRecord()) {
Diag(Record->getLocation(), diag::err_anonymous_struct_not_member)
@@ -1263,12 +1527,14 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Invalid = true;
}
- // Create a declaration for this anonymous struct/union.
+ // Create a declaration for this anonymous struct/union.
NamedDecl *Anon = 0;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(),
- /*IdentifierInfo=*/0,
+ /*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
+ // FIXME: Type source info.
+ /*DInfo=*/0,
/*BitWidth=*/0, /*Mutable=*/false);
Anon->setAccess(AS_public);
if (getLangOptions().CPlusPlus)
@@ -1293,9 +1559,11 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
}
Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
- /*IdentifierInfo=*/0,
+ /*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
- SC, DS.getSourceRange().getBegin());
+ // FIXME: Type source info.
+ /*DInfo=*/0,
+ SC);
}
Anon->setImplicit();
@@ -1315,7 +1583,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// members of this anonymous struct/union type, because otherwise
// the members could be injected twice: once by DeclContext when it
// builds its lookup table, and once by
- // InjectAnonymousStructOrUnionMembers.
+ // InjectAnonymousStructOrUnionMembers.
Record->setAnonymousStructOrUnion(true);
if (Invalid)
@@ -1338,28 +1606,39 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
return DeclarationName(D.getIdentifier());
case Declarator::DK_Constructor: {
- QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
- Ty = Context.getCanonicalType(Ty);
- return Context.DeclarationNames.getCXXConstructorName(Ty);
+ QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
+ return Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(Ty));
}
case Declarator::DK_Destructor: {
- QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
- Ty = Context.getCanonicalType(Ty);
- return Context.DeclarationNames.getCXXDestructorName(Ty);
+ QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
+ return Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(Ty));
}
case Declarator::DK_Conversion: {
// FIXME: We'd like to keep the non-canonical type for diagnostics!
- QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
- Ty = Context.getCanonicalType(Ty);
- return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
+ QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
+ return Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(Ty));
}
case Declarator::DK_Operator:
assert(D.getIdentifier() == 0 && "operator names have no identifier");
return Context.DeclarationNames.getCXXOperatorName(
D.getOverloadedOperator());
+
+ case Declarator::DK_TemplateId: {
+ TemplateName Name
+ = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);
+ if (TemplateDecl *Template = Name.getAsTemplateDecl())
+ return Template->getDeclName();
+ if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
+ return Ovl->getDeclName();
+
+ return DeclarationName();
+ }
}
assert(false && "Unknown name kind");
@@ -1389,8 +1668,8 @@ static bool isNearlyMatchingFunction(ASTContext &Context,
return true;
}
-Sema::DeclPtrTy
-Sema::HandleDeclarator(Scope *S, Declarator &D,
+Sema::DeclPtrTy
+Sema::HandleDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition) {
DeclarationName Name = GetNameForDeclarator(D);
@@ -1404,18 +1683,44 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
return DeclPtrTy();
}
-
+
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
-
+
+ // If this is an out-of-line definition of a member of a class template
+ // or class template partial specialization, we may need to rebuild the
+ // type specifier in the declarator. See RebuildTypeInCurrentInstantiation()
+ // for more information.
+ // FIXME: cope with decltype(expr) and typeof(expr) once the rebuilder can
+ // handle expressions properly.
+ DeclSpec &DS = const_cast<DeclSpec&>(D.getDeclSpec());
+ if (D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid() &&
+ isDependentScopeSpecifier(D.getCXXScopeSpec()) &&
+ (DS.getTypeSpecType() == DeclSpec::TST_typename ||
+ DS.getTypeSpecType() == DeclSpec::TST_typeofType ||
+ DS.getTypeSpecType() == DeclSpec::TST_typeofExpr ||
+ DS.getTypeSpecType() == DeclSpec::TST_decltype)) {
+ if (DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(), true)) {
+ // FIXME: Preserve type source info.
+ QualType T = GetTypeFromParser(DS.getTypeRep());
+ EnterDeclaratorContext(S, DC);
+ T = RebuildTypeInCurrentInstantiation(T, D.getIdentifierLoc(), Name);
+ ExitDeclaratorContext(S);
+ if (T.isNull())
+ return DeclPtrTy();
+ DS.UpdateTypeRep(T.getAsOpaquePtr());
+ }
+ }
+
DeclContext *DC;
NamedDecl *PrevDecl;
NamedDecl *New;
- QualType R = GetTypeForDeclarator(D, S);
+ DeclaratorInfo *DInfo = 0;
+ QualType R = GetTypeForDeclarator(D, S, &DInfo);
// See if this is a redefinition of a variable in the same scope.
if (D.getCXXScopeSpec().isInvalid()) {
@@ -1431,20 +1736,43 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
/* Do nothing*/;
else if (R->isFunctionType()) {
- if (CurContext->isFunctionOrMethod())
+ if (CurContext->isFunctionOrMethod() ||
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
NameKind = LookupRedeclarationWithLinkage;
} else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
NameKind = LookupRedeclarationWithLinkage;
+ else if (CurContext->getLookupContext()->isTranslationUnit() &&
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
+ NameKind = LookupRedeclarationWithLinkage;
DC = CurContext;
- PrevDecl = LookupName(S, Name, NameKind, true,
- D.getDeclSpec().getStorageClassSpec() !=
- DeclSpec::SCS_static,
- D.getIdentifierLoc());
+ LookupResult R;
+ LookupName(R, S, Name, NameKind, true,
+ NameKind == LookupRedeclarationWithLinkage,
+ D.getIdentifierLoc());
+ PrevDecl = R.getAsSingleDecl(Context);
} else { // Something like "int foo::x;"
- DC = computeDeclContext(D.getCXXScopeSpec());
- // FIXME: RequireCompleteDeclContext(D.getCXXScopeSpec()); ?
- PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
+ DC = computeDeclContext(D.getCXXScopeSpec(), true);
+
+ if (!DC) {
+ // If we could not compute the declaration context, it's because the
+ // declaration context is dependent but does not refer to a class,
+ // class template, or class template partial specialization. Complain
+ // and return early, to avoid the coming semantic disaster.
+ Diag(D.getIdentifierLoc(),
+ diag::err_template_qualified_declarator_no_match)
+ << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
+ << D.getCXXScopeSpec().getRange();
+ return DeclPtrTy();
+ }
+
+ if (!DC->isDependentContext() &&
+ RequireCompleteDeclContext(D.getCXXScopeSpec()))
+ return DeclPtrTy();
+
+ LookupResult Res;
+ LookupQualifiedName(Res, DC, Name, LookupOrdinaryName, true);
+ PrevDecl = Res.getAsSingleDecl(Context);
// C++ 7.3.1.2p2:
// Members (including explicit specializations of templates) of a named
@@ -1467,11 +1795,11 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
//
// In this case, PrevDecl will point to the overload set
// containing the two f's declared in X, but neither of them
- // matches.
+ // matches.
// First check whether we named the global scope.
if (isa<TranslationUnitDecl>(DC)) {
- Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope)
+ Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope)
<< Name << D.getCXXScopeSpec().getRange();
} else if (!CurContext->Encloses(DC)) {
// The qualifying scope doesn't enclose the original declaration.
@@ -1480,7 +1808,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
SourceRange R = D.getCXXScopeSpec().getRange();
if (isa<FunctionDecl>(CurContext))
Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
- else
+ else
Diag(L, diag::err_invalid_declarator_scope)
<< Name << cast<NamedDecl>(DC) << R;
D.setInvalidType();
@@ -1489,10 +1817,10 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
- if (!D.isInvalidType())
+ if (!D.isInvalidType())
if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl))
D.setInvalidType();
-
+
// Just pretend that we didn't see the previous declaration.
PrevDecl = 0;
}
@@ -1511,24 +1839,28 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
return DeclPtrTy();
}
-
- New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
+
+ New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, PrevDecl, Redeclaration);
} else if (R->isFunctionType()) {
- New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl,
+ New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, PrevDecl,
move(TemplateParamLists),
IsFunctionDefinition, Redeclaration);
} else {
- New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
+ New = ActOnVariableDeclarator(S, D, DC, R, DInfo, PrevDecl,
+ move(TemplateParamLists),
+ Redeclaration);
}
if (New == 0)
return DeclPtrTy();
-
- // If this has an identifier and is not an invalid redeclaration,
- // add it to the scope stack.
- if (Name && !(Redeclaration && New->isInvalidDecl()))
+
+ // 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()))
PushOnScopeChains(New, S);
-
+
return DeclPtrTy::make(New);
}
@@ -1544,14 +1876,16 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
// constant expression folding, like struct {char x[(int)(char*)2];}
SizeIsNegative = false;
- if (const PointerType* PTy = dyn_cast<PointerType>(T)) {
+ QualifierCollector Qs;
+ const Type *Ty = Qs.strip(T);
+
+ if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
QualType Pointee = PTy->getPointeeType();
QualType FixedType =
TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative);
if (FixedType.isNull()) return FixedType;
FixedType = Context.getPointerType(FixedType);
- FixedType.setCVRQualifiers(T.getCVRQualifiers());
- return FixedType;
+ return Qs.apply(FixedType);
}
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
@@ -1560,7 +1894,7 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
// FIXME: We should probably handle this case
if (VLATy->getElementType()->isVariablyModifiedType())
return QualType();
-
+
Expr::EvalResult EvalResult;
if (!VLATy->getSizeExpr() ||
!VLATy->getSizeExpr()->Evaluate(EvalResult, Context) ||
@@ -1568,9 +1902,18 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
return QualType();
llvm::APSInt &Res = EvalResult.Val.getInt();
- if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned()))
- return Context.getConstantArrayType(VLATy->getElementType(),
- Res, ArrayType::Normal, 0);
+ if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) {
+ Expr* ArySizeExpr = VLATy->getSizeExpr();
+ // FIXME: here we could "steal" (how?) ArySizeExpr from the VLA,
+ // so as to transfer ownership to the ConstantArrayWithExpr.
+ // Alternatively, we could "clone" it (how?).
+ // Since we don't know how to do things above, we just use the
+ // very same Expr*.
+ return Context.getConstantArrayWithExprType(VLATy->getElementType(),
+ Res, ArySizeExpr,
+ ArrayType::Normal, 0,
+ VLATy->getBracketsRange());
+ }
SizeIsNegative = true;
return QualType();
@@ -1578,7 +1921,7 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
/// \brief Register the given locally-scoped external C declaration so
/// that it can be found later for redeclarations
-void
+void
Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
Scope *S) {
assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
@@ -1609,21 +1952,22 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
// FIXME: We should probably indicate the identifier in question to avoid
// confusion for constructs like "inline int a(), b;"
if (D.getDeclSpec().isInlineSpecified())
- Diag(D.getDeclSpec().getInlineSpecLoc(),
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
diag::err_inline_non_function);
if (D.getDeclSpec().isVirtualSpecified())
- Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
diag::err_virtual_non_function);
if (D.getDeclSpec().isExplicitSpecified())
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
diag::err_explicit_non_function);
}
NamedDecl*
Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, Decl* PrevDecl, bool &Redeclaration) {
+ QualType R, DeclaratorInfo *DInfo,
+ NamedDecl* PrevDecl, bool &Redeclaration) {
// Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
@@ -1645,7 +1989,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TypedefDecl *NewTD = ParseTypedefDecl(S, D, R);
if (!NewTD) return 0;
-
+
if (D.isInvalidType())
NewTD->setInvalidDecl();
@@ -1663,7 +2007,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType T = NewTD->getUnderlyingType();
if (T->isVariablyModifiedType()) {
CurFunctionNeedsScopeChecking = true;
-
+
if (S->getFnParent() == 0) {
bool SizeIsNegative;
QualType FixedTy =
@@ -1682,6 +2026,19 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
}
+
+ // If this is the C FILE type, notify the AST context.
+ if (IdentifierInfo *II = NewTD->getIdentifier())
+ if (!NewTD->isInvalidDecl() &&
+ NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) {
+ if (II->isStr("FILE"))
+ Context.setFILEDecl(NewTD);
+ else if (II->isStr("jmp_buf"))
+ Context.setjmp_bufDecl(NewTD);
+ else if (II->isStr("sigjmp_buf"))
+ Context.setsigjmp_bufDecl(NewTD);
+ }
+
return NewTD;
}
@@ -1697,13 +2054,13 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
///
/// \param PrevDecl the previous declaration found by name
/// lookup
-///
+///
/// \param DC the context in which the new declaration is being
/// declared.
///
/// \returns true if PrevDecl is an out-of-scope previous declaration
/// for a new delcaration with the same name.
-static bool
+static bool
isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
ASTContext &Context) {
if (!PrevDecl)
@@ -1737,10 +2094,10 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
OuterContext = OuterContext->getParent();
while (!PrevOuterContext->isFileContext())
PrevOuterContext = PrevOuterContext->getParent();
-
+
// The previous declaration is in a different namespace, so it
// isn't the same function.
- if (OuterContext->getPrimaryContext() !=
+ if (OuterContext->getPrimaryContext() !=
PrevOuterContext->getPrimaryContext())
return false;
}
@@ -1752,7 +2109,9 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
NamedDecl*
Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R,NamedDecl* PrevDecl,
+ QualType R, DeclaratorInfo *DInfo,
+ NamedDecl* PrevDecl,
+ MultiTemplateParamsArg TemplateParamLists,
bool &Redeclaration) {
DeclarationName Name = GetNameForDeclarator(D);
@@ -1792,7 +2151,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
-
+
// If this is a register variable with an asm label specified, then this
// is a GNU extension.
if (SC == VarDecl::Register && D.getAsmLabel())
@@ -1805,7 +2164,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (DC->isRecord() && !CurContext->isRecord()) {
// This is an out-of-line definition of a static data member.
if (SC == VarDecl::Static) {
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< CodeModificationHint::CreateRemoval(
SourceRange(D.getDeclSpec().getStorageClassSpecLoc()));
@@ -1815,22 +2174,48 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (SC == VarDecl::Static) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
if (RD->isLocalClass())
- Diag(D.getIdentifierLoc(),
+ Diag(D.getIdentifierLoc(),
diag::err_static_data_member_not_allowed_in_local_class)
<< Name << RD->getDeclName();
}
}
-
-
- // The variable can not
- NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
- II, R, SC,
- // FIXME: Move to DeclGroup...
- D.getDeclSpec().getSourceRange().getBegin());
+
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
+ bool isExplicitSpecialization = false;
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ D.getCXXScopeSpec(),
+ (TemplateParameterList**)TemplateParamLists.get(),
+ TemplateParamLists.size(),
+ isExplicitSpecialization)) {
+ if (TemplateParams->size() > 0) {
+ // There is no such thing as a variable template.
+ Diag(D.getIdentifierLoc(), diag::err_template_variable)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+ return 0;
+ } else {
+ // There is an extraneous 'template<>' for this variable. Complain
+ // about it, but allow the declaration of the variable.
+ Diag(TemplateParams->getTemplateLoc(),
+ diag::err_template_variable_noparams)
+ << II
+ << SourceRange(TemplateParams->getTemplateLoc(),
+ TemplateParams->getRAngleLoc());
+
+ isExplicitSpecialization = true;
+ }
+ }
+
+ NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
+ II, R, DInfo, SC);
if (D.isInvalidType())
NewVD->setInvalidDecl();
-
+
if (D.getDeclSpec().isThreadSpecified()) {
if (NewVD->hasLocalStorage())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@@ -1850,7 +2235,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
- StringLiteral *SE = cast<StringLiteral>(E);
+ StringLiteral *SE = cast<StringLiteral>(E);
NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -1861,8 +2246,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
!(NewVD->hasLinkage() &&
isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
- PrevDecl = 0;
-
+ PrevDecl = 0;
+
// Merge the decl with the existing one if appropriate.
if (PrevDecl) {
if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
@@ -1875,16 +2260,31 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
} else if (D.getCXXScopeSpec().isSet()) {
// No previous declaration in the qualifying scope.
- Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
- << Name << D.getCXXScopeSpec().getRange();
+ Diag(D.getIdentifierLoc(), diag::err_no_member)
+ << Name << computeDeclContext(D.getCXXScopeSpec(), true)
+ << D.getCXXScopeSpec().getRange();
NewVD->setInvalidDecl();
}
CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration);
+ // This is an explicit specialization of a static data member. Check it.
+ if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
+ CheckMemberSpecialization(NewVD, PrevDecl))
+ NewVD->setInvalidDecl();
+
+ // attributes declared post-definition are currently ignored
+ if (PrevDecl) {
+ const VarDecl *Def = 0, *PrevVD = dyn_cast<VarDecl>(PrevDecl);
+ if (PrevVD->getDefinition(Def) && D.hasAttributes()) {
+ Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ }
+ }
+
// If this is a locally-scoped extern C variable, update the map of
// such variables.
- if (CurContext->isFunctionOrMethod() && NewVD->isExternC(Context) &&
+ if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
!NewVD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S);
@@ -1906,17 +2306,17 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
// If the decl is already known invalid, don't check it.
if (NewVD->isInvalidDecl())
return;
-
+
QualType T = NewVD->getType();
if (T->isObjCInterfaceType()) {
Diag(NewVD->getLocation(), diag::err_statically_allocated_object);
return NewVD->setInvalidDecl();
}
-
+
// The variable can not have an abstract class type.
if (RequireNonAbstractType(NewVD->getLocation(), T,
- diag::err_abstract_type_in_decl,
+ diag::err_abstract_type_in_decl,
AbstractVariableType))
return NewVD->setInvalidDecl();
@@ -1934,21 +2334,22 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
bool isVM = T->isVariablyModifiedType();
- if (isVM || NewVD->hasAttr<CleanupAttr>())
+ if (isVM || NewVD->hasAttr<CleanupAttr>() ||
+ NewVD->hasAttr<BlocksAttr>())
CurFunctionNeedsScopeChecking = true;
-
+
if ((isVM && NewVD->hasLinkage()) ||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
bool SizeIsNegative;
QualType FixedTy =
TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
-
+
if (FixedTy.isNull() && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
- // FIXME: This won't give the correct result for
- // int a[10][n];
+ // FIXME: This won't give the correct result for
+ // int a[10][n];
SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
-
+
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
<< SizeRange;
@@ -1959,8 +2360,8 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
<< SizeRange;
return NewVD->setInvalidDecl();
- }
-
+ }
+
if (FixedTy.isNull()) {
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope);
@@ -1968,12 +2369,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
return NewVD->setInvalidDecl();
}
-
+
Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
NewVD->setType(FixedTy);
}
- if (!PrevDecl && NewVD->isExternC(Context)) {
+ if (!PrevDecl && NewVD->isExternC()) {
// Since we did not find anything by this name and we're declaring
// an extern "C" variable, look for a non-visible extern "C"
// declaration with the same name.
@@ -1993,7 +2394,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
return NewVD->setInvalidDecl();
}
-
+
if (isVM && NewVD->hasAttr<BlocksAttr>()) {
Diag(NewVD->getLocation(), diag::err_block_on_vm);
return NewVD->setInvalidDecl();
@@ -2005,9 +2406,43 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
}
}
-NamedDecl*
+static bool isUsingDecl(Decl *D) {
+ return isa<UsingDecl>(D) || isa<UnresolvedUsingDecl>(D);
+}
+
+/// \brief Data used with FindOverriddenMethod
+struct FindOverriddenMethodData {
+ Sema *S;
+ CXXMethodDecl *Method;
+};
+
+/// \brief Member lookup function that determines whether a given C++
+/// method overrides a method in a base class, to be used with
+/// CXXRecordDecl::lookupInBases().
+static bool FindOverriddenMethod(CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *UserData) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ FindOverriddenMethodData *Data
+ = reinterpret_cast<FindOverriddenMethodData*>(UserData);
+ for (Path.Decls = BaseRecord->lookup(Data->Method->getDeclName());
+ Path.Decls.first != Path.Decls.second;
+ ++Path.Decls.first) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) {
+ OverloadedFunctionDecl::function_iterator MatchedDecl;
+ if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, MatchedDecl))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
- QualType R, NamedDecl* PrevDecl,
+ QualType R, DeclaratorInfo *DInfo,
+ NamedDecl* PrevDecl,
MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
@@ -2019,7 +2454,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
case DeclSpec::SCS_auto:
case DeclSpec::SCS_register:
case DeclSpec::SCS_mutable:
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_typecheck_sclass_func);
D.setInvalidType();
break;
@@ -2032,11 +2467,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// block scope shall have no explicit storage-class specifier
// other than extern
// See also (C++ [dcl.stc]p4).
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_block_func);
SC = FunctionDecl::None;
} else
- SC = FunctionDecl::Static;
+ SC = FunctionDecl::Static;
break;
}
case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break;
@@ -2045,35 +2480,43 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+ bool isFriend = D.getDeclSpec().isFriendSpecified();
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
// Check that the return type is not an abstract class type.
// For record types, this is done by the AbstractClassUsageDiagnoser once
- // the class has been completely parsed.
+ // the class has been completely parsed.
if (!DC->isRecord() &&
- RequireNonAbstractType(D.getIdentifierLoc(),
- R->getAsFunctionType()->getResultType(),
- diag::err_abstract_type_in_decl,
+ RequireNonAbstractType(D.getIdentifierLoc(),
+ R->getAs<FunctionType>()->getResultType(),
+ diag::err_abstract_type_in_decl,
AbstractReturnType))
D.setInvalidType();
-
+
// Do not allow returning a objc interface by-value.
- if (R->getAsFunctionType()->getResultType()->isObjCInterfaceType()) {
+ if (R->getAs<FunctionType>()->getResultType()->isObjCInterfaceType()) {
Diag(D.getIdentifierLoc(),
diag::err_object_cannot_be_passed_returned_by_value) << 0
- << R->getAsFunctionType()->getResultType();
+ << R->getAs<FunctionType>()->getResultType();
D.setInvalidType();
}
- // Check that we can declare a template here.
- if (TemplateParamLists.size() &&
- CheckTemplateDeclScope(S, TemplateParamLists))
- return 0;
-
bool isVirtualOkay = false;
FunctionDecl *NewFD;
+
+ if (isFriend) {
+ // DC is the namespace in which the function is being declared.
+ assert((DC->isFileContext() || PrevDecl) && "previously-undeclared "
+ "friend function being created in a non-namespace context");
+
+ // C++ [class.friend]p5
+ // A function can be defined in a friend declaration of a
+ // class . . . . Such a function is implicitly inline.
+ isInline |= IsFunctionDefinition;
+ }
+
if (D.getKind() == Declarator::DK_Constructor) {
// This is a C++ constructor declaration.
assert(DC->isRecord() &&
@@ -2082,19 +2525,19 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
R = CheckConstructorDeclarator(D, R, SC);
// Create the new declaration
- NewFD = CXXConstructorDecl::Create(Context,
+ NewFD = CXXConstructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R,
+ D.getIdentifierLoc(), Name, R, DInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
} else if (D.getKind() == Declarator::DK_Destructor) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
R = CheckDestructorDeclarator(D, SC);
-
+
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R,
+ D.getIdentifierLoc(), Name, R,
isInline,
/*isImplicitlyDeclared=*/false);
@@ -2105,10 +2548,8 @@ 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, SC, isInline,
- /*hasPrototype=*/true,
- // FIXME: Move to DeclGroup...
- D.getDeclSpec().getSourceRange().getBegin());
+ Name, R, DInfo, SC, isInline,
+ /*hasPrototype=*/true);
D.setInvalidType();
}
} else if (D.getKind() == Declarator::DK_Conversion) {
@@ -2117,29 +2558,29 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
diag::err_conv_function_not_member);
return 0;
}
-
+
CheckConversionDeclarator(D, R, SC);
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R,
+ D.getIdentifierLoc(), Name, R, DInfo,
isInline, isExplicit);
-
+
isVirtualOkay = true;
} else if (DC->isRecord()) {
// If the of the function is the same as the name of the record, then this
- // must be an invalid constructor that has a return type.
- // (The parser checks for a return type and makes the declarator a
+ // must be an invalid constructor that has a return type.
+ // (The parser checks for a return type and makes the declarator a
// constructor if it has no return type).
- // must have an invalid constructor that has a return type
+ // must have an invalid constructor that has a return type
if (Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
return 0;
}
-
+
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R,
+ D.getIdentifierLoc(), Name, R, DInfo,
(SC == FunctionDecl::Static), isInline);
isVirtualOkay = (SC != FunctionDecl::Static);
@@ -2150,44 +2591,56 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// - there is a prototype in the declarator, or
// - the type R of the function is some kind of typedef or other reference
// to a type name (which eventually refers to a function type).
- bool HasPrototype =
+ bool HasPrototype =
getLangOptions().CPlusPlus ||
(D.getNumTypeObjects() && D.getTypeObject(0).Fun.hasPrototype) ||
(!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
-
+
NewFD = FunctionDecl::Create(Context, DC,
D.getIdentifierLoc(),
- Name, R, SC, isInline, HasPrototype,
- // FIXME: Move to DeclGroup...
- D.getDeclSpec().getSourceRange().getBegin());
+ Name, R, DInfo, SC, isInline, HasPrototype);
}
if (D.isInvalidType())
NewFD->setInvalidDecl();
-
+
// Set the lexical context. If the declarator has a C++
- // scope specifier, the lexical context will be different
- // from the semantic context.
+ // scope specifier, or is the object of a friend declaration, the
+ // lexical context will be different from the semantic context.
NewFD->setLexicalDeclContext(CurContext);
- // If there is a template parameter list, then we are dealing with a
- // template declaration or specialization.
+ // Match up the template parameter lists with the scope specifier, then
+ // determine whether we have a template or a template specialization.
FunctionTemplateDecl *FunctionTemplate = 0;
- if (TemplateParamLists.size()) {
- // FIXME: member templates!
- TemplateParameterList *TemplateParams
- = static_cast<TemplateParameterList *>(*TemplateParamLists.release());
-
+ bool isExplicitSpecialization = false;
+ bool isFunctionTemplateSpecialization = false;
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ D.getCXXScopeSpec(),
+ (TemplateParameterList**)TemplateParamLists.get(),
+ TemplateParamLists.size(),
+ isExplicitSpecialization)) {
if (TemplateParams->size() > 0) {
// This is a function template
- FunctionTemplate = FunctionTemplateDecl::Create(Context, CurContext,
+
+ // Check that we can declare a template here.
+ if (CheckTemplateDeclScope(S, TemplateParams))
+ return 0;
+
+ FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
NewFD->getLocation(),
Name, TemplateParams,
NewFD);
+ FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
} else {
- // FIXME: Handle function template specializations
+ // This is a function template specialization.
+ isFunctionTemplateSpecialization = true;
}
+
+ // FIXME: Free this memory properly.
+ TemplateParamLists.release();
}
// C++ [dcl.fct.spec]p5:
@@ -2197,7 +2650,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
//
if (isVirtual && !NewFD->isInvalidDecl()) {
if (!isVirtualOkay) {
- Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ Diag(D.getDeclSpec().getVirtualSpecLoc(),
diag::err_virtual_non_function);
} else if (!CurContext->isRecord()) {
// 'virtual' was specified outside of the class.
@@ -2210,28 +2663,47 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
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);
+ }
+ }
+
+ if (isFriend) {
+ if (FunctionTemplate) {
+ FunctionTemplate->setObjectOfFriendDecl(
+ /* PreviouslyDeclared= */ PrevDecl != NULL);
+ FunctionTemplate->setAccess(AS_public);
}
+ else
+ NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL);
+
+ NewFD->setAccess(AS_public);
}
+
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) {
// Look for virtual methods in base classes that this method might override.
-
- BasePaths Paths;
- if (LookupInBases(cast<CXXRecordDecl>(DC),
- MemberLookupCriteria(NewMD), Paths)) {
- for (BasePaths::decl_iterator I = Paths.found_decls_begin(),
+ CXXBasePaths Paths;
+ FindOverriddenMethodData Data;
+ Data.Method = NewMD;
+ Data.S = this;
+ if (cast<CXXRecordDecl>(DC)->lookupInBases(&FindOverriddenMethod, &Data,
+ Paths)) {
+ for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(),
E = Paths.found_decls_end(); I != E; ++I) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
- if (!CheckOverridingFunctionReturnType(NewMD, OldMD))
+ if (!CheckOverridingFunctionReturnType(NewMD, OldMD) &&
+ !CheckOverridingFunctionExceptionSpec(NewMD, OldMD))
NewMD->addOverriddenMethod(OldMD);
}
}
}
}
-
- if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) &&
+
+ if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) &&
!CurContext->isRecord()) {
// C++ [class.static]p1:
// A data or function member of a class may be declared static
@@ -2240,7 +2712,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Complain about the 'static' specifier if it's on an out-of-line
// member function definition.
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< CodeModificationHint::CreateRemoval(
SourceRange(D.getDeclSpec().getStorageClassSpecLoc()));
@@ -2249,7 +2721,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
- StringLiteral *SE = cast<StringLiteral>(E);
+ StringLiteral *SE = cast<StringLiteral>(E);
NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -2278,11 +2750,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(Param->getLocation(), diag::err_param_typedef_of_void);
// FIXME: Leaks decl?
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
- Params.push_back(FTI.ArgInfo[i].Param.getAs<ParmVarDecl>());
+ for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+ ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ assert(Param->getDeclContext() != NewFD && "Was set before ?");
+ Param->setDeclContext(NewFD);
+ Params.push_back(Param);
+ }
}
-
- } else if (const FunctionProtoType *FT = R->getAsFunctionProtoType()) {
+
+ } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) {
// When we're declaring a function with a typedef, typeof, etc as in the
// following example, we'll need to synthesize (unnamed)
// parameters for use in the declaration.
@@ -2291,13 +2767,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// typedef void fn(int);
// fn f;
// @endcode
-
+
// Synthesize a parameter for each argument type.
for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
AE = FT->arg_type_end(); AI != AE; ++AI) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, DC,
SourceLocation(), 0,
- *AI, VarDecl::None, 0);
+ *AI, /*DInfo=*/0,
+ VarDecl::None, 0);
Param->setImplicit();
Params.push_back(Param);
}
@@ -2307,7 +2784,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
// Finally, we know we have the right number of parameters, install them.
NewFD->setParams(Context, Params.data(), Params.size());
-
+
// If name lookup finds a previous declaration that is not in the
// same scope as the new declaration, this may still be an
// acceptable redeclaration.
@@ -2316,27 +2793,80 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
PrevDecl = 0;
+ // If the declarator is a template-id, translate the parser's template
+ // argument list into our AST format.
+ bool HasExplicitTemplateArgs = false;
+ llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ SourceLocation LAngleLoc, RAngleLoc;
+ if (D.getKind() == Declarator::DK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getTemplateId();
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->getTemplateArgIsType(),
+ TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr,
+ TemplateId->getTemplateArgLocations(),
+ TemplateArgs);
+ TemplateArgsPtr.release();
+
+ HasExplicitTemplateArgs = true;
+ LAngleLoc = TemplateId->LAngleLoc;
+ RAngleLoc = TemplateId->RAngleLoc;
+
+ if (FunctionTemplate) {
+ // FIXME: Diagnose function template with explicit template
+ // arguments.
+ HasExplicitTemplateArgs = false;
+ } else if (!isFunctionTemplateSpecialization &&
+ !D.getDeclSpec().isFriendSpecified()) {
+ // We have encountered something that the user meant to be a
+ // specialization (because it has explicitly-specified template
+ // arguments) but that was not introduced with a "template<>" (or had
+ // too few of them).
+ Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header)
+ << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
+ << CodeModificationHint::CreateInsertion(
+ D.getDeclSpec().getSourceRange().getBegin(),
+ "template<> ");
+ isFunctionTemplateSpecialization = true;
+ }
+ }
+
+ if (isFunctionTemplateSpecialization) {
+ if (CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs,
+ LAngleLoc, TemplateArgs.data(),
+ TemplateArgs.size(), RAngleLoc,
+ PrevDecl))
+ NewFD->setInvalidDecl();
+ } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
+ CheckMemberSpecialization(NewFD, PrevDecl))
+ NewFD->setInvalidDecl();
+
// Perform semantic checking on the function declaration.
bool OverloadableAttrRequired = false; // FIXME: HACK!
- CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration,
- /*FIXME:*/OverloadableAttrRequired);
+ CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization,
+ Redeclaration, /*FIXME:*/OverloadableAttrRequired);
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
- if (!IsFunctionDefinition) {
+ // Note that this is not the case for explicit specializations of
+ // function templates or member functions of class templates, per
+ // C++ [temp.expl.spec]p2.
+ if (!IsFunctionDefinition && !isFriend &&
+ !isFunctionTemplateSpecialization && !isExplicitSpecialization) {
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
- } else if (!Redeclaration && (!PrevDecl || !isa<UsingDecl>(PrevDecl))) {
+ } else if (!Redeclaration && (!PrevDecl || !isUsingDecl(PrevDecl))) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
- // was no such member function declared (C++ [class.mfct]p2,
+ // was no such member function declared (C++ [class.mfct]p2,
// C++ [namespace.memdef]p2). For example:
- //
+ //
// class X {
// void f() const;
- // };
+ // };
//
// void X::f() { } // ill-formed
//
@@ -2344,12 +2874,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// matches (e.g., those that differ only in cv-qualifiers and
// whether the parameter types are references).
Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
- << cast<NamedDecl>(DC) << D.getCXXScopeSpec().getRange();
+ << Name << DC << D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
-
- LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName,
- true);
- assert(!Prev.isAmbiguous() &&
+
+ LookupResult Prev;
+ LookupQualifiedName(Prev, DC, Name, LookupOrdinaryName, true);
+ assert(!Prev.isAmbiguous() &&
"Cannot have an ambiguity in previous-declaration lookup");
for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
Func != FuncEnd; ++Func) {
@@ -2357,7 +2887,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
Diag((*Func)->getLocation(), diag::note_member_def_close_match);
}
-
+
PrevDecl = 0;
}
}
@@ -2367,6 +2897,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// FIXME: This needs to happen before we merge declarations. Then,
// let attribute merging cope with attribute conflicts.
ProcessDeclAttributes(S, NewFD, D);
+
+ // attributes declared post-definition are currently ignored
+ if (Redeclaration && PrevDecl) {
+ const FunctionDecl *Def, *PrevFD = dyn_cast<FunctionDecl>(PrevDecl);
+ if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) {
+ Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ }
+ }
+
AddKnownFunctionAttributes(NewFD);
if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
@@ -2375,14 +2915,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
<< Redeclaration << NewFD;
if (PrevDecl)
- Diag(PrevDecl->getLocation(),
+ Diag(PrevDecl->getLocation(),
diag::note_attribute_overloadable_prev_overload);
NewFD->addAttr(::new (Context) OverloadableAttr());
}
// If this is a locally-scoped extern C function, update the
// map of such names.
- if (CurContext->isFunctionOrMethod() && NewFD->isExternC(Context)
+ if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
&& !NewFD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S);
@@ -2391,10 +2931,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (FunctionTemplate && NewFD->isInvalidDecl())
FunctionTemplate->setInvalidDecl();
-
+
if (FunctionTemplate)
return FunctionTemplate;
-
+
return NewFD;
}
@@ -2408,8 +2948,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// that have been instantiated via C++ template instantiation (called
/// via InstantiateDecl).
///
+/// \param IsExplicitSpecialiation whether this new function declaration is
+/// an explicit specialization of the previous declaration.
+///
/// This sets NewFD->isInvalidDecl() to true if there was an error.
void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+ bool IsExplicitSpecialization,
bool &Redeclaration,
bool &OverloadableAttrRequired) {
// If NewFD is already known erroneous, don't do any of this checking.
@@ -2423,51 +2967,11 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
return NewFD->setInvalidDecl();
}
- // Semantic checking for this function declaration (in isolation).
- if (getLangOptions().CPlusPlus) {
- // C++-specific checks.
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
- CheckConstructor(Constructor);
- } else if (isa<CXXDestructorDecl>(NewFD)) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
- Record->setUserDeclaredDestructor(true);
- // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
- // user-defined destructor.
- Record->setPOD(false);
-
- // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
- // declared destructor.
- Record->setHasTrivialDestructor(false);
- } else if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>(NewFD))
- ActOnConversionDeclarator(Conversion);
-
- // Extra checking for C++ overloaded operators (C++ [over.oper]).
- if (NewFD->isOverloadedOperator() &&
- CheckOverloadedOperatorDeclaration(NewFD))
- return NewFD->setInvalidDecl();
- }
-
- // C99 6.7.4p6:
- // [... ] For a function with external linkage, the following
- // restrictions apply: [...] If all of the file scope declarations
- // for a function in a translation unit include the inline
- // function specifier without extern, then the definition in that
- // translation unit is an inline definition. An inline definition
- // does not provide an external definition for the function, and
- // does not forbid an external definition in another translation
- // unit.
- //
- // Here we determine whether this function, in isolation, would be a
- // C99 inline definition. MergeCompatibleFunctionDecls looks at
- // previous declarations.
- if (NewFD->isInline() && getLangOptions().C99 &&
- NewFD->getStorageClass() == FunctionDecl::None &&
- NewFD->getDeclContext()->getLookupContext()->isTranslationUnit())
- NewFD->setC99InlineDefinition(true);
+ if (NewFD->isMain())
+ CheckMain(NewFD);
// Check for a previous declaration of this name.
- if (!PrevDecl && NewFD->isExternC(Context)) {
+ if (!PrevDecl && NewFD->isExternC()) {
// Since we did not find anything by this name and we're declaring
// an extern "C" function, look for a non-visible extern "C"
// declaration with the same name.
@@ -2492,24 +2996,23 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
// Functions marked "overloadable" must have a prototype (that
// we can't get through declaration merging).
- if (!NewFD->getType()->getAsFunctionProtoType()) {
+ 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()->getAsFunctionType()->getResultType(),
+ NewFD->getType()->getAs<FunctionType>()->getResultType(),
0, 0, true, 0);
NewFD->setType(R);
return NewFD->setInvalidDecl();
}
}
- if (PrevDecl &&
- (!AllowOverloadingOfFunction(PrevDecl, Context) ||
- !IsOverload(NewFD, PrevDecl, MatchedDecl)) &&
- !isa<UsingDecl>(PrevDecl)) {
+ if (PrevDecl &&
+ (!AllowOverloadingOfFunction(PrevDecl, Context) ||
+ !IsOverload(NewFD, PrevDecl, MatchedDecl)) && !isUsingDecl(PrevDecl)) {
Redeclaration = true;
Decl *OldDecl = PrevDecl;
@@ -2519,23 +3022,160 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
OldDecl = *MatchedDecl;
// NewFD and OldDecl represent declarations that need to be
- // merged.
+ // merged.
if (MergeFunctionDecl(NewFD, OldDecl))
return NewFD->setInvalidDecl();
if (FunctionTemplateDecl *OldTemplateDecl
- = dyn_cast<FunctionTemplateDecl>(OldDecl))
- NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
- else
+ = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
+ NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ FunctionTemplateDecl *NewTemplateDecl
+ = NewFD->getDescribedFunctionTemplate();
+ assert(NewTemplateDecl && "Template/non-template mismatch");
+ if (CXXMethodDecl *Method
+ = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) {
+ Method->setAccess(OldTemplateDecl->getAccess());
+ NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
+ }
+
+ // If this is an explicit specialization of a member that is a function
+ // template, mark it as a member specialization.
+ if (IsExplicitSpecialization &&
+ NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+ NewTemplateDecl->setMemberSpecialization();
+ assert(OldTemplateDecl->isMemberSpecialization());
+ }
+ } else {
+ if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
+ NewFD->setAccess(OldDecl->getAccess());
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+ }
}
}
- // In C++, check default arguments now that we have merged decls. Unless
- // the lexical context is the class, because in this case this is done
- // during delayed parsing anyway.
- if (getLangOptions().CPlusPlus && !CurContext->isRecord())
- CheckCXXDefaultArguments(NewFD);
+ // Semantic checking for this function declaration (in isolation).
+ if (getLangOptions().CPlusPlus) {
+ // C++-specific checks.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+ CheckConstructor(Constructor);
+ } else if (isa<CXXDestructorDecl>(NewFD)) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
+ QualType ClassType = Context.getTypeDeclType(Record);
+ if (!ClassType->isDependentType()) {
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(ClassType));
+ if (NewFD->getDeclName() != Name) {
+ Diag(NewFD->getLocation(), diag::err_destructor_name);
+ return NewFD->setInvalidDecl();
+ }
+ }
+ Record->setUserDeclaredDestructor(true);
+ // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
+ // user-defined destructor.
+ Record->setPOD(false);
+
+ // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly-
+ // declared destructor.
+ // FIXME: C++0x: don't do this for "= default" destructors
+ Record->setHasTrivialDestructor(false);
+ } else if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>(NewFD))
+ ActOnConversionDeclarator(Conversion);
+
+ // Extra checking for C++ overloaded operators (C++ [over.oper]).
+ if (NewFD->isOverloadedOperator() &&
+ CheckOverloadedOperatorDeclaration(NewFD))
+ return NewFD->setInvalidDecl();
+
+ // In C++, check default arguments now that we have merged decls. Unless
+ // the lexical context is the class, because in this case this is done
+ // during delayed parsing anyway.
+ if (!CurContext->isRecord())
+ CheckCXXDefaultArguments(NewFD);
+ }
+}
+
+void Sema::CheckMain(FunctionDecl* FD) {
+ // C++ [basic.start.main]p3: A program that declares main to be inline
+ // or static is ill-formed.
+ // C99 6.7.4p4: In a hosted environment, the inline function specifier
+ // shall not appear in a declaration of main.
+ // static main is not an error under C99, but we should warn about it.
+ bool isInline = FD->isInline();
+ bool isStatic = FD->getStorageClass() == FunctionDecl::Static;
+ if (isInline || isStatic) {
+ unsigned diagID = diag::warn_unusual_main_decl;
+ if (isInline || getLangOptions().CPlusPlus)
+ diagID = diag::err_unusual_main_decl;
+
+ int which = isStatic + (isInline << 1) - 1;
+ Diag(FD->getLocation(), diagID) << which;
+ }
+
+ QualType T = FD->getType();
+ assert(T->isFunctionType() && "function decl is not of function type");
+ const FunctionType* FT = T->getAs<FunctionType>();
+
+ if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) {
+ // TODO: add a replacement fixit to turn the return type into 'int'.
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+ FD->setInvalidDecl(true);
+ }
+
+ // Treat protoless main() as nullary.
+ if (isa<FunctionNoProtoType>(FT)) return;
+
+ const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT);
+ unsigned nparams = FTP->getNumArgs();
+ assert(FD->getNumParams() == nparams);
+
+ if (nparams > 3) {
+ Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams;
+ FD->setInvalidDecl(true);
+ nparams = 3;
+ }
+
+ // FIXME: a lot of the following diagnostics would be improved
+ // if we had some location information about types.
+
+ QualType CharPP =
+ Context.getPointerType(Context.getPointerType(Context.CharTy));
+ QualType Expected[] = { Context.IntTy, CharPP, CharPP };
+
+ for (unsigned i = 0; i < nparams; ++i) {
+ QualType AT = FTP->getArgType(i);
+
+ bool mismatch = true;
+
+ if (Context.hasSameUnqualifiedType(AT, Expected[i]))
+ mismatch = false;
+ else if (Expected[i] == CharPP) {
+ // As an extension, the following forms are okay:
+ // char const **
+ // char const * const *
+ // char * const *
+
+ QualifierCollector qs;
+ const PointerType* PT;
+ if ((PT = qs.strip(AT)->getAs<PointerType>()) &&
+ (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) &&
+ (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) {
+ qs.removeConst();
+ mismatch = !qs.empty();
+ }
+ }
+
+ if (mismatch) {
+ Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i];
+ // TODO: suggest replacing given type with expected type
+ FD->setInvalidDecl(true);
+ }
+ }
+
+ if (nparams == 1 && !FD->isInvalidDecl()) {
+ Diag(FD->getLocation(), diag::warn_main_one_arg);
+ }
}
bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
@@ -2554,8 +3194,8 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
return true;
}
-void Sema::AddInitializerToDecl(DeclPtrTy dcl, FullExprArg init) {
- AddInitializerToDecl(dcl, init.release(), /*DirectInit=*/false);
+void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init) {
+ AddInitializerToDecl(dcl, move(init), /*DirectInit=*/false);
}
/// AddInitializerToDecl - Adds the initializer Init to the
@@ -2567,7 +3207,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// the initializer.
if (RealDecl == 0)
return;
-
+
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
// With declarators parsed the way they are, the parser cannot
// distinguish between a normal initializer and a pure-specifier.
@@ -2616,7 +3256,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
const VarDecl *Def = 0;
if (VDecl->getDefinition(Def)) {
- Diag(VDecl->getLocation(), diag::err_redefinition)
+ Diag(VDecl->getLocation(), diag::err_redefinition)
<< VDecl->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition);
VDecl->setInvalidDecl();
@@ -2639,7 +3279,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
VDecl->getDeclName(), DirectInit))
VDecl->setInvalidDecl();
-
+
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
// Don't check invalid declarations to avoid emitting useless diagnostics.
if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
@@ -2647,7 +3287,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
CheckForConstantInitializer(Init, DclT);
}
}
- } else if (VDecl->isStaticDataMember() &&
+ } else if (VDecl->isStaticDataMember() &&
VDecl->getLexicalDeclContext()->isRecord()) {
// This is an in-class initialization for a static data member, e.g.,
//
@@ -2663,7 +3303,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// if it declares a static member (9.4) of const integral or
// const enumeration type, see 9.4.2.
QualType T = VDecl->getType();
- if (!T->isDependentType() &&
+ if (!T->isDependentType() &&
(!Context.getCanonicalType(T).isConstQualified() ||
!T->isIntegralType())) {
Diag(VDecl->getLocation(), diag::err_member_initialization)
@@ -2678,7 +3318,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
if (!Init->isTypeDependent() &&
!Init->getType()->isIntegralType()) {
// We have a non-dependent, non-integral or enumeration type.
- Diag(Init->getSourceRange().getBegin(),
+ Diag(Init->getSourceRange().getBegin(),
diag::err_in_class_initializer_non_integral_type)
<< Init->getType() << Init->getSourceRange();
VDecl->setInvalidDecl();
@@ -2701,7 +3341,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
VDecl->getDeclName(), DirectInit))
VDecl->setInvalidDecl();
-
+
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
// Don't check invalid declarations to avoid emitting useless diagnostics.
if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
@@ -2710,14 +3350,16 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
}
}
// If the type changed, it means we had an incomplete type that was
- // completed by the initializer. For example:
+ // completed by the initializer. For example:
// int ary[] = { 1, 3, 5 };
// "ary" transitions from a VariableArrayType to a ConstantArrayType.
if (!VDecl->isInvalidDecl() && (DclT != SavT)) {
VDecl->setType(DclT);
Init->setType(DclT);
}
-
+
+ Init = MaybeCreateCXXExprWithTemporaries(Init,
+ /*ShouldDestroyTemporaries=*/true);
// Attach the initializer to the decl.
VDecl->setInit(Context, Init);
@@ -2725,17 +3367,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// remove it from the set of tentative definitions.
if (VDecl->getPreviousDeclaration() &&
VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) {
- llvm::DenseMap<DeclarationName, VarDecl *>::iterator Pos
- = TentativeDefinitions.find(VDecl->getDeclName());
- assert(Pos != TentativeDefinitions.end() &&
- "Unrecorded tentative definition?");
- TentativeDefinitions.erase(Pos);
+ bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName());
+ assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted;
}
return;
}
-void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
+void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
+ bool TypeContainsUndeducedAuto) {
Decl *RealDecl = dcl.getAs<Decl>();
// If there is no declaration, there was an error parsing it. Just ignore it.
@@ -2746,8 +3386,20 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
QualType Type = Var->getType();
// Record tentative definitions.
- if (Var->isTentativeDefinition(Context))
- TentativeDefinitions[Var->getDeclName()] = Var;
+ if (Var->isTentativeDefinition(Context)) {
+ std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool>
+ InsertPair =
+ TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var));
+
+ // 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;
+
+ // 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());
+ }
// C++ [dcl.init.ref]p3:
// The initializer can be omitted for a reference only in a
@@ -2763,46 +3415,72 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
return;
}
+ // C++0x [dcl.spec.auto]p3
+ if (TypeContainsUndeducedAuto) {
+ Diag(Var->getLocation(), diag::err_auto_var_requires_init)
+ << Var->getDeclName() << Type;
+ 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;
+
// 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 = Array->getElementType();
- if ((!Var->hasExternalStorage() && !Var->isExternC(Context)) &&
+ if ((!Var->hasExternalStorage() && !Var->isExternC()) &&
InitType->isRecordType() && !InitType->isDependentType()) {
- CXXRecordDecl *RD =
- cast<CXXRecordDecl>(InitType->getAsRecordType()->getDecl());
- CXXConstructorDecl *Constructor = 0;
- if (!RequireCompleteType(Var->getLocation(), InitType,
- diag::err_invalid_incomplete_type_use))
- Constructor
- = PerformInitializationByConstructor(InitType, 0, 0,
+ if (!RequireCompleteType(Var->getLocation(), InitType,
+ diag::err_invalid_incomplete_type_use)) {
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+
+ CXXConstructorDecl *Constructor
+ = PerformInitializationByConstructor(InitType,
+ MultiExprArg(*this, 0, 0),
Var->getLocation(),
SourceRange(Var->getLocation(),
Var->getLocation()),
Var->getDeclName(),
- IK_Default);
- if (!Constructor)
+ IK_Default,
+ ConstructorArgs);
+
+ // FIXME: Location info for the variable initialization?
+ if (!Constructor)
+ Var->setInvalidDecl();
+ else {
+ // FIXME: Cope with initialization of arrays
+ if (!Constructor->isTrivial() &&
+ InitializeVarWithConstructor(Var, Constructor, InitType,
+ move_arg(ConstructorArgs)))
+ Var->setInvalidDecl();
+
+ FinalizeVarWithDestructor(Var, InitType);
+ }
+ } else {
Var->setInvalidDecl();
- else {
- if (!RD->hasTrivialConstructor())
- InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
- // FIXME. Must do all that is needed to destroy the object
- // on scope exit. For now, just mark the destructor as used.
- MarkDestructorReferenced(Var->getLocation(), InitType);
}
}
}
#if 0
// FIXME: Temporarily disabled because we are not properly parsing
- // linkage specifications on declarations, e.g.,
+ // linkage specifications on declarations, e.g.,
//
// extern "C" const CGPoint CGPointerZero;
//
@@ -2844,7 +3522,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
for (unsigned i = 0; i != NumDecls; ++i)
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) {
@@ -2852,38 +3530,40 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
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 (!IDecl->isInvalidDecl() &&
- RequireCompleteType(IDecl->getLocation(), T,
+ RequireCompleteType(IDecl->getLocation(), T,
diag::err_typecheck_decl_incomplete_type))
IDecl->setInvalidDecl();
}
- // File scope. C99 6.9.2p2: A declaration of an identifier for and
+ // 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)) {
- QualType CheckType = T;
- unsigned DiagID = diag::err_typecheck_decl_incomplete_type;
-
- const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(T);
- if (ArrayT) {
- CheckType = ArrayT->getElementType();
- DiagID = diag::err_illegal_decl_array_incomplete_type;
- }
-
- if (IDecl->isInvalidDecl()) {
- // Do nothing with invalid declarations
- } else if ((ArrayT || IDecl->getStorageClass() == VarDecl::Static) &&
- RequireCompleteType(IDecl->getLocation(), CheckType, DiagID)) {
+ 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
+ // a tentative definition and has internal linkage (C99 6.2.2p3), the
// declared type shall not be an incomplete type.
- IDecl->setInvalidDecl();
+ // 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);
}
}
}
@@ -2894,7 +3574,7 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
/// to introduce parameters into function prototype scope.
-Sema::DeclPtrTy
+Sema::DeclPtrTy
Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
@@ -2917,10 +3597,12 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// parameter (C++ only).
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
-
+
+ DeclaratorInfo *DInfo = 0;
TagDecl *OwnedDecl = 0;
- QualType parmDeclType = GetTypeForDeclarator(D, S, /*Skip=*/0, &OwnedDecl);
-
+ QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0,
+ &OwnedDecl);
+
if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
@@ -2933,7 +3615,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// among each other. Here they can only shadow globals, which is ok.
IdentifierInfo *II = D.getIdentifier();
if (II) {
- if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
+ if (NamedDecl *PrevDecl = LookupSingleName(S, II, LookupOrdinaryName)) {
if (PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
@@ -2951,26 +3633,26 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
- // the class has been completely parsed.
- if (!CurContext->isRecord() &&
- RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType,
+ // the class has been completely parsed.
+ if (!CurContext->isRecord() &&
+ RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType,
diag::err_abstract_type_in_decl,
AbstractParamType))
D.setInvalidType(true);
QualType T = adjustParameterType(parmDeclType);
-
+
ParmVarDecl *New;
if (T == parmDeclType) // parameter type did not need adjustment
- New = ParmVarDecl::Create(Context, CurContext,
+ New = ParmVarDecl::Create(Context, CurContext,
D.getIdentifierLoc(), II,
- parmDeclType, StorageClass,
+ parmDeclType, DInfo, StorageClass,
0);
else // keep track of both the adjusted and unadjusted types
- New = OriginalParmVarDecl::Create(Context, CurContext,
- D.getIdentifierLoc(), II, T,
+ New = OriginalParmVarDecl::Create(Context, CurContext,
+ D.getIdentifierLoc(), II, T, DInfo,
parmDeclType, StorageClass, 0);
-
+
if (D.isInvalidType())
New->setInvalidDecl();
@@ -2981,14 +3663,25 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
diag::err_object_cannot_be_passed_returned_by_value) << 1 << T;
New->setInvalidDecl();
}
-
+
// Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
if (D.getCXXScopeSpec().isSet()) {
Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator)
<< D.getCXXScopeSpec().getRange();
New->setInvalidDecl();
}
-
+
+ // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
+ // duration shall not be qualified by an address-space qualifier."
+ // Since all parameters have automatic store duration, they can not have
+ // an address space.
+ if (T.getAddressSpace() != 0) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_arg_with_address_space);
+ New->setInvalidDecl();
+ }
+
+
// Add the parameter declaration into this scope.
S->AddDecl(DeclPtrTy::make(New));
if (II)
@@ -3025,14 +3718,15 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
// type.
DeclSpec DS;
const char* PrevSpec; // unused
- DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
- PrevSpec);
+ unsigned DiagID; // unused
+ DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc,
+ PrevSpec, DiagID);
Declarator ParamD(DS, Declarator::KNRTypeListContext);
ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc);
FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD);
}
}
- }
+ }
}
Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
@@ -3043,12 +3737,12 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
if (FTI.hasPrototype) {
- // FIXME: Diagnose arguments without names in C.
+ // FIXME: Diagnose arguments without names in C.
}
-
+
Scope *ParentScope = FnBodyScope->getParent();
- DeclPtrTy DP = HandleDeclarator(ParentScope, D,
+ DeclPtrTy DP = HandleDeclarator(ParentScope, D,
MultiTemplateParamsArg(*this),
/*IsFunctionDefinition=*/true);
return ActOnStartOfFunctionDef(FnBodyScope, DP);
@@ -3057,10 +3751,16 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
if (!D)
return D;
- FunctionDecl *FD = cast<FunctionDecl>(D.getAs<Decl>());
+ FunctionDecl *FD = 0;
+
+ if (FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>(D.getAs<Decl>()))
+ FD = FunTmpl->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(D.getAs<Decl>());
CurFunctionNeedsScopeChecking = false;
-
+
// See if this is a redefinition.
const FunctionDecl *Definition;
if (FD->getBody(Definition)) {
@@ -3069,7 +3769,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
}
// Builtin functions cannot be defined.
- if (unsigned BuiltinID = FD->getBuiltinID(Context)) {
+ if (unsigned BuiltinID = FD->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
Diag(FD->getLocation(), diag::err_builtin_definition) << FD;
FD->setInvalidDecl();
@@ -3126,7 +3826,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// Checking attributes of current function definition
// dllimport attribute.
- if (FD->getAttr<DLLImportAttr>() &&
+ if (FD->getAttr<DLLImportAttr>() &&
(!FD->getAttr<DLLExportAttr>())) {
// dllimport attribute cannot be applied to definition.
if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
@@ -3155,23 +3855,39 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
bool IsInstantiation) {
Decl *dcl = D.getAs<Decl>();
Stmt *Body = BodyArg.takeAs<Stmt>();
- if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
+
+ FunctionDecl *FD = 0;
+ FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
+ if (FunTmpl)
+ FD = FunTmpl->getTemplatedDecl();
+ else
+ FD = dyn_cast_or_null<FunctionDecl>(dcl);
+
+ if (FD) {
FD->setBody(Body);
-
+ if (FD->isMain())
+ // C and C++ allow for main to automagically return 0.
+ // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3.
+ FD->setHasImplicitReturnZero(true);
+ else
+ CheckFallThroughForFunctionDef(FD, Body);
+
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);
-
+
assert(FD == getCurFunctionDecl() && "Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
-
+ CheckFallThroughForFunctionDef(MD, Body);
+ MD->setEndLoc(Body->getLocEnd());
+
if (!MD->isInvalidDecl())
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
} else {
@@ -3184,21 +3900,21 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
// Verify and clean out per-function state.
assert(&getLabelMap() == &FunctionLabelMap && "Didn't pop block right?");
-
+
// Check goto/label use.
for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
I = FunctionLabelMap.begin(), E = FunctionLabelMap.end(); I != E; ++I) {
LabelStmt *L = I->second;
-
+
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
// definitions are indicated with a null substmt.
if (L->getSubStmt() != 0)
continue;
-
+
// Emit error.
Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
-
+
// At this point, we have gotos that use the bogus label. Stitch it into
// the function body so that they aren't leaked and that the AST is well
// formed.
@@ -3207,7 +3923,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
L->Destroy(Context);
continue;
}
-
+
// Otherwise, the body is valid: we want to stitch the label decl into the
// function somewhere so that it is properly owned and so that the goto
// has a valid target. Do this by creating a new compound stmt with the
@@ -3231,17 +3947,20 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
if (CurFunctionNeedsScopeChecking)
DiagnoseInvalidJumps(Body);
- // C++ constructors that have function-try-blocks can't have return statements
- // in the handlers of that block. (C++ [except.handle]p14) Verify this.
- if (isa<CXXConstructorDecl>(dcl) && isa<CXXTryStmt>(Body))
+ // C++ constructors that have function-try-blocks can't have return
+ // statements in the handlers of that block. (C++ [except.handle]p14)
+ // Verify this.
+ if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body))
DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
+ if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
+ computeBaseOrMembersToDestroy(Destructor);
return D;
}
/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
-NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
+NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
IdentifierInfo &II, Scope *S) {
// Before we produce a declaration for an implicitly defined
// function, see whether there was a locally-scoped declaration of
@@ -3256,25 +3975,26 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
}
// Extension in C99. Legal in C90, but warn about it.
- if (getLangOptions().C99)
+ static const unsigned int BuiltinLen = strlen("__builtin_");
+ if (II.getLength() > BuiltinLen &&
+ std::equal(II.getName(), II.getName() + BuiltinLen, "__builtin_"))
+ Diag(Loc, diag::warn_builtin_unknown) << &II;
+ else if (getLangOptions().C99)
Diag(Loc, diag::ext_implicit_function_decl) << &II;
else
Diag(Loc, diag::warn_implicit_function_decl) << &II;
-
- // FIXME: handle stuff like:
- // void foo() { extern float X(); }
- // void bar() { X(); } <-- implicit decl for X in another scope.
// Set a Declarator for the implicit definition: int foo();
const char *Dummy;
DeclSpec DS;
- bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy);
+ unsigned DiagID;
+ bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID);
Error = Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
Declarator D(DS, Declarator::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
0, 0, false, SourceLocation(),
- false, 0,0,0, Loc, D),
+ false, 0,0,0, Loc, Loc, D),
SourceLocation());
D.SetIdentifier(&II, Loc);
@@ -3282,8 +4002,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
DeclContext *PrevDC = CurContext;
CurContext = Context.getTranslationUnitDecl();
-
- FunctionDecl *FD =
+
+ FunctionDecl *FD =
dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
FD->setImplicit();
@@ -3306,7 +4026,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// If this is a built-in function, map its builtin attributes to
// actual attributes.
- if (unsigned BuiltinID = FD->getBuiltinID(Context)) {
+ if (unsigned BuiltinID = FD->getBuiltinID()) {
// Handle printf-formatting attributes.
unsigned FormatIdx;
bool HasVAListArg;
@@ -3324,15 +4044,18 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (!FD->getAttr<ConstAttr>())
FD->addAttr(::new (Context) ConstAttr());
}
+
+ if (Context.BuiltinInfo.isNoReturn(BuiltinID))
+ FD->addAttr(::new (Context) NoReturnAttr());
}
IdentifierInfo *Name = FD->getIdentifier();
if (!Name)
return;
- if ((!getLangOptions().CPlusPlus &&
+ if ((!getLangOptions().CPlusPlus &&
FD->getDeclContext()->isTranslationUnit()) ||
(isa<LinkageSpecDecl>(FD->getDeclContext()) &&
- cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() ==
+ cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() ==
LinkageSpecDecl::lang_c)) {
// Okay: this could be a libc/libm/Objective-C function we know
// about.
@@ -3340,13 +4063,16 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
return;
if (Name->isStr("NSLog") || Name->isStr("NSLogv")) {
+ // 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");
- } else
+ } else
FD->addAttr(::new (Context) FormatAttr("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,
Name->isStr("vasprintf") ? 0 : 3));
@@ -3356,16 +4082,16 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
-
+
// Scope manipulation handled by caller.
TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext,
D.getIdentifierLoc(),
- D.getIdentifier(),
+ D.getIdentifier(),
T);
-
- if (TagType *TT = dyn_cast<TagType>(T)) {
+
+ if (const TagType *TT = T->getAs<TagType>()) {
TagDecl *TD = TT->getDecl();
-
+
// If the TagDecl that the TypedefDecl points to is an anonymous decl
// keep track of the TypedefDecl.
if (!TD->getIdentifier() && !TD->getTypedefForAnonDecl())
@@ -3382,7 +4108,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) {
/// as a redeclaration of the given tag declaration.
///
/// \returns true if the new tag kind is acceptable, false otherwise.
-bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
+bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
TagDecl::TagKind NewTag,
SourceLocation NewTagLoc,
const IdentifierInfo &Name) {
@@ -3402,7 +4128,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
TagDecl::TagKind OldTag = Previous->getTagKind();
if (OldTag == NewTag)
return true;
-
+
if ((OldTag == TagDecl::TK_struct || OldTag == TagDecl::TK_class) &&
(NewTag == TagDecl::TK_struct || NewTag == TagDecl::TK_class)) {
// Warn about the struct/class tag mismatch.
@@ -3423,33 +4149,58 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the
/// former case, Name will be non-null. In the later case, Name will be null.
-/// TagSpec indicates what kind of tag this is. TK indicates whether this is a
+/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
/// reference/declaration/definition of a tag.
-Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
+Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
- bool &OwnedDecl) {
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent) {
// If this is not a definition, it must have a name.
- assert((Name != 0 || TK == TK_Definition) &&
+ assert((Name != 0 || TUK == TUK_Definition) &&
"Nameless record must be a definition!");
OwnedDecl = false;
- TagDecl::TagKind Kind;
- switch (TagSpec) {
- default: assert(0 && "Unknown tag type!");
- case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
- case DeclSpec::TST_union: Kind = TagDecl::TK_union; break;
- case DeclSpec::TST_class: Kind = TagDecl::TK_class; break;
- case DeclSpec::TST_enum: Kind = TagDecl::TK_enum; break;
+ TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
+
+ // FIXME: Check explicit specializations more carefully.
+ bool isExplicitSpecialization = false;
+ if (TUK != TUK_Reference) {
+ if (TemplateParameterList *TemplateParams
+ = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
+ (TemplateParameterList**)TemplateParameterLists.get(),
+ TemplateParameterLists.size(),
+ isExplicitSpecialization)) {
+ if (TemplateParams->size() > 0) {
+ // This is a declaration or definition of a class template (which may
+ // be a member of another template).
+ OwnedDecl = false;
+ DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
+ SS, Name, NameLoc, Attr,
+ TemplateParams,
+ AS);
+ TemplateParameterLists.release();
+ return Result.get();
+ } else {
+ // The "template<>" header is extraneous.
+ Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
+ << ElaboratedType::getNameForTagKind(Kind) << Name;
+ isExplicitSpecialization = true;
+ }
+ }
+
+ TemplateParameterLists.release();
}
-
+
DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
NamedDecl *PrevDecl = 0;
-
+ bool isStdBadAlloc = false;
bool Invalid = false;
+ bool RedeclarationOnly = (TUK != TUK_Reference);
+
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
@@ -3459,18 +4210,35 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
goto CreateNewDecl;
}
+ // If this is a friend or a reference to a class in a dependent
+ // context, don't try to make a decl for it.
+ if (TUK == TUK_Friend || TUK == TUK_Reference) {
+ DC = computeDeclContext(SS, false);
+ if (!DC) {
+ IsDependent = true;
+ return DeclPtrTy();
+ }
+ }
+
if (RequireCompleteDeclContext(SS))
return DeclPtrTy::make((Decl *)0);
- DC = computeDeclContext(SS);
+ DC = computeDeclContext(SS, true);
SearchDC = DC;
// Look-up name inside 'foo::'.
- PrevDecl
- = dyn_cast_or_null<TagDecl>(
- LookupQualifiedName(DC, Name, LookupTagName, true).getAsDecl());
+ LookupResult R;
+ LookupQualifiedName(R, DC, Name, LookupTagName, RedeclarationOnly);
+
+ if (R.isAmbiguous()) {
+ DiagnoseAmbiguousLookup(R, Name, NameLoc, SS.getRange());
+ return DeclPtrTy();
+ }
+
+ if (R.getKind() == LookupResult::Found)
+ PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl());
// A tag 'foo::bar' must already exist.
- if (PrevDecl == 0) {
+ if (!PrevDecl) {
Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
Name = 0;
Invalid = true;
@@ -3482,8 +4250,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
// FIXME: We're looking into outer scopes here, even when we
// shouldn't be. Doing so can result in ambiguities that we
// shouldn't be diagnosing.
- LookupResult R = LookupName(S, Name, LookupTagName,
- /*RedeclarationOnly=*/(TK != TK_Reference));
+ LookupResult R;
+ LookupName(R, S, Name, LookupTagName, RedeclarationOnly);
if (R.isAmbiguous()) {
DiagnoseAmbiguousLookup(R, Name, NameLoc);
// FIXME: This is not best way to recover from case like:
@@ -3494,11 +4262,10 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
Name = 0;
PrevDecl = 0;
Invalid = true;
- }
- else
- PrevDecl = R;
+ } else
+ PrevDecl = R.getAsSingleDecl(Context);
- if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
+ if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
// with C structs, unions, and enums when looking for a matching
// tag declaration or definition. See the similar lookup tweak
@@ -3515,23 +4282,37 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
PrevDecl = 0;
}
+ if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
+ DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) {
+ // This is a declaration of or a reference to "std::bad_alloc".
+ isStdBadAlloc = true;
+
+ if (!PrevDecl && StdBadAlloc) {
+ // std::bad_alloc has been implicitly declared (but made invisible to
+ // name lookup). Fill in this implicit declaration as the previous
+ // declaration, so that the declarations get chained appropriately.
+ PrevDecl = StdBadAlloc;
+ }
+ }
+
if (PrevDecl) {
// Check whether the previous declaration is usable.
(void)DiagnoseUseOfDecl(PrevDecl, NameLoc);
-
+
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
// If this is a use of a previous tag, or if the tag is already declared
// in the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
- if (TK == TK_Reference || isDeclInScope(PrevDecl, SearchDC, S)) {
+ if (TUK == TUK_Reference || TUK == TUK_Friend ||
+ isDeclInScope(PrevDecl, SearchDC, S)) {
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) {
- bool SafeToContinue
+ bool SafeToContinue
= (PrevTagDecl->getTagKind() != TagDecl::TK_enum &&
Kind != TagDecl::TK_enum);
if (SafeToContinue)
- Diag(KWLoc, diag::err_use_with_wrong_tag)
+ Diag(KWLoc, diag::err_use_with_wrong_tag)
<< Name
<< CodeModificationHint::CreateReplacement(SourceRange(KWLoc),
PrevTagDecl->getKindName());
@@ -3539,7 +4320,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
Diag(PrevDecl->getLocation(), diag::note_previous_use);
- if (SafeToContinue)
+ if (SafeToContinue)
Kind = PrevTagDecl->getTagKind();
else {
// Recover by making this an anonymous redefinition.
@@ -3556,27 +4337,35 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
// for the consumer of this Decl to know it doesn't own it.
// For our current ASTs this shouldn't be a problem, but will
// need to be changed with DeclGroups.
- if (TK == TK_Reference)
+ if (TUK == TUK_Reference || TUK == TUK_Friend)
return DeclPtrTy::make(PrevDecl);
// Diagnose attempts to redefine a tag.
- if (TK == TK_Definition) {
+ if (TUK == TUK_Definition) {
if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
- Diag(NameLoc, diag::err_redefinition) << Name;
- Diag(Def->getLocation(), diag::note_previous_definition);
- // If this is a redefinition, recover by making this
- // struct be anonymous, which will make any later
- // references get the previous definition.
- Name = 0;
- PrevDecl = 0;
- Invalid = true;
+ // 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.
+ if (!isExplicitSpecialization ||
+ !isa<CXXRecordDecl>(Def) ||
+ cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization) {
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ // If this is a redefinition, recover by making this
+ // struct be anonymous, which will make any later
+ // references get the previous definition.
+ Name = 0;
+ PrevDecl = 0;
+ Invalid = true;
+ }
} else {
// If the type is currently being defined, complain
// about a nested redefinition.
TagType *Tag = cast<TagType>(Context.getTagDeclType(PrevTagDecl));
if (Tag->isBeingDefined()) {
Diag(NameLoc, diag::err_nested_redefinition) << Name;
- Diag(PrevTagDecl->getLocation(),
+ Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
Name = 0;
PrevDecl = 0;
@@ -3589,10 +4378,11 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
}
}
// If we get here we have (another) forward declaration or we
- // have a definition. Just create a new decl.
+ // have a definition. Just create a new decl.
+
} else {
// If we get here, this is a definition of a new tag type in a nested
- // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
+ // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
// new decl/type. We set PrevDecl to NULL so that the entities
// have distinct types.
PrevDecl = 0;
@@ -3617,10 +4407,10 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
PrevDecl = 0;
}
}
- } else if (TK == TK_Reference && SS.isEmpty() && Name &&
+ } else if (TUK == TUK_Reference && SS.isEmpty() && Name &&
(Kind != TagDecl::TK_enum || !getLangOptions().CPlusPlus)) {
// C++ [basic.scope.pdecl]p5:
- // -- for an elaborated-type-specifier of the form
+ // -- for an elaborated-type-specifier of the form
//
// class-key identifier
//
@@ -3641,26 +4431,38 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
//
// Find the context where we'll be declaring the tag.
// FIXME: We would like to maintain the current DeclContext as the
- // lexical context,
+ // lexical context,
while (SearchDC->isRecord())
SearchDC = SearchDC->getParent();
// Find the scope where we'll be declaring the tag.
- while (S->isClassScope() ||
+ while (S->isClassScope() ||
(getLangOptions().CPlusPlus && S->isFunctionPrototypeScope()) ||
((S->getFlags() & Scope::DeclScope) == 0) ||
- (S->getEntity() &&
+ (S->getEntity() &&
((DeclContext *)S->getEntity())->isTransparentContext()))
S = S->getParent();
+
+ } else if (TUK == TUK_Friend && SS.isEmpty() && Name) {
+ // C++ [namespace.memdef]p3:
+ // If a friend declaration in a non-local class first declares a
+ // class or function, the friend class or function is a member of
+ // the innermost enclosing namespace.
+ while (!SearchDC->isFileContext())
+ SearchDC = SearchDC->getParent();
+
+ // The entity of a decl scope is a DeclContext; see PushDeclContext.
+ while (S->getEntity() != SearchDC)
+ S = S->getParent();
}
CreateNewDecl:
-
+
// If there is an identifier, use the location of the identifier as the
// location of the decl, otherwise use the location of the struct/union
// keyword.
SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc;
-
+
// Otherwise, create a new declaration. If there is a previous
// declaration of the same entity, the two will be linked via
// PrevDecl.
@@ -3669,10 +4471,10 @@ CreateNewDecl:
if (Kind == TagDecl::TK_enum) {
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
// enum X { A, B, C } D; D should chain to X.
- New = EnumDecl::Create(Context, SearchDC, Loc, Name,
+ New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc,
cast_or_null<EnumDecl>(PrevDecl));
// If this is an undefined enum, warn.
- if (TK != TK_Definition && !Invalid) {
+ if (TUK != TUK_Definition && !Invalid) {
unsigned DK = getLangOptions().CPlusPlus? diag::err_forward_ref_enum
: diag::ext_forward_ref_enum;
Diag(Loc, DK);
@@ -3682,12 +4484,15 @@ CreateNewDecl:
// FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
// struct X { int A; } D; D should chain to X.
- if (getLangOptions().CPlusPlus)
+ if (getLangOptions().CPlusPlus) {
// FIXME: Look for a way to use RecordDecl for simple structs.
- New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name,
+ New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
cast_or_null<CXXRecordDecl>(PrevDecl));
- else
- New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name,
+
+ if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit()))
+ StdBadAlloc = cast<CXXRecordDecl>(New);
+ } else
+ New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
cast_or_null<RecordDecl>(PrevDecl));
}
@@ -3704,7 +4509,7 @@ CreateNewDecl:
// the #pragma tokens are effectively skipped over during the
// parsing of the struct).
if (unsigned Alignment = getPragmaPackAlignment())
- New->addAttr(::new (Context) PackedAttr(Alignment * 8));
+ New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8));
}
if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) {
@@ -3713,12 +4518,14 @@ CreateNewDecl:
// shall not be declared with the same name as a typedef-name
// that is declared in that scope and refers to a type other
// than the class or enumeration itself.
- LookupResult Lookup = LookupName(S, Name, LookupOrdinaryName, true);
+ LookupResult Lookup;
+ LookupName(Lookup, S, Name, LookupOrdinaryName, true);
TypedefDecl *PrevTypedef = 0;
- if (Lookup.getKind() == LookupResult::Found)
- PrevTypedef = dyn_cast<TypedefDecl>(Lookup.getAsDecl());
+ if (NamedDecl *Prev = Lookup.getAsSingleDecl(Context))
+ PrevTypedef = dyn_cast<TypedefDecl>(Prev);
- if (PrevTypedef && isDeclInScope(PrevTypedef, SearchDC, S) &&
+ NamedDecl *PrevTypedefNamed = PrevTypedef;
+ if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) &&
Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) !=
Context.getCanonicalType(Context.getTypeDeclType(New))) {
Diag(Loc, diag::err_tag_definition_of_typedef)
@@ -3729,6 +4536,11 @@ CreateNewDecl:
}
}
+ // If this is a specialization of a member class (of a class template),
+ // check the specialization.
+ if (isExplicitSpecialization && CheckMemberSpecialization(New, PrevDecl))
+ Invalid = true;
+
if (Invalid)
New->setInvalidDecl();
@@ -3744,21 +4556,45 @@ CreateNewDecl:
// lexical context will be different from the semantic context.
New->setLexicalDeclContext(CurContext);
+ // Mark this as a friend decl if applicable.
+ if (TUK == TUK_Friend)
+ New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL);
+
// Set the access specifier.
- if (!Invalid)
+ if (!Invalid && TUK != TUK_Friend)
SetMemberAccessSpecifier(New, PrevDecl, AS);
- if (TK == TK_Definition)
+ if (TUK == TUK_Definition)
New->startDefinition();
-
+
// If this has an identifier, add it to the scope stack.
- if (Name) {
+ if (TUK == TUK_Friend) {
+ // We might be replacing an existing declaration in the lookup tables;
+ // if so, borrow its access specifier.
+ if (PrevDecl)
+ New->setAccess(PrevDecl->getAccess());
+
+ // Friend tag decls are visible in fairly strange ways.
+ if (!CurContext->isDependentContext()) {
+ DeclContext *DC = New->getDeclContext()->getLookupContext();
+ DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+ if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+ PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
+ }
+ } else if (Name) {
S = getNonFieldDeclScope(S);
PushOnScopeChains(New, S);
} else {
CurContext->addDecl(New);
}
+ // If this is the C FILE type, notify the AST context.
+ if (IdentifierInfo *II = New->getIdentifier())
+ if (!New->isInvalidDecl() &&
+ New->getDeclContext()->getLookupContext()->isTranslationUnit() &&
+ II->isStr("FILE"))
+ Context.setFILEDecl(New);
+
OwnedDecl = true;
return DeclPtrTy::make(New);
}
@@ -3774,7 +4610,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) {
FieldCollector->StartClass();
if (Record->getIdentifier()) {
- // C++ [class]p2:
+ // C++ [class]p2:
// [...] The class-name is also inserted into the scope of the
// class itself; this is known as the injected-class-name. For
// purposes of access checking, the injected-class-name is treated
@@ -3782,21 +4618,25 @@ void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) {
CXXRecordDecl *InjectedClassName
= CXXRecordDecl::Create(Context, Record->getTagKind(),
CurContext, Record->getLocation(),
- Record->getIdentifier(), Record);
+ Record->getIdentifier(),
+ Record->getTagKeywordLoc(),
+ Record);
InjectedClassName->setImplicit();
InjectedClassName->setAccess(AS_public);
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate())
InjectedClassName->setDescribedClassTemplate(Template);
PushOnScopeChains(InjectedClassName, S);
- assert(InjectedClassName->isInjectedClassName() &&
+ assert(InjectedClassName->isInjectedClassName() &&
"Broken injected-class-name");
}
}
}
-void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD) {
+void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
+ SourceLocation RBraceLoc) {
AdjustDeclIfTemplate(TagD);
TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+ Tag->setRBraceLoc(RBraceLoc);
if (isa<CXXRecordDecl>(Tag))
FieldCollector->FinishClass();
@@ -3809,9 +4649,13 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD) {
}
// Note that FieldName may be null for anonymous bitfields.
-bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
- QualType FieldTy, const Expr *BitWidth) {
-
+bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+ QualType FieldTy, const Expr *BitWidth,
+ bool *ZeroWidth) {
+ // Default to true; that shouldn't confuse checks for emptiness
+ if (ZeroWidth)
+ *ZeroWidth = true;
+
// C99 6.7.2.1p4 - verify the field type.
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) {
@@ -3834,13 +4678,16 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
if (VerifyIntegerConstantExpression(BitWidth, &Value))
return true;
+ if (Value != 0 && ZeroWidth)
+ *ZeroWidth = false;
+
// Zero-width bitfield is ok for anonymous field.
if (Value == 0 && FieldName)
return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
-
+
if (Value.isSigned() && Value.isNegative()) {
if (FieldName)
- return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
+ return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
<< FieldName << Value.toString(10);
return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
<< Value.toString(10);
@@ -3863,7 +4710,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
/// ActOnField - Each field of a struct/union/class is passed into this in order
/// to create a FieldDecl object for it.
Sema::DeclPtrTy Sema::ActOnField(Scope *S, DeclPtrTy TagD,
- SourceLocation DeclStart,
+ SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth) {
FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD.getAs<Decl>()),
DeclStart, D, static_cast<Expr*>(BitfieldWidth),
@@ -3880,8 +4727,9 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
IdentifierInfo *II = D.getIdentifier();
SourceLocation Loc = DeclStart;
if (II) Loc = D.getIdentifierLoc();
-
- QualType T = GetTypeForDeclarator(D, S);
+
+ DeclaratorInfo *DInfo = 0;
+ QualType T = GetTypeForDeclarator(D, S, &DInfo);
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
@@ -3890,7 +4738,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true);
+ NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
@@ -3902,10 +4750,12 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
PrevDecl = 0;
- FieldDecl *NewFD
- = CheckFieldDecl(II, T, Record, Loc,
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable,
- BitWidth, AS, PrevDecl, &D);
+ bool Mutable
+ = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable);
+ SourceLocation TSSL = D.getSourceRange().getBegin();
+ FieldDecl *NewFD
+ = CheckFieldDecl(II, T, DInfo, Record, Loc, Mutable, BitWidth, TSSL,
+ AS, PrevDecl, &D);
if (NewFD->isInvalidDecl() && PrevDecl) {
// Don't introduce NewFD into scope; there's already something
// with the same name in the same scope.
@@ -3926,10 +4776,12 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
///
/// \returns a new FieldDecl.
///
-/// \todo The Declarator argument is a hack. It will be removed once
-FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
+/// \todo The Declarator argument is a hack. It will be removed once
+FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
+ DeclaratorInfo *DInfo,
RecordDecl *Record, SourceLocation Loc,
- bool Mutable, Expr *BitWidth,
+ bool Mutable, Expr *BitWidth,
+ SourceLocation TSSL,
AccessSpecifier AS, NamedDecl *PrevDecl,
Declarator *D) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
@@ -3957,25 +4809,26 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
Diag(Loc, diag::err_typecheck_negative_array_size);
else
Diag(Loc, diag::err_typecheck_field_variable_size);
- T = Context.IntTy;
InvalidDecl = true;
}
}
-
+
// Fields can not have abstract class types
- if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl,
+ if (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)) {
+ if (BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
InvalidDecl = true;
DeleteExpr(BitWidth);
BitWidth = 0;
+ ZeroWidth = false;
}
-
- FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth,
- Mutable);
+
+ FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, DInfo,
+ BitWidth, Mutable);
if (InvalidDecl)
NewFD->setInvalidDecl();
@@ -3985,8 +4838,61 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
NewFD->setInvalidDecl();
}
- if (getLangOptions().CPlusPlus && !T->isPODType())
- cast<CXXRecordDecl>(Record)->setPOD(false);
+ if (getLangOptions().CPlusPlus) {
+ QualType EltTy = Context.getBaseElementType(T);
+
+ CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
+
+ if (!T->isPODType())
+ CXXRecord->setPOD(false);
+ if (!ZeroWidth)
+ CXXRecord->setEmpty(false);
+
+ if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+
+ if (!RDecl->hasTrivialConstructor())
+ CXXRecord->setHasTrivialConstructor(false);
+ if (!RDecl->hasTrivialCopyConstructor())
+ CXXRecord->setHasTrivialCopyConstructor(false);
+ if (!RDecl->hasTrivialCopyAssignment())
+ CXXRecord->setHasTrivialCopyAssignment(false);
+ if (!RDecl->hasTrivialDestructor())
+ CXXRecord->setHasTrivialDestructor(false);
+
+ // C++ 9.5p1: An object of a class with a non-trivial
+ // constructor, a non-trivial copy constructor, a non-trivial
+ // destructor, or a non-trivial copy assignment operator
+ // cannot be a member of a union, nor can an array of such
+ // objects.
+ // TODO: C++0x alters this restriction significantly.
+ if (Record->isUnion()) {
+ // We check for copy constructors before constructors
+ // because otherwise we'll never get complaints about
+ // copy constructors.
+
+ const CXXSpecialMember invalid = (CXXSpecialMember) -1;
+
+ CXXSpecialMember member;
+ if (!RDecl->hasTrivialCopyConstructor())
+ member = CXXCopyConstructor;
+ else if (!RDecl->hasTrivialConstructor())
+ member = CXXDefaultConstructor;
+ else if (!RDecl->hasTrivialCopyAssignment())
+ member = CXXCopyAssignment;
+ else if (!RDecl->hasTrivialDestructor())
+ member = CXXDestructor;
+ else
+ member = invalid;
+
+ if (member != invalid) {
+ Diag(Loc, diag::err_illegal_union_member) << Name << member;
+ DiagnoseNontrivial(RT, member);
+ NewFD->setInvalidDecl();
+ }
+ }
+ }
+ }
// FIXME: We need to pass in the attributes given an AST
// representation, not a parser representation.
@@ -4013,7 +4919,131 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
return NewFD;
}
-/// TranslateIvarVisibility - Translate visibility from a token ID to an
+/// DiagnoseNontrivial - Given that a class has a non-trivial
+/// special member, figure out why.
+void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
+ QualType QT(T, 0U);
+ CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl());
+
+ // Check whether the member was user-declared.
+ switch (member) {
+ case CXXDefaultConstructor:
+ if (RD->hasUserDeclaredConstructor()) {
+ typedef CXXRecordDecl::ctor_iterator ctor_iter;
+ for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce; ++ci)
+ if (!ci->isImplicitlyDefined(Context)) {
+ SourceLocation CtorLoc = ci->getLocation();
+ Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+
+ assert(0 && "found no user-declared constructors");
+ return;
+ }
+ break;
+
+ case CXXCopyConstructor:
+ if (RD->hasUserDeclaredCopyConstructor()) {
+ SourceLocation CtorLoc =
+ RD->getCopyConstructor(Context, 0)->getLocation();
+ Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ break;
+
+ case CXXCopyAssignment:
+ if (RD->hasUserDeclaredCopyAssignment()) {
+ // FIXME: this should use the location of the copy
+ // assignment, not the type.
+ SourceLocation TyLoc = RD->getSourceRange().getBegin();
+ Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ break;
+
+ case CXXDestructor:
+ if (RD->hasUserDeclaredDestructor()) {
+ SourceLocation DtorLoc = RD->getDestructor(Context)->getLocation();
+ Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+ return;
+ }
+ break;
+ }
+
+ typedef CXXRecordDecl::base_class_iterator base_iter;
+
+ // Virtual bases and members inhibit trivial copying/construction,
+ // but not trivial destruction.
+ if (member != CXXDestructor) {
+ // Check for virtual bases. vbases includes indirect virtual bases,
+ // so we just iterate through the direct bases.
+ for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi)
+ if (bi->isVirtual()) {
+ SourceLocation BaseLoc = bi->getSourceRange().getBegin();
+ Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1;
+ return;
+ }
+
+ // Check for virtual methods.
+ typedef CXXRecordDecl::method_iterator meth_iter;
+ for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
+ ++mi) {
+ if (mi->isVirtual()) {
+ SourceLocation MLoc = mi->getSourceRange().getBegin();
+ Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0;
+ return;
+ }
+ }
+ }
+
+ bool (CXXRecordDecl::*hasTrivial)() const;
+ switch (member) {
+ case CXXDefaultConstructor:
+ hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break;
+ case CXXCopyConstructor:
+ hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
+ case CXXCopyAssignment:
+ hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break;
+ case CXXDestructor:
+ hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break;
+ default:
+ assert(0 && "unexpected special member"); return;
+ }
+
+ // Check for nontrivial bases (and recurse).
+ for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) {
+ const RecordType *BaseRT = bi->getType()->getAs<RecordType>();
+ assert(BaseRT);
+ CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
+ if (!(BaseRecTy->*hasTrivial)()) {
+ SourceLocation BaseLoc = bi->getSourceRange().getBegin();
+ Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member;
+ DiagnoseNontrivial(BaseRT, member);
+ return;
+ }
+ }
+
+ // Check for nontrivial members (and recurse).
+ typedef RecordDecl::field_iterator field_iter;
+ for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe;
+ ++fi) {
+ QualType EltTy = Context.getBaseElementType((*fi)->getType());
+ if (const RecordType *EltRT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl());
+
+ if (!(EltRD->*hasTrivial)()) {
+ SourceLocation FLoc = (*fi)->getLocation();
+ Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member;
+ DiagnoseNontrivial(EltRT, member);
+ return;
+ }
+ }
+ }
+
+ assert(0 && "found no explanation for non-trivial member");
+}
+
+/// TranslateIvarVisibility - Translate visibility from a token ID to an
/// AST enum value.
static ObjCIvarDecl::AccessControl
TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
@@ -4026,24 +5056,25 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
}
}
-/// ActOnIvar - Each ivar field of an objective-c class is passed into this
+/// ActOnIvar - Each ivar field of an objective-c class is passed into this
/// in order to create an IvarDecl object for it.
Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
- SourceLocation DeclStart,
+ SourceLocation DeclStart,
DeclPtrTy IntfDecl,
Declarator &D, ExprTy *BitfieldWidth,
tok::ObjCKeywordKind Visibility) {
-
+
IdentifierInfo *II = D.getIdentifier();
Expr *BitWidth = (Expr*)BitfieldWidth;
SourceLocation Loc = DeclStart;
if (II) Loc = D.getIdentifierLoc();
-
+
// FIXME: Unnamed fields can be handled in various different ways, for
// example, unnamed unions inject all members into the struct namespace!
-
- QualType T = GetTypeForDeclarator(D, S);
-
+
+ DeclaratorInfo *DInfo = 0;
+ QualType T = GetTypeForDeclarator(D, S, &DInfo);
+
if (BitWidth) {
// 6.7.2.1p3, 6.7.2.1p4
if (VerifyBitField(Loc, II, T, BitWidth)) {
@@ -4053,43 +5084,42 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
}
} else {
// Not a bitfield.
-
+
// validate II.
-
+
}
-
+
// 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()) {
Diag(Loc, diag::err_typecheck_ivar_variable_size);
D.setInvalidType();
}
-
+
// Get the visibility (access control) for this ivar.
- ObjCIvarDecl::AccessControl ac =
+ ObjCIvarDecl::AccessControl ac =
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
: ObjCIvarDecl::None;
// Must set ivar's DeclContext to its enclosing interface.
Decl *EnclosingDecl = IntfDecl.getAs<Decl>();
DeclContext *EnclosingContext;
- if (ObjCImplementationDecl *IMPDecl =
+ if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
// Case of ivar declared in an implementation. Context is that of its class.
ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface();
assert(IDecl && "No class- ActOnIvar");
EnclosingContext = cast_or_null<DeclContext>(IDecl);
- }
- else
+ } else
EnclosingContext = dyn_cast<DeclContext>(EnclosingDecl);
assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar");
-
+
// Construct the decl.
- ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,
- EnclosingContext, Loc, II, T,ac,
- (Expr *)BitfieldWidth);
-
+ ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,
+ EnclosingContext, Loc, II, T,
+ DInfo, ac, (Expr *)BitfieldWidth);
+
if (II) {
- NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true);
+ NamedDecl *PrevDecl = LookupSingleName(S, II, LookupMemberName, true);
if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
&& !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
@@ -4100,7 +5130,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
// Process attributes attached to the ivar.
ProcessDeclAttributes(S, NewID, D);
-
+
if (D.isInvalidType())
NewID->setInvalidDecl();
@@ -4121,7 +5151,7 @@ void Sema::ActOnFields(Scope* S,
AttributeList *Attr) {
Decl *EnclosingDecl = RecDecl.getAs<Decl>();
assert(EnclosingDecl && "missing record or interface decl");
-
+
// If the decl this is being inserted into is invalid, then it may be a
// redeclaration or some other bogus case. Don't try to add fields to it.
if (EnclosingDecl->isInvalidDecl()) {
@@ -4129,7 +5159,7 @@ void Sema::ActOnFields(Scope* S,
return;
}
-
+
// Verify that all the fields are okay.
unsigned NumNamedMembers = 0;
llvm::SmallVector<FieldDecl*, 32> RecFields;
@@ -4137,7 +5167,7 @@ void Sema::ActOnFields(Scope* S,
RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
for (unsigned i = 0; i != NumFields; ++i) {
FieldDecl *FD = cast<FieldDecl>(Fields[i].getAs<Decl>());
-
+
// Get the type for the field.
Type *FDTy = FD->getType().getTypePtr();
@@ -4145,12 +5175,12 @@ void Sema::ActOnFields(Scope* S,
// Remember all fields written by the user.
RecFields.push_back(FD);
}
-
+
// If the field is already invalid for some reason, don't emit more
// diagnostics about it.
if (FD->isInvalidDecl())
continue;
-
+
// C99 6.7.2.1p2:
// A structure or union shall not contain a member with
// incomplete or function type (hence, a structure shall not
@@ -4182,13 +5212,13 @@ void Sema::ActOnFields(Scope* S,
if (Record)
Record->setHasFlexibleArrayMember(true);
} else if (!FDTy->isDependentType() &&
- RequireCompleteType(FD->getLocation(), FD->getType(),
+ RequireCompleteType(FD->getLocation(), FD->getType(),
diag::err_field_incomplete)) {
// Incomplete type
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
- } else if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
+ } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) {
if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
// If this is a member of a union, then entire union becomes "flexible".
if (Record && Record->isUnion()) {
@@ -4210,13 +5240,20 @@ void Sema::ActOnFields(Scope* S,
}
}
}
+ if (Record && FDTTy->getDecl()->hasObjectMember())
+ Record->setHasObjectMember(true);
} else if (FDTy->isObjCInterfaceType()) {
/// A field cannot be an Objective-c object
Diag(FD->getLocation(), diag::err_statically_allocated_object);
FD->setInvalidDecl();
EnclosingDecl->setInvalidDecl();
continue;
- }
+ } else if (getLangOptions().ObjC1 &&
+ getLangOptions().getGCMode() != LangOptions::NonGC &&
+ Record &&
+ (FD->getType()->isObjCObjectPointerType() ||
+ FD->getType().isObjCGCStrong()))
+ Record->setHasObjectMember(true);
// Keep track of the number of named members.
if (FD->getIdentifier())
++NumNamedMembers;
@@ -4239,7 +5276,7 @@ void Sema::ActOnFields(Scope* S,
// Must enforce the rule that ivars in the base classes may not be
// duplicates.
if (ID->getSuperClass()) {
- for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
+ for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(),
IVE = ID->ivar_end(); IVI != IVE; ++IVI) {
ObjCIvarDecl* Ivar = (*IVI);
@@ -4253,7 +5290,7 @@ void Sema::ActOnFields(Scope* S,
}
}
}
- } else if (ObjCImplementationDecl *IMPDecl =
+ } else if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl");
for (unsigned I = 0, N = RecFields.size(); I != N; ++I)
@@ -4294,7 +5331,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EltTy = Val->getType();
}
}
-
+
if (!Val) {
if (LastEnumConst) {
// Assign the last value + 1.
@@ -4304,7 +5341,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// 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.
@@ -4312,10 +5349,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
}
}
-
+
val.release();
return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
- Val, EnumVal);
+ Val, EnumVal);
}
@@ -4332,10 +5369,10 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
S = getNonFieldDeclScope(S);
-
+
// Verify that there isn't already something declared with this name in this
// scope.
- NamedDecl *PrevDecl = LookupName(S, Id, LookupOrdinaryName);
+ NamedDecl *PrevDecl = LookupSingleName(S, Id, LookupOrdinaryName);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
@@ -4371,28 +5408,34 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, DeclPtrTy EnumDeclX,
- DeclPtrTy *Elements, unsigned NumElements) {
+ DeclPtrTy *Elements, unsigned NumElements,
+ Scope *S, AttributeList *Attr) {
EnumDecl *Enum = cast<EnumDecl>(EnumDeclX.getAs<Decl>());
QualType EnumType = Context.getTypeDeclType(Enum);
-
+
+ if (Attr)
+ ProcessDeclAttributeList(S, Enum, Attr);
+
// 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.
unsigned IntWidth = Context.Target.getIntWidth();
-
+ unsigned CharWidth = Context.Target.getCharWidth();
+ unsigned ShortWidth = Context.Target.getShortWidth();
+
// Verify that all the values are okay, compute the size of the values, and
// reverse the list.
unsigned NumNegativeBits = 0;
unsigned NumPositiveBits = 0;
-
+
// Keep track of whether all elements have type int.
bool AllElementsInt = true;
-
+
for (unsigned i = 0; i != NumElements; ++i) {
EnumConstantDecl *ECD =
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 &&
@@ -4405,7 +5448,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
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())
NumPositiveBits = std::max(NumPositiveBits,
@@ -4416,28 +5459,39 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// Keep track of whether every enum element has type int (very commmon).
if (AllElementsInt)
- AllElementsInt = ECD->getType() == Context.IntTy;
+ AllElementsInt = ECD->getType() == Context.IntTy;
}
-
+
// Figure out the type that should be used for this enum.
- // FIXME: Support attribute(packed) on enums and -fshort-enums.
+ // FIXME: Support -fshort-enums.
QualType BestType;
unsigned BestWidth;
-
+
+ bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
+
if (NumNegativeBits) {
- // If there is a negative value, figure out the smallest integer type (of
+ // If there is a negative value, figure out the smallest integer type (of
// int/long/longlong) that fits.
- if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
+ // 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;
+ } else if (Packed && NumNegativeBits <= ShortWidth &&
+ NumPositiveBits < ShortWidth) {
+ 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)
BestType = Context.LongTy;
else {
BestWidth = Context.Target.getLongLongWidth();
-
+
if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
Diag(Enum->getLocation(), diag::warn_enum_too_large);
BestType = Context.LongLongTy;
@@ -4446,7 +5500,15 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
} else {
// If there is no negative value, figure out which of uint, ulong, ulonglong
// fits.
- if (NumPositiveBits <= IntWidth) {
+ // If it's packed, check also if it fits a char or a short.
+ if (Packed && NumPositiveBits <= CharWidth) {
+ BestType = Context.UnsignedCharTy;
+ BestWidth = CharWidth;
+ } else if (Packed && NumPositiveBits <= ShortWidth) {
+ BestType = Context.UnsignedShortTy;
+ BestWidth = ShortWidth;
+ }
+ else if (NumPositiveBits <= IntWidth) {
BestType = Context.UnsignedIntTy;
BestWidth = IntWidth;
} else if (NumPositiveBits <=
@@ -4459,7 +5521,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
BestType = Context.UnsignedLongLongTy;
}
}
-
+
// 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) {
@@ -4481,7 +5543,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
if (getLangOptions().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
- // enumeration.
+ // enumeration.
ECD->setType(EnumType);
continue; // Already int type.
}
@@ -4508,7 +5570,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
if (getLangOptions().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
- // enumeration.
+ // enumeration.
ECD->setType(EnumType);
continue;
} else {
@@ -4521,20 +5583,22 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
InitVal.extOrTrunc(NewWidth);
InitVal.setIsSigned(NewSign);
ECD->setInitVal(InitVal);
-
+
// Adjust the Expr initializer and type.
if (ECD->getInitExpr())
- ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy, ECD->getInitExpr(),
+ ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy,
+ CastExpr::CK_Unknown,
+ ECD->getInitExpr(),
/*isLvalue=*/false));
if (getLangOptions().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
- // enumeration.
+ // enumeration.
ECD->setType(EnumType);
else
ECD->setType(NewTy);
}
-
+
Enum->completeDefinition(Context, BestType);
}
@@ -4551,15 +5615,15 @@ Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
SourceLocation PragmaLoc,
SourceLocation NameLoc) {
- Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName);
+ Decl *PrevDecl = LookupSingleName(TUScope, Name, LookupOrdinaryName);
- // FIXME: This implementation is an ugly hack!
if (PrevDecl) {
PrevDecl->addAttr(::new (Context) WeakAttr());
- return;
+ } else {
+ (void)WeakUndeclaredIdentifiers.insert(
+ std::pair<IdentifierInfo*,WeakInfo>
+ (Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
}
- Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
- return;
}
void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
@@ -4567,14 +5631,15 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
SourceLocation PragmaLoc,
SourceLocation NameLoc,
SourceLocation AliasNameLoc) {
- Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName);
+ Decl *PrevDecl = LookupSingleName(TUScope, AliasName, LookupOrdinaryName);
+ WeakInfo W = WeakInfo(Name, NameLoc);
- // FIXME: This implementation is an ugly hack!
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName()));
- PrevDecl->addAttr(::new (Context) WeakAttr());
- return;
+ if (!PrevDecl->hasAttr<AliasAttr>())
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
+ DeclApplyPragmaWeak(TUScope, ND, W);
+ } else {
+ (void)WeakUndeclaredIdentifiers.insert(
+ std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
}
- Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
- return;
}
OpenPOWER on IntegriCloud