summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/IdentifierResolver.cpp38
-rw-r--r--lib/Sema/Lookup.h44
-rw-r--r--lib/Sema/Makefile1
-rw-r--r--lib/Sema/Sema.cpp280
-rw-r--r--lib/Sema/Sema.h327
-rw-r--r--lib/Sema/SemaAccess.cpp592
-rw-r--r--lib/Sema/SemaCXXCast.cpp59
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp4
-rw-r--r--lib/Sema/SemaChecking.cpp554
-rw-r--r--lib/Sema/SemaCodeComplete.cpp16
-rw-r--r--lib/Sema/SemaDecl.cpp682
-rw-r--r--lib/Sema/SemaDeclAttr.cpp211
-rw-r--r--lib/Sema/SemaDeclCXX.cpp730
-rw-r--r--lib/Sema/SemaDeclObjC.cpp219
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp83
-rw-r--r--lib/Sema/SemaExpr.cpp148
-rw-r--r--lib/Sema/SemaExprCXX.cpp127
-rw-r--r--lib/Sema/SemaExprObjC.cpp31
-rw-r--r--lib/Sema/SemaInit.cpp692
-rw-r--r--lib/Sema/SemaInit.h35
-rw-r--r--lib/Sema/SemaLookup.cpp318
-rw-r--r--lib/Sema/SemaOverload.cpp646
-rw-r--r--lib/Sema/SemaOverload.h62
-rw-r--r--lib/Sema/SemaStmt.cpp178
-rw-r--r--lib/Sema/SemaTemplate.cpp199
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp361
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp242
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp182
-rw-r--r--lib/Sema/SemaType.cpp188
-rw-r--r--lib/Sema/TargetAttributesSema.cpp44
-rw-r--r--lib/Sema/TreeTransform.h160
31 files changed, 4717 insertions, 2736 deletions
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index bff4751..b09526e 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -14,8 +14,6 @@
#include "IdentifierResolver.h"
#include "clang/Basic/LangOptions.h"
-#include <list>
-#include <vector>
using namespace clang;
@@ -27,14 +25,31 @@ using namespace clang;
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
/// individual IdDeclInfo to heap.
class IdentifierResolver::IdDeclInfoMap {
- static const unsigned int VECTOR_SIZE = 512;
- // Holds vectors of IdDeclInfos that serve as 'pools'.
- // New vectors are added when the current one is full.
- std::list< std::vector<IdDeclInfo> > IDIVecs;
+ static const unsigned int POOL_SIZE = 512;
+
+ /// We use our own linked-list implementation because it is sadly
+ /// impossible to add something to a pre-C++0x STL container without
+ /// a completely unnecessary copy.
+ struct IdDeclInfoPool {
+ IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
+
+ IdDeclInfoPool *Next;
+ IdDeclInfo Pool[POOL_SIZE];
+ };
+
+ IdDeclInfoPool *CurPool;
unsigned int CurIndex;
public:
- IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
+ IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
+
+ ~IdDeclInfoMap() {
+ IdDeclInfoPool *Cur = CurPool;
+ while (IdDeclInfoPool *P = Cur) {
+ Cur = Cur->Next;
+ delete P;
+ }
+ }
/// Returns the IdDeclInfo associated to the DeclarationName.
/// It creates a new IdDeclInfo if one was not created before for this id.
@@ -235,14 +250,11 @@ IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
if (Ptr) return *toIdDeclInfo(Ptr);
- if (CurIndex == VECTOR_SIZE) {
- // Add a IdDeclInfo vector 'pool'
- IDIVecs.push_back(std::vector<IdDeclInfo>());
- // Fill the vector
- IDIVecs.back().resize(VECTOR_SIZE);
+ if (CurIndex == POOL_SIZE) {
+ CurPool = new IdDeclInfoPool(CurPool);
CurIndex = 0;
}
- IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
+ IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
Name.setFETokenInfo(reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(IDI) | 0x1)
);
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index f4cea2e..6b26945 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -224,6 +224,10 @@ public:
return Ambiguity;
}
+ const UnresolvedSetImpl &asUnresolvedSet() const {
+ return Decls;
+ }
+
iterator begin() const { return iterator(Decls.begin()); }
iterator end() const { return iterator(Decls.end()); }
@@ -499,7 +503,7 @@ private:
if (isAmbiguous())
SemaRef.DiagnoseAmbiguousLookup(*this);
else if (isClassLookup() && SemaRef.getLangOptions().AccessControl)
- SemaRef.CheckAccess(*this);
+ SemaRef.CheckLookupAccess(*this);
}
void setAmbiguous(AmbiguityKind AK) {
@@ -583,6 +587,44 @@ private:
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
bool InBaseClass) = 0;
};
+
+/// \brief A class for storing results from argument-dependent lookup.
+class ADLResult {
+private:
+ /// A map from canonical decls to the 'most recent' decl.
+ llvm::DenseMap<NamedDecl*, NamedDecl*> Decls;
+
+public:
+ /// Adds a new ADL candidate to this map.
+ void insert(NamedDecl *D);
+
+ /// Removes any data associated with a given decl.
+ void erase(NamedDecl *D) {
+ Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
+ }
+
+ class iterator {
+ typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator;
+ inner_iterator iter;
+
+ friend class ADLResult;
+ iterator(const inner_iterator &iter) : iter(iter) {}
+ public:
+ iterator() {}
+
+ iterator &operator++() { ++iter; return *this; }
+ iterator operator++(int) { return iterator(iter++); }
+
+ NamedDecl *operator*() const { return iter->second; }
+
+ bool operator==(const iterator &other) const { return iter == other.iter; }
+ bool operator!=(const iterator &other) const { return iter != other.iter; }
+ };
+
+ iterator begin() { return iterator(Decls.begin()); }
+ iterator end() { return iterator(Decls.end()); }
+};
+
}
#endif
diff --git a/lib/Sema/Makefile b/lib/Sema/Makefile
index 0f4c796..158f1af 100644
--- a/lib/Sema/Makefile
+++ b/lib/Sema/Makefile
@@ -15,7 +15,6 @@
LEVEL = ../../../..
LIBRARYNAME := clangSema
BUILD_ARCHIVE = 1
-CXXFLAGS = -fno-rtti
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 171101b..38c842e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -15,260 +15,18 @@
#include "Sema.h"
#include "TargetAttributesSema.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/APFloat.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
-
-/// Determines whether we should have an a.k.a. clause when
-/// pretty-printing a type. There are three main criteria:
-///
-/// 1) Some types provide very minimal sugar that doesn't impede the
-/// user's understanding --- for example, elaborated type
-/// specifiers. If this is all the sugar we see, we don't want an
-/// a.k.a. clause.
-/// 2) Some types are technically sugared but are much more familiar
-/// when seen in their sugared form --- for example, va_list,
-/// vector types, and the magic Objective C types. We don't
-/// want to desugar these, even if we do produce an a.k.a. clause.
-/// 3) Some types may have already been desugared previously in this diagnostic.
-/// if this is the case, doing another "aka" would just be clutter.
-///
-static bool ShouldAKA(ASTContext &Context, QualType QT,
- const Diagnostic::ArgumentValue *PrevArgs,
- unsigned NumPrevArgs,
- QualType &DesugaredQT) {
- QualType InputTy = QT;
-
- bool AKA = false;
- QualifierCollector Qc;
-
- while (true) {
- const Type *Ty = Qc.strip(QT);
-
- // Don't aka just because we saw an elaborated type...
- if (isa<ElaboratedType>(Ty)) {
- QT = cast<ElaboratedType>(Ty)->desugar();
- continue;
- }
-
- // ...or a qualified name type...
- if (isa<QualifiedNameType>(Ty)) {
- QT = cast<QualifiedNameType>(Ty)->desugar();
- continue;
- }
-
- // ...or a substituted template type parameter.
- if (isa<SubstTemplateTypeParmType>(Ty)) {
- QT = cast<SubstTemplateTypeParmType>(Ty)->desugar();
- continue;
- }
-
- // Don't desugar template specializations.
- if (isa<TemplateSpecializationType>(Ty))
- break;
-
- // Don't desugar magic Objective-C types.
- if (QualType(Ty,0) == Context.getObjCIdType() ||
- QualType(Ty,0) == Context.getObjCClassType() ||
- QualType(Ty,0) == Context.getObjCSelType() ||
- QualType(Ty,0) == Context.getObjCProtoType())
- break;
-
- // Don't desugar va_list.
- if (QualType(Ty,0) == Context.getBuiltinVaListType())
- break;
-
- // Otherwise, do a single-step desugar.
- QualType Underlying;
- bool IsSugar = false;
- switch (Ty->getTypeClass()) {
-#define ABSTRACT_TYPE(Class, Base)
-#define TYPE(Class, Base) \
- case Type::Class: { \
- const Class##Type *CTy = cast<Class##Type>(Ty); \
- if (CTy->isSugared()) { \
- IsSugar = true; \
- Underlying = CTy->desugar(); \
- } \
- break; \
- }
-#include "clang/AST/TypeNodes.def"
- }
-
- // If it wasn't sugared, we're done.
- if (!IsSugar)
- break;
-
- // If the desugared type is a vector type, we don't want to expand
- // it, it will turn into an attribute mess. People want their "vec4".
- if (isa<VectorType>(Underlying))
- break;
-
- // Don't desugar through the primary typedef of an anonymous type.
- if (isa<TagType>(Underlying) && isa<TypedefType>(QT))
- if (cast<TagType>(Underlying)->getDecl()->getTypedefForAnonDecl() ==
- cast<TypedefType>(QT)->getDecl())
- break;
-
- // Otherwise, we're tearing through something opaque; note that
- // we'll eventually need an a.k.a. clause and keep going.
- AKA = true;
- QT = Underlying;
- continue;
- }
-
- // If we never tore through opaque sugar, don't print aka.
- if (!AKA) return false;
-
- // If we did, check to see if we already desugared this type in this
- // diagnostic. If so, don't do it again.
- for (unsigned i = 0; i != NumPrevArgs; ++i) {
- // TODO: Handle ak_declcontext case.
- if (PrevArgs[i].first == Diagnostic::ak_qualtype) {
- void *Ptr = (void*)PrevArgs[i].second;
- QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
- if (PrevTy == InputTy)
- return false;
- }
- }
-
- DesugaredQT = Qc.apply(QT);
- return true;
-}
-
-/// \brief Convert the given type to a string suitable for printing as part of
-/// a diagnostic.
-///
-/// \param Context the context in which the type was allocated
-/// \param Ty the type to print
-static std::string
-ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
- const Diagnostic::ArgumentValue *PrevArgs,
- unsigned NumPrevArgs) {
- // FIXME: Playing with std::string is really slow.
- std::string S = Ty.getAsString(Context.PrintingPolicy);
-
- // Consider producing an a.k.a. clause if removing all the direct
- // sugar gives us something "significantly different".
-
- QualType DesugaredTy;
- if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) {
- S = "'"+S+"' (aka '";
- S += DesugaredTy.getAsString(Context.PrintingPolicy);
- S += "')";
- return S;
- }
-
- S = "'" + S + "'";
- return S;
-}
-/// ConvertQualTypeToStringFn - This function is used to pretty print the
-/// specified QualType as a string in diagnostics.
-static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
- const char *Modifier, unsigned ModLen,
- const char *Argument, unsigned ArgLen,
- const Diagnostic::ArgumentValue *PrevArgs,
- unsigned NumPrevArgs,
- llvm::SmallVectorImpl<char> &Output,
- void *Cookie) {
- ASTContext &Context = *static_cast<ASTContext*>(Cookie);
-
- std::string S;
- bool NeedQuotes = true;
-
- switch (Kind) {
- default: assert(0 && "unknown ArgumentKind");
- case Diagnostic::ak_qualtype: {
- assert(ModLen == 0 && ArgLen == 0 &&
- "Invalid modifier for QualType argument");
-
- QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
- S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);
- NeedQuotes = false;
- break;
- }
- case Diagnostic::ak_declarationname: {
- DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
- S = N.getAsString();
-
- if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
- S = '+' + S;
- else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0)
- S = '-' + S;
- else
- assert(ModLen == 0 && ArgLen == 0 &&
- "Invalid modifier for DeclarationName argument");
- break;
- }
- case Diagnostic::ak_nameddecl: {
- bool Qualified;
- if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
- Qualified = true;
- else {
- assert(ModLen == 0 && ArgLen == 0 &&
- "Invalid modifier for NamedDecl* argument");
- Qualified = false;
- }
- reinterpret_cast<NamedDecl*>(Val)->
- getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
- break;
- }
- case Diagnostic::ak_nestednamespec: {
- llvm::raw_string_ostream OS(S);
- reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
- Context.PrintingPolicy);
- NeedQuotes = false;
- break;
- }
- case Diagnostic::ak_declcontext: {
- DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
- assert(DC && "Should never have a null declaration context");
-
- if (DC->isTranslationUnit()) {
- // FIXME: Get these strings from some localized place
- if (Context.getLangOptions().CPlusPlus)
- S = "the global namespace";
- else
- S = "the global scope";
- } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
- S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type),
- PrevArgs, NumPrevArgs);
- } else {
- // FIXME: Get these strings from some localized place
- NamedDecl *ND = cast<NamedDecl>(DC);
- if (isa<NamespaceDecl>(ND))
- S += "namespace ";
- else if (isa<ObjCMethodDecl>(ND))
- S += "method ";
- else if (isa<FunctionDecl>(ND))
- S += "function ";
-
- S += "'";
- ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
- S += "'";
- }
- NeedQuotes = false;
- break;
- }
- }
-
- if (NeedQuotes)
- Output.push_back('\'');
-
- Output.append(S.begin(), S.end());
-
- if (NeedQuotes)
- Output.push_back('\'');
-}
-
-
static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
if (C.getLangOptions().CPlusPlus)
return CXXRecordDecl::Create(C, TagDecl::TK_struct,
@@ -363,14 +121,15 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), NonInstantiationEntries(0),
- CurrentInstantiationScope(0)
+ CurrentInstantiationScope(0), TyposCorrected(0)
{
TUScope = 0;
if (getLangOptions().CPlusPlus)
FieldCollector.reset(new CXXFieldCollector());
// Tell diagnostics how to render things from the AST library.
- PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context);
+ PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
+ &Context);
ExprEvalContexts.push_back(
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
@@ -426,6 +185,12 @@ void Sema::DeleteStmt(StmtTy *S) {
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
+ // Remove functions that turned out to be used.
+ UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(),
+ UnusedStaticFuncs.end(),
+ std::mem_fun(&FunctionDecl::isUsed)),
+ UnusedStaticFuncs.end());
+
while (1) {
// C++: Perform implicit template instantiations.
//
@@ -472,12 +237,14 @@ void Sema::ActOnEndOfTranslationUnit() {
// translation unit contains a file scope declaration of that
// identifier, with the composite type as of the end of the
// translation unit, with an initializer equal to 0.
- for (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) {
- VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]);
-
- // If the tentative definition was completed, it will be in the list, but
- // not the map.
- if (VD == 0 || VD->isInvalidDecl() || !VD->isTentativeDefinition(Context))
+ llvm::SmallSet<VarDecl *, 32> Seen;
+ for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) {
+ VarDecl *VD = TentativeDefinitions[i]->getActingDefinition();
+
+ // If the tentative definition was completed, getActingDefinition() returns
+ // null. If we've already seen this variable before, insert()'s second
+ // return value is false.
+ if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
continue;
if (const IncompleteArrayType *ArrayT
@@ -504,6 +271,15 @@ void Sema::ActOnEndOfTranslationUnit() {
Consumer.CompleteTentativeDefinition(VD);
}
+
+ // Output warning for unused functions.
+ for (std::vector<FunctionDecl*>::iterator
+ F = UnusedStaticFuncs.begin(),
+ FEnd = UnusedStaticFuncs.end();
+ F != FEnd;
+ ++F)
+ Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName();
+
}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 06e9e3a..3c7492a 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -60,6 +60,7 @@ namespace clang {
class CallExpr;
class DeclRefExpr;
class UnresolvedLookupExpr;
+ class UnresolvedMemberExpr;
class VarDecl;
class ParmVarDecl;
class TypedefDecl;
@@ -95,6 +96,7 @@ namespace clang {
class ObjCPropertyDecl;
class ObjCContainerDecl;
class FunctionProtoType;
+ class CXXBasePath;
class CXXBasePaths;
class CXXTemporary;
class LookupResult;
@@ -103,6 +105,7 @@ namespace clang {
class InitializationSequence;
class VisibleDeclConsumer;
class TargetAttributesSema;
+ class ADLResult;
/// BlockSemaInfo - When a block is being parsed, this contains information
/// about the block. It is pointed to from Sema::CurBlock.
@@ -150,7 +153,7 @@ class LocInfoType : public Type {
enum {
// The last number that can fit in Type's TC.
// Avoids conflict with an existing Type class.
- LocInfo = (1 << TypeClassBitSize) - 1
+ LocInfo = Type::TypeLast + 1
};
TypeSourceInfo *DeclInfo;
@@ -270,18 +273,124 @@ public:
/// not visible.
llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls;
- /// \brief The set of tentative declarations seen so far in this
- /// translation unit for which no definition has been seen.
- ///
- /// The tentative declarations are indexed by the name of the
- /// declaration, and only the most recent tentative declaration for
- /// a given variable will be recorded here.
- llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions;
- std::vector<DeclarationName> TentativeDefinitionList;
+ /// \brief All the tentative definitions encountered in the TU.
+ std::vector<VarDecl *> TentativeDefinitions;
+
+ /// \brief The set of static functions seen so far that have not been used.
+ std::vector<FunctionDecl*> UnusedStaticFuncs;
+
+ /// An enum describing the kind of diagnostics to use when checking
+ /// access.
+ enum AccessDiagnosticsKind {
+ /// Suppress diagnostics.
+ ADK_quiet,
+
+ /// Use the normal diagnostics.
+ ADK_normal,
+
+ /// Use the diagnostics appropriate for checking a covariant
+ /// return type.
+ ADK_covariance
+ };
+
+ class AccessedEntity {
+ public:
+ enum Kind {
+ /// A member declaration found through lookup. The target is the
+ /// member.
+ Member,
+
+ /// A base-to-derived conversion. The target is the base class.
+ BaseToDerivedConversion,
+
+ /// A derived-to-base conversion. The target is the base class.
+ DerivedToBaseConversion
+ };
+
+ bool isMemberAccess() const { return K == Member; }
+
+ static AccessedEntity makeMember(CXXRecordDecl *NamingClass,
+ AccessSpecifier Access,
+ NamedDecl *Target) {
+ AccessedEntity E;
+ E.K = Member;
+ E.Access = Access;
+ E.Target = Target;
+ E.NamingClass = NamingClass;
+ return E;
+ }
+
+ static AccessedEntity makeBaseClass(bool BaseToDerived,
+ CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass,
+ AccessSpecifier Access) {
+ AccessedEntity E;
+ E.K = BaseToDerived ? BaseToDerivedConversion : DerivedToBaseConversion;
+ E.Access = Access;
+ E.Target = BaseClass;
+ E.NamingClass = DerivedClass;
+ return E;
+ }
+
+ Kind getKind() const { return Kind(K); }
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ // These apply to member decls...
+ NamedDecl *getTargetDecl() const { return Target; }
+ CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
+ // ...and these apply to hierarchy conversions.
+ CXXRecordDecl *getBaseClass() const { return cast<CXXRecordDecl>(Target); }
+ CXXRecordDecl *getDerivedClass() const { return NamingClass; }
+
+ private:
+ unsigned K : 2;
+ unsigned Access : 2;
+ NamedDecl *Target;
+ CXXRecordDecl *NamingClass;
+ };
- /// \brief The collection of delayed deprecation warnings.
- llvm::SmallVector<std::pair<SourceLocation,NamedDecl*>, 8>
- DelayedDeprecationWarnings;
+ struct DelayedDiagnostic {
+ enum DDKind { Deprecation, Access };
+
+ unsigned char Kind; // actually a DDKind
+ bool Triggered;
+
+ SourceLocation Loc;
+
+ union {
+ /// Deprecation.
+ struct { NamedDecl *Decl; } DeprecationData;
+
+ /// Access control.
+ AccessedEntity AccessData;
+ };
+
+ static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
+ NamedDecl *D) {
+ DelayedDiagnostic DD;
+ DD.Kind = Deprecation;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ DD.DeprecationData.Decl = D;
+ return DD;
+ }
+
+ static DelayedDiagnostic makeAccess(SourceLocation Loc,
+ const AccessedEntity &Entity) {
+ DelayedDiagnostic DD;
+ DD.Kind = Access;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ DD.AccessData = Entity;
+ return DD;
+ }
+
+ };
+
+ /// \brief The stack of diagnostics that were delayed due to being
+ /// produced during the parsing of a declaration.
+ llvm::SmallVector<DelayedDiagnostic, 8> DelayedDiagnostics;
/// \brief The depth of the current ParsingDeclaration stack.
/// If nonzero, we are currently parsing a declaration (and
@@ -517,8 +626,8 @@ public:
//===--------------------------------------------------------------------===//
// Type Analysis / Processing: SemaType.cpp.
//
+
QualType adjustParameterType(QualType T);
- void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
@@ -548,13 +657,15 @@ public:
static QualType GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
+ bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
bool CheckEquivalentExceptionSpec(
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc);
bool CheckEquivalentExceptionSpec(
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Old, SourceLocation OldLoc,
- const FunctionProtoType *New, SourceLocation NewLoc);
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingEmptyExceptionSpecification = 0);
bool CheckExceptionSpecSubset(
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Superset, SourceLocation SuperLoc,
@@ -634,6 +745,7 @@ public:
bool &OverloadableAttrRequired);
void CheckMain(FunctionDecl *FD);
virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
+ virtual void ActOnObjCCatchParam(DeclPtrTy D);
virtual void ActOnParamDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc,
ExprArg defarg);
@@ -950,31 +1062,38 @@ public:
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
// TODO: make this is a typesafe union.
typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet;
-
- typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet;
typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
+ void AddOverloadCandidate(NamedDecl *Function,
+ AccessSpecifier Access,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet &CandidateSet);
+
void AddOverloadCandidate(FunctionDecl *Function,
+ AccessSpecifier Access,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false,
bool PartialOverloading = false);
- void AddFunctionCandidates(const FunctionSet &Functions,
+ void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
- void AddMethodCandidate(NamedDecl *Decl,
- QualType ObjectType, Expr **Args, unsigned NumArgs,
+ void AddMethodCandidate(NamedDecl *Decl, AccessSpecifier Access,
+ QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false,
bool ForceRValue = false);
- void AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
- QualType ObjectType, Expr **Args, unsigned NumArgs,
+ void AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
@@ -983,20 +1102,24 @@ public:
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ AccessSpecifier Access,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddConversionCandidate(CXXConversionDecl *Conversion,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet);
void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
QualType ObjectTy, Expr **Args, unsigned NumArgs,
@@ -1021,12 +1144,14 @@ public:
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);
void AddArgumentDependentLookupCandidates(DeclarationName Name,
+ bool Operator,
Expr **Args, unsigned NumArgs,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading = false);
bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
- const OverloadCandidate& Cand2);
+ const OverloadCandidate& Cand2,
+ SourceLocation Loc);
OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
SourceLocation Loc,
OverloadCandidateSet::iterator& Best);
@@ -1072,12 +1197,12 @@ public:
OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
unsigned Opc,
- FunctionSet &Functions,
+ const UnresolvedSetImpl &Fns,
ExprArg input);
OwningExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
unsigned Opc,
- FunctionSet &Functions,
+ const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS);
OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
@@ -1217,16 +1342,15 @@ public:
bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
bool AllowBuiltinCreation = false,
bool EnteringContext = false);
-
ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II);
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
- FunctionSet &Functions);
+ UnresolvedSetImpl &Functions);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
- FunctionSet &Functions);
+ ADLResult &Functions);
void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer);
@@ -1302,6 +1426,14 @@ public:
void CollectImmediateProperties(ObjCContainerDecl *CDecl,
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap);
+ /// LookupPropertyDecl - Looks up a property in the current class and all
+ /// its protocols.
+ ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl,
+ IdentifierInfo *II);
+
+ ObjCIvarDecl *SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *NameII);
+
/// AtomicPropertySetterGetterRules - This routine enforces the rule (via
/// warning) when atomic property has one but not the other user-declared
/// setter or getter.
@@ -1373,6 +1505,8 @@ public:
SourceLocation ElseLoc, StmtArg ElseVal);
virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond,
DeclPtrTy CondVar);
+ virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch,
+ StmtArg Body);
virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
StmtArg Switch, StmtArg Body);
virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
@@ -1416,7 +1550,7 @@ public:
bool IsVolatile,
unsigned NumOutputs,
unsigned NumInputs,
- std::string *Names,
+ IdentifierInfo **Names,
MultiExprArg Constraints,
MultiExprArg Exprs,
ExprArg AsmString,
@@ -1466,6 +1600,8 @@ public:
void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D);
void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
+ void HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Decl *Ctx);
+
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
@@ -1770,7 +1906,8 @@ public:
// Act on C++ namespaces
virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
IdentifierInfo *Ident,
- SourceLocation LBrace);
+ SourceLocation LBrace,
+ AttributeList *AttrList);
virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace);
virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
@@ -1847,7 +1984,8 @@ public:
QualType DeclInitType,
CXXConstructorDecl *Constructor,
MultiExprArg Exprs,
- bool RequiresZeroInit = false);
+ bool RequiresZeroInit = false,
+ bool BaseInitialization = false);
// FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
// the constructor can be elidable?
@@ -1856,13 +1994,8 @@ public:
CXXConstructorDecl *Constructor,
bool Elidable,
MultiExprArg Exprs,
- bool RequiresZeroInit = false);
-
- OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
- QualType writtenTy,
- SourceLocation tyBeginLoc,
- MultiExprArg Args,
- SourceLocation rParenLoc);
+ bool RequiresZeroInit = false,
+ bool BaseInitialization = false);
OwningExprResult BuildCXXCastArgument(SourceLocation CastLoc,
QualType Ty,
@@ -1878,7 +2011,7 @@ public:
/// FinalizeVarWithDestructor - Prepare for calling destructor on the
/// constructed variable.
- void FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType);
+ void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
/// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
@@ -1917,14 +2050,6 @@ public:
Expr **Args, unsigned NumArgs,
SourceLocation Loc,
InitializationKind Kind);
-
- CXXConstructorDecl *
- PerformInitializationByConstructor(QualType ClassType,
- MultiExprArg ArgsPtr,
- SourceLocation Loc, SourceRange Range,
- DeclarationName InitEntity,
- InitializationKind Kind,
- ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs);
bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
@@ -2218,9 +2343,10 @@ public:
CXXRecordDecl *ClassDecl);
bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers,
- bool IsImplicitConstructor);
+ CXXBaseOrMemberInitializer **Initializers,
+ unsigned NumInitializers,
+ bool IsImplicitConstructor,
+ bool AnyErrors);
/// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl,
/// mark all its non-trivial member and base destructor declarations
@@ -2252,7 +2378,8 @@ public:
virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits);
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors);
void CheckCompletedCXXClass(CXXRecordDecl *Record);
virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
@@ -2326,7 +2453,7 @@ public:
SourceLocation Loc, SourceRange Range,
bool IgnoreAccess = false);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
- unsigned InaccessibleBaseID,
+ AccessDiagnosticsKind ADK,
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name);
@@ -2353,22 +2480,43 @@ public:
// C++ Access Control
//
+ enum AccessResult {
+ AR_accessible,
+ AR_inaccessible,
+ AR_dependent,
+ AR_delayed
+ };
+
bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
NamedDecl *PrevMemberDecl,
AccessSpecifier LexicalAS);
- const CXXBaseSpecifier *FindInaccessibleBase(QualType Derived, QualType Base,
- CXXBasePaths &Paths,
- bool NoPrivileges = false);
-
- void CheckAccess(const LookupResult &R);
- bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access);
-
- bool CheckBaseClassAccess(QualType Derived, QualType Base,
- unsigned InaccessibleBaseID,
- CXXBasePaths& Paths, SourceLocation AccessLoc,
- DeclarationName Name);
-
+ AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+ NamedDecl *D,
+ AccessSpecifier Access);
+ AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+ NamedDecl *D,
+ AccessSpecifier Access);
+ AccessResult CheckConstructorAccess(SourceLocation Loc,
+ CXXConstructorDecl *D,
+ AccessSpecifier Access);
+ AccessResult CheckDestructorAccess(SourceLocation Loc,
+ const RecordType *Record);
+ AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
+ Expr *ObjectExpr,
+ NamedDecl *D,
+ AccessSpecifier Access);
+ AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
+ bool IsBaseToDerived,
+ QualType Base, QualType Derived,
+ const CXXBasePath &Path,
+ bool ForceCheck = false,
+ bool ForceUnprivileged = false,
+ AccessDiagnosticsKind ADK = ADK_normal);
+
+ void CheckLookupAccess(const LookupResult &R);
+
+ void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx);
enum AbstractDiagSelID {
AbstractNone = -1,
@@ -2758,17 +2906,28 @@ public:
///
TemplateArgumentList *Deduced;
+ /// \brief The source location at which template argument
+ /// deduction is occurring.
+ SourceLocation Loc;
+
// do not implement these
TemplateDeductionInfo(const TemplateDeductionInfo&);
TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
public:
- TemplateDeductionInfo(ASTContext &Context) : Context(Context), Deduced(0) { }
+ TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
+ : Context(Context), Deduced(0), Loc(Loc) { }
~TemplateDeductionInfo() {
// FIXME: if (Deduced) Deduced->Destroy(Context);
}
+ /// \brief Returns the location at which template argument is
+ /// occuring.
+ SourceLocation getLocation() const {
+ return Loc;
+ }
+
/// \brief Take ownership of the deduced template argument list.
TemplateArgumentList *take() {
TemplateArgumentList *Result = Deduced;
@@ -2866,20 +3025,21 @@ public:
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
TemplatePartialOrderingContext TPOC);
- FunctionDecl *getMostSpecialized(FunctionDecl **Specializations,
- unsigned NumSpecializations,
- TemplatePartialOrderingContext TPOC,
- SourceLocation Loc,
- const PartialDiagnostic &NoneDiag,
- const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &CandidateDiag,
- unsigned *Index = 0);
+ UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
+ UnresolvedSetIterator SEnd,
+ TemplatePartialOrderingContext TPOC,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag);
ClassTemplatePartialSpecializationDecl *
getMoreSpecializedPartialSpecialization(
ClassTemplatePartialSpecializationDecl *PS1,
- ClassTemplatePartialSpecializationDecl *PS2);
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc);
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced,
@@ -2893,7 +3053,8 @@ public:
//
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
- const TemplateArgumentList *Innermost = 0);
+ const TemplateArgumentList *Innermost = 0,
+ bool RelativeToPrimary = false);
/// \brief A template instantiation that is currently in progress.
struct ActiveTemplateInstantiation {
@@ -3243,6 +3404,9 @@ public:
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
+ /// \brief The number of typos corrected by CorrectTypo.
+ unsigned TyposCorrected;
+
/// \brief An entity for which implicit template instantiation is required.
///
/// The source location associated with the declaration is the first place in
@@ -3550,6 +3714,11 @@ public:
// to their respective pointers (C99 6.3.2.1).
void DefaultFunctionArrayConversion(Expr *&expr);
+ // DefaultFunctionArrayLvalueConversion - converts functions and
+ // arrays to their respective pointers and performs the
+ // lvalue-to-rvalue conversion.
+ void DefaultFunctionArrayLvalueConversion(Expr *&expr);
+
// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
// do not have a prototype. Integer promotions are performed on each
// argument, and arguments that have type float are promoted to double.
@@ -3944,12 +4113,15 @@ public:
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
+
+public:
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
+
private:
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
- SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
- unsigned ByteNo) const;
bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall);
bool CheckObjCString(Expr *Arg);
@@ -3957,7 +4129,7 @@ private:
CallExpr *TheCall);
bool SemaBuiltinVAStart(CallExpr *TheCall);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
- bool SemaBuiltinUnaryFP(CallExpr *TheCall);
+ bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned LastArg=1);
bool SemaBuiltinStackAddress(CallExpr *TheCall);
public:
@@ -3987,7 +4159,6 @@ private:
const PartialDiagnostic &PD,
bool Equality = false);
void CheckImplicitConversion(Expr *E, QualType Target);
-
};
//===--------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 51f9e30..eca8bb4 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -16,6 +16,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+
using namespace clang;
/// SetMemberAccessSpecifier - Set the access specifier of a member.
@@ -47,192 +49,500 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
return false;
}
-/// Find a class on the derivation path between Derived and Base that is
-/// inaccessible. If @p NoPrivileges is true, special access rights (members
-/// and friends) are not considered.
-const CXXBaseSpecifier *Sema::FindInaccessibleBase(
- QualType Derived, QualType Base, CXXBasePaths &Paths, bool NoPrivileges) {
- Base = Context.getCanonicalType(Base).getUnqualifiedType();
- assert(!Paths.isAmbiguous(Base) &&
- "Can't check base class access if set of paths is ambiguous");
- assert(Paths.isRecordingPaths() &&
- "Can't check base class access without recorded paths");
-
-
- const CXXBaseSpecifier *InaccessibleBase = 0;
-
- const CXXRecordDecl *CurrentClassDecl = 0;
- if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(getCurFunctionDecl()))
- CurrentClassDecl = MD->getParent();
-
- for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
- Path != PathsEnd; ++Path) {
-
- bool FoundInaccessibleBase = false;
-
- for (CXXBasePath::const_iterator Element = Path->begin(),
- ElementEnd = Path->end(); Element != ElementEnd; ++Element) {
- const CXXBaseSpecifier *Base = Element->Base;
-
- switch (Base->getAccessSpecifier()) {
- default:
- assert(0 && "invalid access specifier");
- case AS_public:
- // Nothing to do.
- break;
- case AS_private:
- // FIXME: Check if the current function/class is a friend.
- if (NoPrivileges || CurrentClassDecl != Element->Class)
- FoundInaccessibleBase = true;
- break;
- case AS_protected:
- // FIXME: Implement
- break;
- }
+namespace {
+struct EffectiveContext {
+ EffectiveContext() : Record(0), Function(0) {}
+
+ explicit EffectiveContext(DeclContext *DC) {
+ if (isa<FunctionDecl>(DC)) {
+ Function = cast<FunctionDecl>(DC);
+ DC = Function->getDeclContext();
+ } else
+ Function = 0;
+
+ if (isa<CXXRecordDecl>(DC))
+ Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+ else
+ Record = 0;
+ }
+
+ bool isClass(const CXXRecordDecl *R) const {
+ return R->getCanonicalDecl() == Record;
+ }
+
+ CXXRecordDecl *Record;
+ FunctionDecl *Function;
+};
+}
+
+static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) {
+ CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext());
+ while (DeclaringClass->isAnonymousStructOrUnion())
+ DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext());
+ return DeclaringClass;
+}
+
+static Sema::AccessResult GetFriendKind(Sema &S,
+ const EffectiveContext &EC,
+ const CXXRecordDecl *Class) {
+ if (EC.isClass(Class))
+ return Sema::AR_accessible;
+
+ // FIXME: implement
+ return Sema::AR_inaccessible;
+}
- if (FoundInaccessibleBase) {
- InaccessibleBase = Base;
- break;
+/// Finds the best path from the naming class to the declaring class,
+/// taking friend declarations into account.
+///
+/// \return null if friendship is dependent
+static CXXBasePath *FindBestPath(Sema &S,
+ const EffectiveContext &EC,
+ CXXRecordDecl *Derived,
+ CXXRecordDecl *Base,
+ CXXBasePaths &Paths) {
+ // Derive the paths to the desired base.
+ bool isDerived = Derived->isDerivedFrom(Base, Paths);
+ assert(isDerived && "derived class not actually derived from base");
+ (void) isDerived;
+
+ CXXBasePath *BestPath = 0;
+
+ // Derive the friend-modified access along each path.
+ for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
+ PI != PE; ++PI) {
+
+ // Walk through the path backwards.
+ AccessSpecifier PathAccess = AS_public;
+ CXXBasePath::iterator I = PI->end(), E = PI->begin();
+ while (I != E) {
+ --I;
+
+ AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();
+ if (BaseAccess != AS_public) {
+ switch (GetFriendKind(S, EC, I->Class)) {
+ case Sema::AR_inaccessible: break;
+ case Sema::AR_accessible: BaseAccess = AS_public; break;
+ case Sema::AR_dependent: return 0;
+ case Sema::AR_delayed:
+ llvm_unreachable("friend resolution is never delayed"); break;
+ }
}
+
+ PathAccess = CXXRecordDecl::MergeAccess(BaseAccess, PathAccess);
}
- if (!FoundInaccessibleBase) {
- // We found a path to the base, our work here is done.
- return 0;
+ // Note that we modify the path's Access field to the
+ // friend-modified access.
+ if (BestPath == 0 || PathAccess < BestPath->Access) {
+ BestPath = &*PI;
+ BestPath->Access = PathAccess;
}
}
- assert(InaccessibleBase && "no path found, but no inaccessible base");
- return InaccessibleBase;
+ return BestPath;
}
-/// CheckBaseClassAccess - Check that a derived class can access its base class
-/// and report an error if it can't. [class.access.base]
-bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
- unsigned InaccessibleBaseID,
- CXXBasePaths &Paths, SourceLocation AccessLoc,
- DeclarationName Name) {
+/// Diagnose the path which caused the given declaration or base class
+/// to become inaccessible.
+static void DiagnoseAccessPath(Sema &S,
+ const EffectiveContext &EC,
+ CXXRecordDecl *NamingClass,
+ CXXRecordDecl *DeclaringClass,
+ NamedDecl *D, AccessSpecifier Access) {
+ // Easy case: the decl's natural access determined its path access.
+ // We have to check against AS_private here in case Access is AS_none,
+ // indicating a non-public member of a private base class.
+ //
+ // DependentFriend should be impossible here.
+ if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
+ switch (GetFriendKind(S, EC, DeclaringClass)) {
+ case Sema::AR_inaccessible: {
+ S.Diag(D->getLocation(), diag::note_access_natural)
+ << (unsigned) (Access == AS_protected)
+ << /*FIXME: not implicitly*/ 0;
+ return;
+ }
- if (!getLangOptions().AccessControl)
- return false;
- const CXXBaseSpecifier *InaccessibleBase = FindInaccessibleBase(
- Derived, Base, Paths);
+ case Sema::AR_accessible: break;
- if (InaccessibleBase) {
- Diag(AccessLoc, InaccessibleBaseID)
- << Derived << Base << Name;
+ case Sema::AR_dependent:
+ case Sema::AR_delayed:
+ llvm_unreachable("dependent/delayed not allowed");
+ return;
+ }
+ }
- AccessSpecifier AS = InaccessibleBase->getAccessSpecifierAsWritten();
+ CXXBasePaths Paths;
+ CXXBasePath &Path = *FindBestPath(S, EC, NamingClass, DeclaringClass, Paths);
- // If there's no written access specifier, then the inheritance specifier
- // is implicitly private.
- if (AS == AS_none)
- Diag(InaccessibleBase->getSourceRange().getBegin(),
- diag::note_inheritance_implicitly_private_here);
- else
- Diag(InaccessibleBase->getSourceRange().getBegin(),
- diag::note_inheritance_specifier_here) << AS;
+ CXXBasePath::iterator I = Path.end(), E = Path.begin();
+ while (I != E) {
+ --I;
- return true;
+ const CXXBaseSpecifier *BS = I->Base;
+ AccessSpecifier BaseAccess = BS->getAccessSpecifier();
+
+ // If this is public inheritance, or the derived class is a friend,
+ // skip this step.
+ if (BaseAccess == AS_public)
+ continue;
+
+ switch (GetFriendKind(S, EC, I->Class)) {
+ case Sema::AR_accessible: continue;
+ case Sema::AR_inaccessible: break;
+
+ case Sema::AR_dependent:
+ case Sema::AR_delayed:
+ llvm_unreachable("dependent friendship, should not be diagnosing");
+ }
+
+ // Check whether this base specifier is the tighest point
+ // constraining access. We have to check against AS_private for
+ // the same reasons as above.
+ if (BaseAccess == AS_private || BaseAccess >= Access) {
+
+ // We're constrained by inheritance, but we want to say
+ // "declared private here" if we're diagnosing a hierarchy
+ // conversion and this is the final step.
+ unsigned diagnostic;
+ if (D) diagnostic = diag::note_access_constrained_by_path;
+ else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural;
+ else diagnostic = diag::note_access_constrained_by_path;
+
+ S.Diag(BS->getSourceRange().getBegin(), diagnostic)
+ << BS->getSourceRange()
+ << (BaseAccess == AS_protected)
+ << (BS->getAccessSpecifierAsWritten() == AS_none);
+ return;
+ }
}
- return false;
+ llvm_unreachable("access not apparently constrained by path");
}
-/// Diagnose the path which caused the given declaration to become
-/// inaccessible.
-static void DiagnoseAccessPath(Sema &S, const LookupResult &R, NamedDecl *D,
- AccessSpecifier Access) {
- // Easy case: the decl's natural access determined its path access.
- if (Access == D->getAccess() || D->getAccess() == AS_private) {
- S.Diag(D->getLocation(), diag::note_access_natural)
- << (unsigned) (Access == AS_protected);
- return;
+/// Diagnose an inaccessible class member.
+static void DiagnoseInaccessibleMember(Sema &S, SourceLocation Loc,
+ const EffectiveContext &EC,
+ CXXRecordDecl *NamingClass,
+ AccessSpecifier Access,
+ const Sema::AccessedEntity &Entity) {
+ NamedDecl *D = Entity.getTargetDecl();
+ CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
+
+ if (isa<CXXConstructorDecl>(D)) {
+ unsigned DiagID = (Access == AS_protected ? diag::err_access_ctor_protected
+ : diag::err_access_ctor_private);
+ S.Diag(Loc, DiagID)
+ << S.Context.getTypeDeclType(DeclaringClass);
+ } else {
+ unsigned DiagID = (Access == AS_protected ? diag::err_access_protected
+ : diag::err_access_private);
+ S.Diag(Loc, DiagID)
+ << D->getDeclName()
+ << S.Context.getTypeDeclType(DeclaringClass);
}
+ DiagnoseAccessPath(S, EC, NamingClass, DeclaringClass, D, Access);
+}
- // TODO: flesh this out
- S.Diag(D->getLocation(), diag::note_access_constrained_by_path)
- << (unsigned) (Access == AS_protected);
+/// Diagnose an inaccessible hierarchy conversion.
+static void DiagnoseInaccessibleBase(Sema &S, SourceLocation Loc,
+ const EffectiveContext &EC,
+ AccessSpecifier Access,
+ const Sema::AccessedEntity &Entity,
+ Sema::AccessDiagnosticsKind ADK) {
+ if (ADK == Sema::ADK_covariance) {
+ S.Diag(Loc, diag::err_covariant_return_inaccessible_base)
+ << S.Context.getTypeDeclType(Entity.getDerivedClass())
+ << S.Context.getTypeDeclType(Entity.getBaseClass())
+ << (Access == AS_protected);
+ } else if (Entity.getKind() == Sema::AccessedEntity::BaseToDerivedConversion) {
+ S.Diag(Loc, diag::err_downcast_from_inaccessible_base)
+ << S.Context.getTypeDeclType(Entity.getDerivedClass())
+ << S.Context.getTypeDeclType(Entity.getBaseClass())
+ << (Access == AS_protected);
+ } else {
+ S.Diag(Loc, diag::err_upcast_to_inaccessible_base)
+ << S.Context.getTypeDeclType(Entity.getDerivedClass())
+ << S.Context.getTypeDeclType(Entity.getBaseClass())
+ << (Access == AS_protected);
+ }
+ DiagnoseAccessPath(S, EC, Entity.getDerivedClass(),
+ Entity.getBaseClass(), 0, Access);
}
-/// Checks access to the given declaration in the current context.
-///
-/// \param R the means via which the access was made; must have a naming
-/// class set
-/// \param D the declaration accessed
-/// \param Access the best access along any inheritance path from the
-/// naming class to the declaration. AS_none means the path is impossible
-bool Sema::CheckAccess(const LookupResult &R, NamedDecl *D,
- AccessSpecifier Access) {
- assert(R.getNamingClass() && "performing access check without naming class");
+static void DiagnoseBadAccess(Sema &S,
+ SourceLocation Loc,
+ const EffectiveContext &EC,
+ CXXRecordDecl *NamingClass,
+ AccessSpecifier Access,
+ const Sema::AccessedEntity &Entity,
+ Sema::AccessDiagnosticsKind ADK) {
+ if (Entity.isMemberAccess())
+ DiagnoseInaccessibleMember(S, Loc, EC, NamingClass, Access, Entity);
+ else
+ DiagnoseInaccessibleBase(S, Loc, EC, Access, Entity, ADK);
+}
- // If the access path is public, it's accessible everywhere.
- if (Access == AS_public)
- return false;
- // Otherwise, derive the current class context.
- DeclContext *DC = CurContext;
- while (isa<CXXRecordDecl>(DC) &&
- cast<CXXRecordDecl>(DC)->isAnonymousStructOrUnion())
- DC = DC->getParent();
-
- CXXRecordDecl *CurRecord;
- if (isa<CXXRecordDecl>(DC))
- CurRecord = cast<CXXRecordDecl>(DC);
- else if (isa<CXXMethodDecl>(DC))
- CurRecord = cast<CXXMethodDecl>(DC)->getParent();
- else {
- Diag(R.getNameLoc(), diag::err_access_outside_class)
- << (Access == AS_protected);
- DiagnoseAccessPath(*this, R, D, Access);
- return true;
+/// Try to elevate access using friend declarations. This is
+/// potentially quite expensive.
+static void TryElevateAccess(Sema &S,
+ const EffectiveContext &EC,
+ const Sema::AccessedEntity &Entity,
+ AccessSpecifier &Access) {
+ CXXRecordDecl *DeclaringClass;
+ if (Entity.isMemberAccess()) {
+ DeclaringClass = FindDeclaringClass(Entity.getTargetDecl());
+ } else {
+ DeclaringClass = Entity.getBaseClass();
}
+ CXXRecordDecl *NamingClass = Entity.getNamingClass();
+
+ // Adjust the declaration of the referred entity.
+ AccessSpecifier DeclAccess = AS_none;
+ if (Entity.isMemberAccess()) {
+ NamedDecl *Target = Entity.getTargetDecl();
+
+ DeclAccess = Target->getAccess();
+ if (DeclAccess != AS_public) {
+ switch (GetFriendKind(S, EC, DeclaringClass)) {
+ case Sema::AR_accessible: DeclAccess = AS_public; break;
+ case Sema::AR_inaccessible: break;
+ case Sema::AR_dependent: /* FIXME: delay dependent friendship */ return;
+ case Sema::AR_delayed: llvm_unreachable("friend status is never delayed");
+ }
+ }
+
+ if (DeclaringClass == NamingClass) {
+ Access = DeclAccess;
+ return;
+ }
+ }
+
+ assert(DeclaringClass != NamingClass);
- CXXRecordDecl *NamingClass = R.getNamingClass();
+ // Append the declaration's access if applicable.
+ CXXBasePaths Paths;
+ CXXBasePath *Path = FindBestPath(S, EC, Entity.getNamingClass(),
+ DeclaringClass, Paths);
+ if (!Path) {
+ // FIXME: delay dependent friendship
+ return;
+ }
+
+ // Grab the access along the best path.
+ AccessSpecifier NewAccess = Path->Access;
+ if (Entity.isMemberAccess())
+ NewAccess = CXXRecordDecl::MergeAccess(NewAccess, DeclAccess);
+
+ assert(NewAccess <= Access && "access along best path worse than direct?");
+ Access = NewAccess;
+}
+
+/// Checks access to an entity from the given effective context.
+static Sema::AccessResult CheckEffectiveAccess(Sema &S,
+ const EffectiveContext &EC,
+ SourceLocation Loc,
+ Sema::AccessedEntity const &Entity,
+ Sema::AccessDiagnosticsKind ADK) {
+ AccessSpecifier Access = Entity.getAccess();
+ assert(Access != AS_public);
+
+ CXXRecordDecl *NamingClass = Entity.getNamingClass();
while (NamingClass->isAnonymousStructOrUnion())
// This should be guaranteed by the fact that the decl has
// non-public access. If not, we should make it guaranteed!
NamingClass = cast<CXXRecordDecl>(NamingClass);
+ if (!EC.Record) {
+ TryElevateAccess(S, EC, Entity, Access);
+ if (Access == AS_public) return Sema::AR_accessible;
+
+ if (ADK != Sema::ADK_quiet)
+ DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity, ADK);
+ return Sema::AR_inaccessible;
+ }
+
// White-list accesses from within the declaring class.
- if (Access != AS_none &&
- CurRecord->getCanonicalDecl() == NamingClass->getCanonicalDecl())
- return false;
+ if (Access != AS_none && EC.isClass(NamingClass))
+ return Sema::AR_accessible;
+
+ // If the access is worse than 'protected', try to promote to it using
+ // friend declarations.
+ bool TriedElevation = false;
+ if (Access != AS_protected) {
+ TryElevateAccess(S, EC, Entity, Access);
+ if (Access == AS_public) return Sema::AR_accessible;
+ TriedElevation = true;
+ }
// Protected access.
if (Access == AS_protected) {
// FIXME: implement [class.protected]p1
- if (CurRecord->isDerivedFrom(NamingClass))
- return false;
+ if (EC.Record->isDerivedFrom(NamingClass))
+ return Sema::AR_accessible;
- // FIXME: dependent classes
+ // FIXME: delay dependent classes
}
- // FIXME: friends
+ // We're about to reject; one last chance to promote access.
+ if (!TriedElevation) {
+ TryElevateAccess(S, EC, Entity, Access);
+ if (Access == AS_public) return Sema::AR_accessible;
+ }
+
+ // Okay, that's it, reject it.
+ if (ADK != Sema::ADK_quiet)
+ DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity, ADK);
+ return Sema::AR_inaccessible;
+}
- // Okay, it's a bad access, reject it.
+static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
+ const Sema::AccessedEntity &Entity,
+ Sema::AccessDiagnosticsKind ADK
+ = Sema::ADK_normal) {
+ // If the access path is public, it's accessible everywhere.
+ if (Entity.getAccess() == AS_public)
+ return Sema::AR_accessible;
+
+ // If we're currently parsing a top-level declaration, delay
+ // diagnostics. This is the only case where parsing a declaration
+ // can actually change our effective context for the purposes of
+ // access control.
+ if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
+ assert(ADK == Sema::ADK_normal && "delaying abnormal access check");
+ S.DelayedDiagnostics.push_back(
+ Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
+ return Sema::AR_delayed;
+ }
-
- CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext());
+ return CheckEffectiveAccess(S, EffectiveContext(S.CurContext),
+ Loc, Entity, ADK);
+}
- if (Access == AS_protected) {
- Diag(R.getNameLoc(), diag::err_access_protected)
- << Context.getTypeDeclType(DeclaringClass)
- << Context.getTypeDeclType(CurRecord);
- DiagnoseAccessPath(*this, R, D, Access);
- return true;
- }
+void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
+ // Pretend we did this from the context of the newly-parsed
+ // declaration.
+ EffectiveContext EC(Ctx->getDeclContext());
+
+ if (CheckEffectiveAccess(*this, EC, DD.Loc, DD.AccessData, ADK_normal))
+ DD.Triggered = true;
+}
+
+Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+ NamedDecl *D,
+ AccessSpecifier Access) {
+ if (!getLangOptions().AccessControl || !E->getNamingClass())
+ return AR_accessible;
- assert(Access == AS_private || Access == AS_none);
- Diag(R.getNameLoc(), diag::err_access_private)
- << Context.getTypeDeclType(DeclaringClass)
- << Context.getTypeDeclType(CurRecord);
- DiagnoseAccessPath(*this, R, D, Access);
- return true;
+ return CheckAccess(*this, E->getNameLoc(),
+ AccessedEntity::makeMember(E->getNamingClass(), Access, D));
+}
+
+/// Perform access-control checking on a previously-unresolved member
+/// access which has now been resolved to a member.
+Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+ NamedDecl *D,
+ AccessSpecifier Access) {
+ if (!getLangOptions().AccessControl)
+ return AR_accessible;
+
+ return CheckAccess(*this, E->getMemberLoc(),
+ AccessedEntity::makeMember(E->getNamingClass(), Access, D));
+}
+
+Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
+ const RecordType *RT) {
+ if (!getLangOptions().AccessControl)
+ return AR_accessible;
+
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+ CXXDestructorDecl *Dtor = NamingClass->getDestructor(Context);
+
+ AccessSpecifier Access = Dtor->getAccess();
+ if (Access == AS_public)
+ return AR_accessible;
+
+ return CheckAccess(*this, Loc,
+ AccessedEntity::makeMember(NamingClass, Access, Dtor));
+}
+
+/// Checks access to a constructor.
+Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
+ CXXConstructorDecl *Constructor,
+ AccessSpecifier Access) {
+ if (!getLangOptions().AccessControl)
+ return AR_accessible;
+
+ CXXRecordDecl *NamingClass = Constructor->getParent();
+ return CheckAccess(*this, UseLoc,
+ AccessedEntity::makeMember(NamingClass, Access, Constructor));
+}
+
+/// Checks access to an overloaded member operator, including
+/// conversion operators.
+Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
+ Expr *ObjectExpr,
+ NamedDecl *MemberOperator,
+ AccessSpecifier Access) {
+ if (!getLangOptions().AccessControl)
+ return AR_accessible;
+
+ const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
+ assert(RT && "found member operator but object expr not of record type");
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
+
+ return CheckAccess(*this, OpLoc,
+ AccessedEntity::makeMember(NamingClass, Access, MemberOperator));
+}
+
+/// Checks access for a hierarchy conversion.
+///
+/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
+/// or a derived-to-base conversion (false)
+/// \param ForceCheck true if this check should be performed even if access
+/// control is disabled; some things rely on this for semantics
+/// \param ForceUnprivileged true if this check should proceed as if the
+/// context had no special privileges
+/// \param ADK controls the kind of diagnostics that are used
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+ bool IsBaseToDerived,
+ QualType Base,
+ QualType Derived,
+ const CXXBasePath &Path,
+ bool ForceCheck,
+ bool ForceUnprivileged,
+ AccessDiagnosticsKind ADK) {
+ if (!ForceCheck && !getLangOptions().AccessControl)
+ return AR_accessible;
+
+ if (Path.Access == AS_public)
+ return AR_accessible;
+
+ // TODO: preserve the information about which types exactly were used.
+ CXXRecordDecl *BaseD, *DerivedD;
+ BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl());
+ DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl());
+ AccessedEntity Entity = AccessedEntity::makeBaseClass(IsBaseToDerived,
+ BaseD, DerivedD,
+ Path.Access);
+
+ if (ForceUnprivileged)
+ return CheckEffectiveAccess(*this, EffectiveContext(),
+ AccessLoc, Entity, ADK);
+ return CheckAccess(*this, AccessLoc, Entity, ADK);
}
/// Checks access to all the declarations in the given result set.
-void Sema::CheckAccess(const LookupResult &R) {
+void Sema::CheckLookupAccess(const LookupResult &R) {
+ assert(getLangOptions().AccessControl
+ && "performing access check without access control");
+ assert(R.getNamingClass() && "performing access check without naming class");
+
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- CheckAccess(R, *I, I.getAccess());
+ if (I.getAccess() != AS_public)
+ CheckAccess(*this, R.getNameLoc(),
+ AccessedEntity::makeMember(R.getNamingClass(),
+ I.getAccess(), *I));
}
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 57c4f9b..0097cd3 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -204,7 +204,30 @@ bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
T2 = T2PtrType->getPointeeType();
return true;
}
-
+ const ObjCObjectPointerType *T1ObjCPtrType =
+ T1->getAs<ObjCObjectPointerType>(),
+ *T2ObjCPtrType =
+ T2->getAs<ObjCObjectPointerType>();
+ if (T1ObjCPtrType) {
+ if (T2ObjCPtrType) {
+ T1 = T1ObjCPtrType->getPointeeType();
+ T2 = T2ObjCPtrType->getPointeeType();
+ return true;
+ }
+ else if (T2PtrType) {
+ T1 = T1ObjCPtrType->getPointeeType();
+ T2 = T2PtrType->getPointeeType();
+ return true;
+ }
+ }
+ else if (T2ObjCPtrType) {
+ if (T1PtrType) {
+ T2 = T2ObjCPtrType->getPointeeType();
+ T1 = T1PtrType->getPointeeType();
+ return true;
+ }
+ }
+
const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
*T2MPType = T2->getAs<MemberPointerType>();
if (T1MPType && T2MPType) {
@@ -225,9 +248,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
// C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
// the rules are non-trivial. So first we construct Tcv *...cv* as described
// in C++ 5.2.11p8.
- assert((SrcType->isPointerType() || SrcType->isMemberPointerType()) &&
+ assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType()) &&
"Source type is not pointer or pointer to member.");
- assert((DestType->isPointerType() || DestType->isMemberPointerType()) &&
+ assert((DestType->isAnyPointerType() || DestType->isMemberPointerType()) &&
"Destination type is not pointer or pointer to member.");
QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
@@ -368,7 +391,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
}
// C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
- const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(Self.Context);
+ const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition();
assert(SrcDecl && "Definition missing");
if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
@@ -388,7 +411,7 @@ void
CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange, const SourceRange &DestRange) {
if (!DestType->isLValueReferenceType())
- Self.DefaultFunctionArrayConversion(SrcExpr);
+ Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
@@ -407,7 +430,7 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange, const SourceRange &DestRange,
CastExpr::CastKind &Kind) {
if (!DestType->isLValueReferenceType())
- Self.DefaultFunctionArrayConversion(SrcExpr);
+ Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
@@ -434,7 +457,7 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
}
if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
- Self.DefaultFunctionArrayConversion(SrcExpr);
+ Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
@@ -755,9 +778,10 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
return TC_Failed;
}
- if (!CStyle && Self.CheckBaseClassAccess(DestType, SrcType,
- diag::err_downcast_from_inaccessible_base, Paths,
- OpRange.getBegin(), DeclarationName())) {
+ if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(),
+ /*IsBaseToDerived*/ true,
+ SrcType, DestType,
+ Paths.front())) {
msg = 0;
return TC_Failed;
}
@@ -821,9 +845,10 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,
return TC_Failed;
}
- if (!CStyle && Self.CheckBaseClassAccess(DestType, SrcType,
- diag::err_downcast_from_inaccessible_base, Paths,
- OpRange.getBegin(), DeclarationName())) {
+ if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(),
+ /*IsBaseToDerived*/ false,
+ DestType, SrcType,
+ Paths.front())) {
msg = 0;
return TC_Failed;
}
@@ -1083,10 +1108,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_Failed;
}
- bool destIsPtr =
- CStyle? DestType->isAnyPointerType() : DestType->isPointerType();
- bool srcIsPtr =
- CStyle ? SrcType->isAnyPointerType() : SrcType->isPointerType();
+ bool destIsPtr = DestType->isAnyPointerType();
+ bool srcIsPtr = SrcType->isAnyPointerType();
if (!destIsPtr && !srcIsPtr) {
// Except for std::nullptr_t->integer and lvalue->reference, which are
// handled above, at least one of the two arguments must be a pointer.
@@ -1197,7 +1220,7 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
return false;
if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
- DefaultFunctionArrayConversion(CastExpr);
+ DefaultFunctionArrayLvalueConversion(CastExpr);
// C++ [expr.cast]p5: The conversions performed by
// - a const_cast,
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 7a0b625..52e9e9b 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -241,6 +241,10 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
DeclContext *DC = computeDeclContext(SS, true);
if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+ // If this is a dependent type, then we consider it complete.
+ if (Tag->isDependentContext())
+ return false;
+
// If we're currently defining this type, then lookup into the
// type is okay: don't complain that it isn't complete yet.
const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>();
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 6ff8b1d..b62cd19 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -14,7 +14,8 @@
#include "Sema.h"
#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/PathSensitive/AnalysisContext.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/Analyses/PrintfFormatString.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
@@ -140,12 +141,16 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinUnorderedCompare(TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_fpclassify:
+ if (SemaBuiltinFPClassification(TheCall, 6))
+ return ExprError();
+ break;
case Builtin::BI__builtin_isfinite:
case Builtin::BI__builtin_isinf:
case Builtin::BI__builtin_isinf_sign:
case Builtin::BI__builtin_isnan:
case Builtin::BI__builtin_isnormal:
- if (SemaBuiltinUnaryFP(TheCall))
+ if (SemaBuiltinFPClassification(TheCall))
return ExprError();
break;
case Builtin::BI__builtin_return_address:
@@ -583,20 +588,21 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
return false;
}
-/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isnan and
-/// friends. This is declared to take (...), so we have to check everything.
-bool Sema::SemaBuiltinUnaryFP(CallExpr *TheCall) {
- if (TheCall->getNumArgs() < 1)
+/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like
+/// __builtin_isnan and friends. This is declared to take (...), so we have
+/// to check everything.
+bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned LastArg) {
+ if (TheCall->getNumArgs() < LastArg)
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
<< 0 /*function call*/;
- if (TheCall->getNumArgs() > 1)
- return Diag(TheCall->getArg(1)->getLocStart(),
+ if (TheCall->getNumArgs() > LastArg)
+ return Diag(TheCall->getArg(LastArg)->getLocStart(),
diag::err_typecheck_call_too_many_args)
<< 0 /*function call*/
- << SourceRange(TheCall->getArg(1)->getLocStart(),
+ << SourceRange(TheCall->getArg(LastArg)->getLocStart(),
(*(TheCall->arg_end()-1))->getLocEnd());
- Expr *OrigArg = TheCall->getArg(0);
+ Expr *OrigArg = TheCall->getArg(LastArg-1);
if (OrigArg->isTypeDependent())
return false;
@@ -748,7 +754,7 @@ bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) {
if (!TheCall->getArg(0)->isIntegerConstantExpr(Result, Context))
return Diag(TheCall->getLocStart(), diag::err_expr_not_ice)
<< TheCall->getArg(0)->getSourceRange();
-
+
return false;
}
@@ -845,8 +851,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
}
if (isConstant) {
- const VarDecl *Def = 0;
- if (const Expr *Init = VD->getDefinition(Def))
+ if (const Expr *Init = VD->getAnyInitializer())
return SemaCheckStringLiteral(Init, TheCall,
HasVAListArg, format_idx, firstDataArg);
}
@@ -925,7 +930,7 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end();
i != e; ++i) {
const Expr *ArgExpr = TheCall->getArg(*i);
- if (ArgExpr->isNullPointerConstant(Context,
+ if (ArgExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull))
Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg)
<< ArgExpr->getSourceRange();
@@ -1032,248 +1037,309 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
<< OrigFormatExpr->getSourceRange();
}
-void Sema::CheckPrintfString(const StringLiteral *FExpr,
- const Expr *OrigFormatExpr,
- const CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg) {
-
- const ObjCStringLiteral *ObjCFExpr =
- dyn_cast<ObjCStringLiteral>(OrigFormatExpr);
-
- // CHECK: is the format string a wide literal?
- if (FExpr->isWide()) {
- Diag(FExpr->getLocStart(),
- diag::warn_printf_format_string_is_wide_literal)
- << OrigFormatExpr->getSourceRange();
- return;
- }
+namespace {
+class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
+ Sema &S;
+ const StringLiteral *FExpr;
+ const Expr *OrigFormatExpr;
+ unsigned NumConversions;
+ const unsigned NumDataArgs;
+ const bool IsObjCLiteral;
+ const char *Beg; // Start of format string.
+ const bool HasVAListArg;
+ const CallExpr *TheCall;
+ unsigned FormatIdx;
+public:
+ CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
+ : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
+ NumConversions(0), NumDataArgs(numDataArgs),
+ IsObjCLiteral(isObjCLiteral), Beg(beg),
+ HasVAListArg(hasVAListArg),
+ TheCall(theCall), FormatIdx(formatIdx) {}
+
+ void DoneProcessing();
+
+ void HandleIncompleteFormatSpecifier(const char *startSpecifier,
+ unsigned specifierLen);
+
+ void
+ HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ void HandleNullChar(const char *nullCharacter);
+
+ bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+private:
+ SourceRange getFormatStringRange();
+ SourceRange getFormatSpecifierRange(const char *startSpecifier,
+ unsigned specifierLen);
+ SourceLocation getLocationOfByte(const char *x);
+
+ bool HandleAmount(const analyze_printf::OptionalAmount &Amt,
+ unsigned MissingArgDiag, unsigned BadTypeDiag,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleFlags(const analyze_printf::FormatSpecifier &FS,
+ llvm::StringRef flag, llvm::StringRef cspec,
+ const char *startSpecifier, unsigned specifierLen);
+
+ const Expr *getDataArg(unsigned i) const;
+};
+}
- // Str - The format string. NOTE: this is NOT null-terminated!
- const char *Str = FExpr->getStrData();
+SourceRange CheckPrintfHandler::getFormatStringRange() {
+ return OrigFormatExpr->getSourceRange();
+}
- // CHECK: empty format string?
- unsigned StrLen = FExpr->getByteLength();
+SourceRange CheckPrintfHandler::
+getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
+ return SourceRange(getLocationOfByte(startSpecifier),
+ getLocationOfByte(startSpecifier+specifierLen-1));
+}
- if (StrLen == 0) {
- Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
- << OrigFormatExpr->getSourceRange();
- return;
- }
+SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) {
+ return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
+}
- // We process the format string using a binary state machine. The
- // current state is stored in CurrentState.
- enum {
- state_OrdChr,
- state_Conversion
- } CurrentState = state_OrdChr;
+void CheckPrintfHandler::
+HandleIncompleteFormatSpecifier(const char *startSpecifier,
+ unsigned specifierLen) {
+ SourceLocation Loc = getLocationOfByte(startSpecifier);
+ S.Diag(Loc, diag::warn_printf_incomplete_specifier)
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+}
- // numConversions - The number of conversions seen so far. This is
- // incremented as we traverse the format string.
- unsigned numConversions = 0;
+void CheckPrintfHandler::
+HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ ++NumConversions;
+ const analyze_printf::ConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+ SourceLocation Loc = getLocationOfByte(CS.getStart());
+ S.Diag(Loc, diag::warn_printf_invalid_conversion)
+ << llvm::StringRef(CS.getStart(), CS.getLength())
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+}
- // numDataArgs - The number of data arguments after the format
- // string. This can only be determined for non vprintf-like
- // functions. For those functions, this value is 1 (the sole
- // va_arg argument).
- unsigned numDataArgs = TheCall->getNumArgs()-firstDataArg;
+void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) {
+ // The presence of a null character is likely an error.
+ S.Diag(getLocationOfByte(nullCharacter),
+ diag::warn_printf_format_string_contains_null_char)
+ << getFormatStringRange();
+}
- // Inspect the format string.
- unsigned StrIdx = 0;
+const Expr *CheckPrintfHandler::getDataArg(unsigned i) const {
+ return TheCall->getArg(FormatIdx + i);
+}
- // LastConversionIdx - Index within the format string where we last saw
- // a '%' character that starts a new format conversion.
- unsigned LastConversionIdx = 0;
- for (; StrIdx < StrLen; ++StrIdx) {
- // Is the number of detected conversion conversions greater than
- // the number of matching data arguments? If so, stop.
- if (!HasVAListArg && numConversions > numDataArgs) break;
+void CheckPrintfHandler::HandleFlags(const analyze_printf::FormatSpecifier &FS,
+ llvm::StringRef flag,
+ llvm::StringRef cspec,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+ S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_nonsensical_flag)
+ << flag << cspec << getFormatSpecifierRange(startSpecifier, specifierLen);
+}
- // Handle "\0"
- if (Str[StrIdx] == '\0') {
- // The string returned by getStrData() is not null-terminated,
- // so the presence of a null character is likely an error.
- Diag(getLocationOfStringLiteralByte(FExpr, StrIdx),
- diag::warn_printf_format_string_contains_null_char)
- << OrigFormatExpr->getSourceRange();
- return;
- }
+bool
+CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
+ unsigned MissingArgDiag,
+ unsigned BadTypeDiag,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ if (Amt.hasDataArgument()) {
+ ++NumConversions;
+ if (!HasVAListArg) {
+ if (NumConversions > NumDataArgs) {
+ S.Diag(getLocationOfByte(Amt.getStart()), MissingArgDiag)
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+ // Don't do any more checking. We will just emit
+ // spurious errors.
+ return false;
+ }
- // Ordinary characters (not processing a format conversion).
- if (CurrentState == state_OrdChr) {
- if (Str[StrIdx] == '%') {
- CurrentState = state_Conversion;
- LastConversionIdx = StrIdx;
+ // Type check the data argument. It should be an 'int'.
+ // Although not in conformance with C99, we also allow the argument to be
+ // an 'unsigned int' as that is a reasonably safe case. GCC also
+ // doesn't emit a warning for that case.
+ const Expr *Arg = getDataArg(NumConversions);
+ QualType T = Arg->getType();
+
+ const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context);
+ assert(ATR.isValid());
+
+ if (!ATR.matchesType(S.Context, T)) {
+ S.Diag(getLocationOfByte(Amt.getStart()), BadTypeDiag)
+ << ATR.getRepresentativeType(S.Context) << T
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Arg->getSourceRange();
+ // Don't do any more checking. We will just emit
+ // spurious errors.
+ return false;
}
- continue;
}
+ }
+ return true;
+}
- // Seen '%'. Now processing a format conversion.
- switch (Str[StrIdx]) {
- // Handle dynamic precision or width specifier.
- case '*': {
- ++numConversions;
-
- if (!HasVAListArg) {
- if (numConversions > numDataArgs) {
- SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
-
- if (Str[StrIdx-1] == '.')
- Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg)
- << OrigFormatExpr->getSourceRange();
- else
- Diag(Loc, diag::warn_printf_asterisk_width_missing_arg)
- << OrigFormatExpr->getSourceRange();
-
- // Don't do any more checking. We'll just emit spurious errors.
- return;
- }
+bool
+CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
+ &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ using namespace analyze_printf;
+ const ConversionSpecifier &CS = FS.getConversionSpecifier();
+
+ // First check if the field width, precision, and conversion specifier
+ // have matching data arguments.
+ if (!HandleAmount(FS.getFieldWidth(),
+ diag::warn_printf_asterisk_width_missing_arg,
+ diag::warn_printf_asterisk_width_wrong_type,
+ startSpecifier, specifierLen)) {
+ return false;
+ }
- // Perform type checking on width/precision specifier.
- const Expr *E = TheCall->getArg(format_idx+numConversions);
- if (const BuiltinType *BT = E->getType()->getAs<BuiltinType>())
- if (BT->getKind() == BuiltinType::Int)
- break;
+ if (!HandleAmount(FS.getPrecision(),
+ diag::warn_printf_asterisk_precision_missing_arg,
+ diag::warn_printf_asterisk_precision_wrong_type,
+ startSpecifier, specifierLen)) {
+ return false;
+ }
- SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
+ // Check for using an Objective-C specific conversion specifier
+ // in a non-ObjC literal.
+ if (!IsObjCLiteral && CS.isObjCArg()) {
+ HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen);
- if (Str[StrIdx-1] == '.')
- Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type)
- << E->getType() << E->getSourceRange();
- else
- Diag(Loc, diag::warn_printf_asterisk_width_wrong_type)
- << E->getType() << E->getSourceRange();
+ // Continue checking the other format specifiers.
+ return true;
+ }
- break;
- }
- }
+ if (!CS.consumesDataArgument()) {
+ // FIXME: Technically specifying a precision or field width here
+ // makes no sense. Worth issuing a warning at some point.
+ return true;
+ }
- // Characters which can terminate a format conversion
- // (e.g. "%d"). Characters that specify length modifiers or
- // other flags are handled by the default case below.
- //
- // FIXME: additional checks will go into the following cases.
- case 'i':
- case 'd':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- case 'D':
- case 'O':
- case 'U':
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- case 'a':
- case 'A':
- case 'c':
- case 'C':
- case 'S':
- case 's':
- case 'p':
- ++numConversions;
- CurrentState = state_OrdChr;
- break;
+ ++NumConversions;
- case 'm':
- // FIXME: Warn in situations where this isn't supported!
- CurrentState = state_OrdChr;
- break;
+ // Are we using '%n'? Issue a warning about this being
+ // a possible security issue.
+ if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) {
+ S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back)
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+ // Continue checking the other format specifiers.
+ return true;
+ }
- // CHECK: Are we using "%n"? Issue a warning.
- case 'n': {
- ++numConversions;
- CurrentState = state_OrdChr;
- SourceLocation Loc = getLocationOfStringLiteralByte(FExpr,
- LastConversionIdx);
+ if (CS.getKind() == ConversionSpecifier::VoidPtrArg) {
+ if (FS.getPrecision().getHowSpecified() != OptionalAmount::NotSpecified)
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_nonsensical_precision)
+ << CS.getCharacters()
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+ }
+ if (CS.getKind() == ConversionSpecifier::VoidPtrArg ||
+ CS.getKind() == ConversionSpecifier::CStrArg) {
+ // FIXME: Instead of using "0", "+", etc., eventually get them from
+ // the FormatSpecifier.
+ if (FS.hasLeadingZeros())
+ HandleFlags(FS, "0", CS.getCharacters(), startSpecifier, specifierLen);
+ if (FS.hasPlusPrefix())
+ HandleFlags(FS, "+", CS.getCharacters(), startSpecifier, specifierLen);
+ if (FS.hasSpacePrefix())
+ HandleFlags(FS, " ", CS.getCharacters(), startSpecifier, specifierLen);
+ }
- Diag(Loc, diag::warn_printf_write_back)<<OrigFormatExpr->getSourceRange();
- break;
- }
+ // The remaining checks depend on the data arguments.
+ if (HasVAListArg)
+ return true;
- // Handle "%@"
- case '@':
- // %@ is allowed in ObjC format strings only.
- if (ObjCFExpr != NULL)
- CurrentState = state_OrdChr;
- else {
- // Issue a warning: invalid format conversion.
- SourceLocation Loc =
- getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
-
- Diag(Loc, diag::warn_printf_invalid_conversion)
- << std::string(Str+LastConversionIdx,
- Str+std::min(LastConversionIdx+2, StrLen))
- << OrigFormatExpr->getSourceRange();
- }
- ++numConversions;
- break;
+ if (NumConversions > NumDataArgs) {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_insufficient_data_args)
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+ // Don't do any more checking.
+ return false;
+ }
- // Handle "%%"
- case '%':
- // Sanity check: Was the first "%" character the previous one?
- // If not, we will assume that we have a malformed format
- // conversion, and that the current "%" character is the start
- // of a new conversion.
- if (StrIdx - LastConversionIdx == 1)
- CurrentState = state_OrdChr;
- else {
- // Issue a warning: invalid format conversion.
- SourceLocation Loc =
- getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
-
- Diag(Loc, diag::warn_printf_invalid_conversion)
- << std::string(Str+LastConversionIdx, Str+StrIdx)
- << OrigFormatExpr->getSourceRange();
-
- // This conversion is broken. Advance to the next format
- // conversion.
- LastConversionIdx = StrIdx;
- ++numConversions;
- }
- break;
+ // Now type check the data expression that matches the
+ // format specifier.
+ const Expr *Ex = getDataArg(NumConversions);
+ const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context);
+ if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
+ // Check if we didn't match because of an implicit cast from a 'char'
+ // or 'short' to an 'int'. This is done because printf is a varargs
+ // function.
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex))
+ if (ICE->getType() == S.Context.IntTy)
+ if (ATR.matchesType(S.Context, ICE->getSubExpr()->getType()))
+ return true;
- default:
- // This case catches all other characters: flags, widths, etc.
- // We should eventually process those as well.
- break;
- }
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
}
- if (CurrentState == state_Conversion) {
- // Issue a warning: invalid format conversion.
- SourceLocation Loc =
- getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
+ return true;
+}
- Diag(Loc, diag::warn_printf_invalid_conversion)
- << std::string(Str+LastConversionIdx,
- Str+std::min(LastConversionIdx+2, StrLen))
- << OrigFormatExpr->getSourceRange();
+void CheckPrintfHandler::DoneProcessing() {
+ // Does the number of data arguments exceed the number of
+ // format conversions in the format string?
+ if (!HasVAListArg && NumConversions < NumDataArgs)
+ S.Diag(getDataArg(NumConversions+1)->getLocStart(),
+ diag::warn_printf_too_many_data_args)
+ << getFormatStringRange();
+}
+
+void Sema::CheckPrintfString(const StringLiteral *FExpr,
+ const Expr *OrigFormatExpr,
+ const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg) {
+
+ // CHECK: is the format string a wide literal?
+ if (FExpr->isWide()) {
+ Diag(FExpr->getLocStart(),
+ diag::warn_printf_format_string_is_wide_literal)
+ << OrigFormatExpr->getSourceRange();
return;
}
- if (!HasVAListArg) {
- // CHECK: Does the number of format conversions exceed the number
- // of data arguments?
- if (numConversions > numDataArgs) {
- SourceLocation Loc =
- getLocationOfStringLiteralByte(FExpr, LastConversionIdx);
-
- Diag(Loc, diag::warn_printf_insufficient_data_args)
- << OrigFormatExpr->getSourceRange();
- }
- // CHECK: Does the number of data arguments exceed the number of
- // format conversions in the format string?
- else if (numConversions < numDataArgs)
- Diag(TheCall->getArg(format_idx+numConversions+1)->getLocStart(),
- diag::warn_printf_too_many_data_args)
- << OrigFormatExpr->getSourceRange();
+ // Str - The format string. NOTE: this is NOT null-terminated!
+ const char *Str = FExpr->getStrData();
+
+ // CHECK: empty format string?
+ unsigned StrLen = FExpr->getByteLength();
+
+ if (StrLen == 0) {
+ Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
+ << OrigFormatExpr->getSourceRange();
+ return;
}
+
+ CheckPrintfHandler H(*this, FExpr, OrigFormatExpr,
+ TheCall->getNumArgs() - firstDataArg,
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+ HasVAListArg, TheCall, format_idx);
+
+ if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen))
+ H.DoneProcessing();
}
//===--- CHECK: Return Address of Stack Variable --------------------------===//
@@ -1300,11 +1366,11 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
if (C->hasBlockDeclRefExprs())
Diag(C->getLocStart(), diag::err_ret_local_block)
<< C->getSourceRange();
-
+
if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp))
Diag(ALE->getLocStart(), diag::warn_ret_addr_label)
<< ALE->getSourceRange();
-
+
} else if (lhsType->isReferenceType()) {
// Perform checking for stack values returned by reference.
// Check for a reference to the stack
@@ -1780,7 +1846,7 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
if (BO->getLHS()->getType()->isPointerType())
return IntRange::forType(C, E->getType());
// fallthrough
-
+
default:
break;
}
@@ -2221,7 +2287,7 @@ void Sema::CheckUnreachable(AnalysisContext &AC) {
CFG *cfg = AC.getCFG();
if (cfg == 0)
return;
-
+
llvm::BitVector live(cfg->getNumBlockIDs());
// Mark all live things first.
count = MarkLive(&cfg->getEntry(), live);
@@ -2268,7 +2334,9 @@ void Sema::CheckUnreachable(AnalysisContext &AC) {
CFGBlock &b = **I;
if (!live[b.getBlockID()])
// Avoid excessive errors by marking everything reachable from here
- lines.push_back(ErrLoc(MarkLiveTop(&b, live, Context.getSourceManager()), SourceRange(), SourceRange()));
+ lines.push_back(ErrLoc(MarkLiveTop(&b, live,
+ Context.getSourceManager()),
+ SourceRange(), SourceRange()));
}
}
@@ -2418,17 +2486,19 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body,
// which this code would then warn about.
if (getDiagnostics().hasErrorOccurred())
return;
-
+
bool ReturnsVoid = false;
bool HasNoReturn = false;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // If the result type of the function is a dependent type, we don't know
- // whether it will be void or not, so don't
- if (FD->getResultType()->isDependentType())
+ // For function templates, class templates and member function templates
+ // we'll do the analysis at instantiation time.
+ if (FD->isDependentContext())
return;
+
if (FD->getResultType()->isVoidType())
ReturnsVoid = true;
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->hasAttr<NoReturnAttr>() ||
+ FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
HasNoReturn = true;
} else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (MD->getResultType()->isVoidType())
@@ -2552,6 +2622,24 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
!Param->isImplicit() &&
!getLangOptions().CPlusPlus)
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+
+ // C99 6.7.5.3p12:
+ // If the function declarator is not part of a definition of that
+ // function, parameters may have incomplete type and may use the [*]
+ // notation in their sequences of declarator specifiers to specify
+ // variable length array types.
+ QualType PType = Param->getOriginalType();
+ if (const ArrayType *AT = Context.getAsArrayType(PType)) {
+ if (AT->getSizeModifier() == ArrayType::Star) {
+ // FIXME: This diagnosic should point the the '[*]' if source-location
+ // information is added for it.
+ Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
+ }
+ }
+
+ if (getLangOptions().CPlusPlus)
+ if (const RecordType *RT = Param->getType()->getAs<RecordType>())
+ FinalizeVarWithDestructor(Param, RT);
}
return HasInvalidParm;
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index fcd419b..a862949 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2196,13 +2196,15 @@ void Sema::CodeCompleteCase(Scope *S) {
namespace {
struct IsBetterOverloadCandidate {
Sema &S;
+ SourceLocation Loc;
public:
- explicit IsBetterOverloadCandidate(Sema &S) : S(S) { }
+ explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
+ : S(S), Loc(Loc) { }
bool
operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
- return S.isBetterOverloadCandidate(X, Y);
+ return S.isBetterOverloadCandidate(X, Y, Loc);
}
};
}
@@ -2228,7 +2230,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
}
// Build an overload candidate set based on the functions we find.
- OverloadCandidateSet CandidateSet;
+ SourceLocation Loc = Fn->getExprLoc();
+ OverloadCandidateSet CandidateSet(Loc);
// FIXME: What if we're calling something that isn't a function declaration?
// FIXME: What if we're calling a pseudo-destructor?
@@ -2247,7 +2250,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
if (!FDecl->getType()->getAs<FunctionProtoType>())
Results.push_back(ResultCandidate(FDecl));
else
- AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet,
+ // FIXME: access?
+ AddOverloadCandidate(FDecl, AS_none, Args, NumArgs, CandidateSet,
false, false, /*PartialOverloading*/ true);
}
}
@@ -2255,7 +2259,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
if (!CandidateSet.empty()) {
// Sort the overload candidate set by placing the best overloads first.
std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
- IsBetterOverloadCandidate(*this));
+ IsBetterOverloadCandidate(*this, Loc));
// Add the remaining viable overload candidates as code-completion reslults.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
@@ -2977,7 +2981,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
- DefaultFunctionArrayConversion(RecExpr);
+ DefaultFunctionArrayLvalueConversion(RecExpr);
QualType ReceiverType = RecExpr->getType();
if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index fbe0289..1fc08ce 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -14,7 +14,7 @@
#include "Sema.h"
#include "SemaInit.h"
#include "Lookup.h"
-#include "clang/Analysis/PathSensitive/AnalysisContext.h"
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -135,6 +135,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
+ Result.suppressDiagnostics();
return 0;
case LookupResult::Ambiguous:
@@ -509,9 +510,18 @@ static void RemoveUsingDecls(LookupResult &R) {
}
static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
+ if (D->isInvalidDecl())
+ return false;
+
if (D->isUsed() || D->hasAttr<UnusedAttr>())
return false;
-
+
+ // White-list anything that isn't a local variable.
+ if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) ||
+ !D->getDeclContext()->isFunctionOrMethod())
+ return false;
+
+ // Types of valid local variables should be complete, so this should succeed.
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
@@ -523,9 +533,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
}
}
- return (isa<VarDecl>(D) && !isa<ParmVarDecl>(D) &&
- !isa<ImplicitParamDecl>(D) &&
- D->getDeclContext()->isFunctionOrMethod());
+ return true;
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
@@ -690,7 +698,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
FT->getArgType(i), /*TInfo=*/0,
VarDecl::None, 0));
- New->setParams(Context, Params.data(), Params.size());
+ New->setParams(Params.data(), Params.size());
}
AddKnownFunctionAttributes(New);
@@ -957,6 +965,44 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
return true;
}
+ // If a function is first declared with a calling convention, but is
+ // later declared or defined without one, the second decl assumes the
+ // calling convention of the first.
+ //
+ // For the new decl, we have to look at the NON-canonical type to tell the
+ // difference between a function that really doesn't have a calling
+ // convention and one that is declared cdecl. That's because in
+ // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
+ // because it is the default calling convention.
+ //
+ // Note also that we DO NOT return at this point, because we still have
+ // other tests to run.
+ const FunctionType *OldType = OldQType->getAs<FunctionType>();
+ const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+ if (OldType->getCallConv() != CC_Default &&
+ NewType->getCallConv() == CC_Default) {
+ NewQType = Context.getCallConvType(NewQType, OldType->getCallConv());
+ New->setType(NewQType);
+ NewQType = Context.getCanonicalType(NewQType);
+ } else if (!Context.isSameCallConv(OldType->getCallConv(),
+ NewType->getCallConv())) {
+ // Calling conventions really aren't compatible, so complain.
+ Diag(New->getLocation(), diag::err_cconv_change)
+ << FunctionType::getNameForCallConv(NewType->getCallConv())
+ << (OldType->getCallConv() == CC_Default)
+ << (OldType->getCallConv() == CC_Default ? "" :
+ FunctionType::getNameForCallConv(OldType->getCallConv()));
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ // FIXME: diagnose the other way around?
+ if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) {
+ NewQType = Context.getNoReturnType(NewQType);
+ New->setType(NewQType);
+ assert(NewQType.isCanonical());
+ }
+
if (getLangOptions().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
@@ -1061,7 +1107,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
Params.push_back(Param);
}
- New->setParams(Context, Params.data(), Params.size());
+ New->setParams(Params.data(), Params.size());
}
return MergeCompatibleFunctionDecls(New, Old);
@@ -1297,6 +1343,18 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
Diag(Old->getLocation(), diag::note_previous_definition);
}
+ // C++ doesn't have tentative definitions, so go right ahead and check here.
+ const VarDecl *Def;
+ if (getLangOptions().CPlusPlus &&
+ New->isThisDeclarationADefinition() == VarDecl::Definition &&
+ (Def = Old->getDefinition())) {
+ Diag(New->getLocation(), diag::err_redefinition)
+ << New->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return;
+ }
+
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
@@ -1855,6 +1913,13 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
if (!DC->isDependentContext() &&
RequireCompleteDeclContext(D.getCXXScopeSpec()))
return DeclPtrTy();
+
+ if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_member_def_undefined_record)
+ << Name << DC << D.getCXXScopeSpec().getRange();
+ D.setInvalidType();
+ }
LookupQualifiedName(Previous, DC);
@@ -2322,7 +2387,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getString()));
+ NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
}
// Don't consider existing declarations that are in a different
@@ -2359,9 +2424,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// attributes declared post-definition are currently ignored
if (Previous.isSingleResult()) {
- const VarDecl *Def = 0;
- VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl());
- if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) {
+ VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
+ if (Def && (Def = Def->getDefinition()) &&
+ Def != NewVD && D.hasAttributes()) {
Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
Diag(Def->getLocation(), diag::note_previous_definition);
}
@@ -2675,7 +2740,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// (The parser checks for a return type and makes the declarator a
// constructor if it has no return type).
// must have an invalid constructor that has a return type
- if (Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
+ if (Name.getAsIdentifierInfo() &&
+ Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){
Diag(D.getIdentifierLoc(), diag::err_constructor_return_type)
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
@@ -2783,6 +2849,28 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
+ // C++ [dcl.fct.spec]p6:
+ // The explicit specifier shall be used only in the declaration of a
+ // constructor or conversion function within its class definition; see 12.3.1
+ // and 12.3.2.
+ if (isExplicit && !NewFD->isInvalidDecl()) {
+ if (!CurContext->isRecord()) {
+ // 'explicit' was specified outside of the class.
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_out_of_class)
+ << CodeModificationHint::CreateRemoval(
+ D.getDeclSpec().getExplicitSpecLoc());
+ } else if (!isa<CXXConstructorDecl>(NewFD) &&
+ !isa<CXXConversionDecl>(NewFD)) {
+ // 'explicit' was specified on a function that wasn't a constructor
+ // or conversion function.
+ Diag(D.getDeclSpec().getExplicitSpecLoc(),
+ diag::err_explicit_non_ctor_or_conv_function)
+ << CodeModificationHint::CreateRemoval(
+ D.getDeclSpec().getExplicitSpecLoc());
+ }
+ }
+
// Filter out previous declarations that don't match the scope.
FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
@@ -2822,7 +2910,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getString()));
+ NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
}
// Copy the parameter declarations from the declarator D to the function
@@ -2882,7 +2970,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
"Should not need args for typedef of non-prototype fn");
}
// Finally, we know we have the right number of parameters, install them.
- NewFD->setParams(Context, Params.data(), Params.size());
+ NewFD->setParams(Params.data(), Params.size());
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
@@ -2950,7 +3038,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
// Fake up an access specifier if it's supposed to be a class member.
- if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+ if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext()))
NewFD->setAccess(AS_public);
// An out-of-line member function declaration must also be a
@@ -3041,6 +3129,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (FunctionTemplate)
return FunctionTemplate;
+
+ // Keep track of static, non-inlined function definitions that
+ // have not been used. We will warn later.
+ // FIXME: Also include static functions declared but not defined.
+ if (!NewFD->isInvalidDecl() && IsFunctionDefinition
+ && !NewFD->isInlined() && NewFD->getLinkage() == InternalLinkage
+ && !NewFD->isUsed())
+ UnusedStaticFuncs.push_back(NewFD);
+
return NewFD;
}
@@ -3412,8 +3509,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
AbstractVariableType))
VDecl->setInvalidDecl();
- const VarDecl *Def = 0;
- if (VDecl->getDefinition(Def)) {
+ const VarDecl *Def;
+ if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition)
<< VDecl->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition);
@@ -3473,7 +3570,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// };
// Attach the initializer
- VDecl->setInit(Context, Init);
+ VDecl->setInit(Init);
// C++ [class.mem]p4:
// A member-declarator can contain a constant-initializer only
@@ -3545,23 +3642,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Init = MaybeCreateCXXExprWithTemporaries(Init);
// Attach the initializer to the decl.
- VDecl->setInit(Context, Init);
-
- // If the previous declaration of VDecl was a tentative definition,
- // remove it from the set of tentative definitions.
- if (VDecl->getPreviousDeclaration() &&
- VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) {
- bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName());
- assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted;
- }
+ VDecl->setInit(Init);
if (getLangOptions().CPlusPlus) {
// Make sure we mark the destructor as used if necessary.
QualType InitType = VDecl->getType();
while (const ArrayType *Array = Context.getAsArrayType(InitType))
InitType = Context.getBaseElementType(Array);
- if (InitType->isRecordType())
- FinalizeVarWithDestructor(VDecl, InitType);
+ if (const RecordType *Record = InitType->getAs<RecordType>())
+ FinalizeVarWithDestructor(VDecl, Record);
}
return;
@@ -3578,136 +3667,140 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
QualType Type = Var->getType();
- // Record tentative definitions.
- if (Var->isTentativeDefinition(Context)) {
- std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool>
- InsertPair =
- TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var));
+ // C++0x [dcl.spec.auto]p3
+ if (TypeContainsUndeducedAuto) {
+ Diag(Var->getLocation(), diag::err_auto_var_requires_init)
+ << Var->getDeclName() << Type;
+ Var->setInvalidDecl();
+ return;
+ }
+
+ switch (Var->isThisDeclarationADefinition()) {
+ case VarDecl::Definition:
+ if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
+ break;
- // Keep the latest definition in the map. If we see 'int i; int i;' we
- // want the second one in the map.
- InsertPair.first->second = Var;
+ // We have an out-of-line definition of a static data member
+ // that has an in-class initializer, so we type-check this like
+ // a declaration.
+ //
+ // Fall through
+
+ case VarDecl::DeclarationOnly:
+ // It's only a declaration.
+
+ // Block scope. C99 6.7p7: If an identifier for an object is
+ // declared with no linkage (C99 6.2.2p6), the type for the
+ // object shall be complete.
+ if (!Type->isDependentType() && Var->isBlockVarDecl() &&
+ !Var->getLinkage() && !Var->isInvalidDecl() &&
+ RequireCompleteType(Var->getLocation(), Type,
+ diag::err_typecheck_decl_incomplete_type))
+ Var->setInvalidDecl();
- // However, for the list, we don't care about the order, just make sure
- // that there are no dupes for a given declaration name.
- if (InsertPair.second)
- TentativeDefinitionList.push_back(Var->getDeclName());
+ // Make sure that the type is not abstract.
+ if (!Type->isDependentType() && !Var->isInvalidDecl() &&
+ RequireNonAbstractType(Var->getLocation(), Type,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ Var->setInvalidDecl();
+ return;
+
+ case VarDecl::TentativeDefinition:
+ // File scope. C99 6.9.2p2: A declaration of an identifier for an
+ // object that has file scope without an initializer, and without a
+ // storage-class specifier or with the storage-class specifier "static",
+ // constitutes a tentative definition. Note: A tentative definition with
+ // external linkage is valid (C99 6.2.2p5).
+ if (!Var->isInvalidDecl()) {
+ if (const IncompleteArrayType *ArrayT
+ = Context.getAsIncompleteArrayType(Type)) {
+ if (RequireCompleteType(Var->getLocation(),
+ ArrayT->getElementType(),
+ diag::err_illegal_decl_array_incomplete_type))
+ Var->setInvalidDecl();
+ } else if (Var->getStorageClass() == VarDecl::Static) {
+ // C99 6.9.2p3: If the declaration of an identifier for an object is
+ // a tentative definition and has internal linkage (C99 6.2.2p3), the
+ // declared type shall not be an incomplete type.
+ // NOTE: code such as the following
+ // static struct s;
+ // struct s { int a; };
+ // is accepted by gcc. Hence here we issue a warning instead of
+ // an error and we do not invalidate the static declaration.
+ // NOTE: to avoid multiple warnings, only check the first declaration.
+ if (Var->getPreviousDeclaration() == 0)
+ RequireCompleteType(Var->getLocation(), Type,
+ diag::ext_typecheck_decl_incomplete_type);
+ }
+ }
+
+ // Record the tentative definition; we're done.
+ if (!Var->isInvalidDecl())
+ TentativeDefinitions.push_back(Var);
+ return;
}
- // C++ [dcl.init.ref]p3:
- // The initializer can be omitted for a reference only in a
- // parameter declaration (8.3.5), in the declaration of a
- // function return type, in the declaration of a class member
- // within its class declaration (9.2), and where the extern
- // specifier is explicitly used.
- if (Type->isReferenceType() && !Var->hasExternalStorage()) {
- Diag(Var->getLocation(), diag::err_reference_var_requires_init)
- << Var->getDeclName()
- << SourceRange(Var->getLocation(), Var->getLocation());
+ // Provide a specific diagnostic for uninitialized variable
+ // definitions with incomplete array type.
+ if (Type->isIncompleteArrayType()) {
+ Diag(Var->getLocation(),
+ diag::err_typecheck_incomplete_array_needs_initializer);
Var->setInvalidDecl();
return;
}
- // C++0x [dcl.spec.auto]p3
- if (TypeContainsUndeducedAuto) {
- Diag(Var->getLocation(), diag::err_auto_var_requires_init)
- << Var->getDeclName() << Type;
+ // Provide a specific diagnostic for uninitialized variable
+ // definitions with reference type.
+ if (Type->isReferenceType()) {
+ Diag(Var->getLocation(), diag::err_reference_var_requires_init)
+ << Var->getDeclName()
+ << SourceRange(Var->getLocation(), Var->getLocation());
+ Var->setInvalidDecl();
+ return;
+ }
+
+ // Do not attempt to type-check the default initializer for a
+ // variable with dependent type.
+ if (Type->isDependentType())
+ return;
+
+ if (Var->isInvalidDecl())
+ return;
+
+ if (RequireCompleteType(Var->getLocation(),
+ Context.getBaseElementType(Type),
+ diag::err_typecheck_decl_incomplete_type)) {
Var->setInvalidDecl();
return;
}
- // An array without size is an incomplete type, and there are no special
- // rules in C++ to make such a definition acceptable.
- if (getLangOptions().CPlusPlus && Type->isIncompleteArrayType() &&
- !Var->hasExternalStorage()) {
- Diag(Var->getLocation(),
- diag::err_typecheck_incomplete_array_needs_initializer);
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(Var->getLocation(), Type,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType)) {
Var->setInvalidDecl();
return;
}
- // C++ [temp.expl.spec]p15:
- // An explicit specialization of a static data member of a template is a
- // definition if the declaration includes an initializer; otherwise, it
- // is a declaration.
- if (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember() &&
- Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
- return;
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+ InitializationKind Kind
+ = InitializationKind::CreateDefault(Var->getLocation());
- // C++ [dcl.init]p9:
- // If no initializer is specified for an object, and the object
- // is of (possibly cv-qualified) non-POD class type (or array
- // thereof), the object shall be default-initialized; if the
- // object is of const-qualified type, the underlying class type
- // shall have a user-declared default constructor.
- //
- // FIXME: Diagnose the "user-declared default constructor" bit.
- if (getLangOptions().CPlusPlus) {
- QualType InitType = Type;
- if (const ArrayType *Array = Context.getAsArrayType(Type))
- InitType = Context.getBaseElementType(Array);
- if ((!Var->hasExternalStorage() && !Var->isExternC()) &&
- InitType->isRecordType() && !InitType->isDependentType()) {
- if (!RequireCompleteType(Var->getLocation(), InitType,
- diag::err_invalid_incomplete_type_use)) {
- InitializedEntity Entity
- = InitializedEntity::InitializeVariable(Var);
- InitializationKind Kind
- = InitializationKind::CreateDefault(Var->getLocation());
-
- InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
- OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, 0, 0));
- if (Init.isInvalid())
- Var->setInvalidDecl();
- else {
- Var->setInit(Context,
- MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
- FinalizeVarWithDestructor(Var, InitType);
- }
- } else {
- Var->setInvalidDecl();
- }
- }
+ InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+ OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, 0, 0));
+ if (Init.isInvalid())
+ Var->setInvalidDecl();
+ else {
+ if (Init.get())
+ Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
- // The variable can not have an abstract class type.
- if (RequireNonAbstractType(Var->getLocation(), Type,
- diag::err_abstract_type_in_decl,
- AbstractVariableType))
- Var->setInvalidDecl();
+ if (getLangOptions().CPlusPlus)
+ if (const RecordType *Record
+ = Context.getBaseElementType(Type)->getAs<RecordType>())
+ FinalizeVarWithDestructor(Var, Record);
}
-
-#if 0
- // FIXME: Temporarily disabled because we are not properly parsing
- // linkage specifications on declarations, e.g.,
- //
- // extern "C" const CGPoint CGPointerZero;
- //
- // C++ [dcl.init]p9:
- //
- // If no initializer is specified for an object, and the
- // object is of (possibly cv-qualified) non-POD class type (or
- // array thereof), the object shall be default-initialized; if
- // the object is of const-qualified type, the underlying class
- // type shall have a user-declared default
- // constructor. Otherwise, if no initializer is specified for
- // an object, the object and its subobjects, if any, have an
- // indeterminate initial value; if the object or any of its
- // subobjects are of const-qualified type, the program is
- // ill-formed.
- //
- // This isn't technically an error in C, so we don't diagnose it.
- //
- // FIXME: Actually perform the POD/user-defined default
- // constructor check.
- if (getLangOptions().CPlusPlus &&
- Context.getCanonicalType(Type).isConstQualified() &&
- !Var->hasExternalStorage())
- Diag(Var->getLocation(), diag::err_const_var_requires_init)
- << Var->getName()
- << SourceRange(Var->getLocation(), Var->getLocation());
-#endif
}
}
@@ -3723,77 +3816,6 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (Decl *D = Group[i].getAs<Decl>())
Decls.push_back(D);
- // Perform semantic analysis that depends on having fully processed both
- // the declarator and initializer.
- for (unsigned i = 0, e = Decls.size(); i != e; ++i) {
- VarDecl *IDecl = dyn_cast<VarDecl>(Decls[i]);
- if (!IDecl)
- continue;
- QualType T = IDecl->getType();
-
- // Block scope. C99 6.7p7: If an identifier for an object is declared with
- // no linkage (C99 6.2.2p6), the type for the object shall be complete...
- if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) {
- if (T->isDependentType()) {
- // If T is dependent, we should not require a complete type.
- // (RequireCompleteType shouldn't be called with dependent types.)
- // But we still can at least check if we've got an array of unspecified
- // size without an initializer.
- if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() &&
- !IDecl->getInit()) {
- Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)
- << T;
- IDecl->setInvalidDecl();
- }
- } else if (!IDecl->isInvalidDecl()) {
- // If T is an incomplete array type with an initializer list that is
- // dependent on something, its size has not been fixed. We could attempt
- // to fix the size for such arrays, but we would still have to check
- // here for initializers containing a C++0x vararg expansion, e.g.
- // template <typename... Args> void f(Args... args) {
- // int vals[] = { args };
- // }
- const IncompleteArrayType *IAT = Context.getAsIncompleteArrayType(T);
- Expr *Init = IDecl->getInit();
- if (IAT && Init &&
- (Init->isTypeDependent() || Init->isValueDependent())) {
- // Check that the member type of the array is complete, at least.
- if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(),
- diag::err_typecheck_decl_incomplete_type))
- IDecl->setInvalidDecl();
- } else if (RequireCompleteType(IDecl->getLocation(), T,
- diag::err_typecheck_decl_incomplete_type))
- IDecl->setInvalidDecl();
- }
- }
- // File scope. C99 6.9.2p2: A declaration of an identifier for an
- // object that has file scope without an initializer, and without a
- // storage-class specifier or with the storage-class specifier "static",
- // constitutes a tentative definition. Note: A tentative definition with
- // external linkage is valid (C99 6.2.2p5).
- if (IDecl->isTentativeDefinition(Context) && !IDecl->isInvalidDecl()) {
- if (const IncompleteArrayType *ArrayT
- = Context.getAsIncompleteArrayType(T)) {
- if (RequireCompleteType(IDecl->getLocation(),
- ArrayT->getElementType(),
- diag::err_illegal_decl_array_incomplete_type))
- IDecl->setInvalidDecl();
- } else if (IDecl->getStorageClass() == VarDecl::Static) {
- // C99 6.9.2p3: If the declaration of an identifier for an object is
- // a tentative definition and has internal linkage (C99 6.2.2p3), the
- // declared type shall not be an incomplete type.
- // NOTE: code such as the following
- // static struct s;
- // struct s { int a; };
- // is accepted by gcc. Hence here we issue a warning instead of
- // an error and we do not invalidate the static declaration.
- // NOTE: to avoid multiple warnings, only check the first declaration.
- if (IDecl->getPreviousDeclaration() == 0)
- RequireCompleteType(IDecl->getLocation(), T,
- diag::ext_typecheck_decl_incomplete_type);
- }
- }
- }
return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
Decls.data(), Decls.size()));
}
@@ -3853,6 +3875,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// Recover by removing the name
II = 0;
D.SetIdentifier(0, D.getIdentifierLoc());
+ D.setInvalidType(true);
}
}
}
@@ -3919,6 +3942,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
return DeclPtrTy::make(New);
}
+void Sema::ActOnObjCCatchParam(DeclPtrTy D) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(D.getAs<Decl>());
+ Param->setDeclContext(CurContext);
+}
+
void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls) {
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
@@ -4297,8 +4325,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1,
- HasVAListArg ? 0 : FormatIdx + 2));
+ FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1,
+ HasVAListArg ? 0 : FormatIdx+2));
}
// Mark const if we don't care about errno and that is the only
@@ -4311,7 +4339,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
}
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
- FD->addAttr(::new (Context) NoReturnAttr());
+ FD->setType(Context.getNoReturnType(FD->getType()));
if (Context.BuiltinInfo.isNoThrow(BuiltinID))
FD->addAttr(::new (Context) NoThrowAttr());
if (Context.BuiltinInfo.isConst(BuiltinID))
@@ -4335,15 +4363,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// FIXME: NSLog and NSLogv should be target specific
if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) {
// FIXME: We known better than our headers.
- const_cast<FormatAttr *>(Format)->setType("printf");
+ const_cast<FormatAttr *>(Format)->setType(Context, "printf");
} else
- FD->addAttr(::new (Context) FormatAttr("printf", 1,
+ FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1,
Name->isStr("NSLogv") ? 0 : 2));
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
// target-specific builtins, perhaps?
if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr("printf", 2,
+ FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2,
Name->isStr("vasprintf") ? 0 : 3));
}
}
@@ -4614,7 +4642,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Diagnose attempts to redefine a tag.
if (TUK == TUK_Definition) {
- if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
+ if (TagDecl *Def = PrevTagDecl->getDefinition()) {
// If we're defining a specialization and the previous definition
// is from an implicit instantiation, don't emit an error
// here; we'll catch this in the general case below.
@@ -4927,9 +4955,17 @@ RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record,
if (Record->isDependentContext() || !Record->isDefinition())
return;
- if (Record->isDynamicClass() && !S.Context.getKeyFunction(Record))
- S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, Loc));
+ if (Record->isDynamicClass()) {
+ const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record);
+ if (!KeyFunction)
+ S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record,
+ Loc));
+
+ if ((!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined()))
+ && Record->getLinkage() == ExternalLinkage)
+ S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record;
+ }
for (DeclContext::decl_iterator D = Record->decls_begin(),
DEnd = Record->decls_end();
D != DEnd; ++D) {
@@ -5156,7 +5192,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
NewFD->setInvalidDecl();
}
- if (getLangOptions().CPlusPlus) {
+ if (!InvalidDecl && getLangOptions().CPlusPlus) {
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
if (!T->isPODType())
@@ -5584,7 +5620,7 @@ void Sema::ActOnFields(Scope* S,
// Okay, we successfully defined 'Record'.
if (Record) {
- Record->completeDefinition(Context);
+ Record->completeDefinition();
} else {
ObjCIvarDecl **ClsFields =
reinterpret_cast<ObjCIvarDecl**>(RecFields.data());
@@ -5628,6 +5664,45 @@ void Sema::ActOnFields(Scope* S,
ProcessDeclAttributeList(S, Record, Attr);
}
+/// \brief Determine whether the given integral value is representable within
+/// the given type T.
+static bool isRepresentableIntegerValue(ASTContext &Context,
+ llvm::APSInt &Value,
+ QualType T) {
+ assert(T->isIntegralType() && "Integral type required!");
+ unsigned BitWidth = Context.getTypeSize(T);
+
+ if (Value.isUnsigned() || Value.isNonNegative())
+ return Value.getActiveBits() < BitWidth;
+
+ return Value.getMinSignedBits() <= BitWidth;
+}
+
+// \brief Given an integral type, return the next larger integral type
+// (or a NULL type of no such type exists).
+static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) {
+ // FIXME: Int128/UInt128 support, which also needs to be introduced into
+ // enum checking below.
+ assert(T->isIntegralType() && "Integral type required!");
+ const unsigned NumTypes = 4;
+ QualType SignedIntegralTypes[NumTypes] = {
+ Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
+ };
+ QualType UnsignedIntegralTypes[NumTypes] = {
+ Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy,
+ Context.UnsignedLongLongTy
+ };
+
+ unsigned BitWidth = Context.getTypeSize(T);
+ QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes
+ : UnsignedIntegralTypes;
+ for (unsigned I = 0; I != NumTypes; ++I)
+ if (Context.getTypeSize(Types[I]) > BitWidth)
+ return Types[I];
+
+ return QualType();
+}
+
EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EnumConstantDecl *LastEnumConst,
SourceLocation IdLoc,
@@ -5635,24 +5710,45 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
ExprArg val) {
Expr *Val = (Expr *)val.get();
- llvm::APSInt EnumVal(32);
+ unsigned IntWidth = Context.Target.getIntWidth();
+ llvm::APSInt EnumVal(IntWidth);
QualType EltTy;
if (Val) {
if (Enum->isDependentType())
EltTy = Context.DependentTy;
else {
- // Make sure to promote the operand type to int.
- UsualUnaryConversions(Val);
- if (Val != val.get()) {
- val.release();
- val = Val;
- }
-
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
SourceLocation ExpLoc;
if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
Val = 0;
- } else {
+ } else {
+ if (!getLangOptions().CPlusPlus) {
+ // C99 6.7.2.2p2:
+ // The expression that defines the value of an enumeration constant
+ // shall be an integer constant expression that has a value
+ // representable as an int.
+
+ // Complain if the value is not representable in an int.
+ if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
+ Diag(IdLoc, diag::ext_enum_value_not_int)
+ << EnumVal.toString(10) << Val->getSourceRange()
+ << EnumVal.isNonNegative();
+ else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
+ // Force the type of the expression to 'int'.
+ ImpCastExprToType(Val, Context.IntTy, CastExpr::CK_IntegralCast);
+
+ if (Val != val.get()) {
+ val.release();
+ val = Val;
+ }
+ }
+ }
+
+ // C++0x [dcl.enum]p5:
+ // If the underlying type is not fixed, the type of each enumerator
+ // is the type of its initializing value:
+ // - If an initializer is specified for an enumerator, the
+ // initializing value has the same type as the expression.
EltTy = Val->getType();
}
}
@@ -5661,25 +5757,76 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (!Val) {
if (Enum->isDependentType())
EltTy = Context.DependentTy;
- else if (LastEnumConst) {
+ else if (!LastEnumConst) {
+ // C++0x [dcl.enum]p5:
+ // If the underlying type is not fixed, the type of each enumerator
+ // is the type of its initializing value:
+ // - If no initializer is specified for the first enumerator, the
+ // initializing value has an unspecified integral type.
+ //
+ // GCC uses 'int' for its unspecified integral type, as does
+ // C99 6.7.2.2p3.
+ EltTy = Context.IntTy;
+ } else {
// Assign the last value + 1.
EnumVal = LastEnumConst->getInitVal();
++EnumVal;
+ EltTy = LastEnumConst->getType();
// Check for overflow on increment.
- if (EnumVal < LastEnumConst->getInitVal())
- Diag(IdLoc, diag::warn_enum_value_overflow);
-
- EltTy = LastEnumConst->getType();
- } else {
- // First value, set to zero.
- EltTy = Context.IntTy;
- EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
- EnumVal.setIsSigned(true);
+ if (EnumVal < LastEnumConst->getInitVal()) {
+ // C++0x [dcl.enum]p5:
+ // If the underlying type is not fixed, the type of each enumerator
+ // is the type of its initializing value:
+ //
+ // - Otherwise the type of the initializing value is the same as
+ // the type of the initializing value of the preceding enumerator
+ // unless the incremented value is not representable in that type,
+ // in which case the type is an unspecified integral type
+ // sufficient to contain the incremented value. If no such type
+ // exists, the program is ill-formed.
+ QualType T = getNextLargerIntegralType(Context, EltTy);
+ if (T.isNull()) {
+ // There is no integral type larger enough to represent this
+ // value. Complain, then allow the value to wrap around.
+ EnumVal = LastEnumConst->getInitVal();
+ EnumVal.zext(EnumVal.getBitWidth() * 2);
+ Diag(IdLoc, diag::warn_enumerator_too_large)
+ << EnumVal.toString(10);
+ } else {
+ EltTy = T;
+ }
+
+ // Retrieve the last enumerator's value, extent that type to the
+ // type that is supposed to be large enough to represent the incremented
+ // value, then increment.
+ EnumVal = LastEnumConst->getInitVal();
+ EnumVal.setIsSigned(EltTy->isSignedIntegerType());
+ EnumVal.zextOrTrunc(Context.getTypeSize(EltTy));
+ ++EnumVal;
+
+ // If we're not in C++, diagnose the overflow of enumerator values,
+ // which in C99 means that the enumerator value is not representable in
+ // an int (C99 6.7.2.2p2). However, we support GCC's extension that
+ // permits enumerator values that are representable in some larger
+ // integral type.
+ if (!getLangOptions().CPlusPlus && !T.isNull())
+ Diag(IdLoc, diag::warn_enum_value_overflow);
+ } else if (!getLangOptions().CPlusPlus &&
+ !isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
+ // Enforce C99 6.7.2.2p2 even when we compute the next value.
+ Diag(IdLoc, diag::ext_enum_value_not_int)
+ << EnumVal.toString(10) << 1;
+ }
}
}
- assert(!EltTy.isNull() && "Enum constant with NULL type");
+ if (!Enum->isDependentType()) {
+ // Make the enumerator value match the signedness and size of the
+ // enumerator's type.
+ EnumVal.zextOrTrunc(Context.getTypeSize(EltTy));
+ EnumVal.setIsSigned(EltTy->isSignedIntegerType());
+ }
val.release();
return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
@@ -5759,7 +5906,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setType(EnumType);
}
- Enum->completeDefinition(Context, Context.DependentTy, Context.DependentTy);
+ Enum->completeDefinition(Context.DependentTy, Context.DependentTy);
return;
}
@@ -5783,18 +5930,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
if (!ECD) continue; // Already issued a diagnostic.
- // If the enum value doesn't fit in an int, emit an extension warning.
const llvm::APSInt &InitVal = ECD->getInitVal();
- assert(InitVal.getBitWidth() >= IntWidth &&
- "Should have promoted value to int");
- if (!getLangOptions().CPlusPlus && InitVal.getBitWidth() > IntWidth) {
- llvm::APSInt V(InitVal);
- V.trunc(IntWidth);
- V.extend(InitVal.getBitWidth());
- if (V != InitVal)
- Diag(ECD->getLocation(), diag::ext_enum_value_not_int)
- << InitVal.toString(10);
- }
// Keep track of the size of positive and negative values.
if (InitVal.isUnsigned() || InitVal.isNonNegative())
@@ -5856,8 +5992,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
}
BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
} else {
- // If there is no negative value, figure out which of uint, ulong, ulonglong
- // fits.
+ // If there is no negative value, figure out the smallest type that fits
+ // all of the enumerator values.
// If it's packed, check also if it fits a char or a short.
if (Packed && NumPositiveBits <= CharWidth) {
BestType = Context.UnsignedCharTy;
@@ -5870,30 +6006,26 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
} else if (NumPositiveBits <= IntWidth) {
BestType = Context.UnsignedIntTy;
BestWidth = IntWidth;
- BestPromotionType = (NumPositiveBits == BestWidth
- ? Context.UnsignedIntTy : Context.IntTy);
+ BestPromotionType
+ = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+ ? Context.UnsignedIntTy : Context.IntTy;
} else if (NumPositiveBits <=
(BestWidth = Context.Target.getLongWidth())) {
BestType = Context.UnsignedLongTy;
- BestPromotionType = (NumPositiveBits == BestWidth
- ? Context.UnsignedLongTy : Context.LongTy);
+ BestPromotionType
+ = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+ ? Context.UnsignedLongTy : Context.LongTy;
} else {
BestWidth = Context.Target.getLongLongWidth();
assert(NumPositiveBits <= BestWidth &&
"How could an initializer get larger than ULL?");
BestType = Context.UnsignedLongLongTy;
- BestPromotionType = (NumPositiveBits == BestWidth
- ? Context.UnsignedLongLongTy : Context.LongLongTy);
+ BestPromotionType
+ = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus)
+ ? Context.UnsignedLongLongTy : Context.LongLongTy;
}
}
- // If we're in C and the promotion type is larger than an int, just
- // use the underlying type, which is generally the unsigned integer
- // type of the same rank as the promotion type. This is how the gcc
- // extension works.
- if (!getLangOptions().CPlusPlus && BestPromotionType != Context.IntTy)
- BestPromotionType = BestType;
-
// Loop over all of the enumerator constants, changing their types to match
// the type of the enum if needed.
for (unsigned i = 0; i != NumElements; ++i) {
@@ -5906,23 +6038,17 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// enumerator value fits in an int, type it as an int, otherwise type it the
// same as the enumerator decl itself. This means that in "enum { X = 1U }"
// that X has type 'int', not 'unsigned'.
- if (!getLangOptions().CPlusPlus && ECD->getType() == Context.IntTy)
- continue;
// Determine whether the value fits into an int.
llvm::APSInt InitVal = ECD->getInitVal();
- bool FitsInInt;
- if (InitVal.isUnsigned() || !InitVal.isNegative())
- FitsInInt = InitVal.getActiveBits() < IntWidth;
- else
- FitsInInt = InitVal.getMinSignedBits() <= IntWidth;
// If it fits into an integer type, force it. Otherwise force it to match
// the enum decl type.
QualType NewTy;
unsigned NewWidth;
bool NewSign;
- if (FitsInInt && !getLangOptions().CPlusPlus) {
+ if (!getLangOptions().CPlusPlus &&
+ isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) {
NewTy = Context.IntTy;
NewWidth = IntWidth;
NewSign = true;
@@ -5960,7 +6086,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
ECD->setType(NewTy);
}
- Enum->completeDefinition(Context, BestType, BestPromotionType);
+ Enum->completeDefinition(BestType, BestPromotionType);
}
Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1a12208..cba1e9e 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -307,7 +307,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned* start = &NonNullArgs[0];
unsigned size = NonNullArgs.size();
std::sort(start, start + size);
- d->addAttr(::new (S.Context) NonNullAttr(start, size));
+ d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size));
}
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -329,7 +329,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: check if target symbol exists in current file
- d->addAttr(::new (S.Context) AliasAttr(Str->getString()));
+ d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString()));
}
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
@@ -391,6 +391,11 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
}
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ // Don't apply as a decl attribute to ValueDecl.
+ // FIXME: probably ought to diagnose this.
+ if (isa<ValueDecl>(d))
+ return;
+
if (HandleCommonNoReturnAttr(d, Attr, S))
d->addAttr(::new (S.Context) NoReturnAttr());
}
@@ -404,7 +409,7 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
- << Attr.getName() << 8; /*function, method, or parameter*/
+ << Attr.getName() << 8 /*function, method, or parameter*/;
return;
}
// FIXME: Actually store the attribute on the declaration
@@ -542,17 +547,16 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- const char *TypeStr = Str->getStrData();
- unsigned TypeLen = Str->getByteLength();
+ llvm::StringRef TypeStr = Str->getString();
VisibilityAttr::VisibilityTypes type;
- if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
+ if (TypeStr == "default")
type = VisibilityAttr::DefaultVisibility;
- else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
+ else if (TypeStr == "hidden")
type = VisibilityAttr::HiddenVisibility;
- else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
+ else if (TypeStr == "internal")
type = VisibilityAttr::HiddenVisibility; // FIXME
- else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
+ else if (TypeStr == "protected")
type = VisibilityAttr::ProtectedVisibility;
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
@@ -938,105 +942,9 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) SectionAttr(SE->getString()));
-}
-
-static void HandleCDeclAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // Attribute has no arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
- // Attribute can be applied only to functions.
- if (!isa<FunctionDecl>(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return;
- }
-
- // cdecl and fastcall attributes are mutually incompatible.
- if (d->getAttr<FastCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "cdecl" << "fastcall";
- return;
- }
-
- // cdecl and stdcall attributes are mutually incompatible.
- if (d->getAttr<StdCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "cdecl" << "stdcall";
- return;
- }
-
- d->addAttr(::new (S.Context) CDeclAttr());
-}
-
-
-static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // Attribute has no arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
- // Attribute can be applied only to functions.
- if (!isa<FunctionDecl>(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return;
- }
-
- // stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<FastCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "stdcall" << "fastcall";
- return;
- }
-
- d->addAttr(::new (S.Context) StdCallAttr());
-}
-
-/// Diagnose the use of a non-standard calling convention on the given
-/// function.
-static void DiagnoseCConv(FunctionDecl *D, const char *CConv,
- SourceLocation Loc, Sema &S) {
- if (!D->hasPrototype()) {
- S.Diag(Loc, diag::err_cconv_knr) << CConv;
- return;
- }
-
- const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>();
- if (T->isVariadic()) {
- S.Diag(Loc, diag::err_cconv_varargs) << CConv;
- return;
- }
+ D->addAttr(::new (S.Context) SectionAttr(S.Context, SE->getString()));
}
-static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // Attribute has no arguments.
- if (Attr.getNumArgs() != 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return;
- }
-
- if (!isa<FunctionDecl>(d)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return;
- }
-
- DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S);
-
- // stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<StdCallAttr>()) {
- S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
- << "fastcall" << "stdcall";
- return;
- }
-
- d->addAttr(::new (S.Context) FastCallAttr());
-}
static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
@@ -1349,7 +1257,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(),
+ d->addAttr(::new (S.Context) FormatAttr(S.Context, Format, Idx.getZExtValue(),
FirstArg.getZExtValue()));
}
@@ -1435,7 +1343,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
return;
}
- d->addAttr(::new (S.Context) AnnotateAttr(SE->getString()));
+ d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString()));
}
static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1608,9 +1516,15 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (!IntegerMode)
NewTy = S.Context.DoubleTy;
else if (OldTy->isSignedIntegerType())
- NewTy = S.Context.LongLongTy;
+ if (S.Context.Target.getLongWidth() == 64)
+ NewTy = S.Context.LongTy;
+ else
+ NewTy = S.Context.LongLongTy;
else
- NewTy = S.Context.UnsignedLongLongTy;
+ if (S.Context.Target.getLongWidth() == 64)
+ NewTy = S.Context.UnsignedLongTy;
+ else
+ NewTy = S.Context.UnsignedLongLongTy;
break;
case 96:
NewTy = S.Context.LongDoubleTy;
@@ -1903,7 +1817,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_base_check: HandleBaseCheckAttr (D, Attr, S); break;
case AttributeList::AT_carries_dependency:
HandleDependencyAttr (D, Attr, S); break;
- case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break;
case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
@@ -1912,7 +1825,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_ext_vector_type:
HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
- case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break;
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
@@ -1935,7 +1847,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
- case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break;
case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break;
@@ -1964,6 +1875,11 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_no_instrument_function: // Interacts with -pg.
// Just ignore
break;
+ case AttributeList::AT_stdcall:
+ case AttributeList::AT_cdecl:
+ case AttributeList::AT_fastcall:
+ // These are all treated as type attributes.
+ break;
default:
// Ask target about the attribute.
const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
@@ -2008,7 +1924,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
IdentifierInfo *NDId = ND->getIdentifier();
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
- NewD->addAttr(::new (Context) AliasAttr(NDId->getName()));
+ NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName()));
NewD->addAttr(::new (Context) WeakAttr());
WeakTopLevelDecl.push_back(NewD);
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
@@ -2062,48 +1978,71 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
/// on the warning stack.
Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
ParsingDeclDepth++;
- return (ParsingDeclStackState) DelayedDeprecationWarnings.size();
-}
-
-static bool isDeclDeprecated(Decl *D) {
- do {
- if (D->hasAttr<DeprecatedAttr>())
- return true;
- } while ((D = cast_or_null<Decl>(D->getDeclContext())));
- return false;
+ return (ParsingDeclStackState) DelayedDiagnostics.size();
}
void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
ParsingDeclDepth--;
- if (DelayedDeprecationWarnings.empty())
+ if (DelayedDiagnostics.empty())
return;
unsigned SavedIndex = (unsigned) S;
- assert(SavedIndex <= DelayedDeprecationWarnings.size() &&
+ assert(SavedIndex <= DelayedDiagnostics.size() &&
"saved index is out of bounds");
- if (Ctx && !isDeclDeprecated(Ctx.getAs<Decl>())) {
- for (unsigned I = 0, E = DelayedDeprecationWarnings.size(); I != E; ++I) {
- SourceLocation Loc = DelayedDeprecationWarnings[I].first;
- NamedDecl *&ND = DelayedDeprecationWarnings[I].second;
- if (ND) {
- Diag(Loc, diag::warn_deprecated) << ND->getDeclName();
-
- // Prevent this from triggering multiple times.
- ND = 0;
+ // We only want to actually emit delayed diagnostics when we
+ // successfully parsed a decl.
+ Decl *D = Ctx ? Ctx.getAs<Decl>() : 0;
+ if (D) {
+ // We really do want to start with 0 here. We get one push for a
+ // decl spec and another for each declarator; in a decl group like:
+ // deprecated_typedef foo, *bar, baz();
+ // only the declarator pops will be passed decls. This is correct;
+ // we really do need to consider delayed diagnostics from the decl spec
+ // for each of the different declarations.
+ for (unsigned I = 0, E = DelayedDiagnostics.size(); I != E; ++I) {
+ if (DelayedDiagnostics[I].Triggered)
+ continue;
+
+ switch (DelayedDiagnostics[I].Kind) {
+ case DelayedDiagnostic::Deprecation:
+ HandleDelayedDeprecationCheck(DelayedDiagnostics[I], D);
+ break;
+
+ case DelayedDiagnostic::Access:
+ HandleDelayedAccessCheck(DelayedDiagnostics[I], D);
+ break;
}
}
}
- DelayedDeprecationWarnings.set_size(SavedIndex);
+ DelayedDiagnostics.set_size(SavedIndex);
+}
+
+static bool isDeclDeprecated(Decl *D) {
+ do {
+ if (D->hasAttr<DeprecatedAttr>())
+ return true;
+ } while ((D = cast_or_null<Decl>(D->getDeclContext())));
+ return false;
+}
+
+void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD,
+ Decl *Ctx) {
+ if (isDeclDeprecated(Ctx))
+ return;
+
+ DD.Triggered = true;
+ Diag(DD.Loc, diag::warn_deprecated)
+ << DD.DeprecationData.Decl->getDeclName();
}
void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
// Delay if we're currently parsing a declaration.
if (ParsingDeclDepth) {
- DelayedDeprecationWarnings.push_back(std::make_pair(Loc, D));
+ DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D));
return;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9ec95f3..9defcca 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -356,9 +356,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
}
}
- if (CheckEquivalentExceptionSpec(
- Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
- New->getType()->getAs<FunctionProtoType>(), New->getLocation()))
+ if (CheckEquivalentExceptionSpec(Old, New))
Invalid = true;
return Invalid;
@@ -433,7 +431,7 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
} else
CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
- if (CurDecl)
+ if (CurDecl && CurDecl->getIdentifier())
return &II == CurDecl->getIdentifier();
else
return false;
@@ -486,7 +484,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
assert(BaseDecl && "Record type has no declaration");
- BaseDecl = BaseDecl->getDefinition(Context);
+ BaseDecl = BaseDecl->getDefinition();
assert(BaseDecl && "Base type is not incomplete, but has no definition");
CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
@@ -641,7 +639,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
}
// Attach the remaining base class specifiers to the derived class.
- Class->setBases(Context, Bases, NumGoodBases);
+ Class->setBases(Bases, NumGoodBases);
// Delete the remaining (good) base class specifiers, since their
// data has been copied into the CXXRecordDecl.
@@ -680,7 +678,8 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl());
CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
- return DerivedRD->isDerivedFrom(BaseRD);
+ // FIXME: instantiate DerivedRD if necessary. We need a PoI for this.
+ return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD);
}
/// \brief Determine whether the type \p Derived is a C++ class that is
@@ -712,7 +711,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
/// if there is an error.
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
- unsigned InaccessibleBaseID,
+ AccessDiagnosticsKind ADK,
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name) {
@@ -728,11 +727,20 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
(void)DerivationOkay;
if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
- if (InaccessibleBaseID == 0)
+ if (ADK == ADK_quiet)
return false;
+
// Check that the base class can be accessed.
- return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc,
- Name);
+ switch (CheckBaseClassAccess(Loc, /*IsBaseToDerived*/ false,
+ Base, Derived, Paths.front(),
+ /*force*/ false,
+ /*unprivileged*/ false,
+ ADK)) {
+ case AR_accessible: return false;
+ case AR_inaccessible: return true;
+ case AR_dependent: return false;
+ case AR_delayed: return false;
+ }
}
// We know that the derived-to-base conversion is ambiguous, and
@@ -763,8 +771,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
bool IgnoreAccess) {
return CheckDerivedToBaseConversion(Derived, Base,
- IgnoreAccess ? 0 :
- diag::err_conv_to_inaccessible_base,
+ IgnoreAccess ? ADK_quiet : ADK_normal,
diag::err_ambiguous_derived_to_base_conv,
Loc, Range, DeclarationName());
}
@@ -1195,10 +1202,6 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
-
// Diagnose value-uses of fields to initialize themselves, e.g.
// foo(foo)
// where foo is not also a parameter to the constructor.
@@ -1220,65 +1223,80 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent();
- CXXConstructorDecl *C = 0;
QualType FieldType = Member->getType();
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
- if (FieldType->isDependentType()) {
- // Can't check init for dependent type.
- } else if (FieldType->isRecordType()) {
- // Member is a record (struct/union/class), so pass the initializer
- // arguments down to the record's constructor.
- if (!HasDependentArg) {
- C = PerformInitializationByConstructor(FieldType,
- MultiExprArg(*this,
- (void**)Args,
- NumArgs),
- IdLoc,
- SourceRange(IdLoc, RParenLoc),
- Member->getDeclName(),
- InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc),
- ConstructorArgs);
-
- if (C) {
- // Take over the constructor arguments as our own.
- NumArgs = ConstructorArgs.size();
- Args = (Expr **)ConstructorArgs.take();
- }
- }
- } else if (NumArgs != 1 && NumArgs != 0) {
- // The member type is not a record type (or an array of record
- // types), so it can be only be default- or copy-initialized.
- return Diag(IdLoc, diag::err_mem_initializer_mismatch)
- << Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
- } else if (!HasDependentArg) {
- Expr *NewExp;
- if (NumArgs == 0) {
- if (FieldType->isReferenceType()) {
- Diag(IdLoc, diag::err_null_intialized_reference_member)
- << Member->getDeclName();
- return Diag(Member->getLocation(), diag::note_declared_at);
- }
- NewExp = new (Context) CXXZeroInitValueExpr(FieldType, IdLoc, RParenLoc);
- NumArgs = 1;
- }
- else
- NewExp = (Expr*)Args[0];
- if (!Member->isInvalidDecl() &&
- PerformCopyInitialization(NewExp, FieldType, AA_Passing))
- return true;
- Args[0] = NewExp;
+ if (FieldType->isDependentType() || HasDependentArg) {
+ // Can't check initialization for a member of dependent type or when
+ // any of the arguments are type-dependent expressions.
+ OwningExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+
+ // Erase any temporaries within this evaluation context; we're not
+ // going to track them in the AST, since we'll be rebuilding the
+ // ASTs during template instantiation.
+ ExprTemporaries.erase(
+ ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+ ExprTemporaries.end());
+
+ return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc);
+
}
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
+ if (Member->isInvalidDecl())
+ return true;
+
+ // Initialize the member.
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(Member, 0);
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
- // FIXME: Perform direct initialization of the member.
+ InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+
+ OwningExprResult MemberInit =
+ InitSeq.Perform(*this, MemberEntity, Kind,
+ MultiExprArg(*this, (void**)Args, NumArgs), 0);
+ if (MemberInit.isInvalid())
+ return true;
+
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ if (MemberInit.isInvalid())
+ return true;
+
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the member
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext()) {
+ // Bump the reference count of all of the arguments.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I]->Retain();
+
+ OwningExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+ return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc);
+ }
+
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
- C, LParenLoc, (Expr **)Args,
- NumArgs, RParenLoc);
+ LParenLoc,
+ MemberInit.takeAs<Expr>(),
+ RParenLoc);
}
Sema::MemInitResult
@@ -1291,76 +1309,118 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
HasDependentArg |= Args[i]->isTypeDependent();
SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getSourceRange().getBegin();
- if (!BaseType->isDependentType()) {
- if (!BaseType->isRecordType())
- return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
- << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
-
- // C++ [class.base.init]p2:
- // [...] Unless the mem-initializer-id names a nonstatic data
- // member of the constructor’s class or a direct or virtual base
- // of that class, the mem-initializer is ill-formed. A
- // mem-initializer-list can initialize a base class using any
- // name that denotes that base class type.
-
- // Check for direct and virtual base classes.
- const CXXBaseSpecifier *DirectBaseSpec = 0;
- const CXXBaseSpecifier *VirtualBaseSpec = 0;
- FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
- VirtualBaseSpec);
-
- // C++ [base.class.init]p2:
- // If a mem-initializer-id is ambiguous because it designates both
- // a direct non-virtual base class and an inherited virtual base
- // class, the mem-initializer is ill-formed.
- if (DirectBaseSpec && VirtualBaseSpec)
- return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
- << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
- // C++ [base.class.init]p2:
- // Unless the mem-initializer-id names a nonstatic data membeer of the
- // constructor's class ot a direst or virtual base of that class, the
- // mem-initializer is ill-formed.
- if (!DirectBaseSpec && !VirtualBaseSpec)
- return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
- << BaseType << ClassDecl->getNameAsCString()
- << BaseTInfo->getTypeLoc().getSourceRange();
- }
-
- CXXConstructorDecl *C = 0;
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
- if (!BaseType->isDependentType() && !HasDependentArg) {
- DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(BaseType).getUnqualifiedType());
-
- C = PerformInitializationByConstructor(BaseType,
- MultiExprArg(*this,
- (void**)Args, NumArgs),
- BaseLoc,
- SourceRange(BaseLoc, RParenLoc),
- Name,
- InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc),
- ConstructorArgs);
- if (C) {
- // Take over the constructor arguments as our own.
- NumArgs = ConstructorArgs.size();
- Args = (Expr **)ConstructorArgs.take();
- }
+ if (BaseType->isDependentType() || HasDependentArg) {
+ // Can't check initialization for a base of dependent type or when
+ // any of the arguments are type-dependent expressions.
+ OwningExprResult BaseInit
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+
+ // Erase any temporaries within this evaluation context; we're not
+ // going to track them in the AST, since we'll be rebuilding the
+ // ASTs during template instantiation.
+ ExprTemporaries.erase(
+ ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+ ExprTemporaries.end());
+
+ return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+ LParenLoc,
+ BaseInit.takeAs<Expr>(),
+ RParenLoc);
}
+
+ if (!BaseType->isRecordType())
+ return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+ << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
+ // C++ [class.base.init]p2:
+ // [...] Unless the mem-initializer-id names a nonstatic data
+ // member of the constructor’s class or a direct or virtual base
+ // of that class, the mem-initializer is ill-formed. A
+ // mem-initializer-list can initialize a base class using any
+ // name that denotes that base class type.
+
+ // Check for direct and virtual base classes.
+ const CXXBaseSpecifier *DirectBaseSpec = 0;
+ const CXXBaseSpecifier *VirtualBaseSpec = 0;
+ FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+ VirtualBaseSpec);
+
+ // C++ [base.class.init]p2:
+ // If a mem-initializer-id is ambiguous because it designates both
+ // a direct non-virtual base class and an inherited virtual base
+ // class, the mem-initializer is ill-formed.
+ if (DirectBaseSpec && VirtualBaseSpec)
+ return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
+ << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+ // C++ [base.class.init]p2:
+ // Unless the mem-initializer-id names a nonstatic data membeer of the
+ // constructor's class ot a direst or virtual base of that class, the
+ // mem-initializer is ill-formed.
+ if (!DirectBaseSpec && !VirtualBaseSpec)
+ return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+ << BaseType << ClassDecl->getNameAsCString()
+ << BaseTInfo->getTypeLoc().getSourceRange();
+
+ CXXBaseSpecifier *BaseSpec
+ = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+ if (!BaseSpec)
+ BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+
+ // Initialize the base.
+ InitializedEntity BaseEntity =
+ InitializedEntity::InitializeBase(Context, BaseSpec);
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+
+ OwningExprResult BaseInit =
+ InitSeq.Perform(*this, BaseEntity, Kind,
+ MultiExprArg(*this, (void**)Args, NumArgs), 0);
+ if (BaseInit.isInvalid())
+ return true;
- return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, C,
- LParenLoc, (Expr **)Args,
- NumArgs, RParenLoc);
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid())
+ return true;
+
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the base
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext()) {
+ // Bump the reference count of all of the arguments.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I]->Retain();
+
+ OwningExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+ return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc);
+ }
+
+ return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+ LParenLoc,
+ BaseInit.takeAs<Expr>(),
+ RParenLoc);
}
bool
Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers,
- bool IsImplicitConstructor) {
+ CXXBaseOrMemberInitializer **Initializers,
+ unsigned NumInitializers,
+ bool IsImplicitConstructor,
+ bool AnyErrors) {
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
@@ -1403,6 +1463,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
AllToInit.push_back(Member);
}
} else {
+ llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit;
+
// Push virtual bases before others.
for (CXXRecordDecl::base_class_iterator VBase =
ClassDecl->vbases_begin(),
@@ -1412,44 +1474,34 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
if (CXXBaseOrMemberInitializer *Value
= AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value);
- }
- else {
- CXXRecordDecl *VBaseDecl =
- cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
- CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
- if (!Ctor) {
- Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 0 << VBase->getType();
- Diag(VBaseDecl->getLocation(), diag::note_previous_decl)
- << Context.getTagDeclType(VBaseDecl);
+ } else if (!AnyErrors) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(Context, VBase);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid()) {
HadError = true;
continue;
}
- ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
- if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
- Constructor->getLocation(), CtorArgs))
+ // Don't attach synthesized base initializers in a dependent
+ // context; they'll be checked again at template instantiation
+ // time.
+ if (CurContext->isDependentContext())
continue;
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if
- // necessary.
- // FIXME: Is there any better source-location information we can give?
- ExprTemporaries.clear();
- CXXBaseOrMemberInitializer *Member =
+ CXXBaseOrMemberInitializer *CXXBaseInit =
new (Context) CXXBaseOrMemberInitializer(Context,
Context.getTrivialTypeSourceInfo(VBase->getType(),
SourceLocation()),
- Ctor,
SourceLocation(),
- CtorArgs.takeAs<Expr>(),
- CtorArgs.size(),
+ BaseInit.takeAs<Expr>(),
SourceLocation());
- AllToInit.push_back(Member);
+ AllToInit.push_back(CXXBaseInit);
}
}
@@ -1466,43 +1518,34 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
= AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value);
}
- else {
- CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
- CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
- if (!Ctor) {
- Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 0 << Base->getType();
- Diag(BaseDecl->getLocation(), diag::note_previous_decl)
- << Context.getTagDeclType(BaseDecl);
+ else if (!AnyErrors) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(Context, Base);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid()) {
HadError = true;
continue;
}
-
- ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
- if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
- Constructor->getLocation(), CtorArgs))
+
+ // Don't attach synthesized base initializers in a dependent
+ // context; they'll be regenerated at template instantiation
+ // time.
+ if (CurContext->isDependentContext())
continue;
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if
- // necessary.
- // FIXME: Is there any better source-location information we can give?
- ExprTemporaries.clear();
- CXXBaseOrMemberInitializer *Member =
+ CXXBaseOrMemberInitializer *CXXBaseInit =
new (Context) CXXBaseOrMemberInitializer(Context,
Context.getTrivialTypeSourceInfo(Base->getType(),
SourceLocation()),
- Ctor,
SourceLocation(),
- CtorArgs.takeAs<Expr>(),
- CtorArgs.size(),
+ BaseInit.takeAs<Expr>(),
SourceLocation());
- AllToInit.push_back(Member);
+ AllToInit.push_back(CXXBaseInit);
}
}
}
@@ -1535,66 +1578,49 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
continue;
}
- if ((*Field)->getType()->isDependentType())
+ if ((*Field)->getType()->isDependentType() || AnyErrors)
continue;
QualType FT = Context.getBaseElementType((*Field)->getType());
- if (const RecordType* RT = FT->getAs<RecordType>()) {
- CXXConstructorDecl *Ctor =
- cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
- if (!Ctor) {
- Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 1 << (*Field)->getDeclName();
- Diag(Field->getLocation(), diag::note_field_decl);
- Diag(RT->getDecl()->getLocation(), diag::note_previous_decl)
- << Context.getTagDeclType(RT->getDecl());
+ if (FT->getAs<RecordType>()) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeMember(*Field);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult MemberInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ if (MemberInit.isInvalid()) {
HadError = true;
continue;
}
-
- if (FT.isConstQualified() && Ctor->isTrivial()) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 1 << (*Field)->getDeclName();
- Diag((*Field)->getLocation(), diag::note_declared_at);
- HadError = true;
- }
-
- // Don't create initializers for trivial constructors, since they don't
- // actually need to be run.
- if (Ctor->isTrivial())
- continue;
-
- ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
- if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
- Constructor->getLocation(), CtorArgs))
+
+ // Don't attach synthesized member initializers in a dependent
+ // context; they'll be regenerated a template instantiation
+ // time.
+ if (CurContext->isDependentContext())
continue;
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
CXXBaseOrMemberInitializer *Member =
new (Context) CXXBaseOrMemberInitializer(Context,
*Field, SourceLocation(),
- Ctor,
SourceLocation(),
- CtorArgs.takeAs<Expr>(),
- CtorArgs.size(),
+ MemberInit.takeAs<Expr>(),
SourceLocation());
AllToInit.push_back(Member);
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
}
else if (FT->isReferenceType()) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+ Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
<< (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
<< 0 << (*Field)->getDeclName();
Diag((*Field)->getLocation(), diag::note_declared_at);
HadError = true;
}
else if (FT.isConstQualified()) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+ Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
<< (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
<< 1 << (*Field)->getDeclName();
Diag((*Field)->getLocation(), diag::note_declared_at);
@@ -1659,7 +1685,8 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member,
/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits) {
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors) {
if (!ConstructorDecl)
return;
@@ -1709,7 +1736,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SetBaseOrMemberInitializers(Constructor,
reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
- NumMemInits, false);
+ NumMemInits, false, AnyErrors);
if (Constructor->isDependentContext())
return;
@@ -1860,7 +1887,7 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
- SetBaseOrMemberInitializers(Constructor, 0, 0, false);
+ SetBaseOrMemberInitializers(Constructor, 0, 0, false, false);
}
namespace {
@@ -1978,13 +2005,15 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
if (!RT)
return false;
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return false;
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (CurrentRD && CurrentRD != RD)
return false;
+ // FIXME: is this reasonable? It matches current behavior, but....
+ if (!RD->getDefinition())
+ return false;
+
if (!RD->isAbstract())
return false;
@@ -2086,6 +2115,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (Record->isInvalidDecl())
return;
+ // Set access bits correctly on the directly-declared conversions.
+ UnresolvedSetImpl *Convs = Record->getConversionFunctions();
+ for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end(); I != E; ++I)
+ Convs->setAccess(I, (*I)->getAccess());
+
if (!Record->isAbstract()) {
// Collect all the pure virtual methods and see if this is an abstract
// class after all.
@@ -2227,7 +2261,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
VarDecl::None, 0);
- CopyConstructor->setParams(Context, &FromParam, 1);
+ CopyConstructor->setParams(&FromParam, 1);
ClassDecl->addDecl(CopyConstructor);
}
@@ -2311,7 +2345,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
VarDecl::None, 0);
- CopyAssignment->setParams(Context, &FromParam, 1);
+ CopyAssignment->setParams(&FromParam, 1);
// Don't call addedAssignmentOperator. There is no way to distinguish an
// implicit from an explicit assignment operator.
@@ -2793,13 +2827,16 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
SourceLocation IdentLoc,
IdentifierInfo *II,
- SourceLocation LBrace) {
+ SourceLocation LBrace,
+ AttributeList *AttrList) {
NamespaceDecl *Namespc =
NamespaceDecl::Create(Context, CurContext, IdentLoc, II);
Namespc->setLBracLoc(LBrace);
Scope *DeclRegionScope = NamespcScope->getParent();
+ ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
+
if (II) {
// C++ [namespace.def]p2:
// The identifier in an original-namespace-definition shall not have been
@@ -3654,7 +3691,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
(NestedNameSpecifier *)SS.getScopeRep(),
IdentLoc, R.getFoundDecl());
- CurContext->addDecl(AliasDecl);
+ PushOnScopeChains(AliasDecl, S);
return DeclPtrTy::make(AliasDecl);
}
@@ -3668,13 +3705,16 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
= cast<CXXRecordDecl>(Constructor->getDeclContext());
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
- if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) {
+ DeclContext *PreviousContext = CurContext;
+ CurContext = Constructor;
+ if (SetBaseOrMemberInitializers(Constructor, 0, 0, true, false)) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
Constructor->setInvalidDecl();
} else {
Constructor->setUsed();
}
+ CurContext = PreviousContext;
}
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
@@ -3683,6 +3723,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
"DefineImplicitDestructor - call it for implicit default dtor");
CXXRecordDecl *ClassDecl = Destructor->getParent();
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+
+ DeclContext *PreviousContext = CurContext;
+ CurContext = Destructor;
+
// C++ [class.dtor] p5
// Before the implicitly-declared default destructor for a class is
// implicitly defined, all the implicitly-declared default destructors
@@ -3729,8 +3773,11 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
<< CXXDestructor << Context.getTagDeclType(ClassDecl);
Destructor->setInvalidDecl();
+ CurContext = PreviousContext;
+
return;
}
+ CurContext = PreviousContext;
Destructor->setUsed();
}
@@ -3745,6 +3792,9 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(MethodDecl->getDeclContext());
+ DeclContext *PreviousContext = CurContext;
+ CurContext = MethodDecl;
+
// C++[class.copy] p12
// Before the implicitly-declared copy assignment operator for a class is
// implicitly defined, all implicitly-declared copy assignment operators
@@ -3788,6 +3838,8 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
}
if (!err)
MethodDecl->setUsed();
+
+ CurContext = PreviousContext;
}
CXXMethodDecl *
@@ -3808,7 +3860,7 @@ Sema::getAssignOperatorMethod(SourceLocation CurrentLocation,
RHSType,
CurrentLocation));
Expr *Args[2] = { &*LHS, &*RHS };
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(CurrentLocation);
AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2,
CandidateSet);
OverloadCandidateSet::iterator Best;
@@ -3830,6 +3882,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+
+ DeclContext *PreviousContext = CurContext;
+ CurContext = CopyConstructor;
+
// C++ [class.copy] p209
// Before the implicitly-declared copy constructor for a class is
// implicitly defined, all the implicitly-declared copy constructors
@@ -3858,13 +3914,16 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
}
}
CopyConstructor->setUsed();
+
+ CurContext = PreviousContext;
}
Sema::OwningExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor,
MultiExprArg ExprArgs,
- bool RequiresZeroInit) {
+ bool RequiresZeroInit,
+ bool BaseInitialization) {
bool Elidable = false;
// C++ [class.copy]p15:
@@ -3897,7 +3956,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
- Elidable, move(ExprArgs), RequiresZeroInit);
+ Elidable, move(ExprArgs), RequiresZeroInit,
+ BaseInitialization);
}
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -3906,32 +3966,17 @@ Sema::OwningExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
MultiExprArg ExprArgs,
- bool RequiresZeroInit) {
+ bool RequiresZeroInit,
+ bool BaseInitialization) {
unsigned NumExprs = ExprArgs.size();
Expr **Exprs = (Expr **)ExprArgs.release();
MarkDeclarationReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
- RequiresZeroInit));
-}
-
-Sema::OwningExprResult
-Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor,
- QualType Ty,
- SourceLocation TyBeginLoc,
- MultiExprArg Args,
- SourceLocation RParenLoc) {
- unsigned NumExprs = Args.size();
- Expr **Exprs = (Expr **)Args.release();
-
- MarkDeclarationReferenced(TyBeginLoc, Constructor);
- return Owned(new (Context) CXXTemporaryObjectExpr(Context, Constructor, Ty,
- TyBeginLoc, Exprs,
- NumExprs, RParenLoc));
+ RequiresZeroInit, BaseInitialization));
}
-
bool Sema::InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
MultiExprArg Exprs) {
@@ -3944,18 +3989,18 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD,
Expr *Temp = TempResult.takeAs<Expr>();
MarkDeclarationReferenced(VD->getLocation(), Constructor);
Temp = MaybeCreateCXXExprWithTemporaries(Temp);
- VD->setInit(Context, Temp);
+ VD->setInit(Temp);
return false;
}
-void Sema::FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType) {
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(
- DeclInitType->getAs<RecordType>()->getDecl());
- if (!ClassDecl->hasTrivialDestructor())
- if (CXXDestructorDecl *Destructor =
- const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context)))
- MarkDeclarationReferenced(VD->getLocation(), Destructor);
+void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
+ if (!ClassDecl->hasTrivialDestructor()) {
+ CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context);
+ MarkDeclarationReferenced(VD->getLocation(), Destructor);
+ CheckDestructorAccess(VD->getLocation(), Record);
+ }
}
/// AddCXXDirectInitializerToDecl - This action is called immediately after
@@ -3991,24 +4036,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
// exactly form was it (like the CodeGen) can handle both cases without
// special case code.
- // If either the declaration has a dependent type or if any of the expressions
- // is type-dependent, we represent the initialization via a ParenListExpr for
- // later use during template instantiation.
- if (VDecl->getType()->isDependentType() ||
- Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) {
- // Let clients know that initialization was done with a direct initializer.
- VDecl->setCXXDirectInitializer(true);
-
- // Store the initialization expressions as a ParenListExpr.
- unsigned NumExprs = Exprs.size();
- VDecl->setInit(Context,
- new (Context) ParenListExpr(Context, LParenLoc,
- (Expr **)Exprs.release(),
- NumExprs, RParenLoc));
- return;
- }
-
-
// C++ 8.5p11:
// The form of initialization (using parentheses or '=') is generally
// insignificant, but does matter when the entity being initialized has a
@@ -4017,7 +4044,8 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
DeclInitType = Context.getBaseElementType(Array);
- if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
+ if (!VDecl->getType()->isDependentType() &&
+ RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
diag::err_typecheck_decl_incomplete_type)) {
VDecl->setInvalidDecl();
return;
@@ -4029,14 +4057,30 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
AbstractVariableType))
VDecl->setInvalidDecl();
- const VarDecl *Def = 0;
- if (VDecl->getDefinition(Def)) {
+ const VarDecl *Def;
+ if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition)
<< VDecl->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition);
VDecl->setInvalidDecl();
return;
}
+
+ // If either the declaration has a dependent type or if any of the
+ // expressions is type-dependent, we represent the initialization
+ // via a ParenListExpr for later use during template instantiation.
+ if (VDecl->getType()->isDependentType() ||
+ Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) {
+ // Let clients know that initialization was done with a direct initializer.
+ VDecl->setCXXDirectInitializer(true);
+
+ // Store the initialization expressions as a ParenListExpr.
+ unsigned NumExprs = Exprs.size();
+ VDecl->setInit(new (Context) ParenListExpr(Context, LParenLoc,
+ (Expr **)Exprs.release(),
+ NumExprs, RParenLoc));
+ return;
+ }
// Capture the variable that is being initialized and the style of
// initialization.
@@ -4056,11 +4100,11 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
}
Result = MaybeCreateCXXExprWithTemporaries(move(Result));
- VDecl->setInit(Context, Result.takeAs<Expr>());
+ VDecl->setInit(Result.takeAs<Expr>());
VDecl->setCXXDirectInitializer(true);
- if (VDecl->getType()->getAs<RecordType>())
- FinalizeVarWithDestructor(VDecl, DeclInitType);
+ if (const RecordType *Record = VDecl->getType()->getAs<RecordType>())
+ FinalizeVarWithDestructor(VDecl, Record);
}
/// \brief Add the applicable constructor candidates for an initialization
@@ -4112,10 +4156,12 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
Constructor->isDefaultConstructor())) {
if (ConstructorTmpl)
SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl,
+ ConstructorTmpl->getAccess(),
/*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet);
else
- SemaRef.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+ SemaRef.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+ Args, NumArgs, CandidateSet);
}
}
}
@@ -4145,7 +4191,7 @@ Sema::TryInitializationByConstructor(QualType ClassType,
SourceLocation Loc,
InitializationKind Kind) {
// Build the overload candidate set
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(Loc);
AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind,
CandidateSet);
@@ -4167,92 +4213,6 @@ Sema::TryInitializationByConstructor(QualType ClassType,
return 0;
}
-/// \brief Perform initialization by constructor (C++ [dcl.init]p14), which
-/// may occur as part of direct-initialization or copy-initialization.
-///
-/// \param ClassType the type of the object being initialized, which must have
-/// class type.
-///
-/// \param ArgsPtr the arguments provided to initialize the object
-///
-/// \param Loc the source location where the initialization occurs
-///
-/// \param Range the source range that covers the entire initialization
-///
-/// \param InitEntity the name of the entity being initialized, if known
-///
-/// \param Kind the type of initialization being performed
-///
-/// \param ConvertedArgs a vector that will be filled in with the
-/// appropriately-converted arguments to the constructor (if initialization
-/// succeeded).
-///
-/// \returns the constructor used to initialize the object, if successful.
-/// Otherwise, emits a diagnostic and returns NULL.
-CXXConstructorDecl *
-Sema::PerformInitializationByConstructor(QualType ClassType,
- MultiExprArg ArgsPtr,
- SourceLocation Loc, SourceRange Range,
- DeclarationName InitEntity,
- InitializationKind Kind,
- ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) {
-
- // Build the overload candidate set
- Expr **Args = (Expr **)ArgsPtr.get();
- unsigned NumArgs = ArgsPtr.size();
- OverloadCandidateSet CandidateSet;
- AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind,
- CandidateSet);
-
- OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Loc, Best)) {
- case OR_Success:
- // We found a constructor. Break out so that we can convert the arguments
- // appropriately.
- break;
-
- case OR_No_Viable_Function:
- if (InitEntity)
- Diag(Loc, diag::err_ovl_no_viable_function_in_init)
- << InitEntity << Range;
- else
- Diag(Loc, diag::err_ovl_no_viable_function_in_init)
- << ClassType << Range;
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
- return 0;
-
- case OR_Ambiguous:
- if (InitEntity)
- Diag(Loc, diag::err_ovl_ambiguous_init) << InitEntity << Range;
- else
- Diag(Loc, diag::err_ovl_ambiguous_init) << ClassType << Range;
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs);
- return 0;
-
- case OR_Deleted:
- if (InitEntity)
- Diag(Loc, diag::err_ovl_deleted_init)
- << Best->Function->isDeleted()
- << InitEntity << Range;
- else {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(ClassType->getAs<RecordType>()->getDecl());
- Diag(Loc, diag::err_ovl_deleted_init)
- << Best->Function->isDeleted()
- << RD->getDeclName() << Range;
- }
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
- return 0;
- }
-
- // Convert the arguments, fill in default arguments, etc.
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
- if (CompleteConstructorCall(Constructor, move(ArgsPtr), Loc, ConvertedArgs))
- return 0;
-
- return Constructor;
-}
-
/// \brief Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
@@ -4453,7 +4413,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
ICS->Standard.Third = ICK_Identity;
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
+ ICS->Standard.setToType(0, T2);
+ ICS->Standard.setToType(1, T1);
+ ICS->Standard.setToType(2, T1);
ICS->Standard.ReferenceBinding = true;
ICS->Standard.DirectBinding = true;
ICS->Standard.RRefBinding = false;
@@ -4486,7 +4448,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(DeclLoc);
const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
for (UnresolvedSetImpl::iterator I = Conversions->begin(),
@@ -4509,10 +4471,11 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
if (Conv->getConversionType()->isLValueReferenceType() &&
(AllowExplicit || !Conv->isExplicit())) {
if (ConvTemplate)
- AddTemplateConversionCandidate(ConvTemplate, ActingDC,
+ AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), ActingDC,
Init, DeclType, CandidateSet);
else
- AddConversionCandidate(Conv, ActingDC, Init, DeclType, CandidateSet);
+ AddConversionCandidate(Conv, I.getAccess(), ActingDC, Init,
+ DeclType, CandidateSet);
}
}
@@ -4606,6 +4569,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
if (!ICS)
Diag(DeclLoc, diag::err_not_reference_to_const_init)
+ << T1.isVolatileQualified()
<< T1 << int(InitLvalue != Expr::LV_Valid)
<< T2 << Init->getSourceRange();
return true;
@@ -4642,7 +4606,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
ICS->Standard.Third = ICK_Identity;
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
+ ICS->Standard.setToType(0, T2);
+ ICS->Standard.setToType(1, T1);
+ ICS->Standard.setToType(2, T1);
ICS->Standard.ReferenceBinding = true;
ICS->Standard.DirectBinding = false;
ICS->Standard.RRefBinding = isRValRef;
@@ -5611,7 +5577,8 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType();
QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType();
- if (Context.hasSameType(NewTy, OldTy))
+ if (Context.hasSameType(NewTy, OldTy) ||
+ NewTy->isDependentType() || OldTy->isDependentType())
return false;
// Check if the return types are covariant
@@ -5665,8 +5632,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
}
// Check if we the conversion from derived to base is valid.
- if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy,
- diag::err_covariant_return_inaccessible_base,
+ if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, ADK_covariance,
diag::err_covariant_return_ambiguous_derived_to_base_conv,
// FIXME: Should this point to the return type?
New->getLocation(), SourceRange(), New->getDeclName())) {
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 1b07d19..1e9b56a 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -446,18 +446,19 @@ Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
// Category
ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
assert (CatDecl && "MatchOneProtocolPropertiesInClass");
- for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
- E = PDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Pr = (*P);
- ObjCCategoryDecl::prop_iterator CP, CE;
- // Is this property already in category's list of properties?
- for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP)
- if ((*CP)->getIdentifier() == Pr->getIdentifier())
- break;
- if (CP != CE)
- // Property protocol already exist in class. Diagnose any mismatch.
- DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
- }
+ if (!CatDecl->IsClassExtension())
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Pr = (*P);
+ ObjCCategoryDecl::prop_iterator CP, CE;
+ // Is this property already in category's list of properties?
+ for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP)
+ if ((*CP)->getIdentifier() == Pr->getIdentifier())
+ break;
+ if (CP != CE)
+ // Property protocol already exist in class. Diagnose any mismatch.
+ DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
+ }
return;
}
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
@@ -596,44 +597,59 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc) {
- ObjCCategoryDecl *CDecl =
- ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc,
- CategoryLoc, CategoryName);
- // FIXME: PushOnScopeChains?
- CurContext->addDecl(CDecl);
-
+ ObjCCategoryDecl *CDecl = 0;
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc);
- /// Check that class of this category is already completely declared.
- if (!IDecl || IDecl->isForwardDecl()) {
- CDecl->setInvalidDecl();
- Diag(ClassLoc, diag::err_undef_interface) << ClassName;
- return DeclPtrTy::make(CDecl);
- }
+ if (!CategoryName) {
+ // Class extensions require a special treatment. Use an existing one.
+ for (CDecl = IDecl->getCategoryList(); CDecl;
+ CDecl = CDecl->getNextClassCategory())
+ if (CDecl->IsClassExtension())
+ break;
+ }
+ if (!CDecl) {
+ CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc,
+ CategoryLoc, CategoryName);
+ // FIXME: PushOnScopeChains?
+ CurContext->addDecl(CDecl);
+
+ /// Check that class of this category is already completely declared.
+ if (!IDecl || IDecl->isForwardDecl()) {
+ CDecl->setInvalidDecl();
+ Diag(ClassLoc, diag::err_undef_interface) << ClassName;
+ return DeclPtrTy::make(CDecl);
+ }
- CDecl->setClassInterface(IDecl);
+ CDecl->setClassInterface(IDecl);
+ // Insert first use of class extension to the list of class's categories.
+ if (!CategoryName)
+ CDecl->insertNextClassCategory();
+ }
// If the interface is deprecated, warn about it.
(void)DiagnoseUseOfDecl(IDecl, ClassLoc);
- /// Check for duplicate interface declaration for this category
- ObjCCategoryDecl *CDeclChain;
- for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
- CDeclChain = CDeclChain->getNextClassCategory()) {
- if (CategoryName && CDeclChain->getIdentifier() == CategoryName) {
- Diag(CategoryLoc, diag::warn_dup_category_def)
- << ClassName << CategoryName;
- Diag(CDeclChain->getLocation(), diag::note_previous_definition);
- break;
+ if (CategoryName) {
+ /// Check for duplicate interface declaration for this category
+ ObjCCategoryDecl *CDeclChain;
+ for (CDeclChain = IDecl->getCategoryList(); CDeclChain;
+ CDeclChain = CDeclChain->getNextClassCategory()) {
+ if (CDeclChain->getIdentifier() == CategoryName) {
+ // Class extensions can be declared multiple times.
+ Diag(CategoryLoc, diag::warn_dup_category_def)
+ << ClassName << CategoryName;
+ Diag(CDeclChain->getLocation(), diag::note_previous_definition);
+ break;
+ }
}
+ if (!CDeclChain)
+ CDecl->insertNextClassCategory();
}
- if (!CDeclChain)
- CDecl->insertNextClassCategory();
if (NumProtoRefs) {
CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
ProtoLocs, Context);
// Protocols in the class extension belong to the class.
- if (!CDecl->getIdentifier())
+ if (CDecl->IsClassExtension())
IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,
NumProtoRefs, ProtoLocs,
Context);
@@ -1102,11 +1118,12 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
CollectImmediateProperties((*PI), PropMap);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
- E = CATDecl->prop_end(); P != E; ++P) {
- ObjCPropertyDecl *Prop = (*P);
- PropMap[Prop->getIdentifier()] = Prop;
- }
+ if (!CATDecl->IsClassExtension())
+ for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
+ E = CATDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ PropMap[Prop->getIdentifier()] = Prop;
+ }
// scan through class's protocols.
for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
E = CATDecl->protocol_end(); PI != E; ++PI)
@@ -1127,6 +1144,46 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
}
}
+/// LookupPropertyDecl - Looks up a property in the current class and all
+/// its protocols.
+ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
+ IdentifierInfo *II) {
+ if (const ObjCInterfaceDecl *IDecl =
+ dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+ for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
+ E = IDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ if (Prop->getIdentifier() == II)
+ return Prop;
+ }
+ // scan through class's protocols.
+ for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
+ E = IDecl->protocol_end(); PI != E; ++PI) {
+ ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+ if (Prop)
+ return Prop;
+ }
+ }
+ else if (const ObjCProtocolDecl *PDecl =
+ dyn_cast<ObjCProtocolDecl>(CDecl)) {
+ for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
+ E = PDecl->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *Prop = (*P);
+ if (Prop->getIdentifier() == II)
+ return Prop;
+ }
+ // scan through protocol's protocols.
+ for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
+ E = PDecl->protocol_end(); PI != E; ++PI) {
+ ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
+ if (Prop)
+ return Prop;
+ }
+ }
+ return 0;
+}
+
+
void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
ObjCContainerDecl *CDecl,
const llvm::DenseSet<Selector>& InsMap) {
@@ -1149,7 +1206,14 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
PropImplMap.count(Prop))
continue;
-
+ if (LangOpts.ObjCNonFragileABI2) {
+ ActOnPropertyImplDecl(IMPDecl->getLocation(),
+ SourceLocation(),
+ true, DeclPtrTy::make(IMPDecl),
+ Prop->getIdentifier(),
+ Prop->getIdentifier());
+ continue;
+ }
if (!InsMap.count(Prop->getGetterName())) {
Diag(Prop->getLocation(),
isa<ObjCCategoryDecl>(CDecl) ?
@@ -1214,7 +1278,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
// Check class extensions (unnamed categories)
for (ObjCCategoryDecl *Categories = I->getCategoryList();
Categories; Categories = Categories->getNextClassCategory()) {
- if (!Categories->getIdentifier()) {
+ if (Categories->IsClassExtension()) {
ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl);
break;
}
@@ -1222,7 +1286,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
// For extended class, unimplemented methods in its protocols will
// be reported in the primary class.
- if (C->getIdentifier()) {
+ if (!C->IsClassExtension()) {
for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
E = C->protocol_end(); PI != E; ++PI)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
@@ -1443,7 +1507,8 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
- Entry.Next = new ObjCMethodList(Method, Entry.Next);
+ ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+ Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next);
}
// FIXME: Finish implementing -Wno-strict-selector-match.
@@ -1506,7 +1571,8 @@ void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
if (!match) {
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
- struct ObjCMethodList *OMI = new ObjCMethodList(Method, FirstMethod.Next);
+ ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+ ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next);
FirstMethod.Next = OMI;
}
}
@@ -1777,17 +1843,18 @@ void Sema::ActOnAtEnd(SourceRange AtEnd,
// Compare protocol properties with those in category
CompareProperties(C, DeclPtrTy::make(C));
- if (C->getIdentifier() == 0)
+ if (C->IsClassExtension())
DiagnoseClassExtensionDupMethods(C, C->getClassInterface());
}
if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
- // ProcessPropertyDecl is responsible for diagnosing conflicts with any
- // user-defined setter/getter. It also synthesizes setter/getter methods
- // and adds them to the DeclContext and global method pools.
- for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
- E = CDecl->prop_end();
- I != E; ++I)
- ProcessPropertyDecl(*I, CDecl);
+ if (CDecl->getIdentifier())
+ // ProcessPropertyDecl is responsible for diagnosing conflicts with any
+ // user-defined setter/getter. It also synthesizes setter/getter methods
+ // and adds them to the DeclContext and global method pools.
+ for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(),
+ E = CDecl->prop_end();
+ I != E; ++I)
+ ProcessPropertyDecl(*I, CDecl);
CDecl->setAtEndRange(AtEnd);
}
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
@@ -2088,7 +2155,22 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
// May modify Attributes.
CheckObjCPropertyAttributes(T, AtLoc, Attributes);
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
- if (!CDecl->getIdentifier()) {
+ if (CDecl->IsClassExtension()) {
+ // Diagnose if this property is already in continuation class.
+ DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
+ assert(DC && "ClassDecl is not a DeclContext");
+ DeclContext::lookup_result Found = DC->lookup(FD.D.getIdentifier());
+ if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
+ Diag(AtLoc, diag::err_duplicate_property);
+ Diag((*Found.first)->getLocation(), diag::note_property_declare);
+ return DeclPtrTy();
+ }
+ ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
+ FD.D.getIdentifierLoc(),
+ FD.D.getIdentifier(),
+ AtLoc, T);
+ DC->addDecl(PDecl);
+
// This is a continuation class. property requires special
// handling.
if ((CCPrimary = CDecl->getClassInterface())) {
@@ -2152,6 +2234,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
ProcessPropertyDecl(PIDecl, CCPrimary);
return DeclPtrTy();
}
+
// No matching property found in the primary class. Just fall thru
// and add property to continuation class's primary class.
ClassDecl = CCPrimary;
@@ -2246,6 +2329,28 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
return DeclPtrTy::make(PDecl);
}
+ObjCIvarDecl*
+Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *NameII) {
+ ObjCIvarDecl *Ivar = 0;
+ ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII);
+ if (Prop && !Prop->isInvalidDecl()) {
+ DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
+ QualType PropType = Context.getCanonicalType(Prop->getType());
+ assert(EnclosingContext &&
+ "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar");
+ Ivar = ObjCIvarDecl::Create(Context, EnclosingContext,
+ Prop->getLocation(),
+ NameII, PropType, /*Dinfo=*/0,
+ ObjCIvarDecl::Public,
+ (Expr *)0);
+ Ivar->setLexicalDeclContext(IDecl);
+ IDecl->addDecl(Ivar);
+ Prop->setPropertyIvarDecl(Ivar);
+ }
+ return Ivar;
+}
+
/// ActOnPropertyImplDecl - This routine performs semantic checks and
/// builds the AST node for a property implementation declaration; declared
/// as @synthesize or @dynamic.
@@ -2283,7 +2388,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
}
if (const ObjCCategoryDecl *CD =
dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
- if (CD->getIdentifier()) {
+ if (!CD->IsClassExtension()) {
Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
Diag(property->getLocation(), diag::note_property_declare);
return DeclPtrTy();
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 7e2a98d..9be411b 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -12,10 +12,11 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
@@ -92,6 +93,52 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
return FnT->hasExceptionSpec();
}
+bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+ bool MissingEmptyExceptionSpecification = false;
+ if (!CheckEquivalentExceptionSpec(diag::err_mismatched_exception_spec,
+ diag::note_previous_declaration,
+ Old->getType()->getAs<FunctionProtoType>(),
+ Old->getLocation(),
+ New->getType()->getAs<FunctionProtoType>(),
+ New->getLocation(),
+ &MissingEmptyExceptionSpecification))
+ return false;
+
+ // The failure was something other than an empty exception
+ // specification; return an error.
+ if (!MissingEmptyExceptionSpecification)
+ return true;
+
+ // The new function declaration is only missing an empty exception
+ // specification "throw()". If the throw() specification came from a
+ // function in a system header that has C linkage, just add an empty
+ // exception specification to the "new" declaration. This is an
+ // egregious workaround for glibc, which adds throw() specifications
+ // to many libc functions as an optimization. Unfortunately, that
+ // optimization isn't permitted by the C++ standard, so we're forced
+ // to work around it here.
+ if (isa<FunctionProtoType>(New->getType()) &&
+ Context.getSourceManager().isInSystemHeader(Old->getLocation()) &&
+ Old->isExternC()) {
+ const FunctionProtoType *NewProto
+ = cast<FunctionProtoType>(New->getType());
+ QualType NewType = Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ NewProto->isVariadic(),
+ NewProto->getTypeQuals(),
+ true, false, 0, 0,
+ NewProto->getNoReturnAttr(),
+ NewProto->getCallConv());
+ New->setType(NewType);
+ return false;
+ }
+
+ Diag(New->getLocation(), diag::err_mismatched_exception_spec);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+}
+
/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
/// exception specifications. Exception specifications are equivalent if
/// they allow exactly the same set of exception types. It does not matter how
@@ -111,12 +158,26 @@ bool Sema::CheckEquivalentExceptionSpec(
bool Sema::CheckEquivalentExceptionSpec(
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Old, SourceLocation OldLoc,
- const FunctionProtoType *New, SourceLocation NewLoc) {
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingEmptyExceptionSpecification) {
+ if (MissingEmptyExceptionSpecification)
+ *MissingEmptyExceptionSpecification = false;
+
bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec();
bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec();
if (OldAny && NewAny)
return false;
if (OldAny || NewAny) {
+ if (MissingEmptyExceptionSpecification && Old->hasExceptionSpec() &&
+ !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0 &&
+ !New->hasExceptionSpec()) {
+ // The old type has a throw() exception specification and the
+ // new type has no exception specification, and the caller asked
+ // to handle this itself.
+ *MissingEmptyExceptionSpecification = true;
+ return true;
+ }
+
Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0)
Diag(OldLoc, NoteID);
@@ -232,8 +293,22 @@ bool Sema::CheckExceptionSpecSubset(
if (Paths.isAmbiguous(CanonicalSuperT))
continue;
- if (FindInaccessibleBase(CanonicalSubT, CanonicalSuperT, Paths, true))
- continue;
+ // Do this check from a context without privileges.
+ switch (CheckBaseClassAccess(SourceLocation(), false,
+ CanonicalSuperT, CanonicalSubT,
+ Paths.front(),
+ /*ForceCheck*/ true,
+ /*ForceUnprivileged*/ true,
+ ADK_quiet)) {
+ case AR_accessible: break;
+ case AR_inaccessible: continue;
+ case AR_dependent:
+ llvm_unreachable("access check dependent for unprivileged context");
+ break;
+ case AR_delayed:
+ llvm_unreachable("access check delayed in non-declaration");
+ break;
+ }
Contained = true;
break;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 50976f7..633884f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -14,7 +14,7 @@
#include "Sema.h"
#include "SemaInit.h"
#include "Lookup.h"
-#include "clang/Analysis/PathSensitive/AnalysisContext.h"
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -200,6 +200,28 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
}
}
+void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
+ DefaultFunctionArrayConversion(E);
+
+ QualType Ty = E->getType();
+ assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type");
+ if (!Ty->isDependentType() && Ty.hasQualifiers() &&
+ (!getLangOptions().CPlusPlus || !Ty->isRecordType()) &&
+ E->isLvalue(Context) == Expr::LV_Valid) {
+ // C++ [conv.lval]p1:
+ // [...] If T is a non-class type, the type of the rvalue is the
+ // cv-unqualified version of T. Otherwise, the type of the
+ // rvalue is T
+ //
+ // C99 6.3.2.1p2:
+ // If the lvalue has qualified type, the value has the unqualified
+ // version of the type of the lvalue; otherwise, the value has the
+ // type of the lvalue.
+ ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp);
+ }
+}
+
+
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
/// sometimes surpressed. For example, the array->pointer conversion doesn't
@@ -233,7 +255,7 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
return Expr;
}
- DefaultFunctionArrayConversion(Expr);
+ DefaultFunctionArrayLvalueConversion(Expr);
return Expr;
}
@@ -678,7 +700,13 @@ static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) {
R.resolveKind();
}
+/// Determines whether the given record is "fully-formed" at the given
+/// location, i.e. whether a qualified lookup into it is assured of
+/// getting consistent results already.
static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
+ if (!Record->hasDefinition())
+ return false;
+
for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
E = Record->bases_end(); I != E; ++I) {
CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
@@ -686,7 +714,7 @@ static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
if (!BaseRT) return false;
CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
- if (!BaseRecord->isDefinition() ||
+ if (!BaseRecord->hasDefinition() ||
!IsFullyFormedScope(SemaRef, BaseRecord))
return false;
}
@@ -719,7 +747,7 @@ static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
if (Bases.count(Record->getCanonicalDecl()))
return false;
- RecordDecl *RD = Record->getDefinition(SemaRef.Context);
+ RecordDecl *RD = Record->getDefinition();
if (!RD) return false;
Record = cast<CXXRecordDecl>(RD);
@@ -1243,9 +1271,9 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
else
LookForIvars = (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
-
+ ObjCInterfaceDecl *IFace = 0;
if (LookForIvars) {
- ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+ IFace = getCurMethodDecl()->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
// Diagnose using an ivar in a class method.
@@ -1314,6 +1342,11 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
}
}
}
+ if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) {
+ ObjCIvarDecl *Ivar = SynthesizeNewPropertyIvar(IFace, II);
+ if (Ivar)
+ return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation);
+ }
// Sentinel value saying that we didn't do anything special.
return Owned((Expr*) 0);
}
@@ -1487,7 +1520,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
bool NeedsADL) {
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
- if (!NeedsADL && R.isSingleResult())
+ if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl());
// We only need to check the declaration if there's exactly one
@@ -1497,16 +1530,20 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
return ExprError();
+ // Otherwise, just build an unresolved lookup expression. Suppress
+ // any lookup-related diagnostics; we'll hash these out later, when
+ // we've picked a target.
+ R.suppressDiagnostics();
+
bool Dependent
= UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0);
UnresolvedLookupExpr *ULE
- = UnresolvedLookupExpr::Create(Context, Dependent,
+ = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
(NestedNameSpecifier*) SS.getScopeRep(),
SS.getRange(),
R.getLookupName(), R.getNameLoc(),
NeedsADL, R.isOverloadedResult());
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- ULE->addDecl(*I);
+ ULE->addDecls(R.begin(), R.end());
return Owned(ULE);
}
@@ -1616,8 +1653,7 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
if (cast<DeclContext>(currentDecl)->isDependentContext()) {
ResTy = Context.DependentTy;
} else {
- unsigned Length =
- PredefinedExpr::ComputeName(Context, IT, currentDecl).length();
+ unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
ResTy = Context.CharTy.withConst();
@@ -1642,6 +1678,8 @@ Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
Ty = Context.IntTy; // 'x' and L'x' -> int in C.
else if (Literal.isWide())
Ty = Context.WCharTy; // L'x' -> wchar_t in C++.
+ else if (Literal.isMultiChar())
+ Ty = Context.IntTy; // 'wxyz' -> int in C++.
else
Ty = Context.CharTy; // 'x' -> char in C++
@@ -2029,8 +2067,9 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
Expr *RHSExp = static_cast<Expr*>(Idx.get());
// Perform default conversions.
- DefaultFunctionArrayConversion(LHSExp);
- DefaultFunctionArrayConversion(RHSExp);
+ if (!LHSExp->getType()->getAs<VectorType>())
+ DefaultFunctionArrayLvalueConversion(LHSExp);
+ DefaultFunctionArrayLvalueConversion(RHSExp);
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
@@ -2072,7 +2111,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
ResultType = VTy->getElementType();
} else if (LHSTy->isArrayType()) {
// If we see an array that wasn't promoted by
- // DefaultFunctionArrayConversion, it must be an array that
+ // DefaultFunctionArrayLvalueConversion, it must be an array that
// wasn't promoted because of the C90 rule that doesn't
// allow promoting non-lvalue arrays. Warn, then
// force the promotion here.
@@ -2542,7 +2581,11 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
bool Dependent =
BaseExprType->isDependentType() ||
R.isUnresolvableResult() ||
- UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
+ OverloadExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
+
+ // Suppress any lookup-related diagnostics; we'll do these when we
+ // pick a member.
+ R.suppressDiagnostics();
UnresolvedMemberExpr *MemExpr
= UnresolvedMemberExpr::Create(Context, Dependent,
@@ -2552,8 +2595,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
Qualifier, SS.getRange(),
MemberName, MemberLoc,
TemplateArgs);
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- MemExpr->addDecl(*I);
+ MemExpr->addDecls(R.begin(), R.end());
return Owned(MemExpr);
}
@@ -3001,7 +3043,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (DiagnoseUseOfDecl(OMD, MemberLoc))
return ExprError();
- return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel,
+ return Owned(new (Context) ObjCMessageExpr(Context, BaseExpr, Sel,
OMD->getResultType(),
OMD, OpLoc, MemberLoc,
NULL, 0));
@@ -3248,7 +3290,8 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
// Instantiate the expression.
- MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD);
+ MultiLevelTemplateArgumentList ArgList
+ = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
InstantiatingTemplate Inst(*this, CallLoc, Param,
ArgList.getInnermost().getFlatArgumentList(),
@@ -3770,7 +3813,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle,
ConversionDecl);
- DefaultFunctionArrayConversion(castExpr);
+ DefaultFunctionArrayLvalueConversion(castExpr);
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
// type needs to be scalar.
@@ -4807,7 +4850,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
//
// Suppress this for references: C++ 8.5.3p5.
if (!lhsType->isReferenceType())
- DefaultFunctionArrayConversion(rExpr);
+ DefaultFunctionArrayLvalueConversion(rExpr);
Sema::AssignConvertType result =
CheckAssignmentConstraints(lhsType, rExpr->getType());
@@ -5690,6 +5733,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_SubObjCPropertySetting:
Diag = diag::error_no_subobject_property_setting;
break;
+ case Expr::MLV_SubObjCPropertyGetterSetting:
+ Diag = diag::error_no_subobject_property_getter_setting;
+ break;
}
SourceRange Assign;
@@ -5770,7 +5816,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
// C99 6.5.17
QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
// Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions.
- DefaultFunctionArrayConversion(RHS);
+ // C++ does not perform this conversion (C++ [expr.comma]p1).
+ if (!getLangOptions().CPlusPlus)
+ DefaultFunctionArrayLvalueConversion(RHS);
// FIXME: Check that RHS type is complete in C mode (it's legal for it to be
// incomplete in C++).
@@ -5961,8 +6009,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
Diag(OpLoc, diag::err_typecheck_address_of)
<< "bit-field" << op->getSourceRange();
return QualType();
- } else if (isa<ExtVectorElementExpr>(op) || (isa<ArraySubscriptExpr>(op) &&
- cast<ArraySubscriptExpr>(op)->getBase()->getType()->isVectorType())){
+ } else if (op->refersToVectorElement()) {
// The operand cannot be an element of a vector
Diag(OpLoc, diag::err_typecheck_address_of)
<< "vector element" << op->getSourceRange();
@@ -6337,17 +6384,11 @@ Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
// the arguments.
- FunctionSet Functions;
+ UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
- if (OverOp != OO_None) {
- if (S)
- LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
- Functions);
- Expr *Args[2] = { lhs, rhs };
- DeclarationName OpName
- = Context.DeclarationNames.getCXXOperatorName(OverOp);
- ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
- }
+ if (S && OverOp != OO_None)
+ LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
+ Functions);
// Build the (potentially-overloaded, potentially-dependent)
// binary operation.
@@ -6383,7 +6424,7 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
resultType = CheckAddressOfOperand(Input, OpLoc);
break;
case UnaryOperator::Deref:
- DefaultFunctionArrayConversion(Input);
+ DefaultFunctionArrayLvalueConversion(Input);
resultType = CheckIndirectionOperand(Input, OpLoc);
break;
case UnaryOperator::Plus:
@@ -6420,7 +6461,7 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
break;
case UnaryOperator::LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
- DefaultFunctionArrayConversion(Input);
+ DefaultFunctionArrayLvalueConversion(Input);
resultType = Input->getType();
if (resultType->isDependentType())
break;
@@ -6456,16 +6497,11 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
// the arguments.
- FunctionSet Functions;
+ UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
- if (OverOp != OO_None) {
- if (S)
- LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
- Functions);
- DeclarationName OpName
- = Context.DeclarationNames.getCXXOperatorName(OverOp);
- ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
- }
+ if (S && OverOp != OO_None)
+ LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+ Functions);
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
}
@@ -6595,7 +6631,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
// Promote the array so it looks more like a normal array subscript
// expression.
- DefaultFunctionArrayConversion(Res);
+ DefaultFunctionArrayLvalueConversion(Res);
// C99 6.5.2.1p1
Expr *Idx = static_cast<Expr*>(OC.U.E);
@@ -6772,6 +6808,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
return;
}
+
+ CurBlock->ReturnType = RetTy;
return;
}
@@ -6792,11 +6830,18 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
// empty arg list, don't push any params.
CurBlock->isVariadic = false;
} else if (FTI.hasPrototype) {
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
- CurBlock->Params.push_back(FTI.ArgInfo[i].Param.getAs<ParmVarDecl>());
+ for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
+ ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ if (Param->getIdentifier() == 0 &&
+ !Param->isImplicit() &&
+ !Param->isInvalidDecl() &&
+ !getLangOptions().CPlusPlus)
+ Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+ CurBlock->Params.push_back(Param);
+ }
CurBlock->isVariadic = FTI.isVariadic;
}
- CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(),
+ CurBlock->TheDecl->setParams(CurBlock->Params.data(),
CurBlock->Params.size());
CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
@@ -7255,6 +7300,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
// FIXME: keep track of references to static functions
Function->setUsed(true);
+
return;
}
@@ -7390,7 +7436,7 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
DiagnoseAssignmentAsCondition(E);
if (!E->isTypeDependent()) {
- DefaultFunctionArrayConversion(E);
+ DefaultFunctionArrayLvalueConversion(E);
QualType T = E->getType();
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index b004fc3..9eeda54 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -72,18 +72,17 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
if (const RecordType *RecordT = T->getAs<RecordType>()) {
CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
// C++ [expr.typeid]p3:
+ // [...] If the type of the expression is a class type, the class
+ // shall be completely-defined.
+ if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
+ return ExprError();
+
+ // C++ [expr.typeid]p3:
// When typeid is applied to an expression other than an lvalue of a
// polymorphic class type [...] [the] expression is an unevaluated
// operand. [...]
if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid)
isUnevaluatedOperand = false;
- else {
- // C++ [expr.typeid]p3:
- // [...] If the type of the expression is a class type, the class
- // shall be completely-defined.
- if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid))
- return ExprError();
- }
}
// C++ [expr.typeid]p4:
@@ -195,7 +194,9 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
MultiExprArg exprs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
- assert(TypeRep && "Missing type!");
+ if (!TypeRep)
+ return ExprError();
+
TypeSourceInfo *TInfo;
QualType Ty = GetTypeFromParser(TypeRep, &TInfo);
if (!TInfo)
@@ -263,29 +264,18 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
if (NumExprs > 1 || !Record->hasTrivialConstructor() ||
!Record->hasTrivialDestructor()) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-
- CXXConstructorDecl *Constructor
- = PerformInitializationByConstructor(Ty, move(exprs),
- TypeRange.getBegin(),
- SourceRange(TypeRange.getBegin(),
- RParenLoc),
- DeclarationName(),
- InitializationKind::CreateDirect(TypeRange.getBegin(),
- LParenLoc,
- RParenLoc),
- ConstructorArgs);
-
- if (!Constructor)
- return ExprError();
-
- OwningExprResult Result =
- BuildCXXTemporaryObjectExpr(Constructor, Ty, TyBeginLoc,
- move_arg(ConstructorArgs), RParenLoc);
- if (Result.isInvalid())
- return ExprError();
-
- return MaybeBindToTemporary(Result.takeAs<Expr>());
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty);
+ InitializationKind Kind
+ = NumExprs ? InitializationKind::CreateDirect(TypeRange.getBegin(),
+ LParenLoc, RParenLoc)
+ : InitializationKind::CreateValue(TypeRange.getBegin(),
+ LParenLoc, RParenLoc);
+ InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ move(exprs));
+
+ // FIXME: Improve AST representation?
+ return move(Result);
}
// Fall through to value-initialize an object of class type that
@@ -530,10 +520,13 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
PlacementArgs.release();
ConstructorArgs.release();
ArraySizeE.release();
- return Owned(new (Context) CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs,
- NumPlaceArgs, ParenTypeId, ArraySize, Constructor, Init,
- ConsArgs, NumConsArgs, OperatorDelete, ResultType,
- StartLoc, Init ? ConstructorRParen : SourceLocation()));
+ return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
+ PlaceArgs, NumPlaceArgs, ParenTypeId,
+ ArraySize, Constructor, Init,
+ ConsArgs, NumConsArgs, OperatorDelete,
+ ResultType, StartLoc,
+ Init ? ConstructorRParen :
+ SourceLocation()));
}
/// CheckAllocatedType - Checks that a type is suitable as the allocated type
@@ -636,19 +629,24 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// FIXME: handle ambiguity
- OverloadCandidateSet Candidates;
+ OverloadCandidateSet Candidates(StartLoc);
for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
Alloc != AllocEnd; ++Alloc) {
// Even member operator new/delete are implicitly treated as
// static, so don't use AddMemberCandidate.
- if (FunctionDecl *Fn =
- dyn_cast<FunctionDecl>((*Alloc)->getUnderlyingDecl())) {
- AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
- /*SuppressUserConversions=*/false);
+
+ if (FunctionTemplateDecl *FnTemplate =
+ dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) {
+ AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(),
+ /*ExplicitTemplateArgs=*/0, Args, NumArgs,
+ Candidates,
+ /*SuppressUserConversions=*/false);
continue;
- }
-
- // FIXME: Handle function templates
+ }
+
+ FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl());
+ AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates,
+ /*SuppressUserConversions=*/false);
}
// Do the resolution.
@@ -779,12 +777,16 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
DeclContext::lookup_iterator Alloc, AllocEnd;
for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
Alloc != AllocEnd; ++Alloc) {
- // FIXME: Do we need to check for default arguments here?
- FunctionDecl *Func = cast<FunctionDecl>(*Alloc);
- if (Func->getNumParams() == 1 &&
+ // Only look at non-template functions, as it is the predefined,
+ // non-templated allocation function we are trying to declare here.
+ if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
+ QualType InitialParamType =
Context.getCanonicalType(
- Func->getParamDecl(0)->getType().getUnqualifiedType()) == Argument)
- return;
+ Func->getParamDecl(0)->getType().getUnqualifiedType());
+ // FIXME: Do we need to check for default arguments here?
+ if (Func->getNumParams() == 1 && InitialParamType == Argument)
+ return;
+ }
}
}
@@ -812,7 +814,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
0, Argument, /*TInfo=*/0,
VarDecl::None, 0);
- Alloc->setParams(Context, &Param, 1);
+ Alloc->setParams(&Param, 1);
// FIXME: Also add this declaration to the IdentifierResolver, but
// make sure it is at the end of the chain to coincide with the
@@ -1487,9 +1489,9 @@ QualType Sema::CheckPointerToMemberOperands(
static QualType TargetType(const ImplicitConversionSequence &ICS) {
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
- return ICS.Standard.getToType();
+ return ICS.Standard.getToType(2);
case ImplicitConversionSequence::UserDefinedConversion:
- return ICS.UserDefined.After.getToType();
+ return ICS.UserDefined.After.getToType(2);
case ImplicitConversionSequence::AmbiguousConversion:
return ICS.Ambiguous.getToType();
case ImplicitConversionSequence::EllipsisConversion:
@@ -1587,7 +1589,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
SourceLocation Loc) {
Expr *Args[2] = { LHS, RHS };
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(Loc);
Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet);
OverloadCandidateSet::iterator Best;
@@ -1689,8 +1691,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LVoid || RVoid) {
// ... then the [l2r] conversions are performed on the second and third
// operands ...
- DefaultFunctionArrayConversion(LHS);
- DefaultFunctionArrayConversion(RHS);
+ DefaultFunctionArrayLvalueConversion(LHS);
+ DefaultFunctionArrayLvalueConversion(RHS);
LTy = LHS->getType();
RTy = RHS->getType();
@@ -1776,8 +1778,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C++0x 5.16p6
// LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
// conversions are performed on the second and third operands.
- DefaultFunctionArrayConversion(LHS);
- DefaultFunctionArrayConversion(RHS);
+ DefaultFunctionArrayLvalueConversion(LHS);
+ DefaultFunctionArrayLvalueConversion(RHS);
LTy = LHS->getType();
RTy = RHS->getType();
@@ -1987,10 +1989,8 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (!RT)
return Owned(E);
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialDestructor())
- return Owned(E);
-
+ // If this is the result of a call expression, our source might
+ // actually be a reference, in which case we shouldn't bind.
if (CallExpr *CE = dyn_cast<CallExpr>(E)) {
QualType Ty = CE->getCallee()->getType();
if (const PointerType *PT = Ty->getAs<PointerType>())
@@ -2000,6 +2000,13 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (FTy->getResultType()->isReferenceType())
return Owned(E);
}
+
+ // That should be enough to guarantee that this type is complete.
+ // If it has a trivial destructor, we can avoid the extra copy.
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialDestructor())
+ return Owned(E);
+
CXXTemporary *Temp = CXXTemporary::Create(Context,
RD->getDestructor(Context));
ExprTemporaries.push_back(Temp);
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index ea8f4e3..0c5d8ef 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -470,11 +470,13 @@ Sema::ExprResult Sema::ActOnClassMessage(
// now, we simply pass the "super" identifier through (which isn't consistent
// with instance methods.
if (isSuper)
- return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method,
- lbrac, rbrac, ArgExprs, NumArgs);
+ return new (Context) ObjCMessageExpr(Context, receiverName, Sel, returnType,
+ Method, lbrac, rbrac, ArgExprs,
+ NumArgs);
else
- return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method,
- lbrac, rbrac, ArgExprs, NumArgs);
+ return new (Context) ObjCMessageExpr(Context, ClassDecl, Sel, returnType,
+ Method, lbrac, rbrac, ArgExprs,
+ NumArgs);
}
// ActOnInstanceMessage - used for both unary and keyword messages.
@@ -492,7 +494,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
- DefaultFunctionArrayConversion(RExpr);
+ DefaultFunctionArrayLvalueConversion(RExpr);
QualType returnType;
QualType ReceiverCType =
@@ -521,8 +523,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
return true;
returnType = returnType.getNonReferenceType();
- return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
- rbrac, ArgExprs, NumArgs);
+ return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType,
+ Method, lbrac, rbrac,
+ ArgExprs, NumArgs);
}
// Handle messages to id.
@@ -536,8 +539,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
lbrac, rbrac, returnType))
return true;
returnType = returnType.getNonReferenceType();
- return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
- rbrac, ArgExprs, NumArgs);
+ return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType,
+ Method, lbrac, rbrac,
+ ArgExprs, NumArgs);
}
// Handle messages to Class.
@@ -582,8 +586,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
lbrac, rbrac, returnType))
return true;
returnType = returnType.getNonReferenceType();
- return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
- rbrac, ArgExprs, NumArgs);
+ return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType,
+ Method, lbrac, rbrac,
+ ArgExprs, NumArgs);
}
ObjCMethodDecl *Method = 0;
@@ -665,7 +670,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
lbrac, rbrac, returnType))
return true;
returnType = returnType.getNonReferenceType();
- return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
- rbrac, ArgExprs, NumArgs);
+ return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, Method,
+ lbrac, rbrac, ArgExprs, NumArgs);
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index fd62e1a..7b4a417 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -66,40 +66,6 @@ static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
return 0;
}
-static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
- bool DirectInit, Sema &S) {
- // Get the type before calling CheckSingleAssignmentConstraints(), since
- // it can promote the expression.
- QualType InitType = Init->getType();
-
- if (S.getLangOptions().CPlusPlus) {
- // FIXME: I dislike this error message. A lot.
- if (S.PerformImplicitConversion(Init, DeclType,
- Sema::AA_Initializing, DirectInit)) {
- ImplicitConversionSequence ICS;
- OverloadCandidateSet CandidateSet;
- if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined,
- CandidateSet,
- true, false, false) != OR_Ambiguous)
- return S.Diag(Init->getSourceRange().getBegin(),
- diag::err_typecheck_convert_incompatible)
- << DeclType << Init->getType() << Sema::AA_Initializing
- << Init->getSourceRange();
- S.Diag(Init->getSourceRange().getBegin(),
- diag::err_typecheck_convert_ambiguous)
- << DeclType << Init->getType() << Init->getSourceRange();
- S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates, &Init, 1);
- return true;
- }
- return false;
- }
-
- Sema::AssignConvertType ConvTy =
- S.CheckSingleAssignmentConstraints(DeclType, Init);
- return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
- InitType, Init, Sema::AA_Initializing);
-}
-
static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
// Get the length of the string as parsed.
uint64_t StrLength =
@@ -174,47 +140,57 @@ class InitListChecker {
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
- void CheckImplicitInitList(InitListExpr *ParentIList, QualType T,
+ void CheckImplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *ParentIList, QualType T,
unsigned &Index, InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
- void CheckExplicitInitList(InitListExpr *IList, QualType &T,
+ void CheckExplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &T,
unsigned &Index, InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
- void CheckListElementTypes(InitListExpr *IList, QualType &DeclType,
+ void CheckListElementTypes(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &DeclType,
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
- void CheckSubElementType(InitListExpr *IList, QualType ElemType,
+ void CheckSubElementType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
- void CheckScalarType(InitListExpr *IList, QualType DeclType,
+ void CheckScalarType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
- void CheckReferenceType(InitListExpr *IList, QualType DeclType,
+ void CheckReferenceType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
- void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index,
+ void CheckVectorType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
- void CheckStructUnionTypes(InitListExpr *IList, QualType DeclType,
+ void CheckStructUnionTypes(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
RecordDecl::field_iterator Field,
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
- void CheckArrayType(InitListExpr *IList, QualType &DeclType,
+ void CheckArrayType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &DeclType,
llvm::APSInt elementIndex,
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
- bool CheckDesignatedInitializer(InitListExpr *IList, DesignatedInitExpr *DIE,
+ bool CheckDesignatedInitializer(const InitializedEntity &Entity,
+ InitListExpr *IList, DesignatedInitExpr *DIE,
unsigned DesigIdx,
QualType &CurrentObjectType,
RecordDecl::field_iterator *NextField,
@@ -433,7 +409,8 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
unsigned newStructuredIndex = 0;
FullyStructuredList
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
- CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex,
+ CheckExplicitInitList(Entity, IL, T, newIndex,
+ FullyStructuredList, newStructuredIndex,
/*TopLevelObject=*/true);
if (!hadError) {
@@ -470,7 +447,8 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
-void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
+void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *ParentIList,
QualType T, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
@@ -504,7 +482,8 @@ void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
// Check the element types and build the structural subobject.
unsigned StartIndex = Index;
- CheckListElementTypes(ParentIList, T, false, Index,
+ CheckListElementTypes(Entity, ParentIList, T,
+ /*SubobjectIsDesignatorContext=*/false, Index,
StructuredSubobjectInitList,
StructuredSubobjectInitIndex,
TopLevelObject);
@@ -520,7 +499,8 @@ void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
}
}
-void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
+void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &T,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
@@ -528,10 +508,10 @@ void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
- CheckListElementTypes(IList, T, true, Index, StructuredList,
- StructuredIndex, TopLevelObject);
- IList->setType(T);
- StructuredList->setType(T);
+ CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
+ Index, StructuredList, StructuredIndex, TopLevelObject);
+ IList->setType(T.getNonReferenceType());
+ StructuredList->setType(T.getNonReferenceType());
if (hadError)
return;
@@ -580,7 +560,8 @@ void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
<< CodeModificationHint::CreateRemoval(IList->getLocEnd());
}
-void InitListChecker::CheckListElementTypes(InitListExpr *IList,
+void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
+ InitListExpr *IList,
QualType &DeclType,
bool SubobjectIsDesignatorContext,
unsigned &Index,
@@ -588,13 +569,15 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList,
unsigned &StructuredIndex,
bool TopLevelObject) {
if (DeclType->isScalarType()) {
- CheckScalarType(IList, DeclType, Index, StructuredList, StructuredIndex);
+ CheckScalarType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
} else if (DeclType->isVectorType()) {
- CheckVectorType(IList, DeclType, Index, StructuredList, StructuredIndex);
+ CheckVectorType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
} else if (DeclType->isAggregateType()) {
if (DeclType->isRecordType()) {
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
- CheckStructUnionTypes(IList, DeclType, RD->field_begin(),
+ CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(),
SubobjectIsDesignatorContext, Index,
StructuredList, StructuredIndex,
TopLevelObject);
@@ -602,7 +585,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList,
llvm::APSInt Zero(
SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
false);
- CheckArrayType(IList, DeclType, Zero, SubobjectIsDesignatorContext, Index,
+ CheckArrayType(Entity, IList, DeclType, Zero,
+ SubobjectIsDesignatorContext, Index,
StructuredList, StructuredIndex);
} else
assert(0 && "Aggregate that isn't a structure or array?!");
@@ -625,7 +609,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList,
<< DeclType << IList->getSourceRange();
hadError = true;
} else if (DeclType->isReferenceType()) {
- CheckReferenceType(IList, DeclType, Index, StructuredList, StructuredIndex);
+ CheckReferenceType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
} else {
// In C, all types are either scalars or aggregates, but
// additional handling is needed here for C++ (and possibly others?).
@@ -633,7 +618,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList,
}
}
-void InitListChecker::CheckSubElementType(InitListExpr *IList,
+void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
+ InitListExpr *IList,
QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
@@ -646,7 +632,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
= getStructuredSubobjectInit(IList, Index, ElemType,
StructuredList, StructuredIndex,
SubInitList->getSourceRange());
- CheckExplicitInitList(SubInitList, ElemType, newIndex,
+ CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex,
newStructuredList, newStructuredIndex);
++StructuredIndex;
++Index;
@@ -655,9 +641,11 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
++Index;
} else if (ElemType->isScalarType()) {
- CheckScalarType(IList, ElemType, Index, StructuredList, StructuredIndex);
+ CheckScalarType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
} else if (ElemType->isReferenceType()) {
- CheckReferenceType(IList, ElemType, Index, StructuredList, StructuredIndex);
+ CheckReferenceType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
} else {
if (SemaRef.getLangOptions().CPlusPlus) {
// C++ [dcl.init.aggr]p12:
@@ -665,17 +653,21 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
// initializing the aggregate member with an ini- tializer from
// an initializer-list. If the initializer can initialize a
// member, the member is initialized. [...]
- ImplicitConversionSequence ICS
- = SemaRef.TryCopyInitialization(expr, ElemType,
- /*SuppressUserConversions=*/false,
- /*ForceRValue=*/false,
- /*InOverloadResolution=*/false);
-
- if (!ICS.isBad()) {
- if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS,
- Sema::AA_Initializing))
+
+ // FIXME: Better EqualLoc?
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+ InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
+
+ if (Seq) {
+ Sema::OwningExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind,
+ Sema::MultiExprArg(SemaRef, (void **)&expr, 1));
+ if (Result.isInvalid())
hadError = true;
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ Result.takeAs<Expr>());
++Index;
return;
}
@@ -707,13 +699,15 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
// considered for the initialization of the first member of
// the subaggregate.
if (ElemType->isAggregateType() || ElemType->isVectorType()) {
- CheckImplicitInitList(IList, ElemType, Index, StructuredList,
+ CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
StructuredIndex);
++StructuredIndex;
} else {
// We cannot initialize this element, so let
// PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(expr, ElemType, Sema::AA_Initializing);
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+ SemaRef.Owned(expr));
+ IList->setInit(Index, 0);
hadError = true;
++Index;
++StructuredIndex;
@@ -721,7 +715,8 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
}
}
-void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType,
+void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
@@ -745,17 +740,26 @@ void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType,
return;
}
- Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
- if (CheckSingleInitializer(expr, DeclType, false, SemaRef))
+ Sema::OwningExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+ SemaRef.Owned(expr));
+
+ Expr *ResultExpr = 0;
+
+ if (Result.isInvalid())
hadError = true; // types weren't compatible.
- else if (savExpr != expr) {
- // The type was promoted, update initializer list.
- IList->setInit(Index, expr);
+ else {
+ ResultExpr = Result.takeAs<Expr>();
+
+ if (ResultExpr != expr) {
+ // The type was promoted, update initializer list.
+ IList->setInit(Index, ResultExpr);
+ }
}
if (hadError)
++StructuredIndex;
else
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
++Index;
} else {
SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
@@ -767,7 +771,8 @@ void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType,
}
}
-void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType,
+void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
@@ -782,17 +787,16 @@ void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType,
return;
}
- Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
- if (SemaRef.CheckReferenceInit(expr, DeclType,
- /*FIXME:*/expr->getLocStart(),
- /*SuppressUserConversions=*/false,
- /*AllowExplicit=*/false,
- /*ForceRValue=*/false))
+ Sema::OwningExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+ SemaRef.Owned(expr));
+
+ if (Result.isInvalid())
hadError = true;
- else if (savExpr != expr) {
- // The type was promoted, update initializer list.
- IList->setInit(Index, expr);
- }
+
+ expr = Result.takeAs<Expr>();
+ IList->setInit(Index, expr);
+
if (hadError)
++StructuredIndex;
else
@@ -814,7 +818,8 @@ void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType,
}
}
-void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
+void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
@@ -825,22 +830,33 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
QualType elementType = VT->getElementType();
if (!SemaRef.getLangOptions().OpenCL) {
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits())
break;
- CheckSubElementType(IList, elementType, Index,
+
+ ElementEntity.setElementIndex(Index);
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
StructuredList, StructuredIndex);
}
} else {
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
// OpenCL initializers allows vectors to be constructed from vectors.
for (unsigned i = 0; i < maxElements; ++i) {
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits())
break;
+
+ ElementEntity.setElementIndex(Index);
+
QualType IType = IList->getInit(Index)->getType();
if (!IType->isVectorType()) {
- CheckSubElementType(IList, elementType, Index,
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
StructuredList, StructuredIndex);
++numEltsInit;
} else {
@@ -848,7 +864,7 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
unsigned numIElts = IVT->getNumElements();
QualType VecType = SemaRef.Context.getExtVectorType(elementType,
numIElts);
- CheckSubElementType(IList, VecType, Index,
+ CheckSubElementType(ElementEntity, IList, VecType, Index,
StructuredList, StructuredIndex);
numEltsInit += numIElts;
}
@@ -864,7 +880,8 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
}
}
-void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
+void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType &DeclType,
llvm::APSInt elementIndex,
bool SubobjectIsDesignatorContext,
unsigned &Index,
@@ -925,7 +942,7 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
// Handle this designated initializer. elementIndex will be
// updated to be the next array element we'll initialize.
- if (CheckDesignatedInitializer(IList, DIE, 0,
+ if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
DeclType, 0, &elementIndex, Index,
StructuredList, StructuredIndex, true,
false)) {
@@ -952,8 +969,11 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
if (maxElementsKnown && elementIndex == maxElements)
break;
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
+ Entity);
// Check this element.
- CheckSubElementType(IList, elementType, Index,
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
StructuredList, StructuredIndex);
++elementIndex;
@@ -978,7 +998,8 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
}
}
-void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
+void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
+ InitListExpr *IList,
QualType DeclType,
RecordDecl::field_iterator Field,
bool SubobjectIsDesignatorContext,
@@ -1027,7 +1048,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
// Handle this designated initializer. Field will be updated to
// the next field that we'll be initializing.
- if (CheckDesignatedInitializer(IList, DIE, 0,
+ if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
DeclType, &Field, 0, Index,
StructuredList, StructuredIndex,
true, TopLevelObject))
@@ -1056,7 +1077,9 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
continue;
}
- CheckSubElementType(IList, Field->getType(), Index,
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
StructuredList, StructuredIndex);
InitializedSomething = true;
@@ -1092,12 +1115,15 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
<< *Field;
}
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+
if (isa<InitListExpr>(IList->getInit(Index)))
- CheckSubElementType(IList, Field->getType(), Index, StructuredList,
- StructuredIndex);
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+ StructuredList, StructuredIndex);
else
- CheckImplicitInitList(IList, Field->getType(), Index, StructuredList,
- StructuredIndex);
+ CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
+ StructuredList, StructuredIndex);
}
/// \brief Expand a field designator that refers to a member of an
@@ -1194,7 +1220,8 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
///
/// @returns true if there was an error, false otherwise.
bool
-InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
+InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
+ InitListExpr *IList,
DesignatedInitExpr *DIE,
unsigned DesigIdx,
QualType &CurrentObjectType,
@@ -1215,7 +1242,7 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
unsigned OldIndex = Index;
IList->setInit(OldIndex, DIE->getInit());
- CheckSubElementType(IList, CurrentObjectType, Index,
+ CheckSubElementType(Entity, IList, CurrentObjectType, Index,
StructuredList, StructuredIndex);
// Restore the designated initializer expression in the syntactic
@@ -1423,8 +1450,12 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
unsigned newStructuredIndex = FieldIndex;
unsigned OldIndex = Index;
IList->setInit(Index, DIE->getInit());
- CheckSubElementType(IList, Field->getType(), Index,
+
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
StructuredList, newStructuredIndex);
+
IList->setInit(OldIndex, DIE);
if (hadError && !prevHadError) {
++Field;
@@ -1438,8 +1469,12 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
// Recurse to check later designated subobjects.
QualType FieldType = (*Field)->getType();
unsigned newStructuredIndex = FieldIndex;
- if (CheckDesignatedInitializer(IList, DIE, DesigIdx + 1, FieldType, 0, 0,
- Index, StructuredList, newStructuredIndex,
+
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(*Field, &Entity);
+ if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
+ FieldType, 0, 0, Index,
+ StructuredList, newStructuredIndex,
true, false))
return true;
}
@@ -1467,7 +1502,8 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
// Check the remaining fields within this class/struct/union subobject.
bool prevHadError = hadError;
- CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
+
+ CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
StructuredList, FieldIndex);
return hadError && !prevHadError;
}
@@ -1552,12 +1588,19 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
// Move to the next designator
unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
unsigned OldIndex = Index;
+
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
while (DesignatedStartIndex <= DesignatedEndIndex) {
// Recurse to check later designated subobjects.
QualType ElementType = AT->getElementType();
Index = OldIndex;
- if (CheckDesignatedInitializer(IList, DIE, DesigIdx + 1, ElementType, 0, 0,
- Index, StructuredList, ElementIndex,
+
+ ElementEntity.setElementIndex(ElementIndex);
+ if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
+ ElementType, 0, 0, Index,
+ StructuredList, ElementIndex,
(DesignatedStartIndex == DesignatedEndIndex),
false))
return true;
@@ -1581,7 +1624,8 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
// Check the remaining elements within this array subobject.
bool prevHadError = hadError;
- CheckArrayType(IList, CurrentObjectType, DesignatedStartIndex, false, Index,
+ CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
+ /*SubobjectIsDesignatorContext=*/false, Index,
StructuredList, ElementIndex);
return hadError && !prevHadError;
}
@@ -1628,7 +1672,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
= new (SemaRef.Context) InitListExpr(InitRange.getBegin(), 0, 0,
InitRange.getEnd());
- Result->setType(CurrentObjectType);
+ Result->setType(CurrentObjectType.getNonReferenceType());
// Pre-allocate storage for the structured initializer list.
unsigned NumElements = 0;
@@ -1927,7 +1971,8 @@ void InitializationSequence::AddAddressOverloadResolutionStep(
Step S;
S.Kind = SK_ResolveAddressOfOverloadedFunction;
S.Type = Function->getType();
- S.Function = Function;
+ // Access is currently ignored for these.
+ S.Function = DeclAccessPair::make(Function, AccessSpecifier(0));
Steps.push_back(S);
}
@@ -1948,11 +1993,12 @@ void InitializationSequence::AddReferenceBindingStep(QualType T,
}
void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
+ AccessSpecifier Access,
QualType T) {
Step S;
S.Kind = SK_UserConversion;
S.Type = T;
- S.Function = Function;
+ S.Function = DeclAccessPair::make(Function, Access);
Steps.push_back(S);
}
@@ -1985,11 +2031,12 @@ void InitializationSequence::AddListInitializationStep(QualType T) {
void
InitializationSequence::AddConstructorInitializationStep(
CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
QualType T) {
Step S;
S.Kind = SK_ConstructorInitialization;
S.Type = T;
- S.Function = Constructor;
+ S.Function = DeclAccessPair::make(Constructor, Access);
Steps.push_back(S);
}
@@ -2129,10 +2176,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ S.AddTemplateOverloadCandidate(ConstructorTmpl,
+ ConstructorTmpl->getAccess(),
+ /*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet);
else
- S.AddOverloadCandidate(Constructor, &Initializer, 1, CandidateSet);
+ S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+ &Initializer, 1, CandidateSet);
}
}
}
@@ -2172,11 +2222,12 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if ((AllowExplicit || !Conv->isExplicit()) &&
(AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer,
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
+ ActingDC, Initializer,
ToType, CandidateSet);
else
- S.AddConversionCandidate(Conv, ActingDC, Initializer, cv1T1,
- CandidateSet);
+ S.AddConversionCandidate(Conv, I.getAccess(), ActingDC,
+ Initializer, cv1T1, CandidateSet);
}
}
}
@@ -2198,7 +2249,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
T2 = cv1T1;
// Add the user-defined conversion step.
- Sequence.AddUserConversionStep(Function, T2.getNonReferenceType());
+ Sequence.AddUserConversionStep(Function, Best->getAccess(),
+ T2.getNonReferenceType());
// Determine whether we need to perform derived-to-base or
// cv-qualification adjustments.
@@ -2281,16 +2333,20 @@ static void TryReferenceInitialization(Sema &S,
// - is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
//
- // Per C++ [over.best.ics]p2, we ignore whether the lvalue is a
+ // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
// bit-field when we're determining whether the reference initialization
- // can occur. This property will be checked by PerformInitialization.
+ // can occur. However, we do pay attention to whether it is a bit-field
+ // to decide whether we're actually binding to a temporary created from
+ // the bit-field.
if (DerivedToBase)
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1, T2Quals),
/*isLValue=*/true);
if (T1Quals != T2Quals)
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
- Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false);
+ bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+ (Initializer->getBitField() || Initializer->refersToVectorElement());
+ Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
return;
}
@@ -2319,7 +2375,7 @@ static void TryReferenceInitialization(Sema &S,
// non-volatile const type (i.e., cv1 shall be const), or the reference
// shall be an rvalue reference and the initializer expression shall
// be an rvalue.
- if (!((isLValueRef && T1Quals.hasConst()) ||
+ if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) ||
(isRValueRef && InitLvalue != Expr::LV_Valid))) {
if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
Sequence.SetOverloadFailure(
@@ -2489,10 +2545,13 @@ static void TryConstructorInitialization(Sema &S,
if (!Constructor->isInvalidDecl() &&
(AllowExplicit || !Constructor->isExplicit())) {
if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ S.AddTemplateOverloadCandidate(ConstructorTmpl,
+ ConstructorTmpl->getAccess(),
+ /*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet);
else
- S.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+ S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+ Args, NumArgs, CandidateSet);
}
}
@@ -2507,14 +2566,26 @@ static void TryConstructorInitialization(Sema &S,
Result);
return;
}
-
+
+ // C++0x [dcl.init]p6:
+ // If a program calls for the default initialization of an object
+ // of a const-qualified type T, T shall be a class type with a
+ // user-provided default constructor.
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ Entity.getType().isConstQualified() &&
+ cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ return;
+ }
+
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
if (Kind.getKind() == InitializationKind::IK_Copy) {
- Sequence.AddUserConversionStep(Best->Function, DestType);
+ Sequence.AddUserConversionStep(Best->Function, Best->getAccess(), DestType);
} else {
Sequence.AddConstructorInitializationStep(
cast<CXXConstructorDecl>(Best->Function),
+ Best->getAccess(),
DestType);
}
}
@@ -2579,10 +2650,7 @@ static void TryDefaultInitialization(Sema &S,
// - if T is a (possibly cv-qualified) class type (Clause 9), the default
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
- if (DestType->isRecordType()) {
- // FIXME: If a program calls for the default initialization of an object of
- // a const-qualified type T, T shall be a class type with a user-provided
- // default constructor.
+ if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
Sequence);
}
@@ -2593,7 +2661,7 @@ static void TryDefaultInitialization(Sema &S,
// If a program calls for the default initialization of an object of
// a const-qualified type T, T shall be a class type with a user-provided
// default constructor.
- if (DestType.isConstQualified())
+ if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus)
Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
}
@@ -2647,10 +2715,13 @@ static void TryUserDefinedConversion(Sema &S,
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ S.AddTemplateOverloadCandidate(ConstructorTmpl,
+ ConstructorTmpl->getAccess(),
+ /*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet);
else
- S.AddOverloadCandidate(Constructor, &Initializer, 1, CandidateSet);
+ S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+ &Initializer, 1, CandidateSet);
}
}
}
@@ -2686,12 +2757,12 @@ static void TryUserDefinedConversion(Sema &S,
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, ActingDC,
- Initializer, DestType,
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
+ ActingDC, Initializer, DestType,
CandidateSet);
else
- S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType,
- CandidateSet);
+ S.AddConversionCandidate(Conv, I.getAccess(), ActingDC,
+ Initializer, DestType, CandidateSet);
}
}
}
@@ -2712,13 +2783,13 @@ static void TryUserDefinedConversion(Sema &S,
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
// subsumed by the initialization.
- Sequence.AddUserConversionStep(Function, DestType);
+ Sequence.AddUserConversionStep(Function, Best->getAccess(), DestType);
return;
}
// Add the user-defined conversion step that calls the conversion function.
QualType ConvType = Function->getResultType().getNonReferenceType();
- Sequence.AddUserConversionStep(Function, ConvType);
+ Sequence.AddUserConversionStep(Function, Best->getAccess(), ConvType);
// If the conversion following the call to the conversion function is
// interesting, add it as a separate step.
@@ -2758,7 +2829,8 @@ InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr **Args,
- unsigned NumArgs) {
+ unsigned NumArgs)
+ : FailedCandidateSet(Kind.getLocation()) {
ASTContext &Context = S.Context;
// C++0x [dcl.init]p16:
@@ -2934,15 +3006,15 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity,
bool IsCopy) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
- case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Member:
return !IsCopy;
case InitializedEntity::EK_New:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
- case InitializedEntity::EK_Member:
- case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_Exception:
return false;
case InitializedEntity::EK_Parameter:
@@ -2960,6 +3032,8 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Sema::OwningExprResult CurInit) {
+ Expr *CurInitExpr = (Expr *)CurInit.get();
+
SourceLocation Loc;
switch (Entity.getKind()) {
@@ -2980,6 +3054,14 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
Loc = Entity.getDecl()->getLocation();
break;
+ case InitializedEntity::EK_ArrayElement:
+ case InitializedEntity::EK_Member:
+ if (Entity.getType()->isReferenceType() ||
+ Kind.getKind() != InitializationKind::IK_Copy)
+ return move(CurInit);
+ Loc = CurInitExpr->getLocStart();
+ break;
+
case InitializedEntity::EK_Parameter:
// FIXME: Do we need this initialization for a parameter?
return move(CurInit);
@@ -2987,14 +3069,11 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
case InitializedEntity::EK_New:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_Base:
- case InitializedEntity::EK_Member:
- case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
// We don't need to copy for any of these initialized entities.
return move(CurInit);
}
- Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = 0;
if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
@@ -3006,7 +3085,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
= S.Context.DeclarationNames.getCXXConstructorName(
S.Context.getCanonicalType(S.Context.getTypeDeclType(Class)));
DeclContext::lookup_iterator Con, ConEnd;
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(Loc);
for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName);
Con != ConEnd; ++Con) {
// Find the constructor (which may be a template).
@@ -3015,7 +3094,8 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
!Constructor->isCopyConstructor())
continue;
- S.AddOverloadCandidate(Constructor, &CurInitExpr, 1, CandidateSet);
+ S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
+ &CurInitExpr, 1, CandidateSet);
}
OverloadCandidateSet::iterator Best;
@@ -3111,6 +3191,9 @@ InitializationSequence::Perform(Sema &S,
if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast())
return Sema::OwningExprResult(S, Args.release()[0]);
+ if (Args.size() == 0)
+ return S.Owned((Expr *)0);
+
unsigned NumArgs = Args.size();
return S.Owned(new (S.Context) ParenListExpr(S.Context,
SourceLocation(),
@@ -3176,7 +3259,9 @@ InitializationSequence::Perform(Sema &S,
case SK_ResolveAddressOfOverloadedFunction:
// Overload resolution determined which function invoke; update the
// initializer to reflect that choice.
- CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function);
+ // Access control was done in overload resolution.
+ CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+ cast<FunctionDecl>(Step->Function.getDecl()));
break;
case SK_CastDerivedToBaseRValue:
@@ -3209,21 +3294,30 @@ InitializationSequence::Perform(Sema &S,
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
return S.ExprError();
}
+
+ if (CurInitExpr->refersToVectorElement()) {
+ // References cannot bind to vector elements.
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+ << Entity.getType().isVolatileQualified()
+ << CurInitExpr->getSourceRange();
+ return S.ExprError();
+ }
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
return S.ExprError();
+
break;
-
+
case SK_BindReferenceToTemporary:
+ // Reference binding does not have any corresponding ASTs.
+
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
return S.ExprError();
- // FIXME: At present, we have no AST to describe when we need to make a
- // temporary to bind a reference to. We should.
break;
case SK_UserConversion: {
@@ -3231,13 +3325,14 @@ InitializationSequence::Perform(Sema &S,
// or a conversion function.
CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
bool IsCopy = false;
- if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(Step->Function)) {
+ FunctionDecl *Fn = cast<FunctionDecl>(Step->Function.getDecl());
+ AccessSpecifier FnAccess = Step->Function.getAccess();
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
SourceLocation Loc = CurInitExpr->getLocStart();
CurInit.release(); // Ownership transferred into MultiExprArg, below.
-
+
// Determine the arguments required to actually perform the constructor
// call.
if (S.CompleteConstructorCall(Constructor,
@@ -3252,6 +3347,8 @@ InitializationSequence::Perform(Sema &S,
move_arg(ConstructorArgs));
if (CurInit.isInvalid())
return S.ExprError();
+
+ S.CheckConstructorAccess(Kind.getLocation(), Constructor, FnAccess);
CastKind = CastExpr::CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
@@ -3260,8 +3357,11 @@ InitializationSequence::Perform(Sema &S,
IsCopy = true;
} else {
// Build a call to the conversion function.
- CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Step->Function);
+ CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
+ S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr,
+ Conversion, FnAccess);
+
// FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
@@ -3326,8 +3426,8 @@ InitializationSequence::Perform(Sema &S,
case SK_ConstructorInitialization: {
CXXConstructorDecl *Constructor
- = cast<CXXConstructorDecl>(Step->Function);
-
+ = cast<CXXConstructorDecl>(Step->Function.getDecl());
+
// Build a call to the selected constructor.
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
SourceLocation Loc = Kind.getLocation();
@@ -3342,9 +3442,13 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Constructor,
move_arg(ConstructorArgs),
- ConstructorInitRequiresZeroInit);
+ ConstructorInitRequiresZeroInit,
+ Entity.getKind() == InitializedEntity::EK_Base);
if (CurInit.isInvalid())
return S.ExprError();
+
+ // Only check access if all of that succeeded.
+ S.CheckConstructorAccess(Loc, Constructor, Step->Function.getAccess());
bool Elidable
= cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
@@ -3422,8 +3526,13 @@ bool InitializationSequence::Diagnose(Sema &S,
QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
- S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
- << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+ // FIXME: Customize for the initialized entity?
+ if (NumArgs == 0)
+ S.Diag(Kind.getLocation(), diag::err_reference_without_init)
+ << DestType.getNonReferenceType();
+ else // FIXME: diagnostic below could be better!
+ S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+ << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
break;
case FK_ArrayNeedsInitList:
@@ -3492,6 +3601,7 @@ bool InitializationSequence::Diagnose(Sema &S,
Failure == FK_NonConstLValueReferenceBindingToTemporary
? diag::err_lvalue_reference_bind_to_temporary
: diag::err_lvalue_reference_bind_to_unrelated)
+ << DestType.getNonReferenceType().isVolatileQualified()
<< DestType.getNonReferenceType()
<< Args[0]->getType()
<< Args[0]->getSourceRange();
@@ -3567,6 +3677,45 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
case OR_No_Viable_Function:
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ (Entity.getKind() == InitializedEntity::EK_Base ||
+ Entity.getKind() == InitializedEntity::EK_Member) &&
+ isa<CXXConstructorDecl>(S.CurContext)) {
+ // This is implicit default initialization of a member or
+ // base within a constructor. If no viable function was
+ // found, notify the user that she needs to explicitly
+ // initialize this base/member.
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(S.CurContext);
+ if (Entity.getKind() == InitializedEntity::EK_Base) {
+ S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*base=*/0
+ << Entity.getType();
+
+ RecordDecl *BaseDecl
+ = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
+ ->getDecl();
+ S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
+ << S.Context.getTagDeclType(BaseDecl);
+ } else {
+ S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*member=*/1
+ << Entity.getName();
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+
+ if (const RecordType *Record
+ = Entity.getType()->getAs<RecordType>())
+ S.Diag(Record->getDecl()->getLocation(),
+ diag::note_previous_decl)
+ << S.Context.getTagDeclType(Record->getDecl());
+ }
+ break;
+ }
+
S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
<< DestType << ArgsRange;
S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
@@ -3597,14 +3746,217 @@ bool InitializationSequence::Diagnose(Sema &S,
}
case FK_DefaultInitOfConst:
- S.Diag(Kind.getLocation(), diag::err_default_init_const)
- << DestType;
+ if (Entity.getKind() == InitializedEntity::EK_Member &&
+ isa<CXXConstructorDecl>(S.CurContext)) {
+ // This is implicit default-initialization of a const member in
+ // a constructor. Complain that it needs to be explicitly
+ // initialized.
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
+ S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*const=*/1
+ << Entity.getName();
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+ << Entity.getName();
+ } else {
+ S.Diag(Kind.getLocation(), diag::err_default_init_const)
+ << DestType << (bool)DestType->getAs<RecordType>();
+ }
break;
}
return true;
}
+void InitializationSequence::dump(llvm::raw_ostream &OS) const {
+ switch (SequenceKind) {
+ case FailedSequence: {
+ OS << "Failed sequence: ";
+ switch (Failure) {
+ case FK_TooManyInitsForReference:
+ OS << "too many initializers for reference";
+ break;
+
+ case FK_ArrayNeedsInitList:
+ OS << "array requires initializer list";
+ break;
+
+ case FK_ArrayNeedsInitListOrStringLiteral:
+ OS << "array requires initializer list or string literal";
+ break;
+
+ case FK_AddressOfOverloadFailed:
+ OS << "address of overloaded function failed";
+ break;
+
+ case FK_ReferenceInitOverloadFailed:
+ OS << "overload resolution for reference initialization failed";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToTemporary:
+ OS << "non-const lvalue reference bound to temporary";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToUnrelated:
+ OS << "non-const lvalue reference bound to unrelated type";
+ break;
+
+ case FK_RValueReferenceBindingToLValue:
+ OS << "rvalue reference bound to an lvalue";
+ break;
+
+ case FK_ReferenceInitDropsQualifiers:
+ OS << "reference initialization drops qualifiers";
+ break;
+
+ case FK_ReferenceInitFailed:
+ OS << "reference initialization failed";
+ break;
+
+ case FK_ConversionFailed:
+ OS << "conversion failed";
+ break;
+
+ case FK_TooManyInitsForScalar:
+ OS << "too many initializers for scalar";
+ break;
+
+ case FK_ReferenceBindingToInitList:
+ OS << "referencing binding to initializer list";
+ break;
+
+ case FK_InitListBadDestinationType:
+ OS << "initializer list for non-aggregate, non-scalar type";
+ break;
+
+ case FK_UserConversionOverloadFailed:
+ OS << "overloading failed for user-defined conversion";
+ break;
+
+ case FK_ConstructorOverloadFailed:
+ OS << "constructor overloading failed";
+ break;
+
+ case FK_DefaultInitOfConst:
+ OS << "default initialization of a const variable";
+ break;
+ }
+ OS << '\n';
+ return;
+ }
+
+ case DependentSequence:
+ OS << "Dependent sequence: ";
+ return;
+
+ case UserDefinedConversion:
+ OS << "User-defined conversion sequence: ";
+ break;
+
+ case ConstructorInitialization:
+ OS << "Constructor initialization sequence: ";
+ break;
+
+ case ReferenceBinding:
+ OS << "Reference binding: ";
+ break;
+
+ case ListInitialization:
+ OS << "List initialization: ";
+ break;
+
+ case ZeroInitialization:
+ OS << "Zero initialization\n";
+ return;
+
+ case NoInitialization:
+ OS << "No initialization\n";
+ return;
+
+ case StandardConversion:
+ OS << "Standard conversion: ";
+ break;
+
+ case CAssignment:
+ OS << "C assignment: ";
+ break;
+
+ case StringInit:
+ OS << "String initialization: ";
+ break;
+ }
+
+ for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
+ if (S != step_begin()) {
+ OS << " -> ";
+ }
+
+ switch (S->Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ OS << "resolve address of overloaded function";
+ break;
+
+ case SK_CastDerivedToBaseRValue:
+ OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_CastDerivedToBaseLValue:
+ OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_BindReference:
+ OS << "bind reference to lvalue";
+ break;
+
+ case SK_BindReferenceToTemporary:
+ OS << "bind reference to a temporary";
+ break;
+
+ case SK_UserConversion:
+ OS << "user-defined conversion via " << S->Function->getNameAsString();
+ break;
+
+ case SK_QualificationConversionRValue:
+ OS << "qualification conversion (rvalue)";
+
+ case SK_QualificationConversionLValue:
+ OS << "qualification conversion (lvalue)";
+ break;
+
+ case SK_ConversionSequence:
+ OS << "implicit conversion sequence (";
+ S->ICS->DebugPrint(); // FIXME: use OS
+ OS << ")";
+ break;
+
+ case SK_ListInitialization:
+ OS << "list initialization";
+ break;
+
+ case SK_ConstructorInitialization:
+ OS << "constructor initialization";
+ break;
+
+ case SK_ZeroInitialization:
+ OS << "zero initialization";
+ break;
+
+ case SK_CAssignment:
+ OS << "C assignment";
+ break;
+
+ case SK_StringInit:
+ OS << "string initialization";
+ break;
+ }
+ }
+}
+
+void InitializationSequence::dump() const {
+ dump(llvm::errs());
+}
+
//===----------------------------------------------------------------------===//
// Initialization helper functions
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index d7d3756..2b49df2 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -15,12 +15,17 @@
#include "SemaOverload.h"
#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
#include "clang/Parse/Action.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
+namespace llvm {
+ class raw_ostream;
+}
+
namespace clang {
class CXXBaseSpecifier;
@@ -62,7 +67,6 @@ public:
/// \brief The entity being initialized is an element of a vector.
/// or vector.
EK_VectorElement
-
};
private:
@@ -91,8 +95,8 @@ private:
/// base class.
CXXBaseSpecifier *Base;
- /// \brief When Kind = EK_ArrayOrVectorElement, the index of the
- /// array or vector element being initialized.
+ /// \brief When Kind = EK_ArrayElement or EK_VectorElement, the
+ /// index of the array or vector element being initialized.
unsigned Index;
};
@@ -197,6 +201,12 @@ public:
/// initialized.
DeclaratorDecl *getDecl() const;
+ /// \brief Retrieve the base specifier.
+ CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base;
+ }
+
/// \brief Determine the location of the 'return' keyword when initializing
/// the result of a function call.
SourceLocation getReturnLoc() const {
@@ -440,7 +450,11 @@ public:
/// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
/// SK_UserConversion, the function that the expression should be
/// resolved to or the conversion function to call, respectively.
- FunctionDecl *Function;
+ ///
+ /// Always a FunctionDecl.
+ /// For conversion decls, the naming class is the source type.
+ /// For construct decls, the naming class is the target type.
+ DeclAccessPair Function;
/// \brief When Kind = SK_ConversionSequence, the implicit conversion
/// sequence
@@ -607,7 +621,9 @@ public:
/// \brief Add a new step invoking a conversion function, which is either
/// a constructor or a conversion function.
- void AddUserConversionStep(FunctionDecl *Function, QualType T);
+ void AddUserConversionStep(FunctionDecl *Function,
+ AccessSpecifier Access,
+ QualType T);
/// \brief Add a new step that performs a qualification conversion to the
/// given type.
@@ -622,6 +638,7 @@ public:
/// \brief Add a constructor-initialization step.
void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
QualType T);
/// \brief Add a zero-initialization step.
@@ -658,6 +675,14 @@ public:
assert(getKind() == FailedSequence && "Not an initialization failure!");
return Failure;
}
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// the given stream, for debugging purposes.
+ void dump(llvm::raw_ostream &OS) const;
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// standard error, for debugging purposes.
+ void dump() const;
};
} // end namespace clang
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index f5d2a7d..c7569d6 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -404,7 +404,7 @@ void LookupResult::resolveKind() {
}
void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
- CXXBasePaths::paths_iterator I, E;
+ CXXBasePaths::const_paths_iterator I, E;
DeclContext::lookup_iterator DI, DE;
for (I = P.begin(), E = P.end(); I != E; ++I)
for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI)
@@ -438,9 +438,42 @@ void LookupResult::print(llvm::raw_ostream &Out) {
}
}
+/// \brief Lookup a builtin function, when name lookup would otherwise
+/// fail.
+static bool LookupBuiltin(Sema &S, LookupResult &R) {
+ Sema::LookupNameKind NameKind = R.getLookupKind();
+
+ // If we didn't find a use of this identifier, and if the identifier
+ // corresponds to a compiler builtin, create the decl object for the builtin
+ // now, injecting it into translation unit scope, and return it.
+ if (NameKind == Sema::LookupOrdinaryName ||
+ NameKind == Sema::LookupRedeclarationWithLinkage) {
+ IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
+ if (II) {
+ // If this is a builtin on this (or all) targets, create the decl.
+ if (unsigned BuiltinID = II->getBuiltinID()) {
+ // In C++, we don't have any predefined library functions like
+ // 'malloc'. Instead, we'll just error.
+ if (S.getLangOptions().CPlusPlus &&
+ S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return false;
+
+ NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
+ S.TUScope, R.isForRedeclaration(),
+ R.getNameLoc());
+ if (D)
+ R.addDecl(D);
+ return (D != NULL);
+ }
+ }
+ }
+
+ return false;
+}
+
// Adds all qualifying matches for a name within a decl context to the
// given lookup result. Returns true if any matches were found.
-static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
+static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
bool Found = false;
DeclContext::lookup_const_iterator I, E;
@@ -452,87 +485,89 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
}
}
+ if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R))
+ return true;
+
if (R.getLookupName().getNameKind()
- == DeclarationName::CXXConversionFunctionName &&
- !R.getLookupName().getCXXNameType()->isDependentType() &&
- isa<CXXRecordDecl>(DC)) {
+ != DeclarationName::CXXConversionFunctionName ||
+ R.getLookupName().getCXXNameType()->isDependentType() ||
+ !isa<CXXRecordDecl>(DC))
+ return Found;
+
+ // C++ [temp.mem]p6:
+ // A specialization of a conversion function template is not found by
+ // name lookup. Instead, any conversion function templates visible in the
+ // context of the use are considered. [...]
+ const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+ if (!Record->isDefinition())
+ return Found;
+
+ const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
+ for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
+ UEnd = Unresolved->end(); U != UEnd; ++U) {
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
+ if (!ConvTemplate)
+ continue;
+
+ // When we're performing lookup for the purposes of redeclaration, just
+ // add the conversion function template. When we deduce template
+ // arguments for specializations, we'll end up unifying the return
+ // type of the new declaration with the type of the function template.
+ if (R.isForRedeclaration()) {
+ R.addDecl(ConvTemplate);
+ Found = true;
+ continue;
+ }
+
// C++ [temp.mem]p6:
- // A specialization of a conversion function template is not found by
- // name lookup. Instead, any conversion function templates visible in the
- // context of the use are considered. [...]
- const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
- if (!Record->isDefinition())
- return Found;
-
- const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions();
- for (UnresolvedSetImpl::iterator U = Unresolved->begin(),
- UEnd = Unresolved->end(); U != UEnd; ++U) {
- FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U);
- if (!ConvTemplate)
- continue;
-
- // When we're performing lookup for the purposes of redeclaration, just
- // add the conversion function template. When we deduce template
- // arguments for specializations, we'll end up unifying the return
- // type of the new declaration with the type of the function template.
- if (R.isForRedeclaration()) {
- R.addDecl(ConvTemplate);
- Found = true;
- continue;
- }
-
- // C++ [temp.mem]p6:
- // [...] For each such operator, if argument deduction succeeds
- // (14.9.2.3), the resulting specialization is used as if found by
- // name lookup.
- //
- // When referencing a conversion function for any purpose other than
- // a redeclaration (such that we'll be building an expression with the
- // result), perform template argument deduction and place the
- // specialization into the result set. We do this to avoid forcing all
- // callers to perform special deduction for conversion functions.
- Sema::TemplateDeductionInfo Info(R.getSema().Context);
- FunctionDecl *Specialization = 0;
-
- const FunctionProtoType *ConvProto
- = ConvTemplate->getTemplatedDecl()->getType()
- ->getAs<FunctionProtoType>();
- assert(ConvProto && "Nonsensical conversion function template type");
-
- // Compute the type of the function that we would expect the conversion
- // function to have, if it were to match the name given.
- // FIXME: Calling convention!
- QualType ExpectedType
- = R.getSema().Context.getFunctionType(
- R.getLookupName().getCXXNameType(),
- 0, 0, ConvProto->isVariadic(),
- ConvProto->getTypeQuals(),
- false, false, 0, 0,
- ConvProto->getNoReturnAttr());
-
- // Perform template argument deduction against the type that we would
- // expect the function to have.
- if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
- Specialization, Info)
- == Sema::TDK_Success) {
- R.addDecl(Specialization);
- Found = true;
- }
+ // [...] For each such operator, if argument deduction succeeds
+ // (14.9.2.3), the resulting specialization is used as if found by
+ // name lookup.
+ //
+ // When referencing a conversion function for any purpose other than
+ // a redeclaration (such that we'll be building an expression with the
+ // result), perform template argument deduction and place the
+ // specialization into the result set. We do this to avoid forcing all
+ // callers to perform special deduction for conversion functions.
+ Sema::TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
+ FunctionDecl *Specialization = 0;
+
+ const FunctionProtoType *ConvProto
+ = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>();
+ assert(ConvProto && "Nonsensical conversion function template type");
+
+ // Compute the type of the function that we would expect the conversion
+ // function to have, if it were to match the name given.
+ // FIXME: Calling convention!
+ QualType ExpectedType
+ = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(),
+ 0, 0, ConvProto->isVariadic(),
+ ConvProto->getTypeQuals(),
+ false, false, 0, 0,
+ ConvProto->getNoReturnAttr());
+
+ // Perform template argument deduction against the type that we would
+ // expect the function to have.
+ if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType,
+ Specialization, Info)
+ == Sema::TDK_Success) {
+ R.addDecl(Specialization);
+ Found = true;
}
}
-
+
return Found;
}
// Performs C++ unqualified lookup into the given file context.
static bool
-CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
- UnqualUsingDirectiveSet &UDirs) {
+CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context,
+ DeclContext *NS, UnqualUsingDirectiveSet &UDirs) {
assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!");
// Perform direct name lookup into the LookupCtx.
- bool Found = LookupDirect(R, NS);
+ bool Found = LookupDirect(S, R, NS);
// Perform direct name lookup into the namespaces nominated by the
// using directives whose common ancestor is this namespace.
@@ -540,7 +575,7 @@ CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS,
llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS);
for (; UI != UEnd; ++UI)
- if (LookupDirect(R, UI->getNominatedNamespace()))
+ if (LookupDirect(S, R, UI->getNominatedNamespace()))
Found = true;
R.resolveKind();
@@ -650,12 +685,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
for (; S; S = S->getParent()) {
DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity());
- if (!Ctx || Ctx->isTransparentContext())
+ if (Ctx && Ctx->isTransparentContext())
continue;
- assert(Ctx && Ctx->isFileContext() &&
- "We should have been looking only at file context here already.");
-
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
@@ -669,16 +701,21 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
}
}
- // Look into context considering using-directives.
- if (CppNamespaceLookup(R, Context, Ctx, UDirs))
- Found = true;
+ if (Ctx) {
+ assert(Ctx->isFileContext() &&
+ "We should have been looking only at file context here already.");
+
+ // Look into context considering using-directives.
+ if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs))
+ Found = true;
+ }
if (Found) {
R.resolveKind();
return true;
}
- if (R.isForRedeclaration() && !Ctx->isTransparentContext())
+ if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext())
return false;
}
@@ -793,26 +830,9 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
- if (NameKind == LookupOrdinaryName ||
- NameKind == LookupRedeclarationWithLinkage) {
- IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (II && AllowBuiltinCreation) {
- // If this is a builtin on this (or all) targets, create the decl.
- if (unsigned BuiltinID = II->getBuiltinID()) {
- // In C++, we don't have any predefined library functions like
- // 'malloc'. Instead, we'll just error.
- if (getLangOptions().CPlusPlus &&
- Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- return false;
+ if (AllowBuiltinCreation)
+ return LookupBuiltin(*this, R);
- NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
- S, R.isForRedeclaration(),
- R.getNameLoc());
- if (D) R.addDecl(D);
- return (D != NULL);
- }
- }
- }
return false;
}
@@ -842,7 +862,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
/// class or enumeration name if and only if the declarations are
/// from the same namespace; otherwise (the declarations are from
/// different namespaces), the program is ill-formed.
-static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
+static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
DeclContext *StartDC) {
assert(StartDC->isFileContext() && "start context is not a file context");
@@ -885,7 +905,7 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R,
// between LookupResults.
bool UseLocal = !R.empty();
LookupResult &DirectR = UseLocal ? LocalR : R;
- bool FoundDirect = LookupDirect(DirectR, ND);
+ bool FoundDirect = LookupDirect(S, DirectR, ND);
if (FoundDirect) {
// First do any local hiding.
@@ -965,7 +985,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
"Declaration context must already be complete!");
// Perform qualified name lookup into the LookupCtx.
- if (LookupDirect(R, LookupCtx)) {
+ if (LookupDirect(*this, R, LookupCtx)) {
R.resolveKind();
if (isa<CXXRecordDecl>(LookupCtx))
R.setNamingClass(cast<CXXRecordDecl>(LookupCtx));
@@ -986,7 +1006,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// If this is a namespace, look it up in the implied namespaces.
if (LookupCtx->isFileContext())
- return LookupQualifiedNameInUsingDirectives(R, LookupCtx);
+ return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx);
// If this isn't a C++ class, we aren't allowed to look into base
// classes, we're done.
@@ -1407,6 +1427,12 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
AssociatedClasses);
}
+ // Only recurse into base classes for complete types.
+ if (!Class->hasDefinition()) {
+ // FIXME: we might need to instantiate templates here
+ return;
+ }
+
// Add direct and indirect base classes along with their associated
// namespaces.
llvm::SmallVector<CXXRecordDecl *, 32> Bases;
@@ -1693,7 +1719,7 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
- FunctionSet &Functions) {
+ UnresolvedSetImpl &Functions) {
// C++ [over.match.oper]p3:
// -- The set of non-member candidates is the result of the
// unqualified lookup of operator@ in the context of the
@@ -1719,29 +1745,58 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
Op != OpEnd; ++Op) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
- Functions.insert(FD); // FIXME: canonical FD
+ Functions.addDecl(FD, Op.getAccess()); // FIXME: canonical FD
} else if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(*Op)) {
// FIXME: friend operators?
// FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
// later?
if (!FunTmpl->getDeclContext()->isRecord())
- Functions.insert(FunTmpl);
+ Functions.addDecl(FunTmpl, Op.getAccess());
}
}
}
-static void CollectFunctionDecl(Sema::FunctionSet &Functions,
- Decl *D) {
- if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
- Functions.insert(Func);
- else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
- Functions.insert(FunTmpl);
+void ADLResult::insert(NamedDecl *New) {
+ NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
+
+ // If we haven't yet seen a decl for this key, or the last decl
+ // was exactly this one, we're done.
+ if (Old == 0 || Old == New) {
+ Old = New;
+ return;
+ }
+
+ // Otherwise, decide which is a more recent redeclaration.
+ FunctionDecl *OldFD, *NewFD;
+ if (isa<FunctionTemplateDecl>(New)) {
+ OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
+ NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
+ } else {
+ OldFD = cast<FunctionDecl>(Old);
+ NewFD = cast<FunctionDecl>(New);
+ }
+
+ FunctionDecl *Cursor = NewFD;
+ while (true) {
+ Cursor = Cursor->getPreviousDeclaration();
+
+ // If we got to the end without finding OldFD, OldFD is the newer
+ // declaration; leave things as they are.
+ if (!Cursor) return;
+
+ // If we do find OldFD, then NewFD is newer.
+ if (Cursor == OldFD) break;
+
+ // Otherwise, keep looking.
+ }
+
+ Old = New;
}
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
- FunctionSet &Functions) {
+ ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@@ -1784,7 +1839,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
// lookup (11.4).
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
- Decl *D = *I;
+ NamedDecl *D = *I;
// If the only declaration here is an ordinary friend, consider
// it only if it was declared in an associated classes.
if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
@@ -1793,10 +1848,18 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
continue;
}
- FunctionDecl *Fn;
- if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
- IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
- CollectFunctionDecl(Functions, D);
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ if (isa<FunctionDecl>(D)) {
+ if (Operator &&
+ !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D),
+ T1, T2, Context))
+ continue;
+ } else if (!isa<FunctionTemplateDecl>(D))
+ continue;
+
+ Result.insert(D);
}
}
}
@@ -1985,6 +2048,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
bool InBaseClass,
VisibleDeclConsumer &Consumer,
VisibleDeclsRecord &Visited) {
+ if (!Ctx)
+ return;
+
// Make sure we don't visit the same context twice.
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
@@ -2022,6 +2088,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Traverse the contexts of inherited C++ classes.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (!Record->hasDefinition())
+ return;
+
for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
BEnd = Record->bases_end();
B != BEnd; ++B) {
@@ -2138,9 +2207,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// For instance methods, look for ivars in the method's interface.
LookupResult IvarResult(Result.getSema(), Result.getLookupName(),
Result.getNameLoc(), Sema::LookupMemberName);
- ObjCInterfaceDecl *IFace = Method->getClassInterface();
- LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
- /*InBaseClass=*/false, Consumer, Visited);
+ if (ObjCInterfaceDecl *IFace = Method->getClassInterface())
+ LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
+ /*InBaseClass=*/false, Consumer, Visited);
}
// We've already performed all of the name lookup that we need
@@ -2312,9 +2381,16 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT) {
-
if (Diags.hasFatalErrorOccurred())
return false;
+
+ // Provide a stop gap for files that are just seriously broken. Trying
+ // to correct all typos can turn into a HUGE performance penalty, causing
+ // some files to take minutes to get rejected by the parser.
+ // FIXME: Is this the right solution?
+ if (TyposCorrected == 20)
+ return false;
+ ++TyposCorrected;
// We only attempt to correct typos for identifiers.
IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 44a8f15..b79b1cc 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -148,7 +148,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
// array-to-pointer or function-to-pointer implicit conversions, so
// check for their presence as well as checking whether FromType is
// a pointer.
- if (getToType()->isBooleanType() &&
+ if (getToType(1)->isBooleanType() &&
(getFromType()->isPointerType() || getFromType()->isBlockPointerType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@@ -164,7 +164,7 @@ bool
StandardConversionSequence::
isPointerConversionToVoidPointer(ASTContext& Context) const {
QualType FromType = getFromType();
- QualType ToType = getToType();
+ QualType ToType = getToType(1);
// Note that FromType has not necessarily been transformed by the
// array-to-pointer implicit conversion, so check for its presence
@@ -447,16 +447,24 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
bool InOverloadResolution,
bool UserCast) {
ImplicitConversionSequence ICS;
- OverloadCandidateSet Conversions;
- OverloadingResult UserDefResult = OR_Success;
- if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard))
+ if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) {
ICS.setStandard();
- else if (getLangOptions().CPlusPlus &&
- (UserDefResult = IsUserDefinedConversion(From, ToType,
- ICS.UserDefined,
- Conversions,
- !SuppressUserConversions, AllowExplicit,
- ForceRValue, UserCast)) == OR_Success) {
+ return ICS;
+ }
+
+ if (!getLangOptions().CPlusPlus) {
+ ICS.setBad();
+ ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
+ return ICS;
+ }
+
+ OverloadCandidateSet Conversions(From->getExprLoc());
+ OverloadingResult UserDefResult
+ = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions,
+ !SuppressUserConversions, AllowExplicit,
+ ForceRValue, UserCast);
+
+ if (UserDefResult == OR_Success) {
ICS.setUserDefined();
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
@@ -477,7 +485,7 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
- ICS.Standard.setToType(ToType);
+ ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
@@ -595,7 +603,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// conversion (4.4). (C++ 4.2p2)
SCS.Second = ICK_Identity;
SCS.Third = ICK_Qualification;
- SCS.setToType(ToType);
+ SCS.setAllToTypes(FromType);
return true;
}
} else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) {
@@ -634,6 +642,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// We don't require any conversions for the first step.
SCS.First = ICK_Identity;
}
+ SCS.setToType(0, FromType);
// The second conversion can be an integral promotion, floating
// point promotion, integral conversion, floating point conversion,
@@ -714,6 +723,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// No second conversion required.
SCS.Second = ICK_Identity;
}
+ SCS.setToType(1, FromType);
QualType CanonFrom;
QualType CanonTo;
@@ -740,13 +750,13 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
CanonFrom = CanonTo;
}
}
+ SCS.setToType(2, FromType);
// If we have not converted the argument type to the parameter type,
// this is a bad conversion sequence.
if (CanonFrom != CanonTo)
return false;
- SCS.setToType(FromType);
return true;
}
@@ -766,7 +776,8 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// int can represent all the values of the source type; otherwise,
// the source rvalue can be converted to an rvalue of type unsigned
// int (C++ 4.5p1).
- if (FromType->isPromotableIntegerType() && !FromType->isBooleanType()) {
+ if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() &&
+ !FromType->isEnumeralType()) {
if (// We can promote any signed, promotable integer type to an int
(FromType->isSignedIntegerType() ||
// We can promote any unsigned integer type whose size is
@@ -1344,14 +1355,13 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
/// CheckMemberPointerConversion - Check the member pointer conversion from the
/// expression From to the type ToType. This routine checks for ambiguous or
-/// virtual (FIXME: or inaccessible) base-to-derived member pointer conversions
+/// virtual or inaccessible base-to-derived member pointer conversions
/// for which IsMemberPointerConversion has already returned true. It returns
/// true and produces a diagnostic if there was an error, or returns false
/// otherwise.
bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
CastExpr::CastKind &Kind,
bool IgnoreBaseAccess) {
- (void)IgnoreBaseAccess;
QualType FromType = From->getType();
const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
if (!FromPtrType) {
@@ -1374,7 +1384,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
assert(FromClass->isRecordType() && "Pointer into non-class.");
assert(ToClass->isRecordType() && "Pointer into non-class.");
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/ true,
/*DetectVirtual=*/true);
bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths);
assert(DerivationOkay &&
@@ -1383,13 +1393,6 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
if (Paths.isAmbiguous(Context.getCanonicalType(FromClass).
getUnqualifiedType())) {
- // Derivation is ambiguous. Redo the check to find the exact paths.
- Paths.clear();
- Paths.setRecordingPaths(true);
- bool StillOkay = IsDerivedFrom(ToClass, FromClass, Paths);
- assert(StillOkay && "Derivation changed due to quantum fluctuation.");
- (void)StillOkay;
-
std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv)
<< 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange();
@@ -1403,6 +1406,10 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
return true;
}
+ if (!IgnoreBaseAccess)
+ CheckBaseClassAccess(From->getExprLoc(), /*BaseToDerived*/ true,
+ FromClass, ToClass, Paths.front());
+
// Must be a base to derived member conversion.
Kind = CastExpr::CK_BaseToDerivedMemberPointer;
return false;
@@ -1418,7 +1425,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
// If FromType and ToType are the same type, this is not a
// qualification conversion.
- if (FromType == ToType)
+ if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType())
return false;
// (C++ 4.4p4):
@@ -1526,13 +1533,16 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
- AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ AddTemplateOverloadCandidate(ConstructorTmpl,
+ ConstructorTmpl->getAccess(),
+ /*ExplicitArgs*/ 0,
&From, 1, CandidateSet,
SuppressUserConversions, ForceRValue);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
- AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
+ AddOverloadCandidate(Constructor, Constructor->getAccess(),
+ &From, 1, CandidateSet,
SuppressUserConversions, ForceRValue);
}
}
@@ -1568,11 +1578,12 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- AddTemplateConversionCandidate(ConvTemplate, ActingContext,
- From, ToType, CandidateSet);
+ AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
+ ActingContext, From, ToType,
+ CandidateSet);
else
- AddConversionCandidate(Conv, ActingContext, From, ToType,
- CandidateSet);
+ AddConversionCandidate(Conv, I.getAccess(), ActingContext,
+ From, ToType, CandidateSet);
}
}
}
@@ -1601,7 +1612,7 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
User.After.setAsIdentityConversion();
User.After.setFromType(
ThisType->getAs<PointerType>()->getPointeeType());
- User.After.setToType(ToType);
+ User.After.setAllToTypes(ToType);
return OR_Success;
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
@@ -1647,7 +1658,7 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
bool
Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(From->getExprLoc());
OverloadingResult OvResult =
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
CandidateSet, true, false, false);
@@ -1718,6 +1729,43 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
return ImplicitConversionSequence::Indistinguishable;
}
+// Per 13.3.3.2p3, compare the given standard conversion sequences to
+// determine if one is a proper subset of the other.
+static ImplicitConversionSequence::CompareKind
+compareStandardConversionSubsets(ASTContext &Context,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
+ ImplicitConversionSequence::CompareKind Result
+ = ImplicitConversionSequence::Indistinguishable;
+
+ if (SCS1.Second != SCS2.Second) {
+ if (SCS1.Second == ICK_Identity)
+ Result = ImplicitConversionSequence::Better;
+ else if (SCS2.Second == ICK_Identity)
+ Result = ImplicitConversionSequence::Worse;
+ else
+ return ImplicitConversionSequence::Indistinguishable;
+ } else if (!Context.hasSameType(SCS1.getToType(1), SCS2.getToType(1)))
+ return ImplicitConversionSequence::Indistinguishable;
+
+ if (SCS1.Third == SCS2.Third) {
+ return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result
+ : ImplicitConversionSequence::Indistinguishable;
+ }
+
+ if (SCS1.Third == ICK_Identity)
+ return Result == ImplicitConversionSequence::Worse
+ ? ImplicitConversionSequence::Indistinguishable
+ : ImplicitConversionSequence::Better;
+
+ if (SCS2.Third == ICK_Identity)
+ return Result == ImplicitConversionSequence::Better
+ ? ImplicitConversionSequence::Indistinguishable
+ : ImplicitConversionSequence::Worse;
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
/// CompareStandardConversionSequences - Compare two standard
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
@@ -1733,21 +1781,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// excluding any Lvalue Transformation; the identity conversion
// sequence is considered to be a subsequence of any
// non-identity conversion sequence) or, if not that,
- if (SCS1.Second == SCS2.Second && SCS1.Third == SCS2.Third)
- // Neither is a proper subsequence of the other. Do nothing.
- ;
- else if ((SCS1.Second == ICK_Identity && SCS1.Third == SCS2.Third) ||
- (SCS1.Third == ICK_Identity && SCS1.Second == SCS2.Second) ||
- (SCS1.Second == ICK_Identity &&
- SCS1.Third == ICK_Identity))
- // SCS1 is a proper subsequence of SCS2.
- return ImplicitConversionSequence::Better;
- else if ((SCS2.Second == ICK_Identity && SCS2.Third == SCS1.Third) ||
- (SCS2.Third == ICK_Identity && SCS2.Second == SCS1.Second) ||
- (SCS2.Second == ICK_Identity &&
- SCS2.Third == ICK_Identity))
- // SCS2 is a proper subsequence of SCS1.
- return ImplicitConversionSequence::Worse;
+ if (ImplicitConversionSequence::CompareKind CK
+ = compareStandardConversionSubsets(Context, SCS1, SCS2))
+ return CK;
// -- the rank of S1 is better than the rank of S2 (by the rules
// defined below), or, if not that,
@@ -1852,8 +1888,8 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// top-level cv-qualifiers, and the type to which the reference
// initialized by S2 refers is more cv-qualified than the type
// to which the reference initialized by S1 refers.
- QualType T1 = SCS1.getToType();
- QualType T2 = SCS2.getToType();
+ QualType T1 = SCS1.getToType(2);
+ QualType T2 = SCS2.getToType(2);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
@@ -1894,8 +1930,8 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
// FIXME: the example in the standard doesn't use a qualification
// conversion (!)
- QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
- QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ QualType T1 = SCS1.getToType(2);
+ QualType T2 = SCS2.getToType(2);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
@@ -1984,9 +2020,9 @@ ImplicitConversionSequence::CompareKind
Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
QualType FromType1 = SCS1.getFromType();
- QualType ToType1 = SCS1.getToType();
+ QualType ToType1 = SCS1.getToType(1);
QualType FromType2 = SCS2.getFromType();
- QualType ToType2 = SCS2.getToType();
+ QualType ToType2 = SCS2.getToType(1);
// Adjust the types we're converting from via the array-to-pointer
// conversion, if we need to.
@@ -2276,7 +2312,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType,
// Success. Mark this as a reference binding.
ICS.setStandard();
ICS.Standard.setFromType(FromType);
- ICS.Standard.setToType(ImplicitParamType);
+ ICS.Standard.setAllToTypes(ImplicitParamType);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
ICS.Standard.RRefBinding = false;
@@ -2360,6 +2396,7 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
/// code completion.
void
Sema::AddOverloadCandidate(FunctionDecl *Function,
+ AccessSpecifier Access,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
@@ -2380,7 +2417,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// function, e.g., X::f(). We use an empty type for the implied
// object argument (C++ [over.call.func]p3), and the acting context
// is irrelevant.
- AddMethodCandidate(Method, Method->getParent(),
+ AddMethodCandidate(Method, Access, Method->getParent(),
QualType(), Args, NumArgs, CandidateSet,
SuppressUserConversions, ForceRValue);
return;
@@ -2410,6 +2447,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.Function = Function;
+ Candidate.Access = Access;
Candidate.Viable = true;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
@@ -2469,35 +2507,33 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
/// \brief Add all of the function declarations in the given function set to
/// the overload canddiate set.
-void Sema::AddFunctionCandidates(const FunctionSet &Functions,
+void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
- for (FunctionSet::const_iterator F = Functions.begin(),
- FEnd = Functions.end();
- F != FEnd; ++F) {
+ for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
// FIXME: using declarations
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) {
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
- AddMethodCandidate(cast<CXXMethodDecl>(FD),
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getAccess(),
cast<CXXMethodDecl>(FD)->getParent(),
Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet, SuppressUserConversions);
else
- AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
+ AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
SuppressUserConversions);
} else {
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*F);
if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
!cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
- AddMethodTemplateCandidate(FunTmpl,
+ AddMethodTemplateCandidate(FunTmpl, F.getAccess(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
/*FIXME: explicit args */ 0,
Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet,
SuppressUserConversions);
else
- AddTemplateOverloadCandidate(FunTmpl,
+ AddTemplateOverloadCandidate(FunTmpl, AS_none,
/*FIXME: explicit args */ 0,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
@@ -2508,6 +2544,7 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
/// AddMethodCandidate - Adds a named decl (which is some kind of
/// method) as a method candidate to the given overload set.
void Sema::AddMethodCandidate(NamedDecl *Decl,
+ AccessSpecifier Access,
QualType ObjectType,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -2520,13 +2557,13 @@ void Sema::AddMethodCandidate(NamedDecl *Decl,
if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
- AddMethodTemplateCandidate(TD, ActingContext, /*ExplicitArgs*/ 0,
+ AddMethodTemplateCandidate(TD, Access, ActingContext, /*ExplicitArgs*/ 0,
ObjectType, Args, NumArgs,
CandidateSet,
SuppressUserConversions,
ForceRValue);
} else {
- AddMethodCandidate(cast<CXXMethodDecl>(Decl), ActingContext,
+ AddMethodCandidate(cast<CXXMethodDecl>(Decl), Access, ActingContext,
ObjectType, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
@@ -2542,8 +2579,9 @@ void Sema::AddMethodCandidate(NamedDecl *Decl,
/// a slightly hacky way to implement the overloading rules for elidable copy
/// initialization in C++0x (C++0x 12.8p15).
void
-Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
- QualType ObjectType, Expr **Args, unsigned NumArgs,
+Sema::AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions, bool ForceRValue) {
const FunctionProtoType* Proto
@@ -2562,6 +2600,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.Function = Method;
+ Candidate.Access = Access;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
@@ -2639,6 +2678,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
/// function template specialization.
void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
@@ -2658,7 +2698,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
// functions. In such a case, the candidate functions generated from each
// function template are combined with the set of non-template candidate
// functions.
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs,
@@ -2674,8 +2714,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
assert(Specialization && "Missing member function template specialization?");
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
- AddMethodCandidate(cast<CXXMethodDecl>(Specialization), ActingContext,
- ObjectType, Args, NumArgs,
+ AddMethodCandidate(cast<CXXMethodDecl>(Specialization), Access,
+ ActingContext, ObjectType, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
@@ -2684,6 +2724,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
/// an appropriate function template specialization.
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ AccessSpecifier Access,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@@ -2701,29 +2742,30 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
// functions. In such a case, the candidate functions generated from each
// function template are combined with the set of non-template candidate
// functions.
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
Args, NumArgs, Specialization, Info)) {
- // FIXME: Record what happened with template argument deduction, so
- // that we can give the user a beautiful diagnostic.
- (void) Result;
-
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate &Candidate = CandidateSet.back();
Candidate.Function = FunctionTemplate->getTemplatedDecl();
+ Candidate.Access = Access;
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
+
+ // TODO: record more information about failed template arguments
+ Candidate.DeductionFailure.Result = Result;
+ Candidate.DeductionFailure.TemplateParameter = Info.Param.getOpaqueValue();
return;
}
// Add the function template specialization produced by template argument
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- AddOverloadCandidate(Specialization, Args, NumArgs, CandidateSet,
+ AddOverloadCandidate(Specialization, Access, Args, NumArgs, CandidateSet,
SuppressUserConversions, ForceRValue);
}
@@ -2735,6 +2777,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
/// conversion function produces).
void
Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet) {
@@ -2751,11 +2794,12 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.Function = Conversion;
+ Candidate.Access = Access;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(Conversion->getConversionType());
- Candidate.FinalConversion.setToType(ToType);
+ Candidate.FinalConversion.setAllToTypes(ToType);
// Determine the implicit conversion sequence for the implicit
// object parameter.
@@ -2837,6 +2881,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
/// [temp.deduct.conv]).
void
Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ AccessSpecifier Access,
CXXRecordDecl *ActingDC,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet) {
@@ -2846,7 +2891,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, CandidateSet.getLocation());
CXXConversionDecl *Specialization = 0;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ToType,
@@ -2860,7 +2905,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
// Add the conversion function template specialization produced by
// template argument deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
- AddConversionCandidate(Specialization, ActingDC, From, ToType, CandidateSet);
+ AddConversionCandidate(Specialization, Access, ActingDC, From, ToType,
+ CandidateSet);
}
/// AddSurrogateCandidate - Adds a "surrogate" candidate function that
@@ -2869,6 +2915,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
/// with the given arguments (C++ [over.call.object]p2-4). Proto is
/// the type of function that we'll eventually be calling.
void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ AccessSpecifier Access,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
QualType ObjectType,
@@ -2883,6 +2930,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.Function = 0;
+ Candidate.Access = Access;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
@@ -2968,7 +3016,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
SourceRange OpRange) {
- FunctionSet Functions;
+ UnresolvedSet<16> Fns;
QualType T1 = Args[0]->getType();
QualType T2;
@@ -2977,9 +3025,10 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
if (S)
- LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
- ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions);
- AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
+ LookupOverloadedOperatorName(Op, S, T1, T2, Fns);
+ AddFunctionCandidates(Fns, Args, NumArgs, CandidateSet, false);
+ AddArgumentDependentLookupCandidates(OpName, false, Args, NumArgs, 0,
+ CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
}
@@ -3029,7 +3078,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
OperEnd = Operators.end();
Oper != OperEnd;
++Oper)
- AddMethodCandidate(*Oper, Args[0]->getType(),
+ AddMethodCandidate(*Oper, Oper.getAccess(), Args[0]->getType(),
Args + 1, NumArgs - 1, CandidateSet,
/* SuppressUserConversions = */ false);
}
@@ -3055,6 +3104,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.Function = 0;
+ Candidate.Access = AS_none;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.BuiltinTypes.ResultTy = ResultTy;
@@ -3362,6 +3412,9 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ if (!ClassDecl->hasDefinition())
+ return VRQuals;
+
const UnresolvedSetImpl *Conversions =
ClassDecl->getVisibleConversionFunctions();
@@ -4108,54 +4161,45 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
/// candidate set (C++ [basic.lookup.argdep]).
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
+ bool Operator,
Expr **Args, unsigned NumArgs,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
- FunctionSet Functions;
+ ADLResult Fns;
- // FIXME: Should we be trafficking in canonical function decls throughout?
-
- // Record all of the function candidates that we've already
- // added to the overload set, so that we don't add those same
- // candidates a second time.
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
- CandEnd = CandidateSet.end();
- Cand != CandEnd; ++Cand)
- if (Cand->Function) {
- Functions.insert(Cand->Function);
- if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
- Functions.insert(FunTmpl);
- }
+ // FIXME: This approach for uniquing ADL results (and removing
+ // redundant candidates from the set) relies on pointer-equality,
+ // which means we need to key off the canonical decl. However,
+ // always going back to the canonical decl might not get us the
+ // right set of default arguments. What default arguments are
+ // we supposed to consider on ADL candidates, anyway?
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions);
+ ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns);
// Erase all of the candidates we already knew about.
- // FIXME: This is suboptimal. Is there a better way?
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
Cand != CandEnd; ++Cand)
if (Cand->Function) {
- Functions.erase(Cand->Function);
+ Fns.erase(Cand->Function);
if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
- Functions.erase(FunTmpl);
+ Fns.erase(FunTmpl);
}
// For each of the ADL candidates we found, add it to the overload
// set.
- for (FunctionSet::iterator Func = Functions.begin(),
- FuncEnd = Functions.end();
- Func != FuncEnd; ++Func) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) {
+ for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
if (ExplicitTemplateArgs)
continue;
- AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
+ AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
false, false, PartialOverloading);
} else
- AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func),
- ExplicitTemplateArgs,
+ AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
+ AS_none, ExplicitTemplateArgs,
Args, NumArgs, CandidateSet);
}
}
@@ -4164,7 +4208,8 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool
Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
- const OverloadCandidate& Cand2) {
+ const OverloadCandidate& Cand2,
+ SourceLocation Loc) {
// Define viable functions to be better candidates than non-viable
// functions.
if (!Cand2.Viable)
@@ -4227,6 +4272,7 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
if (FunctionTemplateDecl *BetterTemplate
= getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
Cand2.Function->getPrimaryTemplate(),
+ Loc,
isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
: TPOC_Call))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
@@ -4279,7 +4325,8 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand) {
if (Cand->Viable) {
- if (Best == CandidateSet.end() || isBetterOverloadCandidate(*Cand, *Best))
+ if (Best == CandidateSet.end() ||
+ isBetterOverloadCandidate(*Cand, *Best, Loc))
Best = Cand;
}
}
@@ -4294,7 +4341,7 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
Cand != CandidateSet.end(); ++Cand) {
if (Cand->Viable &&
Cand != Best &&
- !isBetterOverloadCandidate(*Best, *Cand)) {
+ !isBetterOverloadCandidate(*Best, *Cand, Loc)) {
Best = CandidateSet.end();
return OR_Ambiguous;
}
@@ -4414,6 +4461,20 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
QualType FromTy = Conv.Bad.getFromType();
QualType ToTy = Conv.Bad.getToType();
+ if (FromTy == S.Context.OverloadTy) {
+ assert(FromExpr);
+ Expr *E = FromExpr->IgnoreParens();
+ if (isa<UnaryOperator>(E))
+ E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+ DeclarationName Name = cast<OverloadExpr>(E)->getName();
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << ToTy << Name << I+1;
+ return;
+ }
+
// Do some hand-waving analysis to see if the non-viability is due
// to a qualifier mismatch.
CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
@@ -4520,6 +4581,58 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
<< (unsigned) FnKind << Description << mode << modeCount << NumFormalArgs;
}
+/// Diagnose a failed template-argument deduction.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+ Expr **Args, unsigned NumArgs) {
+ FunctionDecl *Fn = Cand->Function; // pattern
+
+ TemplateParameter Param = TemplateParameter::getFromOpaqueValue(
+ Cand->DeductionFailure.TemplateParameter);
+
+ switch (Cand->DeductionFailure.Result) {
+ case Sema::TDK_Success:
+ llvm_unreachable("TDK_success while diagnosing bad deduction");
+
+ case Sema::TDK_Incomplete: {
+ NamedDecl *ParamD;
+ (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
+ (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
+ (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+ assert(ParamD && "no parameter found for incomplete deduction result");
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
+ << ParamD->getDeclName();
+ return;
+ }
+
+ // TODO: diagnose these individually, then kill off
+ // note_ovl_candidate_bad_deduction, which is uselessly vague.
+ case Sema::TDK_InstantiationDepth:
+ case Sema::TDK_Inconsistent:
+ case Sema::TDK_InconsistentQuals:
+ case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_NonDeducedMismatch:
+ case Sema::TDK_TooManyArguments:
+ case Sema::TDK_TooFewArguments:
+ case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_FailedOverloadResolution:
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
+ return;
+ }
+}
+
+/// Generates a 'note' diagnostic for an overload candidate. We've
+/// already generated a primary error at the call site.
+///
+/// It really does need to be a single diagnostic with its caret
+/// pointed at the candidate declaration. Yes, this creates some
+/// major challenges of technical writing. Yes, this makes pointing
+/// out problems with specific arguments quite awkward. It's still
+/// better than generating twenty screens of text for every failed
+/// overload.
+///
+/// It would be great to be able to express per-candidate problems
+/// more richly for those diagnostic clients that cared, but we'd
+/// still have to be just as careful with the default diagnostics.
void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
Expr **Args, unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
@@ -4546,6 +4659,8 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
+ return DiagnoseBadDeduction(S, Cand, Args, NumArgs);
+
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
return S.NoteOverloadCandidate(Fn);
@@ -4651,8 +4766,8 @@ struct CompareOverloadCandidatesForDisplay {
// TODO: introduce a tri-valued comparison for overload
// candidates. Would be more worthwhile if we had a sort
// that could exploit it.
- if (S.isBetterOverloadCandidate(*L, *R)) return true;
- if (S.isBetterOverloadCandidate(*R, *L)) return false;
+ if (S.isBetterOverloadCandidate(*L, *R, SourceLocation())) return true;
+ if (S.isBetterOverloadCandidate(*R, *L, SourceLocation())) return false;
} else if (R->Viable)
return false;
@@ -4842,6 +4957,14 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
}
}
+static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, NamedDecl *D,
+ AccessSpecifier AS) {
+ if (isa<UnresolvedLookupExpr>(E))
+ return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS);
+
+ return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D, AS);
+}
+
/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
/// an overloaded function (C++ [over.over]), where @p From is an
/// expression with overloaded function type and @p ToType is the type
@@ -4878,52 +5001,28 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
// Find the actual overloaded function declaration.
+ if (From->getType() != Context.OverloadTy)
+ return 0;
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
- Expr *OvlExpr = From->IgnoreParens();
-
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) {
- if (UnOp->getOpcode() == UnaryOperator::AddrOf)
- OvlExpr = UnOp->getSubExpr()->IgnoreParens();
+ OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
+ TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
+ if (OvlExpr->hasExplicitTemplateArgs()) {
+ OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
+ ExplicitTemplateArgs = &ETABuffer;
}
- bool HasExplicitTemplateArgs = false;
- TemplateArgumentListInfo ExplicitTemplateArgs;
-
- llvm::SmallVector<NamedDecl*,8> Fns;
-
- // Look into the overloaded expression.
- if (UnresolvedLookupExpr *UL
- = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
- Fns.append(UL->decls_begin(), UL->decls_end());
- if (UL->hasExplicitTemplateArgs()) {
- HasExplicitTemplateArgs = true;
- UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- }
- } else if (UnresolvedMemberExpr *ME
- = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
- Fns.append(ME->decls_begin(), ME->decls_end());
- if (ME->hasExplicitTemplateArgs()) {
- HasExplicitTemplateArgs = true;
- ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- }
- }
-
- // If we didn't actually find anything, we're done.
- if (Fns.empty())
- return 0;
-
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
- llvm::SmallPtrSet<FunctionDecl *, 4> Matches;
+ UnresolvedSet<4> Matches; // contains only FunctionDecls
bool FoundNonTemplateFunction = false;
- for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
- E = Fns.end(); I != E; ++I) {
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ E = OvlExpr->decls_end(); I != E; ++I) {
// Look through any using declarations to find the underlying function.
NamedDecl *Fn = (*I)->getUnderlyingDecl();
@@ -4953,10 +5052,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// overloaded functions considered.
// FIXME: We don't really want to build the specialization here, do we?
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
if (TemplateDeductionResult Result
- = DeduceTemplateArguments(FunctionTemplate,
- (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0),
+ = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
FunctionType, Specialization, Info)) {
// FIXME: make a note of the failed deduction for diagnostics.
(void)Result;
@@ -4965,8 +5063,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// a candidate? Find a testcase before changing the code.
assert(FunctionType
== Context.getCanonicalType(Specialization->getType()));
- Matches.insert(
- cast<FunctionDecl>(Specialization->getCanonicalDecl()));
+ Matches.addDecl(cast<FunctionDecl>(Specialization->getCanonicalDecl()),
+ I.getAccess());
}
continue;
@@ -4979,7 +5077,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
continue;
// If we have explicit template arguments, skip non-templates.
- if (HasExplicitTemplateArgs)
+ if (OvlExpr->hasExplicitTemplateArgs())
continue;
} else if (IsMember)
continue;
@@ -4989,7 +5087,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
IsNoReturnConversion(Context, FunDecl->getType(), FunctionType,
ResultTy)) {
- Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl()));
+ Matches.addDecl(cast<FunctionDecl>(FunDecl->getCanonicalDecl()),
+ I.getAccess());
FoundNonTemplateFunction = true;
}
}
@@ -4999,14 +5098,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (Matches.empty())
return 0;
else if (Matches.size() == 1) {
- FunctionDecl *Result = *Matches.begin();
+ FunctionDecl *Result = cast<FunctionDecl>(*Matches.begin());
MarkDeclarationReferenced(From->getLocStart(), Result);
+ if (Complain)
+ CheckUnresolvedAccess(*this, OvlExpr, Result, Matches.begin().getAccess());
return Result;
}
// C++ [over.over]p4:
// If more than one function is selected, [...]
- typedef llvm::SmallPtrSet<FunctionDecl *, 4>::iterator MatchIter;
if (!FoundNonTemplateFunction) {
// [...] and any given function template specialization F1 is
// eliminated if the set contains a second function template
@@ -5018,41 +5118,50 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// two-pass algorithm (similar to the one used to identify the
// best viable function in an overload set) that identifies the
// best function template (if it exists).
- llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(),
- Matches.end());
- FunctionDecl *Result =
- getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(),
+
+ UnresolvedSetIterator Result =
+ getMostSpecialized(Matches.begin(), Matches.end(),
TPOC_Other, From->getLocStart(),
PDiag(),
PDiag(diag::err_addr_ovl_ambiguous)
- << TemplateMatches[0]->getDeclName(),
+ << Matches[0]->getDeclName(),
PDiag(diag::note_ovl_candidate)
<< (unsigned) oc_function_template);
- MarkDeclarationReferenced(From->getLocStart(), Result);
- return Result;
+ assert(Result != Matches.end() && "no most-specialized template");
+ MarkDeclarationReferenced(From->getLocStart(), *Result);
+ if (Complain)
+ CheckUnresolvedAccess(*this, OvlExpr, *Result, Result.getAccess());
+ return cast<FunctionDecl>(*Result);
}
// [...] any function template specializations in the set are
// eliminated if the set also contains a non-template function, [...]
- llvm::SmallVector<FunctionDecl *, 4> RemainingMatches;
- for (MatchIter M = Matches.begin(), MEnd = Matches.end(); M != MEnd; ++M)
- if ((*M)->getPrimaryTemplate() == 0)
- RemainingMatches.push_back(*M);
+ for (unsigned I = 0, N = Matches.size(); I != N; ) {
+ if (cast<FunctionDecl>(Matches[I].getDecl())->getPrimaryTemplate() == 0)
+ ++I;
+ else {
+ Matches.erase(I);
+ --N;
+ }
+ }
// [...] After such eliminations, if any, there shall remain exactly one
// selected function.
- if (RemainingMatches.size() == 1) {
- FunctionDecl *Result = RemainingMatches.front();
- MarkDeclarationReferenced(From->getLocStart(), Result);
- return Result;
+ if (Matches.size() == 1) {
+ UnresolvedSetIterator Match = Matches.begin();
+ MarkDeclarationReferenced(From->getLocStart(), *Match);
+ if (Complain)
+ CheckUnresolvedAccess(*this, OvlExpr, *Match, Match.getAccess());
+ return cast<FunctionDecl>(*Match);
}
// FIXME: We should probably return the same thing that BestViableFunction
// returns (even if we issue the diagnostics here).
Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
- << RemainingMatches[0]->getDeclName();
- for (unsigned I = 0, N = RemainingMatches.size(); I != N; ++I)
- NoteOverloadCandidate(RemainingMatches[I]);
+ << Matches[0]->getDeclName();
+ for (UnresolvedSetIterator I = Matches.begin(),
+ E = Matches.end(); I != E; ++I)
+ NoteOverloadCandidate(cast<FunctionDecl>(*I));
return 0;
}
@@ -5067,47 +5176,27 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
- Expr *OvlExpr = From->IgnoreParens();
-
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) {
- if (UnOp->getOpcode() == UnaryOperator::AddrOf)
- OvlExpr = UnOp->getSubExpr()->IgnoreParens();
- }
-
- bool HasExplicitTemplateArgs = false;
- TemplateArgumentListInfo ExplicitTemplateArgs;
-
- llvm::SmallVector<NamedDecl*,8> Fns;
-
- // Look into the overloaded expression.
- if (UnresolvedLookupExpr *UL
- = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
- Fns.append(UL->decls_begin(), UL->decls_end());
- if (UL->hasExplicitTemplateArgs()) {
- HasExplicitTemplateArgs = true;
- UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- }
- } else if (UnresolvedMemberExpr *ME
- = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
- Fns.append(ME->decls_begin(), ME->decls_end());
- if (ME->hasExplicitTemplateArgs()) {
- HasExplicitTemplateArgs = true;
- ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
- }
- }
+
+ if (From->getType() != Context.OverloadTy)
+ return 0;
+
+ OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
// If we didn't actually find any template-ids, we're done.
- if (Fns.empty() || !HasExplicitTemplateArgs)
+ if (!OvlExpr->hasExplicitTemplateArgs())
return 0;
+
+ TemplateArgumentListInfo ExplicitTemplateArgs;
+ OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
FunctionDecl *Matched = 0;
- for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(),
- E = Fns.end(); I != E; ++I) {
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ E = OvlExpr->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
// [...] In contexts where deduction is done and fails, or in contexts
// where deduction is not done, if a template argument list is
@@ -5123,7 +5212,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info)) {
@@ -5145,6 +5234,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
/// \brief Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
NamedDecl *Callee,
+ AccessSpecifier Access,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
@@ -5154,14 +5244,14 @@ static void AddOverloadedCallCandidate(Sema &S,
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
assert(!ExplicitTemplateArgs && "Explicit template arguments?");
- S.AddOverloadCandidate(Func, Args, NumArgs, CandidateSet, false, false,
- PartialOverloading);
+ S.AddOverloadCandidate(Func, Access, Args, NumArgs, CandidateSet,
+ false, false, PartialOverloading);
return;
}
if (FunctionTemplateDecl *FuncTemplate
= dyn_cast<FunctionTemplateDecl>(Callee)) {
- S.AddTemplateOverloadCandidate(FuncTemplate, ExplicitTemplateArgs,
+ S.AddTemplateOverloadCandidate(FuncTemplate, Access, ExplicitTemplateArgs,
Args, NumArgs, CandidateSet);
return;
}
@@ -5217,12 +5307,13 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
E = ULE->decls_end(); I != E; ++I)
- AddOverloadedCallCandidate(*this, *I, ExplicitTemplateArgs,
+ AddOverloadedCallCandidate(*this, *I, I.getAccess(), ExplicitTemplateArgs,
Args, NumArgs, CandidateSet,
PartialOverloading);
if (ULE->requiresADL())
- AddArgumentDependentLookupCandidates(ULE->getName(), Args, NumArgs,
+ AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
+ Args, NumArgs,
ExplicitTemplateArgs,
CandidateSet,
PartialOverloading);
@@ -5321,7 +5412,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
}
#endif
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(Fn->getExprLoc());
// Add the functions denoted by the callee to the set of candidate
// functions, including those from argument-dependent lookup.
@@ -5338,6 +5429,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
+ CheckUnresolvedLookupAccess(ULE, FDecl, Best->getAccess());
Fn = FixOverloadedFunctionReference(Fn, FDecl);
return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
}
@@ -5372,7 +5464,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
return ExprError();
}
-static bool IsOverloaded(const Sema::FunctionSet &Functions) {
+static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
return Functions.size() > 1 ||
(Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
}
@@ -5393,10 +5485,10 @@ static bool IsOverloaded(const Sema::FunctionSet &Functions) {
/// by CreateOverloadedUnaryOp().
///
/// \param input The input argument.
-Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
- unsigned OpcIn,
- FunctionSet &Functions,
- ExprArg input) {
+Sema::OwningExprResult
+Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+ const UnresolvedSetImpl &Fns,
+ ExprArg input) {
UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
Expr *Input = (Expr *)input.get();
@@ -5418,14 +5510,12 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
}
if (Input->isTypeDependent()) {
+ CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+ = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
0, SourceRange(), OpName, OpLoc,
- /*ADL*/ true, IsOverloaded(Functions));
- for (FunctionSet::iterator Func = Functions.begin(),
- FuncEnd = Functions.end();
- Func != FuncEnd; ++Func)
- Fn->addDecl(*Func);
+ /*ADL*/ true, IsOverloaded(Fns));
+ Fn->addDecls(Fns.begin(), Fns.end());
input.release();
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
@@ -5435,14 +5525,20 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
}
// Build an empty overload set.
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(OpLoc);
// Add the candidates from the given function set.
- AddFunctionCandidates(Functions, &Args[0], NumArgs, CandidateSet, false);
+ AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false);
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
+ // Add candidates from ADL.
+ AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+ Args, NumArgs,
+ /*ExplicitTemplateArgs*/ 0,
+ CandidateSet);
+
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
@@ -5459,6 +5555,8 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess());
+
if (PerformObjectArgumentInitialization(Input, Method))
return ExprError();
} else {
@@ -5555,7 +5653,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
Sema::OwningExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
unsigned OpcIn,
- FunctionSet &Functions,
+ const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
@@ -5567,7 +5665,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If either side is type-dependent, create an appropriate dependent
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
- if (Functions.empty()) {
+ if (Fns.empty()) {
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
@@ -5580,17 +5678,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Context.DependentTy,
OpLoc));
}
-
+
+ // FIXME: save results of ADL from here?
+ CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+ = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
0, SourceRange(), OpName, OpLoc,
- /* ADL */ true, IsOverloaded(Functions));
-
- for (FunctionSet::iterator Func = Functions.begin(),
- FuncEnd = Functions.end();
- Func != FuncEnd; ++Func)
- Fn->addDecl(*Func);
+ /*ADL*/ true, IsOverloaded(Fns));
+ Fn->addDecls(Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
Args, 2,
Context.DependentTy,
@@ -5612,14 +5708,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// Build an empty overload set.
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(OpLoc);
// Add the candidates from the given function set.
- AddFunctionCandidates(Functions, Args, 2, CandidateSet, false);
+ AddFunctionCandidates(Fns, Args, 2, CandidateSet, false);
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+ // Add candidates from ADL.
+ AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
+ Args, 2,
+ /*ExplicitTemplateArgs*/ 0,
+ CandidateSet);
+
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
@@ -5636,6 +5738,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+ // Best->Access is only meaningful for class members.
+ CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess());
+
OwningExprResult Arg1
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
@@ -5770,8 +5875,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
+ CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
+ = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
0, SourceRange(), OpName, LLoc,
/*ADL*/ true, /*Overloaded*/ false);
// Can't add any actual overloads yet
@@ -5785,7 +5891,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
}
// Build an empty overload set.
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(LLoc);
// Subscript can only be overloaded as a member function.
@@ -5806,14 +5912,24 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched an overloaded operator. Build a call to that
// operator.
+ CheckMemberOperatorAccess(LLoc, Args[0], FnDecl, Best->getAccess());
+
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
- if (PerformObjectArgumentInitialization(Args[0], Method) ||
- PerformCopyInitialization(Args[1],
- FnDecl->getParamDecl(0)->getType(),
- AA_Passing))
+ if (PerformObjectArgumentInitialization(Args[0], Method))
return ExprError();
+ // Convert the arguments.
+ OwningExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ FnDecl->getParamDecl(0)),
+ SourceLocation(),
+ Owned(Args[1]));
+ if (InputInit.isInvalid())
+ return ExprError();
+
+ Args[1] = InputInit.takeAs<Expr>();
+
// Determine the result type
QualType ResultTy
= FnDecl->getType()->getAs<FunctionType>()->getResultType();
@@ -5914,7 +6030,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
QualType ObjectType = UnresExpr->getBaseType();
// Add overload candidates
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
@@ -5937,11 +6053,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (TemplateArgs)
continue;
- AddMethodCandidate(Method, ActingDC, ObjectType, Args, NumArgs,
+ AddMethodCandidate(Method, I.getAccess(), ActingDC, ObjectType,
+ Args, NumArgs,
CandidateSet, /*SuppressUserConversions=*/false);
} else {
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
- ActingDC, TemplateArgs,
+ I.getAccess(), ActingDC, TemplateArgs,
ObjectType, Args, NumArgs,
CandidateSet,
/*SuppressUsedConversions=*/false);
@@ -5954,6 +6071,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
+ CheckUnresolvedMemberAccess(UnresExpr, Method, Best->getAccess());
break;
case OR_No_Viable_Function:
@@ -6043,7 +6161,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// operators of T. The function call operators of T are obtained by
// ordinary lookup of the name operator() in the context of
// (E).operator().
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(LParenLoc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
if (RequireCompleteType(LParenLoc, Object->getType(),
@@ -6057,7 +6175,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
- AddMethodCandidate(*Oper, Object->getType(), Args, NumArgs, CandidateSet,
+ AddMethodCandidate(*Oper, Oper.getAccess(), Object->getType(),
+ Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/ false);
}
@@ -6101,7 +6220,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
ConvType = ConvPtrType->getPointeeType();
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
- AddSurrogateCandidate(Conv, ActingContext, Proto,
+ AddSurrogateCandidate(Conv, I.getAccess(), ActingContext, Proto,
Object->getType(), Args, NumArgs,
CandidateSet);
}
@@ -6158,6 +6277,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
+ CheckMemberOperatorAccess(LParenLoc, Object, Conv, Best->getAccess());
+
// We selected one of the surrogate functions that converts the
// object parameter to a function pointer. Perform the conversion
// on the object argument, then let ActOnCallExpr finish the job.
@@ -6171,6 +6292,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
CommaLocs, RParenLoc).release();
}
+ CheckMemberOperatorAccess(LParenLoc, Object,
+ Best->Function, Best->getAccess());
+
// We found an overloaded operator(). Build a CXXOperatorCallExpr
// that calls this method, using Object for the implicit object
// parameter and passing along the remaining arguments.
@@ -6232,8 +6356,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
Arg = Args[i];
// Pass the argument.
- QualType ProtoArgType = Proto->getArgType(i);
- IsError |= PerformCopyInitialization(Arg, ProtoArgType, AA_Passing);
+
+ OwningExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Method->getParamDecl(i)),
+ SourceLocation(), Owned(Arg));
+
+ IsError |= InputInit.isInvalid();
+ Arg = InputInit.takeAs<Expr>();
} else {
OwningExprResult DefArg
= BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
@@ -6274,6 +6404,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
Expr *Base = static_cast<Expr *>(BaseIn.get());
assert(Base->getType()->isRecordType() && "left-hand side must have class type");
+ SourceLocation Loc = Base->getExprLoc();
+
// C++ [over.ref]p1:
//
// [...] An expression x->m is interpreted as (x.operator->())->m
@@ -6281,10 +6413,10 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
// the operator is selected as the best match function by the
// overload resolution mechanism (13.3).
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
- OverloadCandidateSet CandidateSet;
+ OverloadCandidateSet CandidateSet(Loc);
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
- if (RequireCompleteType(Base->getLocStart(), Base->getType(),
+ if (RequireCompleteType(Loc, Base->getType(),
PDiag(diag::err_typecheck_incomplete_tag)
<< Base->getSourceRange()))
return ExprError();
@@ -6300,7 +6432,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
- AddMethodCandidate(cast<CXXMethodDecl>(D), ActingContext,
+ AddMethodCandidate(cast<CXXMethodDecl>(D), Oper.getAccess(), ActingContext,
Base->getType(), 0, 0, CandidateSet,
/*SuppressUserConversions=*/false);
}
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index f8353e3..e6dfa74 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -139,9 +139,10 @@ namespace clang {
/// QualType.
void *FromTypePtr;
- /// ToType - The type that this conversion is converting to. This
- /// is an opaque pointer that can be translated into a QualType.
- void *ToTypePtr;
+ /// ToType - The types that this conversion is converting to in
+ /// each step. This is an opaque pointer that can be translated
+ /// into a QualType.
+ void *ToTypePtrs[3];
/// CopyConstructor - The copy constructor that is used to perform
/// this conversion, when the conversion is actually just the
@@ -151,12 +152,22 @@ namespace clang {
CXXConstructorDecl *CopyConstructor;
void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
- void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+ void setToType(unsigned Idx, QualType T) {
+ assert(Idx < 3 && "To type index is out of range");
+ ToTypePtrs[Idx] = T.getAsOpaquePtr();
+ }
+ void setAllToTypes(QualType T) {
+ ToTypePtrs[0] = T.getAsOpaquePtr();
+ ToTypePtrs[1] = ToTypePtrs[0];
+ ToTypePtrs[2] = ToTypePtrs[0];
+ }
+
QualType getFromType() const {
return QualType::getFromOpaquePtr(FromTypePtr);
}
- QualType getToType() const {
- return QualType::getFromOpaquePtr(ToTypePtr);
+ QualType getToType(unsigned Idx) const {
+ assert(Idx < 3 && "To type index is out of range");
+ return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
}
void setAsIdentityConversion();
@@ -446,11 +457,33 @@ namespace clang {
/// Actually an OverloadFailureKind.
unsigned char FailureKind;
- /// FinalConversion - For a conversion function (where Function is
- /// a CXXConversionDecl), the standard conversion that occurs
- /// after the call to the overload candidate to convert the result
- /// of calling the conversion function to the required type.
- StandardConversionSequence FinalConversion;
+ /// PathAccess - The 'path access' to the given function/conversion.
+ /// Actually an AccessSpecifier.
+ unsigned Access;
+
+ AccessSpecifier getAccess() const {
+ return AccessSpecifier(Access);
+ }
+
+ /// A structure used to record information about a failed
+ /// template argument deduction.
+ struct DeductionFailureInfo {
+ // A Sema::TemplateDeductionResult.
+ unsigned Result;
+
+ // A TemplateParameter.
+ void *TemplateParameter;
+ };
+
+ union {
+ DeductionFailureInfo DeductionFailure;
+
+ /// FinalConversion - For a conversion function (where Function is
+ /// a CXXConversionDecl), the standard conversion that occurs
+ /// after the call to the overload candidate to convert the result
+ /// of calling the conversion function to the required type.
+ StandardConversionSequence FinalConversion;
+ };
/// hasAmbiguousConversion - Returns whether this overload
/// candidate requires an ambiguous conversion or not.
@@ -468,8 +501,13 @@ namespace clang {
class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> {
typedef llvm::SmallVector<OverloadCandidate, 16> inherited;
llvm::SmallPtrSet<Decl *, 16> Functions;
-
+
+ SourceLocation Loc;
public:
+ OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+
+ SourceLocation getLocation() const { return Loc; }
+
/// \brief Determine when this overload candidate will be new to the
/// overload set.
bool isNewCandidate(Decl *F) {
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 0c207fa..fa42634 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -93,6 +93,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (isa<ObjCImplicitSetterGetterRefExpr>(E))
DiagID = diag::warn_unused_property_expr;
+ if (const CXXExprWithTemporaries *Temps = dyn_cast<CXXExprWithTemporaries>(E))
+ E = Temps->getSubExpr();
+ if (const CXXZeroInitValueExpr *Zero = dyn_cast<CXXZeroInitValueExpr>(E)) {
+ if (const RecordType *RecordT = Zero->getType()->getAs<RecordType>())
+ if (CXXRecordDecl *RecordD = dyn_cast<CXXRecordDecl>(RecordT->getDecl()))
+ if (!RecordD->hasTrivialDestructor())
+ return;
+ }
+
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// If the callee has attribute pure, const, or warn_unused_result, warn with
// a more specific message to make it clear what is happening.
@@ -370,6 +379,22 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,
return false;
}
+/// CmpEnumVals - Comparison predicate for sorting enumeration values.
+///
+static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+ const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+/// EqEnumVals - Comparison preficate for uniqing enumeration values.
+///
+static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
+ const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs)
+{
+ return lhs.first == rhs.first;
+}
+
/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
/// potentially integral-promoted expression @p expr.
static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) {
@@ -482,6 +507,16 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,
return false;
}
+/// ActOnSwitchBodyError - This is called if there is an error parsing the
+/// body of the switch stmt instead of ActOnFinishSwitchStmt.
+void Sema::ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch,
+ StmtArg Body) {
+ // Keep the switch stack balanced.
+ assert(getSwitchStack().back() == (SwitchStmt*)Switch.get() &&
+ "switch stack missing push/pop!");
+ getSwitchStack().pop_back();
+}
+
Action::OwningStmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
StmtArg Body) {
@@ -550,7 +585,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
CaseValsTy CaseVals;
// Keep track of any GNU case ranges we see. The APSInt is the low value.
- std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRanges;
+ typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy;
+ CaseRangesTy CaseRanges;
DefaultStmt *TheDefaultStmt = 0;
@@ -713,6 +749,75 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
}
}
}
+
+ // Check to see if switch is over an Enum and handles all of its
+ // values
+ const EnumType* ET = dyn_cast<EnumType>(CondTypeBeforePromotion);
+ // If switch has default case, then ignore it.
+ if (!CaseListIsErroneous && !TheDefaultStmt && ET) {
+ const EnumDecl *ED = ET->getDecl();
+ typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy;
+ EnumValsTy EnumVals;
+
+ // Gather all enum values, set their type and sort them, allowing easier comparison
+ // with CaseVals.
+ for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); EDI != ED->enumerator_end(); EDI++) {
+ llvm::APSInt Val = (*EDI)->getInitVal();
+ if(Val.getBitWidth() < CondWidth)
+ Val.extend(CondWidth);
+ Val.setIsSigned(CondIsSigned);
+ EnumVals.push_back(std::make_pair(Val, (*EDI)));
+ }
+ std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals);
+ EnumValsTy::iterator EIend = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals);
+ // See which case values aren't in enum
+ EnumValsTy::const_iterator EI = EnumVals.begin();
+ for (CaseValsTy::const_iterator CI = CaseVals.begin(); CI != CaseVals.end(); CI++) {
+ while (EI != EIend && EI->first < CI->first)
+ EI++;
+ if (EI == EIend || EI->first > CI->first)
+ Diag(CI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName();
+ }
+ // See which of case ranges aren't in enum
+ EI = EnumVals.begin();
+ for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); RI != CaseRanges.end() && EI != EIend; RI++) {
+ while (EI != EIend && EI->first < RI->first)
+ EI++;
+
+ if (EI == EIend || EI->first != RI->first) {
+ Diag(RI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName();
+ }
+
+ llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context);
+ while (EI != EIend && EI->first < Hi)
+ EI++;
+ if (EI == EIend || EI->first != Hi)
+ Diag(RI->second->getRHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName();
+ }
+ //Check which enum vals aren't in switch
+ CaseValsTy::const_iterator CI = CaseVals.begin();
+ CaseRangesTy::const_iterator RI = CaseRanges.begin();
+ EI = EnumVals.begin();
+ for (; EI != EIend; EI++) {
+ //Drop unneeded case values
+ llvm::APSInt CIVal;
+ while (CI != CaseVals.end() && CI->first < EI->first)
+ CI++;
+
+ if (CI != CaseVals.end() && CI->first == EI->first)
+ continue;
+
+ //Drop unneeded case ranges
+ for (; RI != CaseRanges.end(); RI++) {
+ llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context);
+ if (EI->first <= Hi)
+ break;
+ }
+
+ if (RI == CaseRanges.end() || EI->first < RI->first)
+ Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) << EI->second->getDeclName();
+ }
+ }
}
// FIXME: If the case list was broken is some way, we don't have a good system
@@ -863,7 +968,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
<< FirstType << First->getSourceRange();
}
if (Second) {
- DefaultFunctionArrayConversion(Second);
+ DefaultFunctionArrayLvalueConversion(Second);
QualType SecondType = Second->getType();
if (!SecondType->isObjCObjectPointerType())
Diag(ForLoc, diag::err_collection_expr_type)
@@ -896,10 +1001,10 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
Expr* E = DestExp.takeAs<Expr>();
if (!E->isTypeDependent()) {
QualType ETy = E->getType();
+ QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
AssignConvertType ConvTy =
- CheckSingleAssignmentConstraints(Context.VoidPtrTy, E);
- if (DiagnoseAssignmentResult(ConvTy, StarLoc, Context.VoidPtrTy, ETy,
- E, AA_Passing))
+ CheckSingleAssignmentConstraints(DestTy, E);
+ if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
return StmtError();
}
return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
@@ -937,7 +1042,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (RetValExp) {
// Don't call UsualUnaryConversions(), since we don't want to do
// integer promotions here.
- DefaultFunctionArrayConversion(RetValExp);
+ DefaultFunctionArrayLvalueConversion(RetValExp);
CurBlock->ReturnType = RetValExp->getType();
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
// We have to remove a 'const' added to copied-in variable which was
@@ -981,11 +1086,19 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- // FIXME: Leaks RetValExp.
- if (PerformCopyInitialization(RetValExp, FnRetType, AA_Returning))
+ OwningExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeResult(ReturnLoc,
+ FnRetType),
+ SourceLocation(),
+ Owned(RetValExp));
+ if (Res.isInvalid()) {
+ // FIXME: Cleanup temporaries here, anyway?
return StmtError();
-
- if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+ }
+
+ RetValExp = Res.takeAs<Expr>();
+ if (RetValExp)
+ CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
}
return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp));
@@ -1025,7 +1138,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
QualType FnRetType;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
FnRetType = FD->getResultType();
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->hasAttr<NoReturnAttr>() ||
+ FD->getType()->getAs<FunctionType>()->getNoReturnAttr())
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< getCurFunctionOrMethodDecl()->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl())
@@ -1121,6 +1235,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
/// This method checks to see if the argument is an acceptable l-value and
/// returns false if it is a case we can handle.
static bool CheckAsmLValue(const Expr *E, Sema &S) {
+ // Type dependent expressions will be checked during instantiation.
+ if (E->isTypeDependent())
+ return false;
+
if (E->isLvalue(S.Context) == Expr::LV_Valid)
return false; // Cool, this is an lvalue.
@@ -1148,7 +1266,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
bool IsVolatile,
unsigned NumOutputs,
unsigned NumInputs,
- std::string *Names,
+ IdentifierInfo **Names,
MultiExprArg constraints,
MultiExprArg exprs,
ExprArg asmString,
@@ -1175,9 +1293,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
<< Literal->getSourceRange());
- TargetInfo::ConstraintInfo Info(Literal->getStrData(),
- Literal->getByteLength(),
- Names[i]);
+ llvm::StringRef OutputName;
+ if (Names[i])
+ OutputName = Names[i]->getName();
+
+ TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
if (!Context.Target.validateOutputConstraint(Info))
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_invalid_output_constraint)
@@ -1202,9 +1322,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
<< Literal->getSourceRange());
- TargetInfo::ConstraintInfo Info(Literal->getStrData(),
- Literal->getByteLength(),
- Names[i]);
+ llvm::StringRef InputName;
+ if (Names[i])
+ InputName = Names[i]->getName();
+
+ TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
if (!Context.Target.validateInputConstraint(OutputConstraintInfos.data(),
NumOutputs, Info)) {
return StmtError(Diag(Literal->getLocStart(),
@@ -1232,7 +1354,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
}
}
- DefaultFunctionArrayConversion(Exprs[i]);
+ DefaultFunctionArrayLvalueConversion(Exprs[i]);
InputConstraintInfos.push_back(Info);
}
@@ -1244,11 +1366,9 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
<< Literal->getSourceRange());
- std::string Clobber(Literal->getStrData(),
- Literal->getStrData() +
- Literal->getByteLength());
+ llvm::StringRef Clobber = Literal->getString();
- if (!Context.Target.isValidGCCRegisterName(Clobber.c_str()))
+ if (!Context.Target.isValidGCCRegisterName(Clobber))
return StmtError(Diag(Literal->getLocStart(),
diag::err_asm_unknown_register_name) << Clobber);
}
@@ -1258,9 +1378,9 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
asmString.release();
clobbers.release();
AsmStmt *NS =
- new (Context) AsmStmt(AsmLoc, IsSimple, IsVolatile, MSAsm, NumOutputs,
- NumInputs, Names, Constraints, Exprs, AsmString,
- NumClobbers, Clobbers, RParenLoc);
+ new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm,
+ NumOutputs, NumInputs, Names, Constraints, Exprs,
+ AsmString, NumClobbers, Clobbers, RParenLoc);
// Validate the asm string, ensuring it makes sense given the operands we
// have.
llvm::SmallVector<AsmStmt::AsmStringPiece, 8> Pieces;
@@ -1527,7 +1647,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
CurFunctionNeedsScopeChecking = true;
RawHandlers.release();
- return Owned(new (Context) CXXTryStmt(TryLoc,
- static_cast<Stmt*>(TryBlock.release()),
- Handlers, NumHandlers));
+ return Owned(CXXTryStmt::Create(Context, TryLoc,
+ static_cast<Stmt*>(TryBlock.release()),
+ Handlers, NumHandlers));
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 0040156..10e411f 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -823,7 +823,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Check for redefinition of this class template.
if (TUK == TUK_Definition) {
- if (TagDecl *Def = PrevRecordDecl->getDefinition(Context)) {
+ if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
// FIXME: Would it make sense to try to "forget" the previous
@@ -1235,18 +1235,14 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
// such a member, the member declaration shall be preceded by a
// template<> for each enclosing class template that is
// explicitly specialized.
- // We interpret this as forbidding typedefs of template
- // specializations in the scope specifiers of out-of-line decls.
- if (const TypedefType *TT = dyn_cast<TypedefType>(T)) {
- const Type *UnderlyingT = TT->LookThroughTypedefs().getTypePtr();
- if (isa<TemplateSpecializationType>(UnderlyingT))
- // FIXME: better source location information.
- Diag(DeclStartLoc, diag::err_typedef_in_def_scope) << QualType(T,0);
- T = UnderlyingT;
- }
+ //
+ // Following the existing practice of GNU and EDG, we allow a typedef of a
+ // template specialization type.
+ if (const TypedefType *TT = dyn_cast<TypedefType>(T))
+ T = TT->LookThroughTypedefs().getTypePtr();
if (const TemplateSpecializationType *SpecType
- = dyn_cast<TemplateSpecializationType>(T)) {
+ = dyn_cast<TemplateSpecializationType>(T)) {
TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl();
if (!Template)
continue; // FIXME: should this be an error? probably...
@@ -1525,17 +1521,19 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
QualifierRange = SS.getRange();
}
+
+ // We don't want lookup warnings at this point.
+ R.suppressDiagnostics();
bool Dependent
= UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(),
&TemplateArgs);
UnresolvedLookupExpr *ULE
- = UnresolvedLookupExpr::Create(Context, Dependent,
+ = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
Qualifier, QualifierRange,
R.getLookupName(), R.getNameLoc(),
RequiresADL, TemplateArgs);
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
- ULE->addDecl(*I);
+ ULE->addDecls(R.begin(), R.end());
return Owned(ULE);
}
@@ -2305,7 +2303,17 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
} else
DRE = dyn_cast<DeclRefExpr>(Arg);
- if (!DRE || !isa<ValueDecl>(DRE->getDecl()))
+ if (!DRE)
+ return Diag(Arg->getSourceRange().getBegin(),
+ diag::err_template_arg_not_decl_ref)
+ << Arg->getSourceRange();
+
+ // Stop checking the precise nature of the argument if it is value dependent,
+ // it should be checked when instantiated.
+ if (Arg->isValueDependent())
+ return false;
+
+ if (!isa<ValueDecl>(DRE->getDecl()))
return Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_not_object_or_func_form)
<< Arg->getSourceRange();
@@ -2324,7 +2332,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
// Functions must have external linkage.
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) {
- if (Func->getLinkage() != NamedDecl::ExternalLinkage) {
+ if (!isExternalLinkage(Func->getLinkage())) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_function_not_extern)
<< Func << Arg->getSourceRange();
@@ -2339,7 +2347,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
}
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (Var->getLinkage() != NamedDecl::ExternalLinkage) {
+ if (!isExternalLinkage(Var->getLinkage())) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_object_not_extern)
<< Var << Arg->getSourceRange();
@@ -2656,9 +2664,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
return true;
- if (Entity)
- Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
- Converted = TemplateArgument(Entity);
+ if (Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ } else {
+ if (Entity)
+ Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+ Converted = TemplateArgument(Entity);
+ }
return false;
}
@@ -2696,9 +2708,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
return true;
- if (Entity)
- Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
- Converted = TemplateArgument(Entity);
+ if (Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ } else {
+ if (Entity)
+ Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+ Converted = TemplateArgument(Entity);
+ }
return false;
}
@@ -2712,7 +2728,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
assert(ParamRefType->getPointeeType()->isObjectType() &&
"Only object references allowed here");
- if (!Context.hasSameUnqualifiedType(ParamRefType->getPointeeType(), ArgType)) {
+ QualType ReferredType = ParamRefType->getPointeeType();
+ if (!Context.hasSameUnqualifiedType(ReferredType, ArgType)) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_no_ref_bind)
<< InstantiatedParamType << Arg->getType()
@@ -2722,7 +2739,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
unsigned ParamQuals
- = Context.getCanonicalType(ParamType).getCVRQualifiers();
+ = Context.getCanonicalType(ReferredType).getCVRQualifiers();
unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers();
if ((ParamQuals | ArgQuals) != ParamQuals) {
@@ -2738,8 +2755,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
return true;
- Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
- Converted = TemplateArgument(Entity);
+ if (Arg->isValueDependent()) {
+ Converted = TemplateArgument(Arg);
+ } else {
+ Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
+ Converted = TemplateArgument(Entity);
+ }
return false;
}
@@ -3375,12 +3396,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// FIXME: Diagnose friend partial specializations
- // FIXME: Template parameter list matters, too
- ClassTemplatePartialSpecializationDecl::Profile(ID,
- Converted.getFlatArguments(),
- Converted.flatSize(),
- Context);
- } else
+ if (!Name.isDependent() &&
+ !TemplateSpecializationType::anyDependentTemplateArguments(
+ TemplateArgs.getArgumentArray(),
+ TemplateArgs.size())) {
+ Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
+ << ClassTemplate->getDeclName();
+ isPartialSpecialization = false;
+ } else {
+ // FIXME: Template parameter list matters, too
+ ClassTemplatePartialSpecializationDecl::Profile(ID,
+ Converted.getFlatArguments(),
+ Converted.flatSize(),
+ Context);
+ }
+ }
+
+ if (!isPartialSpecialization)
ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
Converted.flatSize(),
@@ -3410,7 +3442,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
QualType CanonType;
if (PrevDecl &&
(PrevDecl->getSpecializationKind() == TSK_Undeclared ||
- TUK == TUK_Friend)) {
+ TUK == TUK_Friend)) {
// Since the only prior class template specialization with these
// arguments was referenced but not declared, or we're only
// referencing this specialization as a friend, reuse that
@@ -3423,8 +3455,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
} else if (isPartialSpecialization) {
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
- CanonType = Context.getTemplateSpecializationType(
- TemplateName(ClassTemplate),
+ TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
+ CanonType = Context.getTemplateSpecializationType(CanonTemplate,
Converted.getFlatArguments(),
Converted.flatSize());
@@ -3532,7 +3564,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Check that this isn't a redefinition of this specialization.
if (TUK == TUK_Definition) {
- if (RecordDecl *Def = Specialization->getDefinition(Context)) {
+ if (RecordDecl *Def = Specialization->getDefinition()) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_redefinition)
<< Context.getTypeDeclType(Specialization) << Range;
@@ -3619,6 +3651,16 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
return DeclPtrTy();
}
+/// \brief Strips various properties off an implicit instantiation
+/// that has just been explicitly specialized.
+static void StripImplicitInstantiation(NamedDecl *D) {
+ D->invalidateAttrs();
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ FD->setInlineSpecified(false);
+ }
+}
+
/// \brief Diagnose cases where we have an explicit template specialization
/// before/after an explicit template instantiation, producing diagnostics
/// for those cases where they are required and determining whether the
@@ -3669,6 +3711,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
if (PrevPointOfInstantiation.isInvalid()) {
// The declaration itself has not actually been instantiated, so it is
// still okay to specialize it.
+ StripImplicitInstantiation(PrevDecl);
return false;
}
// Fall through
@@ -3817,8 +3860,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
LookupResult &Previous) {
// The set of function template specializations that could match this
// explicit function template specialization.
- typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet;
- CandidateSet Candidates;
+ UnresolvedSet<8> Candidates;
DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
@@ -3837,7 +3879,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// Perform template argument deduction to determine whether we may be
// specializing this template.
// FIXME: It is somewhat wasteful to build
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, FD->getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult TDK
= DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs,
@@ -3851,22 +3893,24 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
}
// Record this candidate.
- Candidates.push_back(Specialization);
+ Candidates.addDecl(Specialization, I.getAccess());
}
}
// Find the most specialized function template.
- FunctionDecl *Specialization = getMostSpecialized(Candidates.data(),
- Candidates.size(),
- TPOC_Other,
- FD->getLocation(),
+ UnresolvedSetIterator Result
+ = getMostSpecialized(Candidates.begin(), Candidates.end(),
+ TPOC_Other, FD->getLocation(),
PartialDiagnostic(diag::err_function_template_spec_no_match)
<< FD->getDeclName(),
PartialDiagnostic(diag::err_function_template_spec_ambiguous)
<< FD->getDeclName() << (ExplicitTemplateArgs != 0),
PartialDiagnostic(diag::note_function_template_spec_matched));
- if (!Specialization)
+ if (Result == Candidates.end())
return true;
+
+ // Ignore access information; it doesn't figure into redeclaration checking.
+ FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
// FIXME: Check if the prior specialization has a point of instantiation.
// If so, we have run afoul of .
@@ -3887,15 +3931,15 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
FunctionTemplateSpecializationInfo *SpecInfo
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
- if (SpecInfo->getPointOfInstantiation().isValid()) {
- Diag(FD->getLocation(), diag::err_specialization_after_instantiation)
- << FD;
- Diag(SpecInfo->getPointOfInstantiation(),
- diag::note_instantiation_required_here)
- << (Specialization->getTemplateSpecializationKind()
- != TSK_ImplicitInstantiation);
+
+ bool SuppressNew = false;
+ if (CheckSpecializationInstantiationRedecl(FD->getLocation(),
+ TSK_ExplicitSpecialization,
+ Specialization,
+ SpecInfo->getTemplateSpecializationKind(),
+ SpecInfo->getPointOfInstantiation(),
+ SuppressNew))
return true;
- }
// Mark the prior declaration as an explicit specialization, so that later
// clients know that this is an explicit specialization.
@@ -3904,8 +3948,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// Turn the given function declaration into a function template
// specialization, with the template arguments from the previous
// specialization.
- FD->setFunctionTemplateSpecialization(Context,
- Specialization->getPrimaryTemplate(),
+ FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(),
new (Context) TemplateArgumentList(
*Specialization->getTemplateSpecializationArgs()),
/*InsertPos=*/0,
@@ -3997,14 +4040,15 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
assert(MSInfo && "Member specialization info missing?");
- if (MSInfo->getPointOfInstantiation().isValid()) {
- Diag(Member->getLocation(), diag::err_specialization_after_instantiation)
- << Member;
- Diag(MSInfo->getPointOfInstantiation(),
- diag::note_instantiation_required_here)
- << (MSInfo->getTemplateSpecializationKind() != TSK_ImplicitInstantiation);
+
+ bool SuppressNew = false;
+ if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
+ TSK_ExplicitSpecialization,
+ Instantiation,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew))
return true;
- }
// Check the scope of this explicit specialization.
if (CheckTemplateSpecializationScope(*this,
@@ -4288,13 +4332,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// instantiation.
ClassTemplateSpecializationDecl *Def
= cast_or_null<ClassTemplateSpecializationDecl>(
- Specialization->getDefinition(Context));
+ Specialization->getDefinition());
if (!Def)
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
// Instantiate the members of this class template specialization.
Def = cast_or_null<ClassTemplateSpecializationDecl>(
- Specialization->getDefinition(Context));
+ Specialization->getDefinition());
if (Def)
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
@@ -4371,7 +4415,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Verify that it is okay to explicitly instantiate here.
CXXRecordDecl *PrevDecl
= cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
- if (!PrevDecl && Record->getDefinition(Context))
+ if (!PrevDecl && Record->getDefinition())
PrevDecl = Record;
if (PrevDecl) {
MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
@@ -4388,13 +4432,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,
}
CXXRecordDecl *RecordDef
- = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ = cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (!RecordDef) {
// C++ [temp.explicit]p3:
// A definition of a member class of a class template shall be in scope
// at the point of an explicit instantiation of the member class.
CXXRecordDecl *Def
- = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
+ = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
if (!Def) {
Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
<< 0 << Record->getDeclName() << Record->getDeclContext();
@@ -4407,7 +4451,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
TSK))
return true;
- RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (!RecordDef)
return true;
}
@@ -4568,7 +4612,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// A member function [...] of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
- llvm::SmallVector<FunctionDecl *, 8> Matches;
+ UnresolvedSet<8> Matches;
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
@@ -4577,7 +4621,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
Matches.clear();
- Matches.push_back(Method);
+ Matches.addDecl(Method, P.getAccess());
if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
break;
}
@@ -4588,7 +4632,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (!FunTmpl)
continue;
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, D.getIdentifierLoc());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult TDK
= DeduceTemplateArguments(FunTmpl,
@@ -4599,19 +4643,22 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
continue;
}
- Matches.push_back(Specialization);
+ Matches.addDecl(Specialization, P.getAccess());
}
// Find the most specialized function template specialization.
- FunctionDecl *Specialization
- = getMostSpecialized(Matches.data(), Matches.size(), TPOC_Other,
+ UnresolvedSetIterator Result
+ = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other,
D.getIdentifierLoc(),
PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name,
PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name,
PartialDiagnostic(diag::note_explicit_instantiation_candidate));
- if (!Specialization)
+ if (Result == Matches.end())
return true;
+
+ // Ignore access control bits, we don't need them for redeclaration checking.
+ FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
Diag(D.getIdentifierLoc(),
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 7b433e9..df4d4a8 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -49,7 +49,7 @@ namespace clang {
using namespace clang;
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
@@ -72,7 +72,7 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
/// \brief Deduce the value of the given non-type template parameter
/// from the given constant.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
llvm::APSInt Value,
Sema::TemplateDeductionInfo &Info,
@@ -84,7 +84,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
QualType T = NTTP->getType();
// FIXME: Make sure we didn't overflow our data type!
- unsigned AllowedBits = Context.getTypeSize(T);
+ unsigned AllowedBits = S.Context.getTypeSize(T);
if (Value.getBitWidth() != AllowedBits)
Value.extOrTrunc(AllowedBits);
Value.setIsSigned(T->isSignedIntegerType());
@@ -126,7 +126,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
///
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
Expr *Value,
Sema::TemplateDeductionInfo &Info,
@@ -152,8 +152,8 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
// Compare the expressions for equality
llvm::FoldingSetNodeID ID1, ID2;
- Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, Context, true);
- Value->Profile(ID2, Context, true);
+ Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, S.Context, true);
+ Value->Profile(ID2, S.Context, true);
if (ID1 == ID2)
return Sema::TDK_Success;
@@ -169,7 +169,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
///
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
Decl *D,
Sema::TemplateDeductionInfo &Info,
@@ -202,7 +202,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
TemplateName Param,
TemplateName Arg,
@@ -221,13 +221,13 @@ DeduceTemplateArguments(ASTContext &Context,
TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()];
if (ExistingArg.isNull()) {
// This is the first deduction for this template template parameter.
- ExistingArg = TemplateArgument(Context.getCanonicalTemplateName(Arg));
+ ExistingArg = TemplateArgument(S.Context.getCanonicalTemplateName(Arg));
return Sema::TDK_Success;
}
// Verify that the previous binding matches this deduction.
assert(ExistingArg.getKind() == TemplateArgument::Template);
- if (Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
+ if (S.Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
return Sema::TDK_Success;
// Inconsistent deduction.
@@ -238,7 +238,7 @@ DeduceTemplateArguments(ASTContext &Context,
}
// Verify that the two template names are equivalent.
- if (Context.hasSameTemplateName(Param, Arg))
+ if (S.Context.hasSameTemplateName(Param, Arg))
return Sema::TDK_Success;
// Mismatch of non-dependent template parameter to argument.
@@ -250,7 +250,7 @@ DeduceTemplateArguments(ASTContext &Context,
/// \brief Deduce the template arguments by comparing the template parameter
/// type (which is a template-id) with the template argument type.
///
-/// \param Context the AST context in which this deduction occurs.
+/// \param S the Sema
///
/// \param TemplateParams the template parameters that we are deducing
///
@@ -266,7 +266,7 @@ DeduceTemplateArguments(ASTContext &Context,
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateSpecializationType *Param,
QualType Arg,
@@ -279,7 +279,7 @@ DeduceTemplateArguments(ASTContext &Context,
= dyn_cast<TemplateSpecializationType>(Arg)) {
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
Param->getTemplateName(),
SpecArg->getTemplateName(),
Info, Deduced))
@@ -291,7 +291,7 @@ DeduceTemplateArguments(ASTContext &Context,
unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs());
for (unsigned I = 0; I != NumArgs; ++I)
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
Param->getArg(I),
SpecArg->getArg(I),
Info, Deduced))
@@ -314,7 +314,7 @@ DeduceTemplateArguments(ASTContext &Context,
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context,
+ = DeduceTemplateArguments(S,
TemplateParams,
Param->getTemplateName(),
TemplateName(SpecArg->getSpecializedTemplate()),
@@ -328,7 +328,7 @@ DeduceTemplateArguments(ASTContext &Context,
for (unsigned I = 0; I != NumArgs; ++I)
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
Param->getArg(I),
ArgArgs.get(I),
Info, Deduced))
@@ -340,7 +340,7 @@ DeduceTemplateArguments(ASTContext &Context,
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
-/// \param Context the AST context in which this deduction occurs.
+/// \param S the semantic analysis object within which we are deducing
///
/// \param TemplateParams the template parameters that we are deducing
///
@@ -359,7 +359,7 @@ DeduceTemplateArguments(ASTContext &Context,
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
Sema::TemplateDeductionInfo &Info,
@@ -367,8 +367,8 @@ DeduceTemplateArguments(ASTContext &Context,
unsigned TDF) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
- QualType Param = Context.getCanonicalType(ParamIn);
- QualType Arg = Context.getCanonicalType(ArgIn);
+ QualType Param = S.Context.getCanonicalType(ParamIn);
+ QualType Arg = S.Context.getCanonicalType(ArgIn);
// C++0x [temp.deduct.call]p4 bullet 1:
// - If the original P is a reference type, the deduced A (i.e., the type
@@ -376,10 +376,10 @@ DeduceTemplateArguments(ASTContext &Context,
// transformed A.
if (TDF & TDF_ParamWithReferenceType) {
Qualifiers Quals;
- QualType UnqualParam = Context.getUnqualifiedArrayType(Param, Quals);
+ QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
Arg.getCVRQualifiersThroughArrayTypes());
- Param = Context.getQualifiedType(UnqualParam, Quals);
+ Param = S.Context.getQualifiedType(UnqualParam, Quals);
}
// If the parameter type is not dependent, there is nothing to deduce.
@@ -409,9 +409,9 @@ DeduceTemplateArguments(ASTContext &Context,
// FIXME: address spaces, ObjC GC qualifiers
if (isa<ArrayType>(Arg)) {
Qualifiers Quals;
- Arg = Context.getUnqualifiedArrayType(Arg, Quals);
+ Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
if (Quals) {
- Arg = Context.getQualifiedType(Arg, Quals);
+ Arg = S.Context.getQualifiedType(Arg, Quals);
RecanonicalizeArg = true;
}
}
@@ -426,11 +426,11 @@ DeduceTemplateArguments(ASTContext &Context,
}
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
- assert(Arg != Context.OverloadTy && "Unresolved overloaded function");
+ assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
if (RecanonicalizeArg)
- DeducedType = Context.getCanonicalType(DeducedType);
+ DeducedType = S.Context.getCanonicalType(DeducedType);
if (Deduced[Index].isNull())
Deduced[Index] = TemplateArgument(DeducedType);
@@ -479,7 +479,7 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_NonDeducedMismatch;
unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
cast<PointerType>(Param)->getPointeeType(),
PointerArg->getPointeeType(),
Info, Deduced, SubTDF);
@@ -491,7 +491,7 @@ DeduceTemplateArguments(ASTContext &Context,
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
cast<LValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
Info, Deduced, 0);
@@ -503,7 +503,7 @@ DeduceTemplateArguments(ASTContext &Context,
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
cast<RValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
Info, Deduced, 0);
@@ -512,12 +512,12 @@ DeduceTemplateArguments(ASTContext &Context,
// T [] (implied, but not stated explicitly)
case Type::IncompleteArray: {
const IncompleteArrayType *IncompleteArrayArg =
- Context.getAsIncompleteArrayType(Arg);
+ S.Context.getAsIncompleteArrayType(Arg);
if (!IncompleteArrayArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
- Context.getAsIncompleteArrayType(Param)->getElementType(),
+ return DeduceTemplateArguments(S, TemplateParams,
+ S.Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
Info, Deduced, 0);
}
@@ -525,16 +525,16 @@ DeduceTemplateArguments(ASTContext &Context,
// T [integer-constant]
case Type::ConstantArray: {
const ConstantArrayType *ConstantArrayArg =
- Context.getAsConstantArrayType(Arg);
+ S.Context.getAsConstantArrayType(Arg);
if (!ConstantArrayArg)
return Sema::TDK_NonDeducedMismatch;
const ConstantArrayType *ConstantArrayParm =
- Context.getAsConstantArrayType(Param);
+ S.Context.getAsConstantArrayType(Param);
if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
Info, Deduced, 0);
@@ -542,15 +542,15 @@ DeduceTemplateArguments(ASTContext &Context,
// type [i]
case Type::DependentSizedArray: {
- const ArrayType *ArrayArg = Context.getAsArrayType(Arg);
+ const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
if (!ArrayArg)
return Sema::TDK_NonDeducedMismatch;
// Check the element type of the arrays
const DependentSizedArrayType *DependentArrayParm
- = Context.getAsDependentSizedArrayType(Param);
+ = S.Context.getAsDependentSizedArrayType(Param);
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
DependentArrayParm->getElementType(),
ArrayArg->getElementType(),
Info, Deduced, 0))
@@ -569,12 +569,12 @@ DeduceTemplateArguments(ASTContext &Context,
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
- return DeduceNonTypeTemplateArgument(Context, NTTP, Size,
+ return DeduceNonTypeTemplateArgument(S, NTTP, Size,
Info, Deduced);
}
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
- return DeduceNonTypeTemplateArgument(Context, NTTP,
+ return DeduceNonTypeTemplateArgument(S, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
@@ -606,7 +606,7 @@ DeduceTemplateArguments(ASTContext &Context,
// Check return types.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
FunctionProtoParam->getResultType(),
FunctionProtoArg->getResultType(),
Info, Deduced, 0))
@@ -615,7 +615,7 @@ DeduceTemplateArguments(ASTContext &Context,
for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
// Check argument types.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
FunctionProtoParam->getArgType(I),
FunctionProtoArg->getArgType(I),
Info, Deduced, 0))
@@ -636,7 +636,7 @@ DeduceTemplateArguments(ASTContext &Context,
// Try to deduce template arguments from the template-id.
Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams, SpecParam, Arg,
+ = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
Info, Deduced);
if (Result && (TDF & TDF_DerivedClass)) {
@@ -649,7 +649,13 @@ DeduceTemplateArguments(ASTContext &Context,
// More importantly:
// These alternatives are considered only if type deduction would
// otherwise fail.
- if (const RecordType *RecordT = dyn_cast<RecordType>(Arg)) {
+ if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
+ // We cannot inspect base classes as part of deduction when the type
+ // is incomplete, so either instantiate any templates necessary to
+ // complete the type, or skip over it if it cannot be completed.
+ if (S.RequireCompleteType(Info.getLocation(), Arg, 0))
+ return Result;
+
// Use data recursion to crawl through the list of base classes.
// Visited contains the set of nodes we have already visited, while
// ToVisit is our stack of records that we still need to visit.
@@ -670,7 +676,7 @@ DeduceTemplateArguments(ASTContext &Context,
// deduction from it.
if (NextT != RecordT) {
Sema::TemplateDeductionResult BaseResult
- = DeduceTemplateArguments(Context, TemplateParams, SpecParam,
+ = DeduceTemplateArguments(S, TemplateParams, SpecParam,
QualType(NextT, 0), Info, Deduced);
// If template argument deduction for this base was successful,
@@ -715,14 +721,14 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_NonDeducedMismatch;
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
MemPtrParam->getPointeeType(),
MemPtrArg->getPointeeType(),
Info, Deduced,
TDF & TDF_IgnoreQualifiers))
return Result;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
QualType(MemPtrParam->getClass(), 0),
QualType(MemPtrArg->getClass(), 0),
Info, Deduced, 0);
@@ -740,7 +746,7 @@ DeduceTemplateArguments(ASTContext &Context,
if (!BlockPtrArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
BlockPtrParam->getPointeeType(),
BlockPtrArg->getPointeeType(), Info,
Deduced, 0);
@@ -761,7 +767,7 @@ DeduceTemplateArguments(ASTContext &Context,
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
@@ -774,7 +780,7 @@ DeduceTemplateArguments(ASTContext &Context,
case TemplateArgument::Type:
if (Arg.getKind() == TemplateArgument::Type)
- return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
+ return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(),
Arg.getAsType(), Info, Deduced, 0);
Info.FirstArg = Param;
Info.SecondArg = Arg;
@@ -782,7 +788,7 @@ DeduceTemplateArguments(ASTContext &Context,
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
Param.getAsTemplate(),
Arg.getAsTemplate(), Info, Deduced);
Info.FirstArg = Param;
@@ -826,14 +832,14 @@ DeduceTemplateArguments(ASTContext &Context,
= getDeducedParameterFromExpr(Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
// FIXME: Sign problems here
- return DeduceNonTypeTemplateArgument(Context, NTTP,
+ return DeduceNonTypeTemplateArgument(S, NTTP,
*Arg.getAsIntegral(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
- return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
+ return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Declaration)
- return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsDecl(),
+ return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
Info, Deduced);
assert(false && "Type/value mismatch");
@@ -854,7 +860,7 @@ DeduceTemplateArguments(ASTContext &Context,
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
@@ -863,7 +869,7 @@ DeduceTemplateArguments(ASTContext &Context,
assert(ParamList.size() == ArgList.size());
for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
ParamList[I], ArgList[I],
Info, Deduced))
return Result;
@@ -951,7 +957,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
llvm::SmallVector<TemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context,
+ = ::DeduceTemplateArguments(*this,
Partial->getTemplateParameters(),
Partial->getTemplateArgs(),
TemplateArgs, Info, Deduced))
@@ -1306,6 +1312,91 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
return TDK_Success;
}
+static QualType GetTypeOfFunction(ASTContext &Context,
+ bool isAddressOfOperand,
+ FunctionDecl *Fn) {
+ if (!isAddressOfOperand) return Fn->getType();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
+ if (Method->isInstance())
+ return Context.getMemberPointerType(Fn->getType(),
+ Context.getTypeDeclType(Method->getParent()).getTypePtr());
+ return Context.getPointerType(Fn->getType());
+}
+
+/// Apply the deduction rules for overload sets.
+///
+/// \return the null type if this argument should be treated as an
+/// undeduced context
+static QualType
+ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
+ Expr *Arg, QualType ParamType) {
+ llvm::PointerIntPair<OverloadExpr*,1> R = OverloadExpr::find(Arg);
+
+ bool isAddressOfOperand = bool(R.getInt());
+ OverloadExpr *Ovl = R.getPointer();
+
+ // If there were explicit template arguments, we can only find
+ // something via C++ [temp.arg.explicit]p3, i.e. if the arguments
+ // unambiguously name a full specialization.
+ if (Ovl->hasExplicitTemplateArgs()) {
+ // But we can still look for an explicit specialization.
+ if (FunctionDecl *ExplicitSpec
+ = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+ return GetTypeOfFunction(S.Context, isAddressOfOperand, ExplicitSpec);
+ return QualType();
+ }
+
+ // C++0x [temp.deduct.call]p6:
+ // When P is a function type, pointer to function type, or pointer
+ // to member function type:
+
+ if (!ParamType->isFunctionType() &&
+ !ParamType->isFunctionPointerType() &&
+ !ParamType->isMemberFunctionPointerType())
+ return QualType();
+
+ QualType Match;
+ for (UnresolvedSetIterator I = Ovl->decls_begin(),
+ E = Ovl->decls_end(); I != E; ++I) {
+ NamedDecl *D = (*I)->getUnderlyingDecl();
+
+ // - If the argument is an overload set containing one or more
+ // function templates, the parameter is treated as a
+ // non-deduced context.
+ if (isa<FunctionTemplateDecl>(D))
+ return QualType();
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ QualType ArgType = GetTypeOfFunction(S.Context, isAddressOfOperand, Fn);
+
+ // - If the argument is an overload set (not containing function
+ // templates), trial argument deduction is attempted using each
+ // of the members of the set. If deduction succeeds for only one
+ // of the overload set members, that member is used as the
+ // argument value for the deduction. If deduction succeeds for
+ // more than one member of the overload set the parameter is
+ // treated as a non-deduced context.
+
+ // We do all of this in a fresh context per C++0x [temp.deduct.type]p2:
+ // Type deduction is done independently for each P/A pair, and
+ // the deduced template argument values are then combined.
+ // So we do not reject deductions which were made elsewhere.
+ llvm::SmallVector<TemplateArgument, 8> Deduced(TemplateParams->size());
+ Sema::TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
+ unsigned TDF = 0;
+
+ Sema::TemplateDeductionResult Result
+ = DeduceTemplateArguments(S, TemplateParams,
+ ParamType, ArgType,
+ Info, Deduced, TDF);
+ if (Result) continue;
+ if (!Match.isNull()) return QualType();
+ Match = ArgType;
+ }
+
+ return Match;
+}
+
/// \brief Perform template argument deduction from a function call
/// (C++ [temp.deduct.call]).
///
@@ -1384,6 +1475,15 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType ParamType = ParamTypes[I];
QualType ArgType = Args[I]->getType();
+ // Overload sets usually make this parameter an undeduced
+ // context, but there are sometimes special circumstances.
+ if (ArgType == Context.OverloadTy) {
+ ArgType = ResolveOverloadForDeduction(*this, TemplateParams,
+ Args[I], ParamType);
+ if (ArgType.isNull())
+ continue;
+ }
+
// C++ [temp.deduct.call]p2:
// If P is not a reference type:
QualType CanonParamType = Context.getCanonicalType(ParamType);
@@ -1454,38 +1554,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
ParamType->getAs<PointerType>()->getPointeeType())))
TDF |= TDF_DerivedClass;
- // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function
- // pointer parameters.
-
- if (Context.hasSameUnqualifiedType(ArgType, Context.OverloadTy)) {
- // We know that template argument deduction will fail if the argument is
- // still an overloaded function. Check whether we can resolve this
- // argument as a single function template specialization per
- // C++ [temp.arg.explicit]p3.
- FunctionDecl *ExplicitSpec
- = ResolveSingleFunctionTemplateSpecialization(Args[I]);
- Expr *ResolvedArg = 0;
- if (ExplicitSpec)
- ResolvedArg = FixOverloadedFunctionReference(Args[I], ExplicitSpec);
- if (!ExplicitSpec || !ResolvedArg) {
- // Template argument deduction fails if we can't resolve the overloaded
- // function.
- return TDK_FailedOverloadResolution;
- }
-
- // Get the type of the resolved argument, and adjust it per
- // C++0x [temp.deduct.call]p3.
- ArgType = ResolvedArg->getType();
- if (!ParamWasReference && ArgType->isFunctionType())
- ArgType = Context.getPointerType(ArgType);
- if (ArgType->isPointerType() || ArgType->isMemberPointerType())
- TDF |= TDF_IgnoreQualifiers;
-
- ResolvedArg->Destroy(Context);
- }
-
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
+ = ::DeduceTemplateArguments(*this, TemplateParams,
ParamType, ArgType, Info, Deduced,
TDF))
return Result;
@@ -1548,11 +1618,12 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// Trap any errors that might occur.
SFINAETrap Trap(*this);
+ Deduced.resize(TemplateParams->size());
+
if (!ArgFunctionType.isNull()) {
// Deduce template arguments from the function type.
- Deduced.resize(TemplateParams->size());
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
+ = ::DeduceTemplateArguments(*this, TemplateParams,
FunctionType, ArgFunctionType, Info,
Deduced, 0))
return Result;
@@ -1651,7 +1722,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
(P->isMemberPointerType() && P->isMemberPointerType()))
TDF |= TDF_IgnoreQualifiers;
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
+ = ::DeduceTemplateArguments(*this, TemplateParams,
P, A, Info, Deduced, TDF))
return Result;
@@ -1702,7 +1773,7 @@ enum DeductionQualifierComparison {
/// \brief Deduce the template arguments during partial ordering by comparing
/// the parameter type and the argument type (C++0x [temp.deduct.partial]).
///
-/// \param Context the AST context in which this deduction occurs.
+/// \param S the semantic analysis object within which we are deducing
///
/// \param TemplateParams the template parameters that we are deducing
///
@@ -1718,14 +1789,14 @@ enum DeductionQualifierComparison {
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context,
+DeduceTemplateArgumentsDuringPartialOrdering(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced,
llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
- CanQualType Param = Context.getCanonicalType(ParamIn);
- CanQualType Arg = Context.getCanonicalType(ArgIn);
+ CanQualType Param = S.Context.getCanonicalType(ParamIn);
+ CanQualType Arg = S.Context.getCanonicalType(ArgIn);
// C++0x [temp.deduct.partial]p5:
// Before the partial ordering is done, certain transformations are
@@ -1772,7 +1843,7 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context,
// described in 14.9.2.5. If deduction succeeds for a given type, the type
// from the argument template is considered to be at least as specialized
// as the type from the parameter template.
- return DeduceTemplateArguments(Context, TemplateParams, Param, Arg, Info,
+ return DeduceTemplateArguments(S, TemplateParams, Param, Arg, Info,
Deduced, TDF_None);
}
@@ -1785,6 +1856,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
/// \brief Determine whether the function template \p FT1 is at least as
/// specialized as \p FT2.
static bool isAtLeastAsSpecializedAs(Sema &S,
+ SourceLocation Loc,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
@@ -1802,14 +1874,14 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// C++0x [temp.deduct.partial]p3:
// The types used to determine the ordering depend on the context in which
// the partial ordering is done:
- Sema::TemplateDeductionInfo Info(S.Context);
+ Sema::TemplateDeductionInfo Info(S.Context, Loc);
switch (TPOC) {
case TPOC_Call: {
// - In the context of a function call, the function parameter types are
// used.
unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
for (unsigned I = 0; I != NumParams; ++I)
- if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S,
TemplateParams,
Proto2->getArgType(I),
Proto1->getArgType(I),
@@ -1824,7 +1896,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
case TPOC_Conversion:
// - In the context of a call to a conversion operator, the return types
// of the conversion function templates are used.
- if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S,
TemplateParams,
Proto2->getResultType(),
Proto1->getResultType(),
@@ -1837,7 +1909,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
case TPOC_Other:
// - In other contexts (14.6.6.2) the function template’s function type
// is used.
- if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S,
TemplateParams,
FD2->getType(),
FD1->getType(),
@@ -1916,10 +1988,11 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
FunctionTemplateDecl *
Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
TemplatePartialOrderingContext TPOC) {
llvm::SmallVector<DeductionQualifierComparison, 4> QualifierComparisons;
- bool Better1 = isAtLeastAsSpecializedAs(*this, FT1, FT2, TPOC, 0);
- bool Better2 = isAtLeastAsSpecializedAs(*this, FT2, FT1, TPOC,
+ bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, 0);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
&QualifierComparisons);
if (Better1 != Better2) // We have a clear winner
@@ -1987,11 +2060,11 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// \brief Retrieve the most specialized of the given function template
/// specializations.
///
-/// \param Specializations the set of function template specializations that
-/// we will be comparing.
+/// \param SpecBegin the start iterator of the function template
+/// specializations that we will be comparing.
///
-/// \param NumSpecializations the number of function template specializations in
-/// \p Specializations
+/// \param SpecEnd the end iterator of the function template
+/// specializations, paired with \p SpecBegin.
///
/// \param TPOC the partial ordering context to use to compare the function
/// template specializations.
@@ -2015,42 +2088,38 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) {
/// specialization.
///
/// \returns the most specialized function template specialization, if
-/// found. Otherwise, returns NULL.
+/// found. Otherwise, returns SpecEnd.
///
/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
/// template argument deduction.
-FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations,
- unsigned NumSpecializations,
- TemplatePartialOrderingContext TPOC,
- SourceLocation Loc,
- const PartialDiagnostic &NoneDiag,
- const PartialDiagnostic &AmbigDiag,
- const PartialDiagnostic &CandidateDiag,
- unsigned *Index) {
- if (NumSpecializations == 0) {
+UnresolvedSetIterator
+Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
+ UnresolvedSetIterator SpecEnd,
+ TemplatePartialOrderingContext TPOC,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag) {
+ if (SpecBegin == SpecEnd) {
Diag(Loc, NoneDiag);
- return 0;
+ return SpecEnd;
}
- if (NumSpecializations == 1) {
- if (Index)
- *Index = 0;
-
- return Specializations[0];
- }
-
+ if (SpecBegin + 1 == SpecEnd)
+ return SpecBegin;
// Find the function template that is better than all of the templates it
// has been compared to.
- unsigned Best = 0;
+ UnresolvedSetIterator Best = SpecBegin;
FunctionTemplateDecl *BestTemplate
- = Specializations[Best]->getPrimaryTemplate();
+ = cast<FunctionDecl>(*Best)->getPrimaryTemplate();
assert(BestTemplate && "Not a function template specialization?");
- for (unsigned I = 1; I != NumSpecializations; ++I) {
- FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate();
+ for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) {
+ FunctionTemplateDecl *Challenger
+ = cast<FunctionDecl>(*I)->getPrimaryTemplate();
assert(Challenger && "Not a function template specialization?");
- if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- TPOC),
+ if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
+ Loc, TPOC),
Challenger)) {
Best = I;
BestTemplate = Challenger;
@@ -2060,11 +2129,12 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations,
// Make sure that the "best" function template is more specialized than all
// of the others.
bool Ambiguous = false;
- for (unsigned I = 0; I != NumSpecializations; ++I) {
- FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate();
+ for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
+ FunctionTemplateDecl *Challenger
+ = cast<FunctionDecl>(*I)->getPrimaryTemplate();
if (I != Best &&
!isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
- TPOC),
+ Loc, TPOC),
BestTemplate)) {
Ambiguous = true;
break;
@@ -2073,22 +2143,20 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations,
if (!Ambiguous) {
// We found an answer. Return it.
- if (Index)
- *Index = Best;
- return Specializations[Best];
+ return Best;
}
// Diagnose the ambiguity.
Diag(Loc, AmbigDiag);
// FIXME: Can we order the candidates in some sane way?
- for (unsigned I = 0; I != NumSpecializations; ++I)
- Diag(Specializations[I]->getLocation(), CandidateDiag)
+ for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
+ Diag((*I)->getLocation(), CandidateDiag)
<< getTemplateArgumentBindingsText(
- Specializations[I]->getPrimaryTemplate()->getTemplateParameters(),
- *Specializations[I]->getTemplateSpecializationArgs());
+ cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+ *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
- return 0;
+ return SpecEnd;
}
/// \brief Returns the more specialized class template partial specialization
@@ -2104,7 +2172,8 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations,
ClassTemplatePartialSpecializationDecl *
Sema::getMoreSpecializedPartialSpecialization(
ClassTemplatePartialSpecializationDecl *PS1,
- ClassTemplatePartialSpecializationDecl *PS2) {
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc) {
// C++ [temp.class.order]p1:
// For two class template partial specializations, the first is at least as
// specialized as the second if, given the following rewrite to two
@@ -2127,11 +2196,11 @@ Sema::getMoreSpecializedPartialSpecialization(
// template partial ordering, because class template partial specializations
// are more constrained. We know that every template parameter is deduc
llvm::SmallVector<TemplateArgument, 4> Deduced;
- Sema::TemplateDeductionInfo Info(Context);
+ Sema::TemplateDeductionInfo Info(Context, Loc);
// Determine whether PS1 is at least as specialized as PS2
Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
+ bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
PS2->getTemplateParameters(),
Context.getTypeDeclType(PS2),
Context.getTypeDeclType(PS1),
@@ -2142,7 +2211,7 @@ Sema::getMoreSpecializedPartialSpecialization(
// Determine whether PS2 is at least as specialized as PS1
Deduced.clear();
Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
+ bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
PS1->getTemplateParameters(),
Context.getTypeDeclType(PS1),
Context.getTypeDeclType(PS2),
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 2db0deb..51e17fe 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -33,9 +33,15 @@ using namespace clang;
/// arguments.
///
/// \param Innermost if non-NULL, the innermost template argument list.
+///
+/// \param RelativeToPrimary true if we should get the template
+/// arguments relative to the primary template, even when we're
+/// dealing with a specialization. This is only relevant for function
+/// template specializations.
MultiLevelTemplateArgumentList
Sema::getTemplateInstantiationArgs(NamedDecl *D,
- const TemplateArgumentList *Innermost) {
+ const TemplateArgumentList *Innermost,
+ bool RelativeToPrimary) {
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
@@ -64,8 +70,9 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
}
// Add template arguments from a function template specialization.
else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
- if (Function->getTemplateSpecializationKind()
- == TSK_ExplicitSpecialization)
+ if (!RelativeToPrimary &&
+ Function->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
break;
if (const TemplateArgumentList *TemplateArgs
@@ -86,11 +93,13 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (Function->getFriendObjectKind() &&
Function->getDeclContext()->isFileContext()) {
Ctx = Function->getLexicalDeclContext();
+ RelativeToPrimary = false;
continue;
}
}
Ctx = Ctx->getParent();
+ RelativeToPrimary = false;
}
return Result;
@@ -555,6 +564,8 @@ namespace {
Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E);
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ Sema::OwningExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+ NonTypeTemplateParmDecl *D);
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
@@ -569,6 +580,14 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
+ TTP->getPosition()))
+ return D;
+
TemplateName Template
= TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
@@ -576,14 +595,6 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
return Template.getAsTemplateDecl();
}
- // If the corresponding template argument is NULL or non-existent, it's
- // because we are performing instantiation from explicitly-specified
- // template arguments in a function template, but there were some
- // arguments left unspecified.
- if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
- TTP->getPosition()))
- return D;
-
// Fall through to find the instantiated declaration for this template
// template parameter.
}
@@ -676,8 +687,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
PredefinedExpr::IdentType IT = E->getIdentType();
- unsigned Length =
- PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length();
+ unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length();
llvm::APInt LengthI(32, Length + 1);
QualType ResTy = getSema().Context.CharTy.withConst();
@@ -689,88 +699,145 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
}
Sema::OwningExprResult
-TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
- // FIXME: Clean this up a bit
- NamedDecl *D = E->getDecl();
- if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- if (NTTP->getDepth() < TemplateArgs.getNumLevels()) {
- // If the corresponding template argument is NULL or non-existent, it's
- // because we are performing instantiation from explicitly-specified
- // template arguments in a function template, but there were some
- // arguments left unspecified.
- if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
- NTTP->getPosition()))
- return SemaRef.Owned(E->Retain());
+TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
+ NonTypeTemplateParmDecl *NTTP) {
+ // If the corresponding template argument is NULL or non-existent, it's
+ // because we are performing instantiation from explicitly-specified
+ // template arguments in a function template, but there were some
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+ NTTP->getPosition()))
+ return SemaRef.Owned(E->Retain());
- const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
- NTTP->getPosition());
+ const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
+ NTTP->getPosition());
- // The template argument itself might be an expression, in which
- // case we just return that expression.
- if (Arg.getKind() == TemplateArgument::Expression)
- return SemaRef.Owned(Arg.getAsExpr()->Retain());
+ // The template argument itself might be an expression, in which
+ // case we just return that expression.
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return SemaRef.Owned(Arg.getAsExpr()->Retain());
- if (Arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
- VD = cast_or_null<ValueDecl>(
+ // Find the instantiation of the template argument. This is
+ // required for nested templates.
+ VD = cast_or_null<ValueDecl>(
getSema().FindInstantiatedDecl(VD, TemplateArgs));
- if (!VD)
+ if (!VD)
+ return SemaRef.ExprError();
+
+ // Derive the type we want the substituted decl to have. This had
+ // better be non-dependent, or these checks will have serious problems.
+ QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
+ E->getLocation(),
+ DeclarationName());
+ assert(!TargetType.isNull() && "type substitution failed for param type");
+ assert(!TargetType->isDependentType() && "param type still dependent");
+
+ if (VD->getDeclContext()->isRecord() &&
+ (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) {
+ // If the value is a class member, we might have a pointer-to-member.
+ // Determine whether the non-type template template parameter is of
+ // pointer-to-member type. If so, we need to build an appropriate
+ // expression for a pointer-to-member, since a "normal" DeclRefExpr
+ // would refer to the member itself.
+ if (TargetType->isMemberPointerType()) {
+ QualType ClassType
+ = SemaRef.Context.getTypeDeclType(
+ cast<RecordDecl>(VD->getDeclContext()));
+ NestedNameSpecifier *Qualifier
+ = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ ClassType.getTypePtr());
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ OwningExprResult RefExpr
+ = SemaRef.BuildDeclRefExpr(VD,
+ VD->getType().getNonReferenceType(),
+ E->getLocation(),
+ &SS);
+ if (RefExpr.isInvalid())
return SemaRef.ExprError();
- if (VD->getDeclContext()->isRecord()) {
- // If the value is a class member, we might have a pointer-to-member.
- // Determine whether the non-type template template parameter is of
- // pointer-to-member type. If so, we need to build an appropriate
- // expression for a pointer-to-member, since a "normal" DeclRefExpr
- // would refer to the member itself.
- if (NTTP->getType()->isMemberPointerType()) {
- QualType ClassType
- = SemaRef.Context.getTypeDeclType(
- cast<RecordDecl>(VD->getDeclContext()));
- NestedNameSpecifier *Qualifier
- = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
- ClassType.getTypePtr());
- CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- OwningExprResult RefExpr
- = SemaRef.BuildDeclRefExpr(VD,
- VD->getType().getNonReferenceType(),
- E->getLocation(),
- &SS);
- if (RefExpr.isInvalid())
- return SemaRef.ExprError();
-
- return SemaRef.CreateBuiltinUnaryOp(E->getLocation(),
- UnaryOperator::AddrOf,
- move(RefExpr));
- }
- }
+ RefExpr = SemaRef.CreateBuiltinUnaryOp(E->getLocation(),
+ UnaryOperator::AddrOf,
+ move(RefExpr));
+ assert(!RefExpr.isInvalid() &&
+ SemaRef.Context.hasSameType(((Expr*) RefExpr.get())->getType(),
+ TargetType));
+ return move(RefExpr);
+ }
+ }
- return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
- E->getLocation());
+ QualType T = VD->getType().getNonReferenceType();
+
+ if (TargetType->isPointerType()) {
+ // C++03 [temp.arg.nontype]p5:
+ // - For a non-type template-parameter of type pointer to
+ // object, qualification conversions and the array-to-pointer
+ // conversion are applied.
+ // - For a non-type template-parameter of type pointer to
+ // function, only the function-to-pointer conversion is
+ // applied.
+
+ OwningExprResult RefExpr
+ = SemaRef.BuildDeclRefExpr(VD, T, E->getLocation());
+ if (RefExpr.isInvalid())
+ return SemaRef.ExprError();
+
+ // Decay functions and arrays.
+ Expr *RefE = (Expr *)RefExpr.get();
+ SemaRef.DefaultFunctionArrayConversion(RefE);
+ if (RefE != RefExpr.get()) {
+ RefExpr.release();
+ RefExpr = SemaRef.Owned(RefE);
}
- assert(Arg.getKind() == TemplateArgument::Integral);
- QualType T = Arg.getIntegralType();
- if (T->isCharType() || T->isWideCharType())
- return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
+ // Qualification conversions.
+ RefExpr.release();
+ SemaRef.ImpCastExprToType(RefE, TargetType.getUnqualifiedType(),
+ CastExpr::CK_NoOp);
+ return SemaRef.Owned(RefE);
+ }
+
+ // If the non-type template parameter has reference type, qualify the
+ // resulting declaration reference with the extra qualifiers on the
+ // type that the reference refers to.
+ if (const ReferenceType *TargetRef = TargetType->getAs<ReferenceType>())
+ T = SemaRef.Context.getQualifiedType(T,
+ TargetRef->getPointeeType().getQualifiers());
+
+ return SemaRef.BuildDeclRefExpr(VD, T, E->getLocation());
+ }
+
+ assert(Arg.getKind() == TemplateArgument::Integral);
+ QualType T = Arg.getIntegralType();
+ if (T->isCharType() || T->isWideCharType())
+ return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
Arg.getAsIntegral()->getZExtValue(),
T->isWideCharType(),
T,
E->getSourceRange().getBegin()));
- if (T->isBooleanType())
- return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
+ if (T->isBooleanType())
+ return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
Arg.getAsIntegral()->getBoolValue(),
T,
E->getSourceRange().getBegin()));
- assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
- return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+ assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
+ return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
*Arg.getAsIntegral(),
T,
E->getSourceRange().getBegin()));
- }
+}
+
+
+Sema::OwningExprResult
+TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
+ NamedDecl *D = E->getDecl();
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+ if (NTTP->getDepth() < TemplateArgs.getNumLevels())
+ return TransformTemplateParmRefExpr(E, NTTP);
// We have a non-type template parameter that isn't fully substituted;
// FindInstantiatedDecl will find it in the local instantiation scope.
@@ -986,7 +1053,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool Invalid = false;
CXXRecordDecl *PatternDef
- = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
+ = cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
if (!PatternDef) {
if (!Complain) {
// Say nothing
@@ -1063,9 +1130,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// If this is a polymorphic C++ class without a key function, we'll
// have to mark all of the virtual members to allow emission of a vtable
// in this translation unit.
- if (Instantiation->isDynamicClass() && !Context.getKeyFunction(Instantiation))
+ if (Instantiation->isDynamicClass() &&
+ !Context.getKeyFunction(Instantiation)) {
+ // Local classes need to have their methods instantiated immediately in
+ // order to have the correct instantiation scope.
+ if (Instantiation->isLocalClass()) {
+ MarkVirtualMembersReferenced(PointOfInstantiation,
+ Instantiation);
+ } else {
ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Instantiation,
PointOfInstantiation));
+ }
+ }
if (!Invalid)
Consumer.HandleTagDeclDefinition(Instantiation);
@@ -1124,7 +1200,7 @@ Sema::InstantiateClassTemplateSpecialization(
PartialEnd = Template->getPartialSpecializations().end();
Partial != PartialEnd;
++Partial) {
- TemplateDeductionInfo Info(Context);
+ TemplateDeductionInfo Info(Context, PointOfInstantiation);
if (TemplateDeductionResult Result
= DeduceTemplateArguments(&*Partial,
ClassTemplateSpec->getTemplateArgs(),
@@ -1154,7 +1230,8 @@ Sema::InstantiateClassTemplateSpecialization(
for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
PEnd = Matched.end();
P != PEnd; ++P) {
- if (getMoreSpecializedPartialSpecialization(P->first, Best->first)
+ if (getMoreSpecializedPartialSpecialization(P->first, Best->first,
+ PointOfInstantiation)
== P->first)
Best = P;
}
@@ -1166,7 +1243,8 @@ Sema::InstantiateClassTemplateSpecialization(
PEnd = Matched.end();
P != PEnd; ++P) {
if (P != Best &&
- getMoreSpecializedPartialSpecialization(P->first, Best->first)
+ getMoreSpecializedPartialSpecialization(P->first, Best->first,
+ PointOfInstantiation)
!= Best->first) {
Ambiguous = true;
break;
@@ -1327,8 +1405,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
assert(Pattern && "Missing instantiated-from-template information");
- if (!Record->getDefinition(Context)) {
- if (!Pattern->getDefinition(Context)) {
+ if (!Record->getDefinition()) {
+ if (!Pattern->getDefinition()) {
// C++0x [temp.explicit]p8:
// An explicit instantiation definition that names a class template
// specialization explicitly instantiates the class template
@@ -1348,7 +1426,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
TSK);
}
- Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (Pattern)
InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
TSK);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 23a9430..0b0efcb 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -43,6 +43,7 @@ namespace {
// clang/AST/DeclNodes.def.
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
+ Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
Decl *VisitTypedefDecl(TypedefDecl *D);
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
@@ -126,6 +127,21 @@ TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) {
return D;
}
+Decl *
+TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ NamespaceAliasDecl *Inst
+ = NamespaceAliasDecl::Create(SemaRef.Context, Owner,
+ D->getNamespaceLoc(),
+ D->getAliasLoc(),
+ D->getNamespace()->getIdentifier(),
+ D->getQualifierRange(),
+ D->getQualifier(),
+ D->getTargetNameLoc(),
+ D->getNamespace());
+ Owner->addDecl(Inst);
+ return Inst;
+}
+
Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
bool Invalid = false;
TypeSourceInfo *DI = D->getTypeSourceInfo();
@@ -217,6 +233,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// FIXME: having to fake up a LookupResult is dumb.
LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
Sema::LookupOrdinaryName);
+ if (D->isStaticDataMember())
+ SemaRef.LookupQualifiedName(Previous, Owner, false);
SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
if (D->isOutOfLine()) {
@@ -232,7 +250,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
TSK_ImplicitInstantiation);
- if (D->getInit()) {
+ if (Var->getAnyInitializer()) {
+ // We already have an initializer in the class.
+ } else if (D->getInit()) {
if (Var->isStaticDataMember() && !D->isOutOfLine())
SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated);
else
@@ -241,6 +261,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// Extract the initializer, skipping through any temporary-binding
// expressions and look at the subexpression as it was written.
Expr *DInit = D->getInit();
+ if (CXXExprWithTemporaries *ExprTemp
+ = dyn_cast<CXXExprWithTemporaries>(DInit))
+ DInit = ExprTemp->getSubExpr();
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(DInit))
DInit = Binder->getSubExpr();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(DInit))
@@ -408,9 +431,17 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
Decl *NewND;
// Hack to make this work almost well pending a rewrite.
- if (ND->getDeclContext()->isRecord())
- NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs);
- else if (D->wasSpecialization()) {
+ if (ND->getDeclContext()->isRecord()) {
+ if (!ND->getDeclContext()->isDependentContext()) {
+ NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs);
+ } else {
+ // FIXME: Hack to avoid crashing when incorrectly trying to instantiate
+ // templated friend declarations. This doesn't produce a correct AST;
+ // however this is sufficient for some AST analysis. The real solution
+ // must be put in place during the pending rewrite. See PR5848.
+ return 0;
+ }
+ } else if (D->wasSpecialization()) {
// Totally egregious hack to work around PR5866
return 0;
} else
@@ -493,6 +524,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
}
if (EnumConst) {
+ EnumConst->setAccess(Enum->getAccess());
Enum->addDecl(EnumConst);
Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst));
LastEnumConst = EnumConst;
@@ -734,9 +766,14 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
if (T.isNull())
return 0;
- // Build the instantiated method declaration.
- DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext(),
- TemplateArgs);
+ // If we're instantiating a local function declaration, put the result
+ // in the owner; otherwise we need to find the instantiated context.
+ DeclContext *DC;
+ if (D->getDeclContext()->isFunctionOrMethod())
+ DC = Owner;
+ else
+ DC = SemaRef.FindInstantiatedContext(D->getDeclContext(), TemplateArgs);
+
FunctionDecl *Function =
FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
D->getDeclName(), T, D->getTypeSourceInfo(),
@@ -747,7 +784,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
Params[P]->setOwningFunction(Function);
- Function->setParams(SemaRef.Context, Params.data(), Params.size());
+ Function->setParams(Params.data(), Params.size());
if (TemplateParams) {
// Our resulting instantiation is actually a function template, since we
@@ -772,8 +809,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
} else if (FunctionTemplate) {
// Record this function template specialization.
- Function->setFunctionTemplateSpecialization(SemaRef.Context,
- FunctionTemplate,
+ Function->setFunctionTemplateSpecialization(FunctionTemplate,
&TemplateArgs.getInnermost(),
InsertPos);
}
@@ -926,8 +962,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method->setDescribedFunctionTemplate(FunctionTemplate);
} else if (FunctionTemplate) {
// Record this function template specialization.
- Method->setFunctionTemplateSpecialization(SemaRef.Context,
- FunctionTemplate,
+ Method->setFunctionTemplateSpecialization(FunctionTemplate,
&TemplateArgs.getInnermost(),
InsertPos);
} else {
@@ -944,7 +979,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
Params[P]->setOwningFunction(Method);
- Method->setParams(SemaRef.Context, Params.data(), Params.size());
+ Method->setParams(Params.data(), Params.size());
if (InitMethodInstantiation(Method, D))
Method->setInvalidDecl();
@@ -1804,7 +1839,6 @@ void Sema::InstantiateStaticDataMemberDefinition(
CurContext = PreviousContext;
if (Var) {
- Var->setPreviousDeclaration(OldVar);
MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
assert(MSInfo && "Missing member specialization information?");
Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
@@ -1829,7 +1863,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
const MultiLevelTemplateArgumentList &TemplateArgs) {
llvm::SmallVector<MemInitTy*, 4> NewInits;
-
+ bool AnyErrors = false;
+
// Instantiate all the initializers.
for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
InitsEnd = Tmpl->init_end();
@@ -1837,26 +1872,38 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
CXXBaseOrMemberInitializer *Init = *Inits;
ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
+ llvm::SmallVector<SourceLocation, 4> CommaLocs;
// Instantiate all the arguments.
- for (ExprIterator Args = Init->arg_begin(), ArgsEnd = Init->arg_end();
- Args != ArgsEnd; ++Args) {
- OwningExprResult NewArg = SubstExpr(*Args, TemplateArgs);
-
- if (NewArg.isInvalid())
- New->setInvalidDecl();
- else
- NewArgs.push_back(NewArg.takeAs<Expr>());
+ Expr *InitE = Init->getInit();
+ if (!InitE) {
+ // Nothing to instantiate;
+ } else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) {
+ if (InstantiateInitializationArguments(*this, ParenList->getExprs(),
+ ParenList->getNumExprs(),
+ TemplateArgs, CommaLocs,
+ NewArgs)) {
+ AnyErrors = true;
+ continue;
+ }
+ } else {
+ OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs);
+ if (InitArg.isInvalid()) {
+ AnyErrors = true;
+ continue;
+ }
+
+ NewArgs.push_back(InitArg.release());
}
-
+
MemInitResult NewInit;
-
if (Init->isBaseInitializer()) {
TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(),
TemplateArgs,
Init->getSourceLocation(),
New->getDeclName());
if (!BaseTInfo) {
+ AnyErrors = true;
New->setInvalidDecl();
continue;
}
@@ -1884,9 +1931,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
Init->getRParenLoc());
}
- if (NewInit.isInvalid())
+ if (NewInit.isInvalid()) {
+ AnyErrors = true;
New->setInvalidDecl();
- else {
+ } else {
// FIXME: It would be nice if ASTOwningVector had a release function.
NewArgs.take();
@@ -1898,7 +1946,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
ActOnMemInitializers(DeclPtrTy::make(New),
/*FIXME: ColonLoc */
SourceLocation(),
- NewInits.data(), NewInits.size());
+ NewInits.data(), NewInits.size(),
+ AnyErrors);
}
// TODO: this could be templated if the various decl types used the
@@ -2140,7 +2189,7 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs) {
DeclContext *ParentDC = D->getDeclContext();
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
- isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
ParentDC->isFunctionOrMethod()) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
@@ -2151,10 +2200,11 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
if (!Record->isDependentContext())
return D;
- // If the RecordDecl is actually the injected-class-name or a "templated"
- // declaration for a class template or class template partial
- // specialization, substitute into the injected-class-name of the
- // class template or partial specialization to find the new DeclContext.
+ // If the RecordDecl is actually the injected-class-name or a
+ // "templated" declaration for a class template, class template
+ // partial specialization, or a member class of a class template,
+ // substitute into the injected-class-name of the class template
+ // or partial specialization to find the new DeclContext.
QualType T;
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
@@ -2164,15 +2214,18 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
T = Context.getTypeDeclType(Record);
ClassTemplate = PartialSpec->getSpecializedTemplate();
- }
+ }
if (!T.isNull()) {
- // Substitute into the injected-class-name to get the type corresponding
- // to the instantiation we want. This substitution should never fail,
- // since we know we can instantiate the injected-class-name or we wouldn't
- // have gotten to the injected-class-name!
- // FIXME: Can we use the CurrentInstantiationScope to avoid this extra
- // instantiation in the common case?
+ // Substitute into the injected-class-name to get the type
+ // corresponding to the instantiation we want, which may also be
+ // the current instantiation (if we're in a template
+ // definition). This substitution should never fail, since we
+ // know we can instantiate the injected-class-name or we
+ // wouldn't have gotten to the injected-class-name!
+
+ // FIXME: Can we use the CurrentInstantiationScope to avoid this
+ // extra instantiation in the common case?
T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName());
assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
@@ -2181,26 +2234,37 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
return T->getAs<RecordType>()->getDecl();
}
- // We are performing "partial" template instantiation to create the
- // member declarations for the members of a class template
- // specialization. Therefore, D is actually referring to something in
- // the current instantiation. Look through the current context,
- // which contains actual instantiations, to find the instantiation of
- // the "current instantiation" that D refers to.
+ // We are performing "partial" template instantiation to create
+ // the member declarations for the members of a class template
+ // specialization. Therefore, D is actually referring to something
+ // in the current instantiation. Look through the current
+ // context, which contains actual instantiations, to find the
+ // instantiation of the "current instantiation" that D refers
+ // to.
+ bool SawNonDependentContext = false;
for (DeclContext *DC = CurContext; !DC->isFileContext();
DC = DC->getParent()) {
if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+ = dyn_cast<ClassTemplateSpecializationDecl>(DC))
if (isInstantiationOf(ClassTemplate,
Spec->getSpecializedTemplate()))
return Spec;
+
+ if (!DC->isDependentContext())
+ SawNonDependentContext = true;
}
- assert(false &&
+ // We're performing "instantiation" of a member of the current
+ // instantiation while we are type-checking the
+ // definition. Compute the declaration context and return that.
+ assert(!SawNonDependentContext &&
+ "No dependent context while instantiating record");
+ DeclContext *DC = computeDeclContext(T);
+ assert(DC &&
"Unable to find declaration for the current instantiation");
- return Record;
+ return cast<CXXRecordDecl>(DC);
}
-
+
// Fall through to deal with other dependent record types (e.g.,
// anonymous unions in class templates).
}
@@ -2275,6 +2339,24 @@ void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
VarDecl *Var = cast<VarDecl>(Inst.first);
assert(Var->isStaticDataMember() && "Not a static data member?");
+ // Don't try to instantiate declarations if the most recent redeclaration
+ // is invalid.
+ if (Var->getMostRecentDeclaration()->isInvalidDecl())
+ continue;
+
+ // Check if the most recent declaration has changed the specialization kind
+ // and removed the need for implicit instantiation.
+ switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ assert(false && "Cannot instantitiate an undeclared specialization.");
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ continue; // No longer need implicit instantiation.
+ case TSK_ImplicitInstantiation:
+ break;
+ }
+
PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Var),
Var->getLocation(), *this,
Context.getSourceManager(),
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9065761..7911e76 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -68,12 +68,41 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
return false;
}
+typedef std::pair<const AttributeList*,QualType> DelayedAttribute;
+typedef llvm::SmallVectorImpl<DelayedAttribute> DelayedAttributeSet;
+
+static void ProcessTypeAttributeList(Sema &S, QualType &Type,
+ const AttributeList *Attrs,
+ DelayedAttributeSet &DelayedFnAttrs);
+static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr);
+
+static void ProcessDelayedFnAttrs(Sema &S, QualType &Type,
+ DelayedAttributeSet &Attrs) {
+ for (DelayedAttributeSet::iterator I = Attrs.begin(),
+ E = Attrs.end(); I != E; ++I)
+ if (ProcessFnAttr(S, Type, *I->first))
+ S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
+ << I->first->getName() << I->second;
+ Attrs.clear();
+}
+
+static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) {
+ for (DelayedAttributeSet::iterator I = Attrs.begin(),
+ E = Attrs.end(); I != E; ++I) {
+ S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type)
+ << I->first->getName() << I->second;
+ }
+ Attrs.clear();
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param D the declarator containing the declaration specifier.
/// \returns The type described by the declaration specifiers. This function
/// never returns null.
-static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
+static QualType ConvertDeclSpecToType(Sema &TheSema,
+ Declarator &TheDeclarator,
+ DelayedAttributeSet &Delayed) {
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
const DeclSpec &DS = TheDeclarator.getDeclSpec();
@@ -343,6 +372,11 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
if (TheSema.getLangOptions().Freestanding)
TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
Result = Context.getComplexType(Result);
+ } else if (DS.isTypeAltiVecVector()) {
+ unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
+ assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
+ Result = Context.getVectorType(Result, 128/typeSize, true,
+ DS.isTypeAltiVecPixel());
}
assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary &&
@@ -351,7 +385,7 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){
// See if there are any attributes on the declspec that apply to the type (as
// opposed to the decl).
if (const AttributeList *AL = DS.getAttributes())
- TheSema.ProcessTypeAttributeList(Result, AL);
+ ProcessTypeAttributeList(TheSema, Result, AL, Delayed);
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -885,15 +919,23 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// have a type.
QualType T;
+ llvm::SmallVector<DelayedAttribute,4> FnAttrsFromDeclSpec;
+
switch (D.getName().getKind()) {
case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
- T = ConvertDeclSpecToType(D, *this);
+ T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec);
- if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned())
- *OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+ if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
+ TagDecl* Owned = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+ // Owned is embedded if it was defined here, or if it is the
+ // very first (i.e., canonical) declaration of this tag type.
+ Owned->setEmbeddedInDeclarator(Owned->isDefinition() ||
+ Owned->isCanonicalDecl());
+ if (OwnedDecl) *OwnedDecl = Owned;
+ }
break;
case UnqualifiedId::IK_ConstructorName:
@@ -962,6 +1004,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.getIdentifier())
Name = D.getIdentifier();
+ llvm::SmallVector<DelayedAttribute,4> FnAttrsFromPreviousChunk;
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -1181,6 +1225,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
FTI.hasAnyExceptionSpec,
Exceptions.size(), Exceptions.data());
}
+
+ // For GCC compatibility, we allow attributes that apply only to
+ // function types to be placed on a function's return type
+ // instead (as long as that type doesn't happen to be function
+ // or function-pointer itself).
+ ProcessDelayedFnAttrs(*this, T, FnAttrsFromPreviousChunk);
+
break;
}
case DeclaratorChunk::MemberPointer:
@@ -1239,9 +1290,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
T = Context.IntTy;
}
+ DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
+
// See if there are any attributes on this declarator chunk.
if (const AttributeList *AL = DeclType.getAttrs())
- ProcessTypeAttributeList(T, AL);
+ ProcessTypeAttributeList(*this, T, AL, FnAttrsFromPreviousChunk);
}
if (getLangOptions().CPlusPlus && T->isFunctionType()) {
@@ -1271,10 +1324,18 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
}
- // If there were any type attributes applied to the decl itself (not the
- // type, apply the type attribute to the type!)
- if (const AttributeList *Attrs = D.getAttributes())
- ProcessTypeAttributeList(T, Attrs);
+ // Process any function attributes we might have delayed from the
+ // declaration-specifiers.
+ ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
+
+ // If there were any type attributes applied to the decl itself, not
+ // the type, apply them to the result type. But don't do this for
+ // block-literal expressions, which are parsed wierdly.
+ if (D.getContext() != Declarator::BlockLiteralContext)
+ if (const AttributeList *Attrs = D.getAttributes())
+ ProcessTypeAttributeList(*this, T, Attrs, FnAttrsFromPreviousChunk);
+
+ DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
if (TInfo) {
if (D.isInvalidType())
@@ -1645,20 +1706,79 @@ static void HandleObjCGCTypeAttribute(QualType &Type,
Type = S.Context.getObjCGCQualType(Type, GCAttr);
}
-/// HandleNoReturnTypeAttribute - Process the noreturn attribute on the
-/// specified type. The attribute contains 0 arguments.
-static void HandleNoReturnTypeAttribute(QualType &Type,
- const AttributeList &Attr, Sema &S) {
- if (Attr.getNumArgs() != 0)
- return;
+/// Process an individual function attribute. Returns true if the
+/// attribute does not make sense to apply to this type.
+bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
+ if (Attr.getKind() == AttributeList::AT_noreturn) {
+ // Complain immediately if the arg count is wrong.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return false;
+ }
- // We only apply this to a pointer to function or a pointer to block.
- if (!Type->isFunctionPointerType()
- && !Type->isBlockPointerType()
- && !Type->isFunctionType())
- return;
+ // Delay if this is not a function or pointer to block.
+ if (!Type->isFunctionPointerType()
+ && !Type->isBlockPointerType()
+ && !Type->isFunctionType())
+ return true;
- Type = S.Context.getNoReturnType(Type);
+ // Otherwise we can process right away.
+ Type = S.Context.getNoReturnType(Type);
+ return false;
+ }
+
+ // Otherwise, a calling convention.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return false;
+ }
+
+ QualType T = Type;
+ if (const PointerType *PT = Type->getAs<PointerType>())
+ T = PT->getPointeeType();
+ const FunctionType *Fn = T->getAs<FunctionType>();
+
+ // Delay if the type didn't work out to a function.
+ if (!Fn) return true;
+
+ // TODO: diagnose uses of these conventions on the wrong target.
+ CallingConv CC;
+ switch (Attr.getKind()) {
+ case AttributeList::AT_cdecl: CC = CC_C; break;
+ case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
+ case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
+ default: llvm_unreachable("unexpected attribute kind"); return false;
+ }
+
+ CallingConv CCOld = Fn->getCallConv();
+ if (CC == CCOld) return false;
+
+ if (CCOld != CC_Default) {
+ // Should we diagnose reapplications of the same convention?
+ S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
+ << FunctionType::getNameForCallConv(CC)
+ << FunctionType::getNameForCallConv(CCOld);
+ return false;
+ }
+
+ // Diagnose the use of X86 fastcall on varargs or unprototyped functions.
+ if (CC == CC_X86FastCall) {
+ if (isa<FunctionNoProtoType>(Fn)) {
+ S.Diag(Attr.getLoc(), diag::err_cconv_knr)
+ << FunctionType::getNameForCallConv(CC);
+ return false;
+ }
+
+ const FunctionProtoType *FnP = cast<FunctionProtoType>(Fn);
+ if (FnP->isVariadic()) {
+ S.Diag(Attr.getLoc(), diag::err_cconv_varargs)
+ << FunctionType::getNameForCallConv(CC);
+ return false;
+ }
+ }
+
+ Type = S.Context.getCallConvType(Type, CC);
+ return false;
}
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
@@ -1705,10 +1825,12 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S
// Success! Instantiate the vector type, the number of elements is > 0, and
// not required to be a power of 2, unlike GCC.
- CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
+ CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false);
}
-void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
+void ProcessTypeAttributeList(Sema &S, QualType &Result,
+ const AttributeList *AL,
+ DelayedAttributeSet &FnAttrs) {
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
@@ -1718,17 +1840,23 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
// the LeftOverAttrs list for rechaining.
switch (AL->getKind()) {
default: break;
+
case AttributeList::AT_address_space:
- HandleAddressSpaceTypeAttribute(Result, *AL, *this);
+ HandleAddressSpaceTypeAttribute(Result, *AL, S);
break;
case AttributeList::AT_objc_gc:
- HandleObjCGCTypeAttribute(Result, *AL, *this);
- break;
- case AttributeList::AT_noreturn:
- HandleNoReturnTypeAttribute(Result, *AL, *this);
+ HandleObjCGCTypeAttribute(Result, *AL, S);
break;
case AttributeList::AT_vector_size:
- HandleVectorSizeAttr(Result, *AL, *this);
+ HandleVectorSizeAttr(Result, *AL, S);
+ break;
+
+ case AttributeList::AT_noreturn:
+ case AttributeList::AT_cdecl:
+ case AttributeList::AT_fastcall:
+ case AttributeList::AT_stdcall:
+ if (ProcessFnAttr(S, Result, *AL))
+ FnAttrs.push_back(DelayedAttribute(AL, Result));
break;
}
}
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp
index 7c19bf6..d45d010 100644
--- a/lib/Sema/TargetAttributesSema.cpp
+++ b/lib/Sema/TargetAttributesSema.cpp
@@ -70,6 +70,48 @@ namespace {
};
}
+static void HandleX86ForceAlignArgPointerAttr(Decl *D,
+ const AttributeList& Attr,
+ Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ // If we try to apply it to a function pointer, warn. This is a special
+ // instance of the warn_attribute_ignored warning that can be turned
+ // off with -Wno-force-align-arg-pointer.
+ ValueDecl* VD = dyn_cast<ValueDecl>(D);
+ if (VD && VD->getType()->isFunctionPointerType()) {
+ S.Diag(Attr.getLoc(), diag::warn_faap_attribute_ignored);
+ return;
+ }
+ // Attribute can only be applied to function types.
+ if (!isa<FunctionDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << /* function */0;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr());
+}
+
+namespace {
+ class X86AttributesSema : public TargetAttributesSema {
+ public:
+ X86AttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ if (Attr.getName()->getName() == "force_align_arg_pointer") {
+ HandleX86ForceAlignArgPointerAttr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
const TargetAttributesSema &Sema::getTargetAttributesSema() const {
if (TheTargetAttributesSema)
return *TheTargetAttributesSema;
@@ -81,6 +123,8 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const {
case llvm::Triple::msp430:
return *(TheTargetAttributesSema = new MSP430AttributesSema);
+ case llvm::Triple::x86:
+ return *(TheTargetAttributesSema = new X86AttributesSema);
}
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index b2102af..fc069f7 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -428,7 +428,8 @@ public:
///
/// By default, performs semantic analysis when building the vector type.
/// Subclasses may override this routine to provide different behavior.
- QualType RebuildVectorType(QualType ElementType, unsigned NumElements);
+ QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
+ bool IsAltiVec, bool IsPixel);
/// \brief Build a new extended vector type given the element type and
/// number of elements.
@@ -524,9 +525,13 @@ public:
/// and the given type. Subclasses may override this routine to provide
/// different behavior.
QualType RebuildTypenameType(NestedNameSpecifier *NNS, QualType T) {
- if (NNS->isDependent())
- return SemaRef.Context.getTypenameType(NNS,
+ if (NNS->isDependent()) {
+ CXXScopeSpec SS;
+ SS.setScopeRep(NNS);
+ if (!SemaRef.computeDeclContext(SS))
+ return SemaRef.Context.getTypenameType(NNS,
cast<TemplateSpecializationType>(T));
+ }
return SemaRef.Context.getQualifiedNameType(NNS, T);
}
@@ -776,6 +781,28 @@ public:
StartLoc, EndLoc));
}
+ /// \brief Build a new inline asm statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OwningStmtResult RebuildAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple,
+ bool IsVolatile,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ IdentifierInfo **Names,
+ MultiExprArg Constraints,
+ MultiExprArg Exprs,
+ ExprArg AsmString,
+ MultiExprArg Clobbers,
+ SourceLocation RParenLoc,
+ bool MSAsm) {
+ return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs,
+ NumInputs, Names, move(Constraints),
+ move(Exprs), move(AsmString), move(Clobbers),
+ RParenLoc, MSAsm);
+ }
+
/// \brief Build a new C++ exception declaration.
///
/// By default, performs semantic analysis to build the new decaration.
@@ -1662,6 +1689,7 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
// Transform expressions by calling TransformExpr.
#define STMT(Node, Parent)
+#define ABSTRACT_EXPR(Node, Parent)
#define EXPR(Node, Parent) case Stmt::Node##Class:
#include "clang/AST/StmtNodes.def"
{
@@ -1685,6 +1713,7 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::NoStmtClass: break;
#define STMT(Node, Parent) case Stmt::Node##Class: break;
+#define ABSTRACT_EXPR(Node, Parent)
#define EXPR(Node, Parent) \
case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E));
#include "clang/AST/StmtNodes.def"
@@ -2448,7 +2477,8 @@ QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ElementType != T->getElementType()) {
- Result = getDerived().RebuildVectorType(ElementType, T->getNumElements());
+ Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(),
+ T->isAltiVec(), T->isPixel());
if (Result.isNull())
return QualType();
}
@@ -3327,9 +3357,74 @@ TreeTransform<Derived>::TransformSwitchCase(SwitchCase *S) {
template<typename Derived>
Sema::OwningStmtResult
TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
- // FIXME: Implement!
- assert(false && "Inline assembly cannot be transformed");
- return SemaRef.Owned(S->Retain());
+
+ ASTOwningVector<&ActionBase::DeleteExpr> Constraints(getSema());
+ ASTOwningVector<&ActionBase::DeleteExpr> Exprs(getSema());
+ llvm::SmallVector<IdentifierInfo *, 4> Names;
+
+ OwningExprResult AsmString(SemaRef);
+ ASTOwningVector<&ActionBase::DeleteExpr> Clobbers(getSema());
+
+ bool ExprsChanged = false;
+
+ // Go through the outputs.
+ for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) {
+ Names.push_back(S->getOutputIdentifier(I));
+
+ // No need to transform the constraint literal.
+ Constraints.push_back(S->getOutputConstraintLiteral(I)->Retain());
+
+ // Transform the output expr.
+ Expr *OutputExpr = S->getOutputExpr(I);
+ OwningExprResult Result = getDerived().TransformExpr(OutputExpr);
+ if (Result.isInvalid())
+ return SemaRef.StmtError();
+
+ ExprsChanged |= Result.get() != OutputExpr;
+
+ Exprs.push_back(Result.takeAs<Expr>());
+ }
+
+ // Go through the inputs.
+ for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) {
+ Names.push_back(S->getInputIdentifier(I));
+
+ // No need to transform the constraint literal.
+ Constraints.push_back(S->getInputConstraintLiteral(I)->Retain());
+
+ // Transform the input expr.
+ Expr *InputExpr = S->getInputExpr(I);
+ OwningExprResult Result = getDerived().TransformExpr(InputExpr);
+ if (Result.isInvalid())
+ return SemaRef.StmtError();
+
+ ExprsChanged |= Result.get() != InputExpr;
+
+ Exprs.push_back(Result.takeAs<Expr>());
+ }
+
+ if (!getDerived().AlwaysRebuild() && !ExprsChanged)
+ return SemaRef.Owned(S->Retain());
+
+ // Go through the clobbers.
+ for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I)
+ Clobbers.push_back(S->getClobber(I)->Retain());
+
+ // No need to transform the asm string literal.
+ AsmString = SemaRef.Owned(S->getAsmString());
+
+ return getDerived().RebuildAsmStmt(S->getAsmLoc(),
+ S->isSimple(),
+ S->isVolatile(),
+ S->getNumOutputs(),
+ S->getNumInputs(),
+ Names.data(),
+ move_arg(Constraints),
+ move_arg(Exprs),
+ move(AsmString),
+ move_arg(Clobbers),
+ S->getRParenLoc(),
+ S->isMSAsm());
}
@@ -3742,13 +3837,6 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCastExpr(CastExpr *E) {
- assert(false && "Cannot transform abstract class");
- return SemaRef.Owned(E->Retain());
-}
-
-template<typename Derived>
-Sema::OwningExprResult
TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
@@ -3812,13 +3900,6 @@ TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E) {
- assert(false && "Cannot transform abstract class");
- return SemaRef.Owned(E->Retain());
-}
-
-template<typename Derived>
-Sema::OwningExprResult
TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
TypeSourceInfo *OldT;
TypeSourceInfo *NewT;
@@ -4433,7 +4514,7 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
if (!Param)
return SemaRef.ExprError();
- if (getDerived().AlwaysRebuild() &&
+ if (!getDerived().AlwaysRebuild() &&
Param == E->getParam())
return SemaRef.Owned(E->Retain());
@@ -4733,6 +4814,12 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
+ // CXXConstructExprs are always implicit, so when we have a
+ // 1-argument construction we just transform that argument.
+ if (E->getNumArgs() == 1 ||
+ (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1))))
+ return getDerived().TransformExpr(E->getArg(0));
+
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
@@ -4784,6 +4871,16 @@ TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
return getDerived().TransformExpr(E->getSubExpr());
}
+/// \brief Transform a C++ reference-binding expression.
+///
+/// Since CXXBindReferenceExpr nodes are implicitly generated, we just
+/// transform the subexpression and return that.
+template<typename Derived>
+Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
+ return getDerived().TransformExpr(E->getSubExpr());
+}
+
/// \brief Transform a C++ expression that contains temporaries that should
/// be destroyed after the expression is evaluated.
///
@@ -5330,9 +5427,11 @@ TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
template<typename Derived>
QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
- unsigned NumElements) {
+ unsigned NumElements,
+ bool IsAltiVec, bool IsPixel) {
// FIXME: semantic checking!
- return SemaRef.Context.getVectorType(ElementType, NumElements);
+ return SemaRef.Context.getVectorType(ElementType, NumElements,
+ IsAltiVec, IsPixel);
}
template<typename Derived>
@@ -5563,28 +5662,21 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// Compute the transformed set of functions (and function templates) to be
// used during overload resolution.
- Sema::FunctionSet Functions;
+ UnresolvedSet<16> Functions;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) {
assert(ULE->requiresADL());
// FIXME: Do we have to check
// IsAcceptableNonMemberOperatorCandidate for each of these?
- for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
- E = ULE->decls_end(); I != E; ++I)
- Functions.insert(AnyFunctionDecl::getFromNamedDecl(*I));
+ Functions.append(ULE->decls_begin(), ULE->decls_end());
} else {
- Functions.insert(AnyFunctionDecl::getFromNamedDecl(
- cast<DeclRefExpr>(CalleeExpr)->getDecl()));
+ Functions.addDecl(cast<DeclRefExpr>(CalleeExpr)->getDecl());
}
// Add any functions found via argument-dependent lookup.
Expr *Args[2] = { FirstExpr, SecondExpr };
unsigned NumArgs = 1 + (SecondExpr != 0);
- DeclarationName OpName
- = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
- SemaRef.ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs,
- Functions);
// Create the overloaded operator invocation for unary operators.
if (NumArgs == 1 || isPostIncDec) {
OpenPOWER on IntegriCloud