summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Sema/SemaDecl.cpp
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip
FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp2272
1 files changed, 1588 insertions, 684 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 0092d5d..adf3505 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12,15 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
-#include "clang/Sema/CXXFieldCollector.h"
-#include "clang/Sema/Scope.h"
-#include "clang/Sema/ScopeInfo.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -28,18 +24,21 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/Sema/DeclSpec.h"
-#include "clang/Sema/ParsedTemplate.h"
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Sema/DelayedDiagnostic.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 "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/HeaderSearch.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Lex/ModuleLoader.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Lex/Preprocessor.h" // FIXME: Sema shouldn't depend on Lex
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
#include <algorithm>
@@ -677,9 +676,9 @@ Corrected:
(isa<TypeDecl>(UnderlyingFirstDecl) ||
isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
- UnqualifiedDiag = diag::err_unknown_typename_suggest;
- QualifiedDiag = diag::err_unknown_nested_typename_suggest;
- }
+ UnqualifiedDiag = diag::err_unknown_typename_suggest;
+ QualifiedDiag = diag::err_unknown_nested_typename_suggest;
+ }
if (SS.isEmpty())
Diag(NameLoc, UnqualifiedDiag)
@@ -1097,7 +1096,7 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S,
bool ExplicitInstantiationOrSpecialization) {
- return IdResolver.isDeclInScope(D, Ctx, Context, S,
+ return IdResolver.isDeclInScope(D, Ctx, S,
ExplicitInstantiationOrSpecialization);
}
@@ -1175,6 +1174,31 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
return false;
}
+// We need this to handle
+//
+// typedef struct {
+// void *foo() { return 0; }
+// } A;
+//
+// When we see foo we don't know if after the typedef we will get 'A' or '*A'
+// for example. If 'A', foo will have external linkage. If we have '*A',
+// foo will have no linkage. Since we can't know untill we get to the end
+// of the typedef, this function finds out if D might have non external linkage.
+// Callers should verify at the end of the TU if it D has external linkage or
+// not.
+bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) {
+ const DeclContext *DC = D->getDeclContext();
+ while (!DC->isTranslationUnit()) {
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(DC)){
+ if (!RD->hasNameForLinkage())
+ return true;
+ }
+ DC = DC->getParent();
+ }
+
+ return !D->hasExternalLinkage();
+}
+
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
assert(D);
@@ -1224,10 +1248,7 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
}
// Only warn for unused decls internal to the translation unit.
- if (D->getLinkage() == ExternalLinkage)
- return false;
-
- return true;
+ return mightHaveNonExternalLinkage(D);
}
void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
@@ -1368,7 +1389,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (!D->getDeclName()) continue;
// Diagnose unused variables in this scope.
- if (!S->hasErrorOccurred())
+ if (!S->hasUnrecoverableErrorOccurred())
DiagnoseUnusedDecl(D);
// If this was a forward reference to a label, verify it was defined.
@@ -1465,6 +1486,24 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
+/// \brief Looks up the declaration of "struct objc_super" and
+/// saves it for later use in building builtin declaration of
+/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such
+/// pre-existing declaration exists no action takes place.
+static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S,
+ IdentifierInfo *II) {
+ if (!II->isStr("objc_msgSendSuper"))
+ return;
+ ASTContext &Context = ThisSema.Context;
+
+ LookupResult Result(ThisSema, &Context.Idents.get("objc_super"),
+ SourceLocation(), Sema::LookupTagName);
+ ThisSema.LookupName(Result, S);
+ if (Result.getResultKind() == LookupResult::Found)
+ if (const TagDecl *TD = Result.getAsSingle<TagDecl>())
+ Context.setObjCSuperType(Context.getTagDeclType(TD));
+}
+
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at
/// file scope. lazily create a decl for it. ForRedeclaration is true
/// if we're creating this built-in in anticipation of redeclaring the
@@ -1472,6 +1511,8 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Scope *S, bool ForRedeclaration,
SourceLocation Loc) {
+ LookupPredefedObjCSuperType(*this, S, II);
+
Builtin::ID BID = (Builtin::ID)bid;
ASTContext::GetBuiltinTypeError Error;
@@ -1516,7 +1557,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Context.getTranslationUnitDecl(),
Loc, Loc, II, R, /*TInfo=*/0,
SC_Extern,
- SC_None, false,
+ false,
/*hasPrototype=*/true);
New->setImplicit();
@@ -1529,7 +1570,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
ParmVarDecl::Create(Context, New, SourceLocation(),
SourceLocation(), 0,
FT->getArgType(i), /*TInfo=*/0,
- SC_None, SC_None, 0);
+ SC_None, 0);
parm->setScopeInfo(0, i);
Params.push_back(parm);
}
@@ -1549,6 +1590,49 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
return New;
}
+/// \brief Filter out any previous declarations that the given declaration
+/// should not consider because they are not permitted to conflict, e.g.,
+/// because they come from hidden sub-modules and do not refer to the same
+/// entity.
+static void filterNonConflictingPreviousDecls(ASTContext &context,
+ NamedDecl *decl,
+ LookupResult &previous){
+ // This is only interesting when modules are enabled.
+ if (!context.getLangOpts().Modules)
+ return;
+
+ // Empty sets are uninteresting.
+ if (previous.empty())
+ return;
+
+ LookupResult::Filter filter = previous.makeFilter();
+ while (filter.hasNext()) {
+ NamedDecl *old = filter.next();
+
+ // Non-hidden declarations are never ignored.
+ if (!old->isHidden())
+ continue;
+
+ // If either has no-external linkage, ignore the old declaration.
+ // If this declaration would have external linkage if it were the first
+ // declaration of this name, then it may in fact be a redeclaration of
+ // some hidden declaration, so include those too. We don't need to worry
+ // about some previous visible declaration giving this declaration external
+ // linkage, because in that case, we'll mark this declaration as a redecl
+ // of the visible decl, and that decl will already be a redecl of the
+ // hidden declaration if that's appropriate.
+ //
+ // Don't cache this linkage computation, because it's not yet correct: we
+ // may later give this declaration a previous declaration which changes
+ // its linkage.
+ if (old->getLinkage() != ExternalLinkage ||
+ !decl->hasExternalLinkageUncached())
+ filter.erase();
+ }
+
+ filter.done();
+}
+
bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
QualType OldType;
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
@@ -1769,26 +1853,164 @@ DeclHasAttr(const Decl *D, const Attr *A) {
return false;
}
-bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) {
+static bool isAttributeTargetADefinition(Decl *D) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ return VD->isThisDeclarationADefinition();
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ return TD->isCompleteDefinition() || TD->isBeingDefined();
+ return true;
+}
+
+/// Merge alignment attributes from \p Old to \p New, taking into account the
+/// special semantics of C11's _Alignas specifier and C++11's alignas attribute.
+///
+/// \return \c true if any attributes were added to \p New.
+static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
+ // Look for alignas attributes on Old, and pick out whichever attribute
+ // specifies the strictest alignment requirement.
+ AlignedAttr *OldAlignasAttr = 0;
+ AlignedAttr *OldStrictestAlignAttr = 0;
+ unsigned OldAlign = 0;
+ for (specific_attr_iterator<AlignedAttr>
+ I = Old->specific_attr_begin<AlignedAttr>(),
+ E = Old->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ // FIXME: We have no way of representing inherited dependent alignments
+ // in a case like:
+ // template<int A, int B> struct alignas(A) X;
+ // template<int A, int B> struct alignas(B) X {};
+ // For now, we just ignore any alignas attributes which are not on the
+ // definition in such a case.
+ if (I->isAlignmentDependent())
+ return false;
+
+ if (I->isAlignas())
+ OldAlignasAttr = *I;
+
+ unsigned Align = I->getAlignment(S.Context);
+ if (Align > OldAlign) {
+ OldAlign = Align;
+ OldStrictestAlignAttr = *I;
+ }
+ }
+
+ // Look for alignas attributes on New.
+ AlignedAttr *NewAlignasAttr = 0;
+ unsigned NewAlign = 0;
+ for (specific_attr_iterator<AlignedAttr>
+ I = New->specific_attr_begin<AlignedAttr>(),
+ E = New->specific_attr_end<AlignedAttr>(); I != E; ++I) {
+ if (I->isAlignmentDependent())
+ return false;
+
+ if (I->isAlignas())
+ NewAlignasAttr = *I;
+
+ unsigned Align = I->getAlignment(S.Context);
+ if (Align > NewAlign)
+ NewAlign = Align;
+ }
+
+ if (OldAlignasAttr && NewAlignasAttr && OldAlign != NewAlign) {
+ // Both declarations have 'alignas' attributes. We require them to match.
+ // C++11 [dcl.align]p6 and C11 6.7.5/7 both come close to saying this, but
+ // fall short. (If two declarations both have alignas, they must both match
+ // every definition, and so must match each other if there is a definition.)
+
+ // If either declaration only contains 'alignas(0)' specifiers, then it
+ // specifies the natural alignment for the type.
+ if (OldAlign == 0 || NewAlign == 0) {
+ QualType Ty;
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(New))
+ Ty = VD->getType();
+ else
+ Ty = S.Context.getTagDeclType(cast<TagDecl>(New));
+
+ if (OldAlign == 0)
+ OldAlign = S.Context.getTypeAlign(Ty);
+ if (NewAlign == 0)
+ NewAlign = S.Context.getTypeAlign(Ty);
+ }
+
+ if (OldAlign != NewAlign) {
+ S.Diag(NewAlignasAttr->getLocation(), diag::err_alignas_mismatch)
+ << (unsigned)S.Context.toCharUnitsFromBits(OldAlign).getQuantity()
+ << (unsigned)S.Context.toCharUnitsFromBits(NewAlign).getQuantity();
+ S.Diag(OldAlignasAttr->getLocation(), diag::note_previous_declaration);
+ }
+ }
+
+ if (OldAlignasAttr && !NewAlignasAttr && isAttributeTargetADefinition(New)) {
+ // C++11 [dcl.align]p6:
+ // if any declaration of an entity has an alignment-specifier,
+ // every defining declaration of that entity shall specify an
+ // equivalent alignment.
+ // C11 6.7.5/7:
+ // If the definition of an object does not have an alignment
+ // specifier, any other declaration of that object shall also
+ // have no alignment specifier.
+ S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition)
+ << OldAlignasAttr->isC11();
+ S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration)
+ << OldAlignasAttr->isC11();
+ }
+
+ bool AnyAdded = false;
+
+ // Ensure we have an attribute representing the strictest alignment.
+ if (OldAlign > NewAlign) {
+ AlignedAttr *Clone = OldStrictestAlignAttr->clone(S.Context);
+ Clone->setInherited(true);
+ New->addAttr(Clone);
+ AnyAdded = true;
+ }
+
+ // Ensure we have an alignas attribute if the old declaration had one.
+ if (OldAlignasAttr && !NewAlignasAttr &&
+ !(AnyAdded && OldStrictestAlignAttr->isAlignas())) {
+ AlignedAttr *Clone = OldAlignasAttr->clone(S.Context);
+ Clone->setInherited(true);
+ New->addAttr(Clone);
+ AnyAdded = true;
+ }
+
+ return AnyAdded;
+}
+
+static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr,
+ bool Override) {
InheritableAttr *NewAttr = NULL;
+ unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
- NewAttr = mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
- AA->getIntroduced(), AA->getDeprecated(),
- AA->getObsoleted(), AA->getUnavailable(),
- AA->getMessage());
+ NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
+ AA->getIntroduced(), AA->getDeprecated(),
+ AA->getObsoleted(), AA->getUnavailable(),
+ AA->getMessage(), Override,
+ AttrSpellingListIndex);
else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
- NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility());
+ NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
+ AttrSpellingListIndex);
+ else if (TypeVisibilityAttr *VA = dyn_cast<TypeVisibilityAttr>(Attr))
+ NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(),
+ AttrSpellingListIndex);
else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
- NewAttr = mergeDLLImportAttr(D, ImportA->getRange());
+ NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(),
+ AttrSpellingListIndex);
else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr))
- NewAttr = mergeDLLExportAttr(D, ExportA->getRange());
+ NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(),
+ AttrSpellingListIndex);
else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr))
- NewAttr = mergeFormatAttr(D, FA->getRange(), FA->getType(),
- FA->getFormatIdx(), FA->getFirstArg());
+ NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(),
+ FA->getFormatIdx(), FA->getFirstArg(),
+ AttrSpellingListIndex);
else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr))
- NewAttr = mergeSectionAttr(D, SA->getRange(), SA->getName());
+ NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
+ AttrSpellingListIndex);
+ else if (isa<AlignedAttr>(Attr))
+ // AlignedAttrs are handled separately, because we need to handle all
+ // such attributes on a declaration at the same time.
+ NewAttr = 0;
else if (!DeclHasAttr(D, Attr))
- NewAttr = cast<InheritableAttr>(Attr->clone(Context));
+ NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
if (NewAttr) {
NewAttr->setInherited(true);
@@ -1839,6 +2061,31 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
++I;
continue; // regular attr merging will take care of validating this.
}
+
+ if (isa<C11NoReturnAttr>(NewAttribute)) {
+ // C's _Noreturn is allowed to be added to a function after it is defined.
+ ++I;
+ continue;
+ } else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) {
+ if (AA->isAlignas()) {
+ // C++11 [dcl.align]p6:
+ // if any declaration of an entity has an alignment-specifier,
+ // every defining declaration of that entity shall specify an
+ // equivalent alignment.
+ // C11 6.7.5/7:
+ // If the definition of an object does not have an alignment
+ // specifier, any other declaration of that object shall also
+ // have no alignment specifier.
+ S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition)
+ << AA->isC11();
+ S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration)
+ << AA->isC11();
+ NewAttributes.erase(NewAttributes.begin() + I);
+ --E;
+ continue;
+ }
+ }
+
S.Diag(NewAttribute->getLocation(),
diag::warn_attribute_precede_definition);
S.Diag(Def->getLocation(), diag::note_previous_definition);
@@ -1848,8 +2095,11 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
}
/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
-void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
- bool MergeDeprecation) {
+void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
+ AvailabilityMergeKind AMK) {
+ if (!Old->hasAttrs() && !New->hasAttrs())
+ return;
+
// attributes declared post-definition are currently ignored
checkNewAttributesAfterDef(*this, New, Old);
@@ -1866,17 +2116,31 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
i = Old->specific_attr_begin<InheritableAttr>(),
e = Old->specific_attr_end<InheritableAttr>();
i != e; ++i) {
+ bool Override = false;
// Ignore deprecated/unavailable/availability attributes if requested.
- if (!MergeDeprecation &&
- (isa<DeprecatedAttr>(*i) ||
- isa<UnavailableAttr>(*i) ||
- isa<AvailabilityAttr>(*i)))
- continue;
+ if (isa<DeprecatedAttr>(*i) ||
+ isa<UnavailableAttr>(*i) ||
+ isa<AvailabilityAttr>(*i)) {
+ switch (AMK) {
+ case AMK_None:
+ continue;
- if (mergeDeclAttribute(New, *i))
+ case AMK_Redeclaration:
+ break;
+
+ case AMK_Override:
+ Override = true;
+ break;
+ }
+ }
+
+ if (mergeDeclAttribute(*this, New, *i, Override))
foundAny = true;
}
+ if (mergeAlignedAttrs(*this, New, Old))
+ foundAny = true;
+
if (!foundAny) New->dropAttrs();
}
@@ -1884,7 +2148,25 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old,
/// to the new one.
static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
const ParmVarDecl *oldDecl,
- ASTContext &C) {
+ Sema &S) {
+ // C++11 [dcl.attr.depend]p2:
+ // The first declaration of a function shall specify the
+ // carries_dependency attribute for its declarator-id if any declaration
+ // of the function specifies the carries_dependency attribute.
+ if (newDecl->hasAttr<CarriesDependencyAttr>() &&
+ !oldDecl->hasAttr<CarriesDependencyAttr>()) {
+ S.Diag(newDecl->getAttr<CarriesDependencyAttr>()->getLocation(),
+ diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/;
+ // Find the first declaration of the parameter.
+ // FIXME: Should we build redeclaration chains for function parameters?
+ const FunctionDecl *FirstFD =
+ cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDeclaration();
+ const ParmVarDecl *FirstVD =
+ FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex());
+ S.Diag(FirstVD->getLocation(),
+ diag::note_carries_dependency_missing_first_decl) << 1/*Param*/;
+ }
+
if (!oldDecl->hasAttrs())
return;
@@ -1898,7 +2180,8 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
if (!DeclHasAttr(newDecl, *i)) {
- InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C));
+ InheritableAttr *newAttr =
+ cast<InheritableParamAttr>((*i)->clone(S.Context));
newAttr->setInherited(true);
newDecl->addAttr(newAttr);
foundAny = true;
@@ -1966,6 +2249,22 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) {
return ABIDefaultCC == CC;
}
+template <typename T>
+static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
+ const DeclContext *DC = Old->getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ LanguageLinkage OldLinkage = Old->getLanguageLinkage();
+ if (OldLinkage == CXXLanguageLinkage &&
+ New->getDeclContext()->isExternCContext())
+ return true;
+ if (OldLinkage == CLanguageLinkage &&
+ New->getDeclContext()->isExternCXXContext())
+ return true;
+ return false;
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -1987,6 +2286,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
Old = dyn_cast<FunctionDecl>(OldD);
if (!Old) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
+ if (New->getFriendObjectKind()) {
+ Diag(New->getLocation(), diag::err_using_decl_friend);
+ Diag(Shadow->getTargetDecl()->getLocation(),
+ diag::note_using_decl_target);
+ Diag(Shadow->getUsingDecl()->getLocation(),
+ diag::note_using_decl) << 0;
+ return true;
+ }
+
Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
@@ -2016,9 +2324,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// Don't complain about this if we're in GNU89 mode and the old function
// is an extern inline function.
+ // Don't complain about specializations. They are not supposed to have
+ // storage classes.
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
New->getStorageClass() == SC_Static &&
- Old->getStorageClass() != SC_Static &&
+ isExternalLinkage(Old->getLinkage()) &&
+ !New->getTemplateSpecializationInfo() &&
!canRedefineFunction(Old, getLangOpts())) {
if (getLangOpts().MicrosoftExt) {
Diag(New->getLocation(), diag::warn_static_non_static) << New;
@@ -2060,9 +2371,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
RequiresAdjustment = true;
// Don't complain about mismatches when the default CC is
- // effectively the same as the explict one.
+ // effectively the same as the explict one. Only Old decl contains correct
+ // information about storage class of CXXMethod.
} else if (OldTypeInfo.getCC() == CC_Default &&
- isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) {
+ isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) {
NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
RequiresAdjustment = true;
@@ -2116,6 +2428,23 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
New->setType(QualType(NewType, 0));
NewQType = Context.getCanonicalType(New->getType());
}
+
+ // If this redeclaration makes the function inline, we may need to add it to
+ // UndefinedButUsed.
+ if (!Old->isInlined() && New->isInlined() &&
+ !New->hasAttr<GNUInlineAttr>() &&
+ (getLangOpts().CPlusPlus || !getLangOpts().GNUInline) &&
+ Old->isUsed(false) &&
+ !Old->isDefined() && !New->isThisDeclarationADefinition())
+ UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(),
+ SourceLocation()));
+
+ // If this redeclaration makes it newly gnu_inline, we don't want to warn
+ // about it.
+ if (New->hasAttr<GNUInlineAttr>() &&
+ Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) {
+ UndefinedButUsed.erase(Old->getCanonicalDecl());
+ }
if (getLangOpts().CPlusPlus) {
// (C++98 13.1p2):
@@ -2211,6 +2540,30 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
}
}
+ // C++11 [dcl.attr.noreturn]p1:
+ // The first declaration of a function shall specify the noreturn
+ // attribute if any declaration of that function specifies the noreturn
+ // attribute.
+ if (New->hasAttr<CXX11NoReturnAttr>() &&
+ !Old->hasAttr<CXX11NoReturnAttr>()) {
+ Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(),
+ diag::err_noreturn_missing_on_first_decl);
+ Diag(Old->getFirstDeclaration()->getLocation(),
+ diag::note_noreturn_missing_first_decl);
+ }
+
+ // C++11 [dcl.attr.depend]p2:
+ // The first declaration of a function shall specify the
+ // carries_dependency attribute for its declarator-id if any declaration
+ // of the function specifies the carries_dependency attribute.
+ if (New->hasAttr<CarriesDependencyAttr>() &&
+ !Old->hasAttr<CarriesDependencyAttr>()) {
+ Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(),
+ diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/;
+ Diag(Old->getFirstDeclaration()->getLocation(),
+ diag::note_carries_dependency_missing_first_decl) << 0/*Function*/;
+ }
+
// (C++98 8.3.5p3):
// All declarations for a function shall agree exactly in both the
// return type and the parameter-type-list.
@@ -2226,6 +2579,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
assert(OldQTypeForComparison.isCanonical());
}
+ if (haveIncompatibleLanguageLinkages(Old, New)) {
+ Diag(New->getLocation(), diag::err_different_language_linkage) << New;
+ Diag(Old->getLocation(), PrevDiag);
+ return true;
+ }
+
if (OldQTypeForComparison == NewQType)
return MergeCompatibleFunctionDecls(New, Old, S);
@@ -2247,7 +2606,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(),
OldProto->arg_type_end());
NewQType = Context.getFunctionType(NewFuncType->getResultType(),
- ParamTypes.data(), ParamTypes.size(),
+ ParamTypes,
OldProto->getExtProtoInfo());
New->setType(NewQType);
New->setHasInheritedPrototype();
@@ -2262,7 +2621,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
SourceLocation(),
SourceLocation(), 0,
*ParamType, /*TInfo=*/0,
- SC_None, SC_None,
+ SC_None,
0);
Param->setScopeInfo(0, Params.size());
Param->setImplicit();
@@ -2330,8 +2689,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
diag::note_previous_declaration);
}
- New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
- ArgTypes.size(),
+ New->setType(Context.getFunctionType(MergedReturn, ArgTypes,
OldProto->getExtProtoInfo()));
return MergeCompatibleFunctionDecls(New, Old, S);
}
@@ -2379,25 +2737,30 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
// Merge the attributes
mergeDeclAttributes(New, Old);
- // Merge the storage class.
- if (Old->getStorageClass() != SC_Extern &&
- Old->getStorageClass() != SC_None)
- New->setStorageClass(Old->getStorageClass());
-
// Merge "pure" flag.
if (Old->isPure())
New->setPure();
+ // Merge "used" flag.
+ if (Old->isUsed(false))
+ New->setUsed();
+
// Merge attributes from the parameters. These can mismatch with K&R
// declarations.
if (New->getNumParams() == Old->getNumParams())
for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
- Context);
+ *this);
if (getLangOpts().CPlusPlus)
return MergeCXXFunctionDecl(New, Old, S);
+ // Merge the function types so the we get the composite types for the return
+ // and argument types.
+ QualType Merged = Context.mergeTypes(Old->getType(), New->getType());
+ if (!Merged.isNull())
+ New->setType(Merged);
+
return false;
}
@@ -2406,7 +2769,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
ObjCMethodDecl *oldMethod) {
// Merge the attributes, including deprecated/unavailable
- mergeDeclAttributes(newMethod, oldMethod, /* mergeDeprecation */true);
+ mergeDeclAttributes(newMethod, oldMethod, AMK_Override);
// Merge attributes from the parameters.
ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(),
@@ -2414,9 +2777,9 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
for (ObjCMethodDecl::param_iterator
ni = newMethod->param_begin(), ne = newMethod->param_end();
ni != ne && oi != oe; ++ni, ++oi)
- mergeParamDeclAttributes(*ni, *oi, Context);
+ mergeParamDeclAttributes(*ni, *oi, *this);
- CheckObjCMethodOverride(newMethod, oldMethod, true);
+ CheckObjCMethodOverride(newMethod, oldMethod);
}
/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and
@@ -2426,7 +2789,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
/// to here in AddInitializerToDecl. We can't check them before the initializer
/// is attached.
-void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
+void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) {
if (New->isInvalidDecl() || Old->isInvalidDecl())
return;
@@ -2447,19 +2810,17 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
// absence of a major array bound (8.3.4).
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())
+ const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
+ const ArrayType *NewArray = Context.getAsArrayType(New->getType());
+ if (Context.hasSameType(OldArray->getElementType(),
+ NewArray->getElementType()))
MergedT = New->getType();
} else if (Old->getType()->isArrayType() &&
New->getType()->isIncompleteArrayType()) {
- CanQual<ArrayType> OldArray
- = Context.getCanonicalType(Old->getType())->getAs<ArrayType>();
- CanQual<ArrayType> NewArray
- = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
- if (OldArray->getElementType() == NewArray->getElementType())
+ const ArrayType *OldArray = Context.getAsArrayType(Old->getType());
+ const ArrayType *NewArray = Context.getAsArrayType(New->getType());
+ if (Context.hasSameType(OldArray->getElementType(),
+ NewArray->getElementType()))
MergedT = Old->getType();
} else if (New->getType()->isObjCObjectPointerType()
&& Old->getType()->isObjCObjectPointerType()) {
@@ -2475,7 +2836,11 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
- New->setType(MergedT);
+
+ // Don't actually update the type on the new declaration if the old
+ // declaration was a extern declaration in a different scope.
+ if (!OldWasHidden)
+ New->setType(MergedT);
}
/// MergeVarDecl - We just parsed a variable 'New' which has the same name
@@ -2486,7 +2851,8 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
/// definitions here, since the initializer hasn't been attached.
///
-void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous,
+ bool PreviousWasHidden) {
// If the new decl is already invalid, don't do any other checking.
if (New->isInvalidDecl())
return;
@@ -2526,13 +2892,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
}
// Merge the types.
- MergeVarDeclTypes(New, Old);
+ MergeVarDeclTypes(New, Old, PreviousWasHidden);
if (New->isInvalidDecl())
return;
- // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
+ // [dcl.stc]p8: Check if we have a non-static decl followed by a static.
if (New->getStorageClass() == SC_Static &&
- (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) {
+ !New->isStaticDataMember() &&
+ isExternalLinkage(Old->getLinkage())) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2548,8 +2915,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// identifier has external linkage.
if (New->hasExternalStorage() && Old->hasLinkage())
/* Okay */;
- else if (New->getStorageClass() != SC_Static &&
- Old->getStorageClass() == SC_Static) {
+ else if (New->getCanonicalDecl()->getStorageClass() != SC_Static &&
+ !New->isStaticDataMember() &&
+ Old->getCanonicalDecl()->getStorageClass() == SC_Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2562,8 +2930,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
}
- if (Old->hasExternalStorage() &&
- !New->hasLinkage() && New->isLocalVarDecl()) {
+ if (Old->hasLinkage() && New->isLocalVarDecl() &&
+ !New->hasExternalStorage()) {
Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -2601,17 +2969,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setInvalidDecl();
return;
}
- // c99 6.2.2 P4.
- // For an identifier declared with the storage-class specifier extern in a
- // scope in which a prior declaration of that identifier is visible, if
- // the prior declaration specifies internal or external linkage, the linkage
- // of the identifier at the later declaration is the same as the linkage
- // specified at the prior declaration.
- // FIXME. revisit this code.
- if (New->hasExternalStorage() &&
- Old->getLinkage() == InternalLinkage &&
- New->getDeclContext() == Old->getDeclContext())
- New->setStorageClass(Old->getStorageClass());
+
+ if (haveIncompatibleLanguageLinkages(Old, New)) {
+ Diag(New->getLocation(), diag::err_different_language_linkage) << New;
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return;
+ }
+
+ // Merge "used" flag.
+ if (Old->isUsed(false))
+ New->setUsed();
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
@@ -2628,11 +2996,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
-/// no declarator (e.g. "struct foo;") is parsed. It also accopts template
+/// no declarator (e.g. "struct foo;") is parsed. It also accepts template
/// parameters to cope with template friend declarations.
Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DeclSpec &DS,
- MultiTemplateParamsArg TemplateParams) {
+ MultiTemplateParamsArg TemplateParams,
+ bool IsExplicitInstantiation) {
Decl *TagD = 0;
TagDecl *Tag = 0;
if (DS.getTypeSpecType() == DeclSpec::TST_class ||
@@ -2655,6 +3024,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
if (Tag) {
+ getASTContext().addUnnamedTag(Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -2684,6 +3054,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return TagD;
}
+ DiagnoseFunctionSpecifiers(DS);
+
if (DS.isFriendSpecified()) {
// If we're dealing with a decl but not a TagDecl, assume that
// whatever routines created it handled the friendship aspect.
@@ -2692,10 +3064,28 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return ActOnFriendTypeDecl(S, DS, TemplateParams);
}
- // Track whether we warned about the fact that there aren't any
- // declarators.
- bool emittedWarning = false;
-
+ CXXScopeSpec &SS = DS.getTypeSpecScope();
+ bool IsExplicitSpecialization =
+ !TemplateParams.empty() && TemplateParams.back()->size() == 0;
+ if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
+ !IsExplicitInstantiation && !IsExplicitSpecialization) {
+ // Per C++ [dcl.type.elab]p1, a class declaration cannot have a
+ // nested-name-specifier unless it is an explicit instantiation
+ // or an explicit specialization.
+ // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
+ Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
+ << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 :
+ DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 :
+ DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 :
+ DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4)
+ << SS.getRange();
+ return 0;
+ }
+
+ // Track whether this decl-specifier declares anything.
+ bool DeclaresAnything = true;
+
+ // Handle anonymous struct definitions.
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
if (!Record->getDeclName() && Record->isCompleteDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
@@ -2703,13 +3093,11 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
Record->getDeclContext()->isRecord())
return BuildAnonymousStructOrUnion(S, DS, AS, Record);
- Diag(DS.getLocStart(), diag::ext_no_declarators)
- << DS.getSourceRange();
- emittedWarning = true;
+ DeclaresAnything = false;
}
}
- // Check for Microsoft C extension: anonymous struct.
+ // Check for Microsoft C extension: anonymous struct member.
if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus &&
CurContext->isRecord() &&
DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) {
@@ -2726,70 +3114,82 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return BuildMicrosoftCAnonymousStruct(S, DS, Record);
}
}
-
- if (getLangOpts().CPlusPlus &&
+
+ // Skip all the checks below if we have a type error.
+ if (DS.getTypeSpecType() == DeclSpec::TST_error ||
+ (TagD && TagD->isInvalidDecl()))
+ return TagD;
+
+ if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
if (Enum->enumerator_begin() == Enum->enumerator_end() &&
- !Enum->getIdentifier() && !Enum->isInvalidDecl()) {
- Diag(Enum->getLocation(), diag::ext_no_declarators)
- << DS.getSourceRange();
- emittedWarning = true;
- }
+ !Enum->getIdentifier() && !Enum->isInvalidDecl())
+ DeclaresAnything = false;
- // Skip all the checks below if we have a type error.
- if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD;
-
if (!DS.isMissingDeclaratorOk()) {
- // Warn about typedefs of enums without names, since this is an
- // extension in both Microsoft and GNU.
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
- Tag && isa<EnumDecl>(Tag)) {
+ // Customize diagnostic for a typedef missing a name.
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
Diag(DS.getLocStart(), diag::ext_typedef_without_a_name)
<< DS.getSourceRange();
- return Tag;
- }
-
- Diag(DS.getLocStart(), diag::ext_no_declarators)
- << DS.getSourceRange();
- emittedWarning = true;
+ else
+ DeclaresAnything = false;
}
- // We're going to complain about a bunch of spurious specifiers;
- // only do this if we're declaring a tag, because otherwise we
- // should be getting diag::ext_no_declarators.
- if (emittedWarning || (TagD && TagD->isInvalidDecl()))
+ if (DS.isModulePrivateSpecified() &&
+ Tag && Tag->getDeclContext()->isFunctionOrMethod())
+ Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class)
+ << Tag->getTagKind()
+ << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc());
+
+ ActOnDocumentableDecl(TagD);
+
+ // C 6.7/2:
+ // A declaration [...] shall declare at least a declarator [...], a tag,
+ // or the members of an enumeration.
+ // C++ [dcl.dcl]p3:
+ // [If there are no declarators], and except for the declaration of an
+ // unnamed bit-field, the decl-specifier-seq shall introduce one or more
+ // names into the program, or shall redeclare a name introduced by a
+ // previous declaration.
+ if (!DeclaresAnything) {
+ // In C, we allow this as a (popular) extension / bug. Don't bother
+ // producing further diagnostics for redundant qualifiers after this.
+ Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange();
return TagD;
+ }
+
+ // C++ [dcl.stc]p1:
+ // If a storage-class-specifier appears in a decl-specifier-seq, [...] the
+ // init-declarator-list of the declaration shall not be empty.
+ // C++ [dcl.fct.spec]p1:
+ // If a cv-qualifier appears in a decl-specifier-seq, the
+ // init-declarator-list of the declaration shall not be empty.
+ //
+ // Spurious qualifiers here appear to be valid in C.
+ unsigned DiagID = diag::warn_standalone_specifier;
+ if (getLangOpts().CPlusPlus)
+ DiagID = diag::ext_standalone_specifier;
// Note that a linkage-specification sets a storage class, but
// 'extern "C" struct foo;' is actually valid and not theoretically
// useless.
- if (DeclSpec::SCS scs = DS.getStorageClassSpec())
- if (!DS.isExternInLinkageSpec())
- Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier)
- << DeclSpec::getSpecifierName(scs);
+ if (DeclSpec::SCS SCS = DS.getStorageClassSpec())
+ if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef)
+ Diag(DS.getStorageClassSpecLoc(), DiagID)
+ << DeclSpec::getSpecifierName(SCS);
if (DS.isThreadSpecified())
- Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread";
+ Diag(DS.getThreadSpecLoc(), DiagID) << "__thread";
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
- Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const";
+ Diag(DS.getConstSpecLoc(), DiagID) << "const";
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
- Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile";
+ Diag(DS.getConstSpecLoc(), DiagID) << "volatile";
// Restrict is covered above.
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic";
}
- if (DS.isInlineSpecified())
- Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline";
- if (DS.isVirtualSpecified())
- Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual";
- if (DS.isExplicitSpecified())
- Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit";
-
- if (DS.isModulePrivateSpecified() &&
- Tag && Tag->getDeclContext()->isFunctionOrMethod())
- Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class)
- << Tag->getTagKind()
- << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc());
// Warn about ignored type attributes, for example:
// __attribute__((aligned)) struct A;
@@ -2814,8 +3214,6 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
}
}
- ActOnDocumentableDecl(TagD);
-
return TagD;
}
@@ -2950,25 +3348,6 @@ StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
llvm_unreachable("unknown storage class specifier");
}
-/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
-/// a StorageClass. Any error reporting is up to the caller:
-/// illegal input values are mapped to SC_None.
-static StorageClass
-StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
- switch (StorageClassSpec) {
- case DeclSpec::SCS_unspecified: return SC_None;
- case DeclSpec::SCS_extern: return SC_Extern;
- case DeclSpec::SCS_static: return SC_Static;
- case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
- // Illegal SCSs map to None: error reporting is up to the caller.
- case DeclSpec::SCS_auto: // Fall through.
- case DeclSpec::SCS_mutable: // Fall through.
- case DeclSpec::SCS_register: // Fall through.
- case DeclSpec::SCS_typedef: return SC_None;
- }
- llvm_unreachable("unknown storage class specifier");
-}
-
/// BuildAnonymousStructOrUnion - Handle the declaration of an
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a C11 feature; anonymous structures
@@ -3027,18 +3406,23 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified)
- << Record->isUnion() << 0
+ << Record->isUnion() << "const"
<< FixItHint::CreateRemoval(DS.getConstSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
- Diag(DS.getVolatileSpecLoc(),
+ Diag(DS.getVolatileSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
- << Record->isUnion() << 1
+ << Record->isUnion() << "volatile"
<< FixItHint::CreateRemoval(DS.getVolatileSpecLoc());
if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
- Diag(DS.getRestrictSpecLoc(),
+ Diag(DS.getRestrictSpecLoc(),
diag::ext_anonymous_struct_union_qualified)
- << Record->isUnion() << 2
+ << Record->isUnion() << "restrict"
<< FixItHint::CreateRemoval(DS.getRestrictSpecLoc());
+ if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
+ Diag(DS.getAtomicSpecLoc(),
+ diag::ext_anonymous_struct_union_qualified)
+ << Record->isUnion() << "_Atomic"
+ << FixItHint::CreateRemoval(DS.getAtomicSpecLoc());
DS.ClearTypeQualifiers();
}
@@ -3088,6 +3472,13 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
<< (int)Record->isUnion();
Invalid = true;
}
+ } else {
+ // This is an anonymous type definition within another anonymous type.
+ // This is a popular extension, provided by Plan9, MSVC and GCC, but
+ // not part of standard C++.
+ Diag(MemRecord->getLocation(),
+ diag::ext_anonymous_record_with_anonymous_type)
+ << (int)Record->isUnion();
}
} else if (isa<AccessSpecDecl>(*Mem)) {
// Any access specifier is fine.
@@ -3153,15 +3544,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Invalid = true;
SC = SC_None;
}
- SCSpec = DS.getStorageClassSpecAsWritten();
- VarDecl::StorageClass SCAsWritten
- = StorageClassSpecToVarDeclStorageClass(SCSpec);
Anon = VarDecl::Create(Context, Owner,
DS.getLocStart(),
Record->getLocation(), /*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
- TInfo, SC, SCAsWritten);
+ TInfo, SC);
// Default-initialize the implicit variable. This initialization will be
// trivial in almost all cases, except if a union member has an in-class
@@ -3383,7 +3771,7 @@ static QualType getCoreType(QualType Ty) {
static bool hasSimilarParameters(ASTContext &Context,
FunctionDecl *Declaration,
FunctionDecl *Definition,
- llvm::SmallVectorImpl<unsigned> &Params) {
+ SmallVectorImpl<unsigned> &Params) {
Params.clear();
if (Declaration->param_size() != Definition->param_size())
return false;
@@ -3609,8 +3997,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
return false;
}
-Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParamLists) {
+NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists) {
// TODO: consider using NameInfo for diagnostic.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
@@ -3690,8 +4078,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
return 0;
- NamedDecl *New;
-
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
@@ -3776,6 +4162,13 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
Previous.clear();
+ // Check that there are no default arguments other than in the parameters
+ // of a function declaration (C++ only).
+ if (getLangOpts().CPlusPlus)
+ CheckExtraCXXDefaultArguments(D);
+
+ NamedDecl *New;
+
bool AddToScope = true;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
if (TemplateParamLists.size()) {
@@ -3877,29 +4270,29 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
static void
FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) {
- if (PointerTypeLoc* SrcPTL = dyn_cast<PointerTypeLoc>(&SrcTL)) {
- PointerTypeLoc* DstPTL = cast<PointerTypeLoc>(&DstTL);
- FixInvalidVariablyModifiedTypeLoc(SrcPTL->getPointeeLoc(),
- DstPTL->getPointeeLoc());
- DstPTL->setStarLoc(SrcPTL->getStarLoc());
+ if (PointerTypeLoc SrcPTL = SrcTL.getAs<PointerTypeLoc>()) {
+ PointerTypeLoc DstPTL = DstTL.castAs<PointerTypeLoc>();
+ FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(),
+ DstPTL.getPointeeLoc());
+ DstPTL.setStarLoc(SrcPTL.getStarLoc());
return;
}
- if (ParenTypeLoc* SrcPTL = dyn_cast<ParenTypeLoc>(&SrcTL)) {
- ParenTypeLoc* DstPTL = cast<ParenTypeLoc>(&DstTL);
- FixInvalidVariablyModifiedTypeLoc(SrcPTL->getInnerLoc(),
- DstPTL->getInnerLoc());
- DstPTL->setLParenLoc(SrcPTL->getLParenLoc());
- DstPTL->setRParenLoc(SrcPTL->getRParenLoc());
+ if (ParenTypeLoc SrcPTL = SrcTL.getAs<ParenTypeLoc>()) {
+ ParenTypeLoc DstPTL = DstTL.castAs<ParenTypeLoc>();
+ FixInvalidVariablyModifiedTypeLoc(SrcPTL.getInnerLoc(),
+ DstPTL.getInnerLoc());
+ DstPTL.setLParenLoc(SrcPTL.getLParenLoc());
+ DstPTL.setRParenLoc(SrcPTL.getRParenLoc());
return;
}
- ArrayTypeLoc* SrcATL = cast<ArrayTypeLoc>(&SrcTL);
- ArrayTypeLoc* DstATL = cast<ArrayTypeLoc>(&DstTL);
- TypeLoc SrcElemTL = SrcATL->getElementLoc();
- TypeLoc DstElemTL = DstATL->getElementLoc();
+ ArrayTypeLoc SrcATL = SrcTL.castAs<ArrayTypeLoc>();
+ ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>();
+ TypeLoc SrcElemTL = SrcATL.getElementLoc();
+ TypeLoc DstElemTL = DstATL.getElementLoc();
DstElemTL.initializeFullCopy(SrcElemTL);
- DstATL->setLBracketLoc(SrcATL->getLBracketLoc());
- DstATL->setSizeExpr(SrcATL->getSizeExpr());
- DstATL->setRBracketLoc(SrcATL->getRBracketLoc());
+ DstATL.setLBracketLoc(SrcATL.getLBracketLoc());
+ DstATL.setSizeExpr(SrcATL.getSizeExpr());
+ DstATL.setRBracketLoc(SrcATL.getRBracketLoc());
}
/// Helper method to turn variable array types into constant array
@@ -3921,7 +4314,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
return FixedTInfo;
}
-/// \brief Register the given locally-scoped external C declaration so
+/// \brief Register the given locally-scoped extern "C" declaration so
/// that it can be found later for redeclarations
void
Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
@@ -3930,15 +4323,15 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
"Decl is not a locally-scoped decl!");
// Note that we have a locally-scoped external with this name.
- LocallyScopedExternalDecls[ND->getDeclName()] = ND;
+ LocallyScopedExternCDecls[ND->getDeclName()] = ND;
if (!Previous.isSingleResult())
return;
NamedDecl *PrevDecl = Previous.getFoundDecl();
- // If there was a previous declaration of this variable, it may be
- // in our identifier chain. Update the identifier chain with the new
+ // If there was a previous declaration of this entity, it may be in
+ // our identifier chain. Update the identifier chain with the new
// declaration.
if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) {
// The previous declaration was found on the identifer resolver
@@ -3962,38 +4355,42 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
}
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
-Sema::findLocallyScopedExternalDecl(DeclarationName Name) {
+Sema::findLocallyScopedExternCDecl(DeclarationName Name) {
if (ExternalSource) {
// Load locally-scoped external decls from the external source.
SmallVector<NamedDecl *, 4> Decls;
- ExternalSource->ReadLocallyScopedExternalDecls(Decls);
+ ExternalSource->ReadLocallyScopedExternCDecls(Decls);
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = LocallyScopedExternalDecls.find(Decls[I]->getDeclName());
- if (Pos == LocallyScopedExternalDecls.end())
- LocallyScopedExternalDecls[Decls[I]->getDeclName()] = Decls[I];
+ = LocallyScopedExternCDecls.find(Decls[I]->getDeclName());
+ if (Pos == LocallyScopedExternCDecls.end())
+ LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I];
}
}
- return LocallyScopedExternalDecls.find(Name);
+ return LocallyScopedExternCDecls.find(Name);
}
/// \brief Diagnose function specifiers on a declaration of an identifier that
/// does not identify a function.
-void Sema::DiagnoseFunctionSpecifiers(Declarator& D) {
+void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) {
// 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(),
+ if (DS.isInlineSpecified())
+ Diag(DS.getInlineSpecLoc(),
diag::err_inline_non_function);
- if (D.getDeclSpec().isVirtualSpecified())
- Diag(D.getDeclSpec().getVirtualSpecLoc(),
+ if (DS.isVirtualSpecified())
+ Diag(DS.getVirtualSpecLoc(),
diag::err_virtual_non_function);
- if (D.getDeclSpec().isExplicitSpecified())
- Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ if (DS.isExplicitSpecified())
+ Diag(DS.getExplicitSpecLoc(),
diag::err_explicit_non_function);
+
+ if (DS.isNoreturnSpecified())
+ Diag(DS.getNoreturnSpecLoc(),
+ diag::err_noreturn_non_function);
}
NamedDecl*
@@ -4009,12 +4406,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Previous.clear();
}
- if (getLangOpts().CPlusPlus) {
- // Check that there are no default arguments (C++ only).
- CheckExtraCXXDefaultArguments(D);
- }
-
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
@@ -4090,6 +4482,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
// in an outer scope, it isn't the same thing.
FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
/*ExplicitInstantiationOrSpecialization=*/false);
+ filterNonConflictingPreviousDecls(Context, NewTD, Previous);
if (!Previous.empty()) {
Redeclaration = true;
MergeTypedefNameDecl(NewTD, Previous);
@@ -4220,6 +4613,74 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
return false;
}
+static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
+ // 'weak' only applies to declarations with external linkage.
+ if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) {
+ if (ND.getLinkage() != ExternalLinkage) {
+ S.Diag(Attr->getLocation(), diag::err_attribute_weak_static);
+ ND.dropAttr<WeakAttr>();
+ }
+ }
+ if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) {
+ if (ND.hasExternalLinkage()) {
+ S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static);
+ ND.dropAttr<WeakRefAttr>();
+ }
+ }
+}
+
+/// Given that we are within the definition of the given function,
+/// will that definition behave like C99's 'inline', where the
+/// definition is discarded except for optimization purposes?
+static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
+ // Try to avoid calling GetGVALinkageForFunction.
+
+ // All cases of this require the 'inline' keyword.
+ if (!FD->isInlined()) return false;
+
+ // This is only possible in C++ with the gnu_inline attribute.
+ if (S.getLangOpts().CPlusPlus && !FD->hasAttr<GNUInlineAttr>())
+ return false;
+
+ // Okay, go ahead and call the relatively-more-expensive function.
+
+#ifndef NDEBUG
+ // AST quite reasonably asserts that it's working on a function
+ // definition. We don't really have a way to tell it that we're
+ // currently defining the function, so just lie to it in +Asserts
+ // builds. This is an awful hack.
+ FD->setLazyBody(1);
+#endif
+
+ bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline);
+
+#ifndef NDEBUG
+ FD->setLazyBody(0);
+#endif
+
+ return isC99Inline;
+}
+
+static bool shouldConsiderLinkage(const VarDecl *VD) {
+ const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
+ if (DC->isFunctionOrMethod())
+ return VD->hasExternalStorage();
+ if (DC->isFileContext())
+ return true;
+ if (DC->isRecord())
+ return false;
+ llvm_unreachable("Unexpected context");
+}
+
+static bool shouldConsiderLinkage(const FunctionDecl *FD) {
+ const DeclContext *DC = FD->getDeclContext()->getRedeclContext();
+ if (DC->isFileContext() || DC->isFunctionOrMethod())
+ return true;
+ if (DC->isRecord())
+ return false;
+ llvm_unreachable("Unexpected context");
+}
+
NamedDecl*
Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -4227,14 +4688,21 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
QualType R = TInfo->getType();
DeclarationName Name = GetNameForDeclarator(D).getName();
- // Check that there are no default arguments (C++ only).
- if (getLangOpts().CPlusPlus)
- CheckExtraCXXDefaultArguments(D);
-
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
+
+ if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16)
+ {
+ // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
+ // half array type (unless the cl_khr_fp16 extension is enabled).
+ if (Context.getBaseElementType(R)->isHalfType()) {
+ Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
+ D.setInvalidType();
+ }
+ }
+
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
@@ -4242,9 +4710,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
D.setInvalidType();
SC = SC_None;
}
- SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
- VarDecl::StorageClass SCAsWritten
- = StorageClassSpecToVarDeclStorageClass(SCSpec);
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (!II) {
@@ -4253,7 +4718,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
return 0;
}
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (!DC->isRecord() && S->getFnParent() == 0) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
@@ -4273,8 +4738,33 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (getLangOpts().OpenCL) {
// Set up the special work-group-local storage class for variables in the
// OpenCL __local address space.
- if (R.getAddressSpace() == LangAS::opencl_local)
+ if (R.getAddressSpace() == LangAS::opencl_local) {
SC = SC_OpenCLWorkGroupLocal;
+ }
+
+ // OpenCL v1.2 s6.9.b p4:
+ // The sampler type cannot be used with the __local and __global address
+ // space qualifiers.
+ if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
+ R.getAddressSpace() == LangAS::opencl_global)) {
+ Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
+ }
+
+ // OpenCL 1.2 spec, p6.9 r:
+ // The event type cannot be used to declare a program scope variable.
+ // The event type cannot be used with the __local, __constant and __global
+ // address space qualifiers.
+ if (R->isEventT()) {
+ if (S->getParent() == 0) {
+ Diag(D.getLocStart(), diag::err_event_t_global_var);
+ D.setInvalidType();
+ }
+
+ if (R.getAddressSpace()) {
+ Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
+ D.setInvalidType();
+ }
+ }
}
bool isExplicitSpecialization = false;
@@ -4282,7 +4772,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!getLangOpts().CPlusPlus) {
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
- R, TInfo, SC, SCAsWritten);
+ R, TInfo, SC);
if (D.isInvalidType())
NewVD->setInvalidDecl();
@@ -4293,8 +4783,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
- } else if (SC == SC_None)
- SC = SC_Static;
+ }
}
if (SC == SC_Static && CurContext->isRecord()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
@@ -4307,7 +4796,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// the program is ill-formed. C++11 drops this restriction.
if (RD->isUnion())
Diag(D.getIdentifierLoc(),
- getLangOpts().CPlusPlus0x
+ getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_static_data_member_in_union
: diag::ext_static_data_member_in_union) << Name;
// We conservatively disallow static data members in anonymous structs.
@@ -4352,7 +4841,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
- R, TInfo, SC, SCAsWritten);
+ R, TInfo, SC);
// If this decl has an auto type in need of deduction, make a note of the
// Decl so we can diagnose uses of it in its own initializer.
@@ -4388,6 +4877,25 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setThreadSpecified(true);
}
+ // C99 6.7.4p3
+ // An inline definition of a function with external linkage shall
+ // not contain a definition of a modifiable object with static or
+ // thread storage duration...
+ // We only apply this when the function is required to be defined
+ // elsewhere, i.e. when the function is not 'extern inline'. Note
+ // that a local variable with thread storage duration still has to
+ // be marked 'static'. Also note that it's possible to get these
+ // semantics in C++ using __attribute__((gnu_inline)).
+ if (SC == SC_Static && S->getFnParent() != 0 &&
+ !NewVD->getType().isConstQualified()) {
+ FunctionDecl *CurFD = getCurFunctionDecl();
+ if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) {
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
+ diag::warn_static_local_in_extern_inline);
+ MaybeSuggestAddingStaticToDecl(CurFD);
+ }
+ }
+
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (isExplicitSpecialization)
Diag(NewVD->getLocation(), diag::err_module_private_specialization)
@@ -4405,12 +4913,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
+ if (NewVD->hasAttrs())
+ CheckAlignasUnderalignment(NewVD);
+
if (getLangOpts().CUDA) {
// CUDA B.2.5: "__shared__ and __constant__ variables have implied static
// storage [duration]."
if (SC == SC_None && S->getFnParent() != 0 &&
- (NewVD->hasAttr<CUDASharedAttr>() || NewVD->hasAttr<CUDAConstantAttr>()))
+ (NewVD->hasAttr<CUDASharedAttr>() ||
+ NewVD->hasAttr<CUDAConstantAttr>())) {
NewVD->setStorageClass(SC_Static);
+ }
}
// In auto-retain/release, infer strong retension for variables of
@@ -4459,7 +4972,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
// declaration has linkage).
- FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewVD),
isExplicitSpecialization);
if (!getLangOpts().CPlusPlus) {
@@ -4493,19 +5006,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setInvalidDecl();
}
+ ProcessPragmaWeak(S, NewVD);
+ checkAttributesAfterMerging(*this, *NewVD);
+
// If this is a locally-scoped extern C variable, update the map of
// such variables.
if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
!NewVD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
- // If there's a #pragma GCC visibility in scope, and this isn't a class
- // member, set the visibility of this variable.
- if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
- AddPushedVisibilityAttribute(NewVD);
-
- MarkUnusedFileScopedDecl(NewVD);
-
return NewVD;
}
@@ -4604,6 +5113,32 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
CheckShadow(S, D, R);
}
+template<typename T>
+static bool mayConflictWithNonVisibleExternC(const T *ND) {
+ const DeclContext *DC = ND->getDeclContext();
+ if (DC->getRedeclContext()->isTranslationUnit())
+ return true;
+
+ // We know that is the first decl we see, other than function local
+ // extern C ones. If this is C++ and the decl is not in a extern C context
+ // it cannot have C language linkage. Avoid calling isExternC in that case.
+ // We need to this because of code like
+ //
+ // namespace { struct bar {}; }
+ // auto foo = bar();
+ //
+ // This code runs before the init of foo is set, and therefore before
+ // the type of foo is known. Not knowing the type we cannot know its linkage
+ // unless it is in an extern C block.
+ if (!DC->isExternCContext()) {
+ const ASTContext &Context = ND->getASTContext();
+ if (Context.getLangOpts().CPlusPlus)
+ return false;
+ }
+
+ return ND->isExternC();
+}
+
/// \brief Perform semantic checking on a newly-created variable
/// declaration.
///
@@ -4706,16 +5241,44 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
NewVD->setTypeSourceInfo(FixedTInfo);
}
- if (Previous.empty() && 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.
+ // If we did not find anything by this name, look for a non-visible
+ // extern "C" declaration with the same name.
+ //
+ // Clang has a lot of problems with extern local declarations.
+ // The actual standards text here is:
+ //
+ // C++11 [basic.link]p6:
+ // The name of a function declared in block scope and the name
+ // of a variable declared by a block scope extern declaration
+ // have linkage. If there is a visible declaration of an entity
+ // with linkage having the same name and type, ignoring entities
+ // declared outside the innermost enclosing namespace scope, the
+ // block scope declaration declares that same entity and
+ // receives the linkage of the previous declaration.
+ //
+ // C11 6.2.7p4:
+ // For an identifier with internal or external linkage declared
+ // in a scope in which a prior declaration of that identifier is
+ // visible, if the prior declaration specifies internal or
+ // external linkage, the type of the identifier at the later
+ // declaration becomes the composite type.
+ //
+ // The most important point here is that we're not allowed to
+ // update our understanding of the type according to declarations
+ // not in scope.
+ bool PreviousWasHidden = false;
+ if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) {
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternalDecl(NewVD->getDeclName());
- if (Pos != LocallyScopedExternalDecls.end())
+ = findLocallyScopedExternCDecl(NewVD->getDeclName());
+ if (Pos != LocallyScopedExternCDecls.end()) {
Previous.addDecl(Pos->second);
+ PreviousWasHidden = true;
+ }
}
+ // Filter out any non-conflicting previous declarations.
+ filterNonConflictingPreviousDecls(Context, NewVD, Previous);
+
if (T->isVoidType() && !NewVD->hasExternalStorage()) {
Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
<< T;
@@ -4743,7 +5306,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
}
if (!Previous.empty()) {
- MergeVarDecl(NewVD, Previous);
+ MergeVarDecl(NewVD, Previous, PreviousWasHidden);
return true;
}
return false;
@@ -4778,9 +5341,9 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
}
for (Path.Decls = BaseRecord->lookup(Name);
- Path.Decls.first != Path.Decls.second;
- ++Path.Decls.first) {
- NamedDecl *D = *Path.Decls.first;
+ !Path.Decls.empty();
+ Path.Decls = Path.Decls.slice(1)) {
+ NamedDecl *D = Path.Decls.front();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
return true;
@@ -4832,6 +5395,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
+ !CheckOverridingFunctionAttributes(MD, OldMD) &&
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
hasDeletedOverridenMethods |= OldMD->isDeleted();
@@ -4878,7 +5442,7 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
if (candidate.getEditDistance() == 0)
return false;
- llvm::SmallVector<unsigned, 1> MismatchedParams;
+ SmallVector<unsigned, 1> MismatchedParams;
for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
CDeclEnd = candidate.end();
CDecl != CDeclEnd; ++CDecl) {
@@ -4924,8 +5488,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
DeclContext *NewDC = NewFD->getDeclContext();
LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
- llvm::SmallVector<unsigned, 1> MismatchedParams;
- llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches;
+ SmallVector<unsigned, 1> MismatchedParams;
+ SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches;
TypoCorrection Correction;
bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus &&
ExtraArgs.D.getDeclSpec().isFriendSpecified());
@@ -5029,7 +5593,7 @@ static NamedDecl* DiagnoseInvalidRedeclaration(
if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD))
NewFDisConst = NewMD->isConst();
- for (llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1>::iterator
+ for (SmallVector<std::pair<FunctionDecl *, unsigned>, 1>::iterator
NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end();
NearMatch != NearMatchEnd; ++NearMatch) {
FunctionDecl *FD = NearMatch->first;
@@ -5098,9 +5662,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
FunctionDecl *NewFD = 0;
bool isInline = D.getDeclSpec().isInlineSpecified();
- DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
- FunctionDecl::StorageClass SCAsWritten
- = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
if (!SemaRef.getLangOpts().CPlusPlus) {
// Determine whether the function was written with a
@@ -5114,8 +5675,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
NewFD = FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(), NameInfo, R,
- TInfo, SC, SCAsWritten, isInline,
- HasPrototype);
+ TInfo, SC, isInline,
+ HasPrototype, false);
if (D.isInvalidType())
NewFD->setInvalidDecl();
@@ -5164,7 +5725,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
// If the class is complete, then we now create the implicit exception
// specification. If the class is incomplete or dependent, we can't do
// it yet.
- if (SemaRef.getLangOpts().CPlusPlus0x && !Record->isDependentType() &&
+ if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() &&
Record->getDefinition() && !Record->isBeingDefined() &&
R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
@@ -5182,7 +5743,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(),
D.getIdentifierLoc(), Name, R, TInfo,
- SC, SCAsWritten, isInline,
+ SC, isInline,
/*hasPrototype=*/true, isConstexpr);
}
@@ -5213,36 +5774,21 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
return 0;
}
- bool isStatic = SC == SC_Static;
-
- // [class.free]p1:
- // Any allocation function for a class T is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_New ||
- Name.getCXXOverloadedOperator() == OO_Array_New)
- isStatic = true;
-
- // [class.free]p6 Any deallocation function for a class X is a static member
- // (even if not explicitly declared static).
- if (Name.getCXXOverloadedOperator() == OO_Delete ||
- Name.getCXXOverloadedOperator() == OO_Array_Delete)
- isStatic = true;
-
- IsVirtualOkay = !isStatic;
-
// This is a C++ method declaration.
- return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC),
- D.getLocStart(), NameInfo, R,
- TInfo, isStatic, SCAsWritten, isInline,
- isConstexpr, SourceLocation());
-
+ CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context,
+ cast<CXXRecordDecl>(DC),
+ D.getLocStart(), NameInfo, R,
+ TInfo, SC, isInline,
+ isConstexpr, SourceLocation());
+ IsVirtualOkay = !Ret->isStatic();
+ return Ret;
} else {
// Determine whether the function was written with a
// prototype. This true when:
// - we're in C++ (where every function has a prototype),
return FunctionDecl::Create(SemaRef.Context, DC,
D.getLocStart(),
- NameInfo, R, TInfo, SC, SCAsWritten, isInline,
+ NameInfo, R, TInfo, SC, isInline,
true/*HasPrototype*/, isConstexpr);
}
}
@@ -5291,8 +5837,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
T = Context.getObjCObjectPointerType(T);
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- R = Context.getFunctionType(T, FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI);
+ R = Context.getFunctionType(T,
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI);
}
else if (isa<FunctionNoProtoType>(R))
R = Context.getFunctionNoProtoType(T);
@@ -5504,11 +6052,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (isConstexpr) {
- // C++0x [dcl.constexpr]p2: constexpr functions and constexpr constructors
+ // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors
// are implicitly inline.
NewFD->setImplicitlyInline();
- // C++0x [dcl.constexpr]p3: functions declared constexpr are required to
+ // C++11 [dcl.constexpr]p3: functions declared constexpr are required to
// be either constructors or to return a literal type. Therefore,
// destructors cannot be declared constexpr.
if (isa<CXXDestructorDecl>(NewFD))
@@ -5583,17 +6131,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
const FunctionProtoType *FPT = R->getAs<FunctionProtoType>();
if ((Name.getCXXOverloadedOperator() == OO_Delete ||
Name.getCXXOverloadedOperator() == OO_Array_Delete) &&
- getLangOpts().CPlusPlus0x && FPT && !FPT->hasExceptionSpec()) {
+ getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpecType = EST_BasicNoexcept;
NewFD->setType(Context.getFunctionType(FPT->getResultType(),
- FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI));
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI));
}
}
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD),
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
@@ -5675,6 +6224,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope);
DeclsInPrototypeScope.clear();
+ if (D.getDeclSpec().isNoreturnSpecified())
+ NewFD->addAttr(
+ ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
+ Context));
+
// Process the non-inheritable attributes on this declaration.
ProcessDeclAttributes(S, NewFD, D,
/*NonInheritable=*/true, /*Inheritable=*/false);
@@ -5691,6 +6245,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
ProcessDeclAttributes(S, NewFD, D,
/*NonInheritable=*/false, /*Inheritable=*/true);
+ QualType RetType = NewFD->getResultType();
+ const CXXRecordDecl *Ret = RetType->isRecordType() ?
+ RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl();
+ if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() &&
+ Ret && Ret->hasAttr<WarnUnusedResultAttr>()) {
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+ if (!(MD && MD->getCorrespondingMethodInClass(Ret, true))) {
+ NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(),
+ Context));
+ }
+ }
+
if (!getLangOpts().CPlusPlus) {
// Perform semantic checking on the function declaration.
bool isExplicitSpecialization=false;
@@ -5788,7 +6354,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// A storage-class-specifier shall not be specified in an explicit
// specialization (14.7.3)
if (SC != SC_None) {
- if (SC != NewFD->getStorageClass())
+ if (SC != NewFD->getTemplateSpecializationInfo()->getTemplate()->getTemplatedDecl()->getStorageClass())
Diag(NewFD->getLocation(),
diag::err_explicit_specialization_inconsistent_storage_class)
<< SC
@@ -5938,6 +6504,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
+ ProcessPragmaWeak(S, NewFD);
+ checkAttributesAfterMerging(*this, *NewFD);
+
AddKnownFunctionAttributes(NewFD);
if (NewFD->hasAttr<OverloadableAttr>() &&
@@ -5952,13 +6521,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
EPI.Variadic = true;
EPI.ExtInfo = FT->getExtInfo();
- QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI);
+ QualType R = Context.getFunctionType(FT->getResultType(),
+ ArrayRef<QualType>(),
+ EPI);
NewFD->setType(R);
}
// If there's a #pragma GCC visibility in scope, and this isn't a class
// member, set the visibility of this function.
- if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord())
+ if (!DC->isRecord() && NewFD->hasExternalLinkage())
AddPushedVisibilityAttribute(NewFD);
// If there's a #pragma clang arc_cf_code_audited in scope, consider
@@ -5982,12 +6553,42 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- // OpenCL v1.2 s6.8 static is invalid for kernel functions.
- if ((getLangOpts().OpenCLVersion >= 120)
- && NewFD->hasAttr<OpenCLKernelAttr>()
- && (SC == SC_Static)) {
- Diag(D.getIdentifierLoc(), diag::err_static_kernel);
- D.setInvalidType();
+ if (NewFD->hasAttr<OpenCLKernelAttr>()) {
+ // OpenCL v1.2 s6.8 static is invalid for kernel functions.
+ if ((getLangOpts().OpenCLVersion >= 120)
+ && (SC == SC_Static)) {
+ Diag(D.getIdentifierLoc(), diag::err_static_kernel);
+ D.setInvalidType();
+ }
+
+ // OpenCL v1.2, s6.9 -- Kernels can only have return type void.
+ if (!NewFD->getResultType()->isVoidType()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_expected_kernel_void_return_type);
+ D.setInvalidType();
+ }
+
+ for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
+ PE = NewFD->param_end(); PI != PE; ++PI) {
+ ParmVarDecl *Param = *PI;
+ QualType PT = Param->getType();
+
+ // OpenCL v1.2 s6.9.a:
+ // A kernel function argument cannot be declared as a
+ // pointer to a pointer type.
+ if (PT->isPointerType() && PT->getPointeeType()->isPointerType()) {
+ Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_arg);
+ D.setInvalidType();
+ }
+
+ // OpenCL v1.2 s6.8 n:
+ // A kernel function argument cannot be declared
+ // of event_t type.
+ if (PT->isEventT()) {
+ Diag(Param->getLocation(), diag::err_event_t_kernel_arg);
+ D.setInvalidType();
+ }
+ }
}
MarkUnusedFileScopedDecl(NewFD);
@@ -6043,17 +6644,20 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
&& "Variably modified return types are not handled here");
// Check for a previous declaration of this name.
- if (Previous.empty() && 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.
+ if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) {
+ // Since we did not find anything by this name, look for a non-visible
+ // extern "C" declaration with the same name.
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternalDecl(NewFD->getDeclName());
- if (Pos != LocallyScopedExternalDecls.end())
+ = findLocallyScopedExternCDecl(NewFD->getDeclName());
+ if (Pos != LocallyScopedExternCDecls.end())
Previous.addDecl(Pos->second);
}
+ // Filter out any non-conflicting previous declarations.
+ filterNonConflictingPreviousDecls(Context, NewFD, Previous);
+
bool Redeclaration = false;
+ NamedDecl *OldDecl = 0;
// Merge or overload the declaration with an existing declaration of
// the same name, if appropriate.
@@ -6062,8 +6666,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// a declaration that requires merging. If it's an overload,
// there's no more work to do here; we'll just add the new
// function to the scope.
-
- NamedDecl *OldDecl = 0;
if (!AllowOverloadingOfFunction(Previous, Context)) {
Redeclaration = true;
OldDecl = Previous.getFoundDecl();
@@ -6100,42 +6702,90 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Context));
}
}
+ }
- if (Redeclaration) {
- // NewFD and OldDecl represent declarations that need to be
- // merged.
- if (MergeFunctionDecl(NewFD, OldDecl, S)) {
- NewFD->setInvalidDecl();
- return Redeclaration;
- }
+ // C++11 [dcl.constexpr]p8:
+ // A constexpr specifier for a non-static member function that is not
+ // a constructor declares that member function to be const.
+ //
+ // This needs to be delayed until we know whether this is an out-of-line
+ // definition of a static member function.
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
+ if (MD && MD->isConstexpr() && !MD->isStatic() &&
+ !isa<CXXConstructorDecl>(MD) &&
+ (MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
+ CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
+ if (FunctionTemplateDecl *OldTD =
+ dyn_cast_or_null<FunctionTemplateDecl>(OldDecl))
+ OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl());
+ if (!OldMD || !OldMD->isStatic()) {
+ const FunctionProtoType *FPT =
+ MD->getType()->castAs<FunctionProtoType>();
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.TypeQuals |= Qualifiers::Const;
+ MD->setType(Context.getFunctionType(FPT->getResultType(),
+ ArrayRef<QualType>(FPT->arg_type_begin(),
+ FPT->getNumArgs()),
+ EPI));
+ }
+ }
- Previous.clear();
- Previous.addDecl(OldDecl);
-
- if (FunctionTemplateDecl *OldTemplateDecl
- = 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());
+ if (Redeclaration) {
+ // NewFD and OldDecl represent declarations that need to be
+ // merged.
+ if (MergeFunctionDecl(NewFD, OldDecl, S)) {
+ NewFD->setInvalidDecl();
+ return Redeclaration;
+ }
+
+ Previous.clear();
+ Previous.addDecl(OldDecl);
+
+ if (FunctionTemplateDecl *OldTemplateDecl
+ = 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 {
+ // This needs to happen first so that 'inline' propagates.
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+
+ if (isa<CXXMethodDecl>(NewFD)) {
+ // A valid redeclaration of a C++ method must be out-of-line,
+ // but (unfortunately) it's not necessarily a definition
+ // because of templates, which means that the previous
+ // declaration is not necessarily from the class definition.
+
+ // For just setting the access, that doesn't matter.
+ CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl);
+ NewFD->setAccess(oldMethod->getAccess());
+
+ // Update the key-function state if necessary for this ABI.
+ if (NewFD->isInlined() &&
+ !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
+ // setNonKeyFunction needs to work with the original
+ // declaration from the class definition, and isVirtual() is
+ // just faster in that case, so map back to that now.
+ oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDeclaration());
+ if (oldMethod->isVirtual()) {
+ Context.setNonKeyFunction(oldMethod);
+ }
}
-
- } else {
- if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
- NewFD->setAccess(OldDecl->getAccess());
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
}
}
}
@@ -6208,6 +6858,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// declaration against the expected type for the builtin.
if (unsigned BuiltinID = NewFD->getBuiltinID()) {
ASTContext::GetBuiltinTypeError Error;
+ LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
QualType T = Context.GetBuiltinType(BuiltinID, Error);
if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
// The type of this function differs from the type of the builtin,
@@ -6219,7 +6870,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// If this function is declared as being extern "C", then check to see if
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
- if (NewFD->isExternC()) {
+ // But, issue any diagnostic on the first declaration only.
+ if (NewFD->isExternC() && Previous.empty()) {
QualType R = NewFD->getResultType();
if (R->isIncompleteType() && !R->isVoidType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete)
@@ -6232,12 +6884,30 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
return Redeclaration;
}
+static SourceRange getResultSourceRange(const FunctionDecl *FD) {
+ const TypeSourceInfo *TSI = FD->getTypeSourceInfo();
+ if (!TSI)
+ return SourceRange();
+
+ TypeLoc TL = TSI->getTypeLoc();
+ FunctionTypeLoc FunctionTL = TL.getAs<FunctionTypeLoc>();
+ if (!FunctionTL)
+ return SourceRange();
+
+ TypeLoc ResultTL = FunctionTL.getResultLoc();
+ if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>())
+ return ResultTL.getSourceRange();
+
+ return SourceRange();
+}
+
void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
// C++11 [basic.start.main]p3: A program that declares main to be inline,
// static or constexpr is ill-formed.
- // C99 6.7.4p4: In a hosted environment, the inline function specifier
- // shall not appear in a declaration of main.
+ // C11 6.7.4p4: In a hosted environment, no function specifier(s) shall
+ // appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
+ // We accept _Noreturn main as an extension.
if (FD->getStorageClass() == SC_Static)
Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus
? diag::err_static_main : diag::warn_static_main)
@@ -6245,6 +6915,14 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
if (FD->isInlineSpecified())
Diag(DS.getInlineSpecLoc(), diag::err_inline_main)
<< FixItHint::CreateRemoval(DS.getInlineSpecLoc());
+ if (DS.isNoreturnSpecified()) {
+ SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc();
+ SourceRange NoreturnRange(NoreturnLoc,
+ PP.getLocForEndOfToken(NoreturnLoc));
+ Diag(NoreturnLoc, diag::ext_noreturn_main);
+ Diag(NoreturnLoc, diag::note_main_remove_noreturn)
+ << FixItHint::CreateRemoval(NoreturnRange);
+ }
if (FD->isConstexpr()) {
Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main)
<< FixItHint::CreateRemoval(DS.getConstexprSpecLoc());
@@ -6268,9 +6946,20 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
} else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) {
Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint);
+ SourceRange ResultRange = getResultSourceRange(FD);
+ if (ResultRange.isValid())
+ Diag(ResultRange.getBegin(), diag::note_main_change_return_type)
+ << FixItHint::CreateReplacement(ResultRange, "int");
+
// Otherwise, this is just a flat-out error.
} else {
- Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+ SourceRange ResultRange = getResultSourceRange(FD);
+ if (ResultRange.isValid())
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint)
+ << FixItHint::CreateReplacement(ResultRange, "int");
+ else
+ Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint);
+
FD->setInvalidDecl(true);
}
@@ -6319,7 +7008,8 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) {
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)) {
+ Context.hasSameType(QualType(qs.strip(PT->getPointeeType()), 0),
+ Context.CharTy)) {
qs.removeConst();
mismatch = !qs.empty();
}
@@ -6457,6 +7147,14 @@ namespace {
Visit(Base);
}
+ void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ if (E->getNumArgs() > 0)
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getArg(0)))
+ HandleDeclRefExpr(DRE);
+
+ Inherited::VisitCXXOperatorCallExpr(E);
+ }
+
void VisitUnaryOperator(UnaryOperator *E) {
// For POD record types, addresses of its own members are well-defined.
if (E->getOpcode() == UO_AddrOf && isRecordType &&
@@ -6471,11 +7169,17 @@ namespace {
void VisitObjCMessageExpr(ObjCMessageExpr *E) { return; }
void HandleDeclRefExpr(DeclRefExpr *DRE) {
- Decl* ReferenceDecl = DRE->getDecl();
+ Decl* ReferenceDecl = DRE->getDecl();
if (OrigDecl != ReferenceDecl) return;
- unsigned diag = isReferenceType
- ? diag::warn_uninit_self_reference_in_reference_init
- : diag::warn_uninit_self_reference_in_init;
+ unsigned diag;
+ if (isReferenceType) {
+ diag = diag::warn_uninit_self_reference_in_reference_init;
+ } else if (cast<VarDecl>(OrigDecl)->isStaticLocal()) {
+ diag = diag::warn_static_self_reference_in_init;
+ } else {
+ diag = diag::warn_uninit_self_reference_in_init;
+ }
+
S.DiagRuntimeBehavior(DRE->getLocStart(), DRE,
S.PDiag(diag)
<< DRE->getNameInfo().getName()
@@ -6572,6 +7276,20 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
DeduceInit = CXXDirectInit->getExpr(0);
}
}
+
+ // Expressions default to 'id' when we're in a debugger.
+ bool DefaultedToAuto = false;
+ if (getLangOpts().DebuggerCastResultToId &&
+ Init->getType() == Context.UnknownAnyTy) {
+ ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+ Init = Result.take();
+ DefaultedToAuto = true;
+ }
+
TypeSourceInfo *DeducedType = 0;
if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) ==
DAR_Failed)
@@ -6582,8 +7300,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
VDecl->setTypeSourceInfo(DeducedType);
VDecl->setType(DeducedType->getType());
- VDecl->ClearLinkageCache();
-
+ assert(VDecl->isLinkageValid());
+
// In ARC, infer lifetime.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
VDecl->setInvalidDecl();
@@ -6592,7 +7310,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// 'id' instead of a specific object type prevents most of our usual checks.
// We only want to warn outside of template instantiations, though:
// inside a template, the 'id' could have come from a parameter.
- if (ActiveTemplateInstantiations.empty() &&
+ if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto &&
DeducedType->getType()->isObjCIdType()) {
SourceLocation Loc = DeducedType->getTypeLoc().getBeginLoc();
Diag(Loc, diag::warn_auto_var_is_id)
@@ -6602,7 +7320,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
if (VarDecl *Old = VDecl->getPreviousDecl())
- MergeVarDeclTypes(VDecl, Old);
+ MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false);
}
if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
@@ -6683,17 +7401,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// CheckInitializerTypes may change it.
QualType DclT = VDecl->getType(), SavT = DclT;
- // Top-level message sends default to 'id' when we're in a debugger
- // and we are assigning it to a variable of 'id' type.
- if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType())
- if (Init->getType() == Context.UnknownAnyTy && isa<ObjCMessageExpr>(Init)) {
- ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
- if (Result.isInvalid()) {
- VDecl->setInvalidDecl();
- return;
- }
- Init = Result.take();
+ // Expressions default to 'id' when we're in a debugger
+ // and we are assigning it to a variable of Objective-C pointer type.
+ if (getLangOpts().DebuggerCastResultToId && DclT->isObjCObjectPointerType() &&
+ Init->getType() == Context.UnknownAnyTy) {
+ ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType());
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
}
+ Init = Result.take();
+ }
// Perform the initialization.
if (!VDecl->isInvalidDecl()) {
@@ -6740,9 +7458,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (!VDecl->isInvalidDecl() && (DclT != SavT))
VDecl->setType(DclT);
- // Check any implicit conversions within the expression.
- CheckImplicitConversions(Init, VDecl->getLocation());
-
if (!VDecl->isInvalidDecl()) {
checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
@@ -6765,7 +7480,26 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
}
}
- Init = MaybeCreateExprWithCleanups(Init);
+ // The initialization is usually a full-expression.
+ //
+ // FIXME: If this is a braced initialization of an aggregate, it is not
+ // an expression, and each individual field initializer is a separate
+ // full-expression. For instance, in:
+ //
+ // struct Temp { ~Temp(); };
+ // struct S { S(Temp); };
+ // struct T { S a, b; } t = { Temp(), Temp() }
+ //
+ // we should destroy the first Temp before constructing the second.
+ ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(),
+ false,
+ VDecl->isConstexpr());
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+ Init = Result.take();
+
// Attach the initializer to the decl.
VDecl->setInit(Init);
@@ -6817,7 +7551,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
} else if (DclT->isIntegralOrEnumerationType()) {
// Check whether the expression is a constant expression.
SourceLocation Loc;
- if (getLangOpts().CPlusPlus0x && DclT.isVolatileQualified())
+ if (getLangOpts().CPlusPlus11 && DclT.isVolatileQualified())
// In C++11, a non-constexpr const static data member with an
// in-class initializer cannot be volatile.
Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile);
@@ -6840,21 +7574,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// We allow foldable floating-point constants as an extension.
} else if (DclT->isFloatingType()) { // also permits complex, which is ok
- Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
- << DclT << Init->getSourceRange();
- if (getLangOpts().CPlusPlus0x)
+ // In C++98, this is a GNU extension. In C++11, it is not, but we support
+ // it anyway and provide a fixit to add the 'constexpr'.
+ if (getLangOpts().CPlusPlus11) {
Diag(VDecl->getLocation(),
- diag::note_in_class_initializer_float_type_constexpr)
- << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+ diag::ext_in_class_initializer_float_type_cxx11)
+ << DclT << Init->getSourceRange();
+ Diag(VDecl->getLocStart(),
+ diag::note_in_class_initializer_float_type_cxx11)
+ << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
+ } else {
+ Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
+ << DclT << Init->getSourceRange();
- if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
- Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
- << Init->getSourceRange();
- VDecl->setInvalidDecl();
+ if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
+ Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
+ << Init->getSourceRange();
+ VDecl->setInvalidDecl();
+ }
}
// Suggest adding 'constexpr' in C++11 for literal types.
- } else if (getLangOpts().CPlusPlus0x && DclT->isLiteralType()) {
+ } else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType()) {
Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type)
<< DclT << Init->getSourceRange()
<< FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
@@ -6866,9 +7607,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
}
} else if (VDecl->isFileVarDecl()) {
- if (VDecl->getStorageClassAsWritten() == SC_Extern &&
+ if (VDecl->getStorageClass() == SC_Extern &&
(!getLangOpts().CPlusPlus ||
- !Context.getBaseElementType(VDecl->getType()).isConstQualified()))
+ !(Context.getBaseElementType(VDecl->getType()).isConstQualified() ||
+ VDecl->isExternC())))
Diag(VDecl->getLocation(), diag::warn_extern_init);
// C99 6.7.8p4. All file scoped initializers need to be constant.
@@ -7155,7 +7897,7 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
// for-range-declaration cannot be given a storage class specifier.
int Error = -1;
- switch (VD->getStorageClassAsWritten()) {
+ switch (VD->getStorageClass()) {
case SC_None:
break;
case SC_Extern:
@@ -7206,7 +7948,10 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
if (var->isThisDeclarationADefinition() &&
- var->getLinkage() == ExternalLinkage) {
+ var->hasExternalLinkage() &&
+ getDiagnostics().getDiagnosticLevel(
+ diag::warn_missing_variable_declarations,
+ var->getLocation())) {
// Find a previous declaration that's not a definition.
VarDecl *prev = var->getPreviousDecl();
while (prev && prev->isThisDeclarationADefinition())
@@ -7230,12 +7975,13 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// Regardless, we don't want to ignore array nesting when
// constructing this copy.
if (type->isStructureOrClassType()) {
+ EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated);
SourceLocation poi = var->getLocation();
Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi);
- ExprResult result =
- PerformCopyInitialization(
- InitializedEntity::InitializeBlock(poi, type, false),
- poi, Owned(varRef));
+ ExprResult result
+ = PerformMoveOrCopyInitialization(
+ InitializedEntity::InitializeBlock(poi, type, false),
+ var, var->getType(), varRef, /*AllowNRVO=*/true);
if (!result.isInvalid()) {
result = MaybeCreateExprWithCleanups(result);
Expr *init = result.takeAs<Expr>();
@@ -7259,7 +8005,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
<< Init->getSourceRange();
if (var->isConstexpr()) {
- llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
if (!var->evaluateValue(Notes) || !var->isInitICE()) {
SourceLocation DiagLoc = var->getLocation();
// If the note doesn't add any useful information other than a source
@@ -7294,40 +8040,52 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
// Note that we are no longer parsing the initializer for this declaration.
ParsingInitForAutoVars.erase(ThisDecl);
+ VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDecl);
+ if (!VD)
+ return;
+
+ const DeclContext *DC = VD->getDeclContext();
+ // If there's a #pragma GCC visibility in scope, and this isn't a class
+ // member, set the visibility of this variable.
+ if (!DC->isRecord() && VD->hasExternalLinkage())
+ AddPushedVisibilityAttribute(VD);
+
+ if (VD->isFileVarDecl())
+ MarkUnusedFileScopedDecl(VD);
+
// Now we have parsed the initializer and can update the table of magic
// tag values.
- if (ThisDecl && ThisDecl->hasAttr<TypeTagForDatatypeAttr>()) {
- const VarDecl *VD = dyn_cast<VarDecl>(ThisDecl);
- if (VD && VD->getType()->isIntegralOrEnumerationType()) {
- for (specific_attr_iterator<TypeTagForDatatypeAttr>
- I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
- E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
- I != E; ++I) {
- const Expr *MagicValueExpr = VD->getInit();
- if (!MagicValueExpr) {
- continue;
- }
- llvm::APSInt MagicValueInt;
- if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
- Diag(I->getRange().getBegin(),
- diag::err_type_tag_for_datatype_not_ice)
- << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
- continue;
- }
- if (MagicValueInt.getActiveBits() > 64) {
- Diag(I->getRange().getBegin(),
- diag::err_type_tag_for_datatype_too_large)
- << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
- continue;
- }
- uint64_t MagicValue = MagicValueInt.getZExtValue();
- RegisterTypeTagForDatatype(I->getArgumentKind(),
- MagicValue,
- I->getMatchingCType(),
- I->getLayoutCompatible(),
- I->getMustBeNull());
- }
+ if (!VD->hasAttr<TypeTagForDatatypeAttr>() ||
+ !VD->getType()->isIntegralOrEnumerationType())
+ return;
+
+ for (specific_attr_iterator<TypeTagForDatatypeAttr>
+ I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(),
+ E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>();
+ I != E; ++I) {
+ const Expr *MagicValueExpr = VD->getInit();
+ if (!MagicValueExpr) {
+ continue;
+ }
+ llvm::APSInt MagicValueInt;
+ if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) {
+ Diag(I->getRange().getBegin(),
+ diag::err_type_tag_for_datatype_not_ice)
+ << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
+ continue;
+ }
+ if (MagicValueInt.getActiveBits() > 64) {
+ Diag(I->getRange().getBegin(),
+ diag::err_type_tag_for_datatype_too_large)
+ << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange();
+ continue;
}
+ uint64_t MagicValue = MagicValueInt.getZExtValue();
+ RegisterTypeTagForDatatype(I->getArgumentKind(),
+ MagicValue,
+ I->getMatchingCType(),
+ I->getLayoutCompatible(),
+ I->getMustBeNull());
}
}
@@ -7343,6 +8101,10 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (Decl *D = Group[i])
Decls.push_back(D);
+ if (DeclSpec::isDeclRep(DS.getTypeSpecType()))
+ if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl()))
+ getASTContext().addUnnamedTag(Tag);
+
return BuildDeclaratorGroup(Decls.data(), Decls.size(),
DS.getTypeSpecType() == DeclSpec::TST_auto);
}
@@ -7449,14 +8211,11 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
// C++03 [dcl.stc]p2 also permits 'auto'.
VarDecl::StorageClass StorageClass = SC_None;
- VarDecl::StorageClass StorageClassAsWritten = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
StorageClass = SC_Register;
- StorageClassAsWritten = SC_Register;
} else if (getLangOpts().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_auto) {
StorageClass = SC_Auto;
- StorageClassAsWritten = SC_Auto;
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
@@ -7469,7 +8228,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
<< 0;
- DiagnoseFunctionSpecifiers(D);
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType parmDeclType = TInfo->getType();
@@ -7529,7 +8288,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
D.getLocStart(),
D.getIdentifierLoc(), II,
parmDeclType, TInfo,
- StorageClass, StorageClassAsWritten);
+ StorageClass);
if (D.isInvalidType())
New->setInvalidDecl();
@@ -7568,7 +8327,7 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
location for the unnamed parameters, embedding the parameter's type? */
ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0,
T, Context.getTrivialTypeSourceInfo(T, Loc),
- SC_None, SC_None, 0);
+ SC_None, 0);
Param->setImplicit();
return Param;
}
@@ -7621,8 +8380,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
SourceLocation NameLoc, IdentifierInfo *Name,
QualType T, TypeSourceInfo *TSInfo,
- VarDecl::StorageClass StorageClass,
- VarDecl::StorageClass StorageClassAsWritten) {
+ VarDecl::StorageClass StorageClass) {
// In ARC, infer a lifetime qualifier for appropriate parameter types.
if (getLangOpts().ObjCAutoRefCount &&
T.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -7649,8 +8407,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name,
Context.getAdjustedParameterType(T),
TSInfo,
- StorageClass, StorageClassAsWritten,
- 0);
+ StorageClass, 0);
// Parameters can not be abstract class types.
// For record types, this is done by the AbstractClassUsageDiagnoser once
@@ -7730,7 +8487,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
-static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
+static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
+ const FunctionDecl*& PossibleZeroParamPrototype) {
// Don't warn about invalid declarations.
if (FD->isInvalidDecl())
return false;
@@ -7772,6 +8530,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
continue;
MissingPrototype = !Prev->getType()->isFunctionProtoType();
+ if (FD->getNumParams() == 0)
+ PossibleZeroParamPrototype = Prev;
break;
}
@@ -7837,8 +8597,22 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// prototype declaration. This warning is issued even if the
// definition itself provides a prototype. The aim is to detect
// global functions that fail to be declared in header files.
- if (ShouldWarnAboutMissingPrototype(FD))
+ const FunctionDecl *PossibleZeroParamPrototype = 0;
+ if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) {
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+
+ if (PossibleZeroParamPrototype) {
+ // We found a declaration that is not a prototype,
+ // but that could be a zero-parameter prototype
+ TypeSourceInfo* TI = PossibleZeroParamPrototype->getTypeSourceInfo();
+ TypeLoc TL = TI->getTypeLoc();
+ if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
+ Diag(PossibleZeroParamPrototype->getLocation(),
+ diag::note_declaration_not_a_prototype)
+ << PossibleZeroParamPrototype
+ << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
+ }
+ }
if (FnBodyScope)
PushDeclContext(FnBodyScope, FD);
@@ -7913,7 +8687,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport";
FD->setInvalidDecl();
- return FD;
+ return D;
}
// Visual C++ appears to not think this is an issue, so only issue
@@ -7930,7 +8704,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// We want to attach documentation to original Decl (which might be
// a function template).
ActOnDocumentableDecl(D);
- return FD;
+ return D;
}
/// \brief Given the set of return statements within a function body,
@@ -7967,6 +8741,33 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
+bool Sema::canSkipFunctionBody(Decl *D) {
+ if (!Consumer.shouldSkipFunctionBody(D))
+ return false;
+
+ if (isa<ObjCMethodDecl>(D))
+ return true;
+
+ FunctionDecl *FD = 0;
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ FD = FTD->getTemplatedDecl();
+ else
+ FD = cast<FunctionDecl>(D);
+
+ // We cannot skip the body of a function (or function template) which is
+ // constexpr, since we may need to evaluate its body in order to parse the
+ // rest of the file.
+ return !FD->isConstexpr();
+}
+
+Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
+ if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Decl))
+ FD->setHasSkippedBody();
+ else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl))
+ MD->setHasSkippedBody();
+ return ActOnFinishFunctionBody(Decl, 0);
+}
+
Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
return ActOnFinishFunctionBody(D, BodyArg, false);
}
@@ -7986,6 +8787,18 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD) {
FD->setBody(Body);
+ // The only way to be included in UndefinedButUsed is if there is an
+ // ODR use before the definition. Avoid the expensive map lookup if this
+ // is the first declaration.
+ if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) {
+ if (FD->getLinkage() != ExternalLinkage)
+ UndefinedButUsed.erase(FD);
+ else if (FD->isInlined() &&
+ (LangOpts.CPlusPlus || !LangOpts.GNUInline) &&
+ (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
+ UndefinedButUsed.erase(FD);
+ }
+
// If the function implicitly returns zero (like 'main') or is naked,
// don't complain about missing return statements.
if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())
@@ -8068,7 +8881,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (PP.getDiagnostics().hasErrorOccurred() ||
PP.getDiagnostics().getSuppressAllDiagnostics()) {
DiscardCleanupsInEvaluationContext();
- } else if (!isa<FunctionTemplateDecl>(dcl)) {
+ }
+ if (!PP.getDiagnostics().hasUncompilableErrorOccurred() &&
+ !isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
ActivePolicy = &WP;
@@ -8125,8 +8940,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
// this name as a function or variable. If so, use that
// (non-visible) declaration, and complain about it.
llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
- = findLocallyScopedExternalDecl(&II);
- if (Pos != LocallyScopedExternalDecls.end()) {
+ = findLocallyScopedExternCDecl(&II);
+ if (Pos != LocallyScopedExternCDecls.end()) {
Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second;
Diag(Pos->second->getLocation(), diag::note_previous_declaration);
return Pos->second;
@@ -8202,7 +9017,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
DeclContext *PrevDC = CurContext;
CurContext = Context.getTranslationUnitDecl();
- FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
+ FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
FD->setImplicit();
CurContext = PrevDC;
@@ -8376,9 +9191,13 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) {
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
QualType T = TI->getType();
- if (T->isDependentType() || T->isIntegralType(Context))
+ if (T->isDependentType())
return false;
+ if (const BuiltinType *BT = T->getAs<BuiltinType>())
+ if (BT->isInteger())
+ return false;
+
Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T;
return true;
}
@@ -8575,6 +9394,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TUK == TUK_Friend,
isExplicitSpecialization,
Invalid)) {
+ if (Kind == TTK_Enum) {
+ Diag(KWLoc, diag::err_enum_template);
+ return 0;
+ }
+
if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).
@@ -8703,6 +9527,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// shouldn't be diagnosing.
LookupName(Previous, S);
+ // When declaring or defining a tag, ignore ambiguities introduced
+ // by types using'ed into this scope.
if (Previous.isAmbiguous() &&
(TUK == TUK_Definition || TUK == TUK_Declaration)) {
LookupResult::Filter F = Previous.makeFilter();
@@ -8713,6 +9539,27 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
F.done();
}
+
+ // C++11 [namespace.memdef]p3:
+ // If the name in a friend declaration is neither qualified nor
+ // a template-id and the declaration is a function or an
+ // elaborated-type-specifier, the lookup to determine whether
+ // the entity has been previously declared shall not consider
+ // any scopes outside the innermost enclosing namespace.
+ //
+ // Does it matter that this should be by scope instead of by
+ // semantic context?
+ if (!Previous.empty() && TUK == TUK_Friend) {
+ DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext();
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *ND = F.next();
+ DeclContext *DC = ND->getDeclContext()->getRedeclContext();
+ if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext()))
+ F.erase();
+ }
+ F.done();
+ }
// Note: there used to be some attempt at recovery here.
if (Previous.isAmbiguous())
@@ -9070,7 +9917,8 @@ CreateNewDecl:
// If this is an undefined enum, warn.
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
- if (getLangOpts().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) {
+ if ((getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) &&
+ cast<EnumDecl>(New)->isFixed()) {
// C++0x: 7.2p2: opaque-enum-declaration.
// Conflicts are diagnosed above. Do nothing.
}
@@ -9250,7 +10098,9 @@ CreateNewDecl:
AddPushedVisibilityAttribute(New);
OwnedDecl = true;
- return New;
+ // In C++, don't return an invalid declaration. We can't recover well from
+ // the cases where we make the type anonymous.
+ return (Invalid && getLangOpts().CPlusPlus) ? 0 : New;
}
void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
@@ -9330,7 +10180,11 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
// Exit this scope of this tag's definition.
PopDeclContext();
-
+
+ if (getCurLexicalContext()->isObjCContainer() &&
+ Tag->getDeclContext()->isFileContext())
+ Tag->setTopLevelDeclInObjCContainer();
+
// Notify the consumer that we've defined a tag.
Consumer.HandleTagDeclDefinition(Tag);
}
@@ -9479,14 +10333,24 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
}
}
- DiagnoseFunctionSpecifiers(D);
+ // TR 18037 does not allow fields to be declared with address spaces.
+ if (T.getQualifiers().hasAddressSpace()) {
+ Diag(Loc, diag::err_field_with_address_space);
+ D.setInvalidType();
+ }
+
+ // OpenCL 1.2 spec, s6.9 r:
+ // The event type cannot be used to declare a structure or union field.
+ if (LangOpts.OpenCL && T->isEventT()) {
+ Diag(Loc, diag::err_event_t_struct_field);
+ D.setInvalidType();
+ }
+
+ DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- if (D.getDeclSpec().isConstexprSpecified())
- Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 2;
-
+
// Check to see if this name was declared as a member previously
NamedDecl *PrevDecl = 0;
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
@@ -9587,6 +10451,12 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
}
}
+ // OpenCL v1.2 s6.9.c: bitfields are not supported.
+ if (BitWidth && getLangOpts().OpenCL) {
+ Diag(Loc, diag::err_opencl_bitfields);
+ InvalidDecl = true;
+ }
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
@@ -9686,10 +10556,14 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// FIXME: We need to pass in the attributes given an AST
// representation, not a parser representation.
- if (D)
+ if (D) {
// FIXME: What to pass instead of TUScope?
ProcessDeclAttributes(TUScope, NewFD, *D);
+ if (NewFD->hasAttrs())
+ CheckAlignasUnderalignment(NewFD);
+ }
+
// In auto-retain/release, infer strong retension for fields of
// retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD))
@@ -9711,24 +10585,29 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
QualType EltTy = Context.getBaseElementType(FD->getType());
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
- CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getDecl());
if (RDecl->getDefinition()) {
// We check for copy constructors before constructors
// because otherwise we'll never get complaints about
// copy constructors.
CXXSpecialMember member = CXXInvalid;
- if (!RDecl->hasTrivialCopyConstructor())
+ // We're required to check for any non-trivial constructors. Since the
+ // implicit default constructor is suppressed if there are any
+ // user-declared constructors, we just need to check that there is a
+ // trivial default constructor and a trivial copy constructor. (We don't
+ // worry about move constructors here, since this is a C++98 check.)
+ if (RDecl->hasNonTrivialCopyConstructor())
member = CXXCopyConstructor;
else if (!RDecl->hasTrivialDefaultConstructor())
member = CXXDefaultConstructor;
- else if (!RDecl->hasTrivialCopyAssignment())
+ else if (RDecl->hasNonTrivialCopyAssignment())
member = CXXCopyAssignment;
- else if (!RDecl->hasTrivialDestructor())
+ else if (RDecl->hasNonTrivialDestructor())
member = CXXDestructor;
if (member != CXXInvalid) {
- if (!getLangOpts().CPlusPlus0x &&
+ if (!getLangOpts().CPlusPlus11 &&
getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) {
// Objective-C++ ARC: it is an error to have a non-trivial field of
// a union. However, system headers in Objective-C programs
@@ -9744,192 +10623,17 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
}
}
- Diag(FD->getLocation(), getLangOpts().CPlusPlus0x ?
+ Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member :
diag::err_illegal_union_or_anon_struct_member)
<< (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
- DiagnoseNontrivial(RT, member);
- return !getLangOpts().CPlusPlus0x;
- }
- }
- }
-
- return false;
-}
-
-/// If the given constructor is user-declared, produce a diagnostic explaining
-/// that it makes the class non-trivial.
-static bool diagnoseNonTrivialUserDeclaredCtor(Sema &S, QualType QT,
- CXXConstructorDecl *CD,
- Sema::CXXSpecialMember CSM) {
- if (CD->isImplicit())
- return false;
-
- SourceLocation CtorLoc = CD->getLocation();
- S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM;
- return true;
-}
-
-/// 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 CXXInvalid:
- break;
-
- 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 (diagnoseNonTrivialUserDeclaredCtor(*this, QT, *CI, member))
- return;
-
- // No user-delcared constructors; look for constructor templates.
- typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
- tmpl_iter;
- for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end());
- TI != TE; ++TI) {
- CXXConstructorDecl *CD =
- dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl());
- if (CD && diagnoseNonTrivialUserDeclaredCtor(*this, QT, CD, member))
- return;
- }
- }
- break;
-
- case CXXCopyConstructor:
- if (RD->hasUserDeclaredCopyConstructor()) {
- SourceLocation CtorLoc =
- RD->getCopyConstructor(0)->getLocation();
- Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXMoveConstructor:
- if (RD->hasUserDeclaredMoveConstructor()) {
- SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation();
- Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXCopyAssignment:
- if (RD->hasUserDeclaredCopyAssignment()) {
- SourceLocation AssignLoc =
- RD->getCopyAssignmentOperator(0)->getLocation();
- Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXMoveAssignment:
- if (RD->hasUserDeclaredMoveAssignment()) {
- SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation();
- Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member;
- return;
- }
- break;
-
- case CXXDestructor:
- if (RD->hasUserDeclaredDestructor()) {
- SourceLocation DtorLoc = LookupDestructor(RD)->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->getLocStart();
- 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->getLocStart();
- Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0;
- return;
- }
- }
- }
-
- bool (CXXRecordDecl::*hasTrivial)() const;
- switch (member) {
- case CXXDefaultConstructor:
- hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break;
- case CXXCopyConstructor:
- hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
- case CXXCopyAssignment:
- hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break;
- case CXXDestructor:
- hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break;
- default:
- llvm_unreachable("unexpected special member");
- }
-
- // 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 && "Don't know how to handle dependent bases");
- CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl());
- if (!(BaseRecTy->*hasTrivial)()) {
- SourceLocation BaseLoc = bi->getLocStart();
- 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;
- }
- }
-
- if (EltTy->isObjCLifetimeType()) {
- switch (EltTy.getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- break;
-
- case Qualifiers::OCL_Autoreleasing:
- case Qualifiers::OCL_Weak:
- case Qualifiers::OCL_Strong:
- Diag(fi->getLocation(), diag::note_nontrivial_objc_ownership)
- << QT << EltTy.getObjCLifetime();
- return;
+ DiagnoseNontrivial(RDecl, member);
+ return !getLangOpts().CPlusPlus11;
}
}
}
- llvm_unreachable("found no explanation for non-trivial member");
+ return false;
}
/// TranslateIvarVisibility - Translate visibility from a token ID to an
@@ -10058,8 +10762,8 @@ Decl *Sema::ActOnIvar(Scope *S,
}
/// ActOnLastBitfield - This routine handles synthesized bitfields rules for
-/// class and class extensions. For every class @interface and class
-/// extension @interface, if the last ivar is a bitfield of any type,
+/// class and class extensions. For every class \@interface and class
+/// extension \@interface, if the last ivar is a bitfield of any type,
/// then add an implicit `char :0` ivar to the end of that interface.
void Sema::ActOnLastBitfield(SourceLocation DeclLoc,
SmallVectorImpl<Decl *> &AllIvarDecls) {
@@ -10259,52 +10963,54 @@ void Sema::ActOnFields(Scope* S,
}
if (Record && FDTTy->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
+ if (Record && FDTTy->getDecl()->hasVolatileMember())
+ Record->setHasVolatileMember(true);
} else if (FDTy->isObjCObjectType()) {
/// A field cannot be an Objective-c object
Diag(FD->getLocation(), diag::err_statically_allocated_object)
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
- } else if (!getLangOpts().CPlusPlus) {
- if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) {
- // It's an error in ARC if a field has lifetime.
- // We don't want to report this in a system header, though,
- // so we just make the field unavailable.
- // FIXME: that's really not sufficient; we need to make the type
- // itself invalid to, say, initialize or copy.
- QualType T = FD->getType();
- Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
- if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) {
- SourceLocation loc = FD->getLocation();
- if (getSourceManager().isInSystemHeader(loc)) {
- if (!FD->hasAttr<UnavailableAttr>()) {
- FD->addAttr(new (Context) UnavailableAttr(loc, Context,
- "this system field has retaining ownership"));
- }
- } else {
- Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct)
- << T->isBlockPointerType();
+ } else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported &&
+ (!getLangOpts().CPlusPlus || Record->isUnion())) {
+ // It's an error in ARC if a field has lifetime.
+ // We don't want to report this in a system header, though,
+ // so we just make the field unavailable.
+ // FIXME: that's really not sufficient; we need to make the type
+ // itself invalid to, say, initialize or copy.
+ QualType T = FD->getType();
+ Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
+ if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) {
+ SourceLocation loc = FD->getLocation();
+ if (getSourceManager().isInSystemHeader(loc)) {
+ if (!FD->hasAttr<UnavailableAttr>()) {
+ FD->addAttr(new (Context) UnavailableAttr(loc, Context,
+ "this system field has retaining ownership"));
}
- ARCErrReported = true;
+ } else {
+ Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
+ << T->isBlockPointerType() << Record->getTagKind();
}
+ ARCErrReported = true;
}
- else if (getLangOpts().ObjC1 &&
+ } else if (getLangOpts().ObjC1 &&
getLangOpts().getGC() != LangOptions::NonGC &&
Record && !Record->hasObjectMember()) {
- if (FD->getType()->isObjCObjectPointerType() ||
- FD->getType().isObjCGCStrong())
+ if (FD->getType()->isObjCObjectPointerType() ||
+ FD->getType().isObjCGCStrong())
+ Record->setHasObjectMember(true);
+ else if (Context.getAsArrayType(FD->getType())) {
+ QualType BaseType = Context.getBaseElementType(FD->getType());
+ if (BaseType->isRecordType() &&
+ BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
- else if (Context.getAsArrayType(FD->getType())) {
- QualType BaseType = Context.getBaseElementType(FD->getType());
- if (BaseType->isRecordType() &&
- BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
- Record->setHasObjectMember(true);
- else if (BaseType->isObjCObjectPointerType() ||
- BaseType.isObjCGCStrong())
- Record->setHasObjectMember(true);
- }
+ else if (BaseType->isObjCObjectPointerType() ||
+ BaseType.isObjCGCStrong())
+ Record->setHasObjectMember(true);
}
}
+ if (Record && FD->getType().isVolatileQualified())
+ Record->setHasVolatileMember(true);
// Keep track of the number of named members.
if (FD->getIdentifier())
++NumNamedMembers;
@@ -10316,14 +11022,14 @@ void Sema::ActOnFields(Scope* S,
if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
if (!CXXRecord->isInvalidDecl()) {
// Set access bits correctly on the directly-declared conversions.
- UnresolvedSetImpl *Convs = CXXRecord->getConversionFunctions();
- for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end();
- I != E; ++I)
- Convs->setAccess(I, (*I)->getAccess());
+ for (CXXRecordDecl::conversion_iterator
+ I = CXXRecord->conversion_begin(),
+ E = CXXRecord->conversion_end(); I != E; ++I)
+ I.setAccess((*I)->getAccess());
if (!CXXRecord->isDependentType()) {
// Adjust user-defined destructor exception spec.
- if (getLangOpts().CPlusPlus0x &&
+ if (getLangOpts().CPlusPlus11 &&
CXXRecord->hasUserDeclaredDestructor())
AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor());
@@ -10376,6 +11082,8 @@ void Sema::ActOnFields(Scope* S,
if (!Completed)
Record->completeDefinition();
+ if (Record->hasAttrs())
+ CheckAlignasUnderalignment(Record);
} else {
ObjCIvarDecl **ClsFields =
reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
@@ -10418,11 +11126,12 @@ void Sema::ActOnFields(Scope* S,
Diag(ClsIvar->getLocation(), diag::note_previous_definition);
continue;
}
- for (const ObjCCategoryDecl *ClsExtDecl =
- IDecl->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
- if (const ObjCIvarDecl *ClsExtIvar =
- ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) {
+ for (ObjCInterfaceDecl::known_extensions_iterator
+ Ext = IDecl->known_extensions_begin(),
+ ExtEnd = IDecl->known_extensions_end();
+ Ext != ExtEnd; ++Ext) {
+ if (const ObjCIvarDecl *ClsExtIvar
+ = Ext->getIvarDecl(ClsFields[i]->getIdentifier())) {
Diag(ClsFields[i]->getLocation(),
diag::err_duplicate_ivar_declaration);
Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
@@ -10503,7 +11212,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EltTy = Context.DependentTy;
else {
SourceLocation ExpLoc;
- if (getLangOpts().CPlusPlus0x && Enum->isFixed() &&
+ if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
!getLangOpts().MicrosoftMode) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
@@ -10722,6 +11431,182 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
return New;
}
+// Returns true when the enum initial expression does not trigger the
+// duplicate enum warning. A few common cases are exempted as follows:
+// Element2 = Element1
+// Element2 = Element1 + 1
+// Element2 = Element1 - 1
+// Where Element2 and Element1 are from the same enum.
+static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) {
+ Expr *InitExpr = ECD->getInitExpr();
+ if (!InitExpr)
+ return true;
+ InitExpr = InitExpr->IgnoreImpCasts();
+
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) {
+ if (!BO->isAdditiveOp())
+ return true;
+ IntegerLiteral *IL = dyn_cast<IntegerLiteral>(BO->getRHS());
+ if (!IL)
+ return true;
+ if (IL->getValue() != 1)
+ return true;
+
+ InitExpr = BO->getLHS();
+ }
+
+ // This checks if the elements are from the same enum.
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InitExpr);
+ if (!DRE)
+ return true;
+
+ EnumConstantDecl *EnumConstant = dyn_cast<EnumConstantDecl>(DRE->getDecl());
+ if (!EnumConstant)
+ return true;
+
+ if (cast<EnumDecl>(TagDecl::castFromDeclContext(ECD->getDeclContext())) !=
+ Enum)
+ return true;
+
+ return false;
+}
+
+struct DupKey {
+ int64_t val;
+ bool isTombstoneOrEmptyKey;
+ DupKey(int64_t val, bool isTombstoneOrEmptyKey)
+ : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {}
+};
+
+static DupKey GetDupKey(const llvm::APSInt& Val) {
+ return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(),
+ false);
+}
+
+struct DenseMapInfoDupKey {
+ static DupKey getEmptyKey() { return DupKey(0, true); }
+ static DupKey getTombstoneKey() { return DupKey(1, true); }
+ static unsigned getHashValue(const DupKey Key) {
+ return (unsigned)(Key.val * 37);
+ }
+ static bool isEqual(const DupKey& LHS, const DupKey& RHS) {
+ return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey &&
+ LHS.val == RHS.val;
+ }
+};
+
+// Emits a warning when an element is implicitly set a value that
+// a previous element has already been set to.
+static void CheckForDuplicateEnumValues(Sema &S, Decl **Elements,
+ unsigned NumElements, EnumDecl *Enum,
+ QualType EnumType) {
+ if (S.Diags.getDiagnosticLevel(diag::warn_duplicate_enum_values,
+ Enum->getLocation()) ==
+ DiagnosticsEngine::Ignored)
+ return;
+ // Avoid anonymous enums
+ if (!Enum->getIdentifier())
+ return;
+
+ // Only check for small enums.
+ if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64)
+ return;
+
+ typedef SmallVector<EnumConstantDecl *, 3> ECDVector;
+ typedef SmallVector<ECDVector *, 3> DuplicatesVector;
+
+ typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector;
+ typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey>
+ ValueToVectorMap;
+
+ DuplicatesVector DupVector;
+ ValueToVectorMap EnumMap;
+
+ // Populate the EnumMap with all values represented by enum constants without
+ // an initialier.
+ for (unsigned i = 0; i < NumElements; ++i) {
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+
+ // Null EnumConstantDecl means a previous diagnostic has been emitted for
+ // this constant. Skip this enum since it may be ill-formed.
+ if (!ECD) {
+ return;
+ }
+
+ if (ECD->getInitExpr())
+ continue;
+
+ DupKey Key = GetDupKey(ECD->getInitVal());
+ DeclOrVector &Entry = EnumMap[Key];
+
+ // First time encountering this value.
+ if (Entry.isNull())
+ Entry = ECD;
+ }
+
+ // Create vectors for any values that has duplicates.
+ for (unsigned i = 0; i < NumElements; ++i) {
+ EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+ if (!ValidDuplicateEnum(ECD, Enum))
+ continue;
+
+ DupKey Key = GetDupKey(ECD->getInitVal());
+
+ DeclOrVector& Entry = EnumMap[Key];
+ if (Entry.isNull())
+ continue;
+
+ if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) {
+ // Ensure constants are different.
+ if (D == ECD)
+ continue;
+
+ // Create new vector and push values onto it.
+ ECDVector *Vec = new ECDVector();
+ Vec->push_back(D);
+ Vec->push_back(ECD);
+
+ // Update entry to point to the duplicates vector.
+ Entry = Vec;
+
+ // Store the vector somewhere we can consult later for quick emission of
+ // diagnostics.
+ DupVector.push_back(Vec);
+ continue;
+ }
+
+ ECDVector *Vec = Entry.get<ECDVector*>();
+ // Make sure constants are not added more than once.
+ if (*Vec->begin() == ECD)
+ continue;
+
+ Vec->push_back(ECD);
+ }
+
+ // Emit diagnostics.
+ for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(),
+ DupVectorEnd = DupVector.end();
+ DupVectorIter != DupVectorEnd; ++DupVectorIter) {
+ ECDVector *Vec = *DupVectorIter;
+ assert(Vec->size() > 1 && "ECDVector should have at least 2 elements.");
+
+ // Emit warning for one enum constant.
+ ECDVector::iterator I = Vec->begin();
+ S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values)
+ << (*I)->getName() << (*I)->getInitVal().toString(10)
+ << (*I)->getSourceRange();
+ ++I;
+
+ // Emit one note for each of the remaining enum constants with
+ // the same value.
+ for (ECDVector::iterator E = Vec->end(); I != E; ++I)
+ S.Diag((*I)->getLocation(), diag::note_duplicate_element)
+ << (*I)->getName() << (*I)->getInitVal().toString(10)
+ << (*I)->getSourceRange();
+ delete Vec;
+ }
+}
+
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
SourceLocation RBraceLoc, Decl *EnumDeclX,
Decl **Elements, unsigned NumElements,
@@ -10944,6 +11829,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// it needs to go into the function scope.
if (InFunctionDeclarator)
DeclsInPrototypeScope.push_back(Enum);
+
+ CheckForDuplicateEnumValues(*this, Elements, NumElements, Enum, EnumType);
+
+ // Now that the enum type is defined, ensure it's not been underaligned.
+ if (Enum->hasAttrs())
+ CheckAlignasUnderalignment(Enum);
}
Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
@@ -10967,7 +11858,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
if (!Mod)
return true;
- llvm::SmallVector<SourceLocation, 2> IdentifierLocs;
+ SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
// If we've run out of module parents, just drop the remaining identifiers.
@@ -10987,6 +11878,19 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
return Import;
}
+void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) {
+ // Create the implicit import declaration.
+ TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
+ ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
+ Loc, Mod, Loc);
+ TU->addDecl(ImportD);
+ Consumer.HandleImplicitImportDecl(ImportD);
+
+ // Make the module visible.
+ PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc,
+ /*Complain=*/false);
+}
+
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
OpenPOWER on IntegriCloud