summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/CMakeLists.txt3
-rw-r--r--lib/Sema/JumpDiagnostics.cpp70
-rw-r--r--lib/Sema/Lookup.h5
-rw-r--r--lib/Sema/Makefile6
-rw-r--r--lib/Sema/Sema.cpp45
-rw-r--r--lib/Sema/Sema.h239
-rw-r--r--lib/Sema/SemaAccess.cpp30
-rw-r--r--lib/Sema/SemaAttr.cpp13
-rw-r--r--lib/Sema/SemaCXXCast.cpp62
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp6
-rw-r--r--lib/Sema/SemaChecking.cpp458
-rw-r--r--lib/Sema/SemaCodeComplete.cpp1026
-rw-r--r--lib/Sema/SemaDecl.cpp298
-rw-r--r--lib/Sema/SemaDeclAttr.cpp114
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1385
-rw-r--r--lib/Sema/SemaDeclObjC.cpp52
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp9
-rw-r--r--lib/Sema/SemaExpr.cpp689
-rw-r--r--lib/Sema/SemaExprCXX.cpp255
-rw-r--r--lib/Sema/SemaExprObjC.cpp14
-rw-r--r--lib/Sema/SemaInit.cpp187
-rw-r--r--lib/Sema/SemaInit.h10
-rw-r--r--lib/Sema/SemaLookup.cpp446
-rw-r--r--lib/Sema/SemaObjCProperty.cpp79
-rw-r--r--lib/Sema/SemaOverload.cpp662
-rw-r--r--lib/Sema/SemaStmt.cpp170
-rw-r--r--lib/Sema/SemaTemplate.cpp644
-rw-r--r--lib/Sema/SemaTemplate.h31
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp26
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp87
-rw-r--r--lib/Sema/SemaType.cpp372
-rw-r--r--lib/Sema/TreeTransform.h301
33 files changed, 5104 insertions, 2702 deletions
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index b54e8eb..70b4792 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -34,4 +34,5 @@ add_clang_library(clangSema
TargetAttributesSema.cpp
)
-add_dependencies(clangSema ClangDiagnosticSema ClangStmtNodes)
+add_dependencies(clangSema ClangARMNeon ClangAttrClasses ClangAttrList
+ ClangDiagnosticSema ClangDeclNodes ClangStmtNodes)
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 543c1b6..3431ac6 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -65,6 +65,7 @@ class JumpScopeChecker {
public:
JumpScopeChecker(Stmt *Body, Sema &S);
private:
+ void BuildScopeInformation(Decl *D, unsigned &ParentScope);
void BuildScopeInformation(Stmt *S, unsigned ParentScope);
void VerifyJumps();
void VerifyIndirectJumps();
@@ -130,11 +131,13 @@ static std::pair<unsigned,unsigned>
InDiag = diag::note_protected_by_variable_init;
CanQualType T = VD->getType()->getCanonicalTypeUnqualified();
- while (CanQual<ArrayType> AT = T->getAs<ArrayType>())
- T = AT->getElementType();
- if (CanQual<RecordType> RT = T->getAs<RecordType>())
- if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor())
- OutDiag = diag::note_exits_dtor;
+ if (!T->isDependentType()) {
+ while (CanQual<ArrayType> AT = T->getAs<ArrayType>())
+ T = AT->getElementType();
+ if (CanQual<RecordType> RT = T->getAs<RecordType>())
+ if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor())
+ OutDiag = diag::note_exits_dtor;
+ }
}
return std::make_pair(InDiag, OutDiag);
@@ -148,13 +151,33 @@ static std::pair<unsigned,unsigned>
return std::make_pair(0U, 0U);
}
+/// \brief Build scope information for a declaration that is part of a DeclStmt.
+void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
+ bool isCPlusPlus = this->S.getLangOptions().CPlusPlus;
+
+ // If this decl causes a new scope, push and switch to it.
+ std::pair<unsigned,unsigned> Diags
+ = GetDiagForGotoScopeDecl(D, isCPlusPlus);
+ if (Diags.first || Diags.second) {
+ Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
+ D->getLocation()));
+ ParentScope = Scopes.size()-1;
+ }
+
+ // If the decl has an initializer, walk it with the potentially new
+ // scope we just installed.
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (Expr *Init = VD->getInit())
+ BuildScopeInformation(Init, ParentScope);
+}
/// BuildScopeInformation - The statements from CI to CE are known to form a
/// coherent VLA scope with a specified parent node. Walk through the
/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively
/// walking the AST as needed.
void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
-
+ bool SkipFirstSubStmt = false;
+
// If we found a label, remember that it is in ParentScope scope.
switch (S->getStmtClass()) {
case Stmt::LabelStmtClass:
@@ -172,8 +195,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
IndirectJumps.push_back(cast<IndirectGotoStmt>(S));
break;
- case Stmt::GotoStmtClass:
case Stmt::SwitchStmtClass:
+ // Evaluate the condition variable before entering the scope of the switch
+ // statement.
+ if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
+ BuildScopeInformation(Var, ParentScope);
+ SkipFirstSubStmt = true;
+ }
+ // Fall through
+
+ case Stmt::GotoStmtClass:
// Remember both what scope a goto is in as well as the fact that we have
// it. This makes the second scan not have to walk the AST again.
LabelAndGotoScopes[S] = ParentScope;
@@ -186,33 +217,22 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
++CI) {
+ if (SkipFirstSubStmt) {
+ SkipFirstSubStmt = false;
+ continue;
+ }
+
Stmt *SubStmt = *CI;
if (SubStmt == 0) continue;
- bool isCPlusPlus = this->S.getLangOptions().CPlusPlus;
-
// If this is a declstmt with a VLA definition, it defines a scope from here
// to the end of the containing context.
if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
// The decl statement creates a scope if any of the decls in it are VLAs
// or have the cleanup attribute.
for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
- I != E; ++I) {
- // If this decl causes a new scope, push and switch to it.
- std::pair<unsigned,unsigned> Diags
- = GetDiagForGotoScopeDecl(*I, isCPlusPlus);
- if (Diags.first || Diags.second) {
- Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
- (*I)->getLocation()));
- ParentScope = Scopes.size()-1;
- }
-
- // If the decl has an initializer, walk it with the potentially new
- // scope we just installed.
- if (VarDecl *VD = dyn_cast<VarDecl>(*I))
- if (Expr *Init = VD->getInit())
- BuildScopeInformation(Init, ParentScope);
- }
+ I != E; ++I)
+ BuildScopeInformation(*I, ParentScope);
continue;
}
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index 0961299..271bb5b 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -424,6 +424,11 @@ public:
Diagnose = false;
}
+ /// Determines whether this lookup is suppressing diagnostics.
+ bool isSuppressingDiagnostics() const {
+ return Diagnose;
+ }
+
/// Sets a 'context' source range.
void setContextRange(SourceRange SR) {
NameContextRange = SR;
diff --git a/lib/Sema/Makefile b/lib/Sema/Makefile
index 3a5a99a..90f2dff 100644
--- a/lib/Sema/Makefile
+++ b/lib/Sema/Makefile
@@ -12,11 +12,9 @@
#
##===----------------------------------------------------------------------===##
-LEVEL = ../../../..
+CLANG_LEVEL := ../..
LIBRARYNAME := clangSema
BUILD_ARCHIVE = 1
-CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
-
-include $(LEVEL)/Makefile.common
+include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 523b196..cddc84e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/APFloat.h"
+#include "clang/Sema/ExternalSemaSource.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
@@ -43,7 +44,10 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
TUScope = S;
PushDeclContext(S, Context.getTranslationUnitDecl());
- if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
+ VAListTagName = PP.getIdentifierInfo("__va_list_tag");
+
+ if (!Context.isInt128Installed() && // May be set by PCHReader.
+ PP.getTargetInfo().getPointerWidth(0) >= 64) {
TypeSourceInfo *TInfo;
// Install [u]int128_t for 64-bit targets.
@@ -58,6 +62,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
SourceLocation(),
&Context.Idents.get("__uint128_t"),
TInfo), TUScope);
+ Context.setInt128Installed();
}
@@ -122,8 +127,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
- NumSFINAEErrors(0), NonInstantiationEntries(0),
- CurrentInstantiationScope(0), TyposCorrected(0),
+ NumSFINAEErrors(0), SuppressAccessChecking(false),
+ NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0),
AnalysisWarnings(*this)
{
TUScope = 0;
@@ -223,7 +228,8 @@ 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)),
+ std::bind2nd(std::mem_fun(&FunctionDecl::isUsed),
+ true)),
UnusedStaticFuncs.end());
// Check for #pragma weak identifiers that were never declared
@@ -381,6 +387,34 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) {
return Builder;
}
+/// \brief Determines the active Scope associated with the given declaration
+/// context.
+///
+/// This routine maps a declaration context to the active Scope object that
+/// represents that declaration context in the parser. It is typically used
+/// from "scope-less" code (e.g., template instantiation, lazy creation of
+/// declarations) that injects a name for name-lookup purposes and, therefore,
+/// must update the Scope.
+///
+/// \returns The scope corresponding to the given declaraion context, or NULL
+/// if no such scope is open.
+Scope *Sema::getScopeForContext(DeclContext *Ctx) {
+
+ if (!Ctx)
+ return 0;
+
+ Ctx = Ctx->getPrimaryContext();
+ for (Scope *S = getCurScope(); S; S = S->getParent()) {
+ // Ignore scopes that cannot have declarations. This is important for
+ // out-of-line definitions of static class members.
+ if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
+ if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity()))
+ if (Ctx == Entity->getPrimaryContext())
+ return S;
+ }
+
+ return 0;
+}
/// \brief Enter a new function scope
void Sema::PushFunctionScope() {
@@ -425,3 +459,6 @@ BlockScopeInfo *Sema::getCurBlock() {
return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
}
+
+// Pin this vtable to this file.
+ExternalSemaSource::~ExternalSemaSource() {}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index dfc45ac..ddbe7e0 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -155,24 +155,25 @@ struct FunctionScopeInfo {
/// \brief Retains information about a block that is currently being parsed.
struct BlockScopeInfo : FunctionScopeInfo {
- llvm::SmallVector<ParmVarDecl*, 8> Params;
- bool hasPrototype;
- bool isVariadic;
bool hasBlockDeclRefExprs;
BlockDecl *TheDecl;
-
+
/// TheScope - This is the scope for the block itself, which contains
/// arguments etc.
Scope *TheScope;
- /// ReturnType - This will get set to block result type, by looking at
- /// return types, if any, in the block body.
+ /// ReturnType - The return type of the block, or null if the block
+ /// signature didn't provide an explicit return type.
QualType ReturnType;
+ /// BlockType - The function type of the block, if one was given.
+ /// Its return type may be BuiltinType::Dependent.
+ QualType FunctionType;
+
BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
- : FunctionScopeInfo(NumErrors), hasPrototype(false), isVariadic(false),
- hasBlockDeclRefExprs(false), TheDecl(Block), TheScope(BlockScope)
+ : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
+ TheDecl(Block), TheScope(BlockScope)
{
IsBlockInfo = true;
}
@@ -239,6 +240,10 @@ public:
/// CurContext - This is the current declaration context of parsing.
DeclContext *CurContext;
+ /// VAListTagName - The declaration name corresponding to __va_list_tag.
+ /// This is used as part of a hack to omit that class from ADL results.
+ DeclarationName VAListTagName;
+
/// A RAII object to temporarily push a declaration context.
class ContextRAII {
private:
@@ -669,6 +674,8 @@ public:
virtual void ActOnEndOfTranslationUnit();
+ Scope *getScopeForContext(DeclContext *Ctx);
+
void PushFunctionScope();
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
void PopFunctionOrBlockScope();
@@ -713,9 +720,13 @@ public:
//
QualType adjustParameterType(QualType T);
- QualType BuildPointerType(QualType T, unsigned Quals,
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) {
+ return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR));
+ }
+ QualType BuildPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity);
- QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
+ QualType BuildReferenceType(QualType T, bool LValueRef,
SourceLocation Loc, DeclarationName Entity);
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
@@ -727,13 +738,12 @@ public:
bool Variadic, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType BuildMemberPointerType(QualType T, QualType Class,
- unsigned Quals, SourceLocation Loc,
+ SourceLocation Loc,
DeclarationName Entity);
- QualType BuildBlockPointerType(QualType T, unsigned Quals,
+ QualType BuildBlockPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity);
- QualType GetTypeForDeclarator(Declarator &D, Scope *S,
- TypeSourceInfo **TInfo = 0,
- TagDecl **OwnedDecl = 0);
+ TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S,
+ TagDecl **OwnedDecl = 0);
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
@@ -761,8 +771,6 @@ public:
const FunctionProtoType *Target, SourceLocation TargetLoc,
const FunctionProtoType *Source, SourceLocation SourceLoc);
- bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2);
-
virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
bool RequireCompleteType(SourceLocation Loc, QualType T,
@@ -837,6 +845,9 @@ public:
bool &OverloadableAttrRequired);
void CheckMain(FunctionDecl *FD);
virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
+ ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T);
ParmVarDecl *CheckParameter(DeclContext *DC,
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
@@ -1094,10 +1105,19 @@ public:
/// non-function.
Ovl_NonFunction
};
- OverloadKind CheckOverload(FunctionDecl *New,
+ OverloadKind CheckOverload(Scope *S,
+ FunctionDecl *New,
const LookupResult &OldDecls,
- NamedDecl *&OldDecl);
- bool IsOverload(FunctionDecl *New, FunctionDecl *Old);
+ NamedDecl *&OldDecl,
+ bool IsForUsingDecl);
+ bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl);
+
+ bool TryImplicitConversion(InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *From,
+ bool SuppressUserConversions,
+ bool AllowExplicit,
+ bool InOverloadResolution);
ImplicitConversionSequence
TryImplicitConversion(Expr* From, QualType ToType,
@@ -1170,6 +1190,16 @@ public:
ImplicitConversionSequence TryContextuallyConvertToObjCId(Expr *From);
bool PerformContextuallyConvertToObjCId(Expr *&From);
+ OwningExprResult
+ ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
+ const PartialDiagnostic &NotIntDiag,
+ const PartialDiagnostic &IncompleteDiag,
+ const PartialDiagnostic &ExplicitConvDiag,
+ const PartialDiagnostic &ExplicitConvNote,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &AmbigNote,
+ const PartialDiagnostic &ConvDiag);
+
bool PerformObjectMemberConversion(Expr *&From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
@@ -1448,6 +1478,8 @@ public:
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
UnresolvedSetImpl &Functions);
+ DeclContext::lookup_result LookupConstructors(CXXRecordDecl *Class);
+ CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
@@ -1457,7 +1489,7 @@ public:
VisibleDeclConsumer &Consumer);
void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
VisibleDeclConsumer &Consumer);
-
+
/// \brief The context in which typo-correction occurs.
///
/// The typo-correction context affects which keywords (if any) are
@@ -1555,16 +1587,9 @@ public:
/// CollectImmediateProperties - This routine collects all properties in
/// the class and its conforming protocols; but not those it its super class.
void CollectImmediateProperties(ObjCContainerDecl *CDecl,
- llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap);
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap);
- /// ProtocolConformsToSuperClass - Returns true if class has a super class
- /// and it, or its nested super class conforms to the protocol.
- bool ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl,
- const ObjCProtocolDecl *PDecl);
- /// ProtocolConformsToProtocol - Returns true if 2nd Protocol (PDecl) is
- /// qualified by the 1st.
- bool ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol,
- const ObjCProtocolDecl *PDecl);
/// LookupPropertyDecl - Looks up a property in the current class and all
/// its protocols.
@@ -1583,7 +1608,7 @@ public:
const bool isReadWrite,
const unsigned Attributes,
bool *isOverridingProperty,
- QualType T,
+ TypeSourceInfo *T,
tok::ObjCKeywordKind MethodImplKind);
/// Called by ActOnProperty and HandlePropertyInClassExtension to
@@ -1596,7 +1621,8 @@ public:
Selector SetterSel,
const bool isAssign,
const bool isReadWrite,
- const unsigned Attributes, QualType T,
+ const unsigned Attributes,
+ TypeSourceInfo *T,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC = 0);
@@ -1935,7 +1961,8 @@ public:
OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
bool &IsArrow, SourceLocation OpLoc,
CXXScopeSpec &SS,
- DeclPtrTy ObjCImpDecl);
+ DeclPtrTy ObjCImpDecl,
+ bool HasTemplateArgs);
bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
const CXXScopeSpec &SS,
@@ -2100,6 +2127,7 @@ public:
AttributeList *AttrList);
virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace);
+ NamespaceDecl *getStdNamespace();
virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
SourceLocation UsingLoc,
SourceLocation NamespcLoc,
@@ -2196,26 +2224,69 @@ public:
/// constructed variable.
void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+ /// \brief Declare the implicit default constructor for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// default constructor will be added.
+ ///
+ /// \returns The implicitly-declared default constructor.
+ CXXConstructorDecl *DeclareImplicitDefaultConstructor(
+ CXXRecordDecl *ClassDecl);
+
/// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
+ /// \brief Declare the implicit destructor for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// destructor will be added.
+ ///
+ /// \returns The implicitly-declared destructor.
+ CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl);
+
/// DefineImplicitDestructor - Checks for feasibility of
/// defining this destructor as the default destructor.
void DefineImplicitDestructor(SourceLocation CurrentLocation,
- CXXDestructorDecl *Destructor);
+ CXXDestructorDecl *Destructor);
+ /// \brief Declare the implicit copy constructor for the given class.
+ ///
+ /// \param S The scope of the class, which may be NULL if this is a
+ /// template instantiation.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// copy constructor will be added.
+ ///
+ /// \returns The implicitly-declared copy constructor.
+ CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl);
+
/// DefineImplicitCopyConstructor - Checks for feasibility of
/// defining this constructor as the copy constructor.
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor,
unsigned TypeQuals);
- /// \brief Defined and implicitly-declared copy assignment operator.
+ /// \brief Declare the implicit copy assignment operator for the given class.
+ ///
+ /// \param S The scope of the class, which may be NULL if this is a
+ /// template instantiation.
+ ///
+ /// \param ClassDecl The class declaration into which the implicit
+ /// copy-assignment operator will be added.
+ ///
+ /// \returns The implicitly-declared copy assignment operator.
+ CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl);
+
+ /// \brief Defined an implicitly-declared copy assignment operator.
void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MethodDecl);
+ /// \brief Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
/// it simply returns the passed in expression.
@@ -2295,7 +2366,7 @@ public:
SourceLocation PlacementLParen,
MultiExprArg PlacementArgs,
SourceLocation PlacementRParen,
- bool ParenTypeId, Declarator &D,
+ SourceRange TypeIdParens, Declarator &D,
SourceLocation ConstructorLParen,
MultiExprArg ConstructorArgs,
SourceLocation ConstructorRParen);
@@ -2303,7 +2374,7 @@ public:
SourceLocation PlacementLParen,
MultiExprArg PlacementArgs,
SourceLocation PlacementRParen,
- bool ParenTypeId,
+ SourceRange TypeIdParens,
QualType AllocType,
SourceLocation TypeLoc,
SourceRange TypeRange,
@@ -2529,6 +2600,10 @@ public:
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS);
+ virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc);
+
virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
@@ -2605,14 +2680,14 @@ public:
/// \returns true if any work was done, false otherwise.
bool DefineUsedVTables();
- void AddImplicitlyDeclaredMembersToClass(Scope *S, CXXRecordDecl *ClassDecl);
+ void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits,
bool AnyErrors);
- void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
+ void CheckCompletedCXXClass(CXXRecordDecl *Record);
virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclPtrTy TagDecl,
SourceLocation LBrac,
@@ -2644,7 +2719,7 @@ public:
QualType CheckConstructorDeclarator(Declarator &D, QualType R,
FunctionDecl::StorageClass& SC);
void CheckConstructor(CXXConstructorDecl *Constructor);
- QualType CheckDestructorDeclarator(Declarator &D,
+ QualType CheckDestructorDeclarator(Declarator &D, QualType R,
FunctionDecl::StorageClass& SC);
bool CheckDestructor(CXXDestructorDecl *Destructor);
void CheckConversionDeclarator(Declarator &D, QualType &R,
@@ -2718,6 +2793,7 @@ public:
const CXXMethodDecl *Old);
bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+
//===--------------------------------------------------------------------===//
// C++ Access Control
//
@@ -2744,7 +2820,8 @@ public:
AccessResult CheckConstructorAccess(SourceLocation Loc,
CXXConstructorDecl *D,
const InitializedEntity &Entity,
- AccessSpecifier Access);
+ AccessSpecifier Access,
+ bool IsCopyBindingRefToTemp = false);
AccessResult CheckDestructorAccess(SourceLocation Loc,
CXXDestructorDecl *Dtor,
const PartialDiagnostic &PDiag);
@@ -2772,6 +2849,12 @@ public:
void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx);
+ /// A flag to suppress access checking.
+ bool SuppressAccessChecking;
+
+ void ActOnStartSuppressingAccessChecks();
+ void ActOnStopSuppressingAccessChecks();
+
enum AbstractDiagSelID {
AbstractNone = -1,
AbstractReturnType,
@@ -2826,29 +2909,25 @@ public:
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position);
- virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
- SourceLocation EqualLoc,
- SourceLocation DefaultLoc,
- TypeTy *Default);
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ TypeTy *DefaultArg);
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
- unsigned Position);
- virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- ExprArg Default);
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ExprArg DefaultArg);
virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
SourceLocation TmpLoc,
TemplateParamsTy *Params,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
unsigned Depth,
- unsigned Position);
- virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &Default);
+ unsigned Position,
+ SourceLocation EqualLoc,
+ const ParsedTemplateArgument &DefaultArg);
virtual TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
@@ -2912,11 +2991,13 @@ public:
SourceLocation NameLoc,
const TemplateArgumentListInfo &TemplateArgs);
- virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext);
+ virtual TemplateNameKind ActOnDependentTemplateName(Scope *S,
+ SourceLocation TemplateKWLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ TypeTy *ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template);
bool CheckClassTemplatePartialSpecializationArgs(
TemplateParameterList *TemplateParams,
@@ -3096,25 +3177,29 @@ public:
/// \brief Called when the parser has parsed a C++ typename
/// specifier, e.g., "typename T::type".
///
+ /// \param S The scope in which this typename type occurs.
/// \param TypenameLoc the location of the 'typename' keyword
/// \param SS the nested-name-specifier following the typename (e.g., 'T::').
/// \param II the identifier we're retrieving (e.g., 'type' in the example).
/// \param IdLoc the location of the identifier.
virtual TypeResult
- ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
- const IdentifierInfo &II, SourceLocation IdLoc);
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, const IdentifierInfo &II,
+ SourceLocation IdLoc);
/// \brief Called when the parser has parsed a C++ typename
/// specifier that ends in a template-id, e.g.,
/// "typename MetaFun::template apply<T1, T2>".
///
+ /// \param S The scope in which this typename type occurs.
/// \param TypenameLoc the location of the 'typename' keyword
/// \param SS the nested-name-specifier following the typename (e.g., 'T::').
/// \param TemplateLoc the location of the 'template' keyword, if any.
/// \param Ty the type that the typename specifier refers to.
virtual TypeResult
- ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
- SourceLocation TemplateLoc, TypeTy *Ty);
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+ TypeTy *Ty);
QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
@@ -3478,6 +3563,12 @@ public:
/// to implement it anywhere else.
ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
+ /// \brief The stack of calls expression undergoing template instantiation.
+ ///
+ /// The top of this stack is used by a fixit instantiating unresolved
+ /// function calls to fix the AST to match the textual change it prints.
+ llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation;
+
/// \brief A stack object to be created when performing template
/// instantiation.
///
@@ -4057,6 +4148,9 @@ public:
/// FreePackedContext - Deallocate and null out PackContext.
void FreePackedContext();
+ /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
+ void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
/// cast. If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
@@ -4413,6 +4507,7 @@ public:
//@{
virtual void CodeCompleteOrdinaryName(Scope *S,
CodeCompletionContext CompletionContext);
+ virtual void CodeCompleteExpression(Scope *S, QualType T);
virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
SourceLocation OpLoc,
bool IsArrow);
@@ -4420,6 +4515,10 @@ public:
virtual void CodeCompleteCase(Scope *S);
virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
ExprTy **Args, unsigned NumArgs);
+ virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D);
+ virtual void CodeCompleteReturn(Scope *S);
+ virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS);
+
virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext);
virtual void CodeCompleteUsing(Scope *S);
@@ -4440,7 +4539,7 @@ public:
virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
DeclPtrTy *Methods,
unsigned NumMethods);
-
+ virtual void CodeCompleteObjCMessageReceiver(Scope *S);
virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
IdentifierInfo **SelIdents,
unsigned NumSelIdents);
@@ -4473,6 +4572,13 @@ public:
bool IsInstanceMethod,
TypeTy *ReturnType,
DeclPtrTy IDecl);
+ virtual void CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ TypeTy *ReturnType,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+
//@}
//===--------------------------------------------------------------------===//
@@ -4491,6 +4597,9 @@ private:
Action::OwningExprResult CheckBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall);
+ bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
bool SemaBuiltinVAStart(CallExpr *TheCall);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
@@ -4503,7 +4612,7 @@ private:
bool SemaBuiltinPrefetch(CallExpr *TheCall);
bool SemaBuiltinObjectSize(CallExpr *TheCall);
bool SemaBuiltinLongjmp(CallExpr *TheCall);
- bool SemaBuiltinAtomicOverloaded(CallExpr *TheCall);
+ OwningExprResult SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult);
bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
llvm::APSInt &Result);
bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 444ee79..e110e3d 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -870,6 +870,10 @@ static void DiagnoseAccessPath(Sema &S,
<< BS->getSourceRange()
<< (BaseAccess == AS_protected)
<< (BS->getAccessSpecifierAsWritten() == AS_none);
+
+ if (D)
+ S.Diag(D->getLocation(), diag::note_field_decl);
+
return;
}
}
@@ -1020,6 +1024,9 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
if (Entity.getAccess() == AS_public)
return Sema::AR_accessible;
+ if (S.SuppressAccessChecking)
+ 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
@@ -1153,9 +1160,10 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
/// Checks access to a constructor.
Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
- CXXConstructorDecl *Constructor,
- const InitializedEntity &Entity,
- AccessSpecifier Access) {
+ CXXConstructorDecl *Constructor,
+ const InitializedEntity &Entity,
+ AccessSpecifier Access,
+ bool IsCopyBindingRefToTemp) {
if (!getLangOptions().AccessControl ||
Access == AS_public)
return AR_accessible;
@@ -1166,7 +1174,9 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
QualType());
switch (Entity.getKind()) {
default:
- AccessEntity.setDiag(diag::err_access_ctor);
+ AccessEntity.setDiag(IsCopyBindingRefToTemp
+ ? diag::ext_rvalue_to_reference_access_ctor
+ : diag::err_access_ctor);
break;
case InitializedEntity::EK_Base:
@@ -1327,3 +1337,15 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
}
}
}
+
+void Sema::ActOnStartSuppressingAccessChecks() {
+ assert(!SuppressAccessChecking &&
+ "Tried to start access check suppression when already started.");
+ SuppressAccessChecking = true;
+}
+
+void Sema::ActOnStopSuppressingAccessChecks() {
+ assert(SuppressAccessChecking &&
+ "Tried to stop access check suprression when already stopped.");
+ SuppressAccessChecking = false;
+}
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 82978c9..69f27b0 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -135,13 +135,24 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
return;
}
- // We don't support #pragma options align=power.
switch (Kind) {
+ // For all targets we support native and natural are the same.
+ //
+ // FIXME: This is not true on Darwin/PPC.
+ case POAK_Native:
+ case POAK_Power:
case POAK_Natural:
Context->push(0);
Context->setAlignment(0);
break;
+ // Note that '#pragma options align=packed' is not equivalent to attribute
+ // packed, it has a different precedence relative to attribute aligned.
+ case POAK_Packed:
+ Context->push(0);
+ Context->setAlignment(1);
+ break;
+
case POAK_Mac68k:
// Check if the target supports this.
if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 9b95552..b7e855f 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -233,6 +233,15 @@ bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
T2 = T2MPType->getPointeeType();
return true;
}
+
+ const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(),
+ *T2BPType = T2->getAs<BlockPointerType>();
+ if (T1BPType && T2BPType) {
+ T1 = T1BPType->getPointeeType();
+ T2 = T2BPType->getPointeeType();
+ return true;
+ }
+
return false;
}
@@ -246,9 +255,11 @@ 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->isAnyPointerType() || SrcType->isMemberPointerType()) &&
+ assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
+ SrcType->isBlockPointerType()) &&
"Source type is not pointer or pointer to member.");
- assert((DestType->isAnyPointerType() || DestType->isMemberPointerType()) &&
+ assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
+ DestType->isBlockPointerType()) &&
"Destination type is not pointer or pointer to member.");
QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
@@ -257,10 +268,16 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
// Find the qualifications.
while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
- cv1.push_back(UnwrappedSrcType.getQualifiers());
- cv2.push_back(UnwrappedDestType.getQualifiers());
+ Qualifiers SrcQuals;
+ Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
+ cv1.push_back(SrcQuals);
+
+ Qualifiers DestQuals;
+ Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
+ cv2.push_back(DestQuals);
}
- assert(cv1.size() > 0 && "Must have at least one pointer level.");
+ if (cv1.empty())
+ return false;
// Construct void pointers with those qualifiers (in reverse order of
// unwrapping, of course).
@@ -1014,7 +1031,7 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
// in multi-level pointers may change, but the level count must be the same,
// as must be the final pointee type.
while (SrcType != DestType &&
- Self.UnwrapSimilarPointerTypes(SrcType, DestType)) {
+ Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
Qualifiers Quals;
SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals);
DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals);
@@ -1080,8 +1097,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
}
// See below for the enumeral issue.
- if (SrcType->isNullPtrType() && DestType->isIntegralType() &&
- !DestType->isEnumeralType()) {
+ if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) {
// C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
// type large enough to hold it. A value of std::nullptr_t can be
// converted to an integral type; the conversion has the same meaning
@@ -1098,9 +1114,9 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
bool destIsVector = DestType->isVectorType();
bool srcIsVector = SrcType->isVectorType();
if (srcIsVector || destIsVector) {
- bool srcIsScalar = SrcType->isIntegralType() && !SrcType->isEnumeralType();
- bool destIsScalar =
- DestType->isIntegralType() && !DestType->isEnumeralType();
+ // FIXME: Should this also apply to floating point types?
+ bool srcIsScalar = SrcType->isIntegralType(Self.Context);
+ bool destIsScalar = DestType->isIntegralType(Self.Context);
// Check if this is a cast between a vector and something else.
if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
@@ -1124,8 +1140,10 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_Failed;
}
- bool destIsPtr = DestType->isAnyPointerType();
- bool srcIsPtr = SrcType->isAnyPointerType();
+ bool destIsPtr = DestType->isAnyPointerType() ||
+ DestType->isBlockPointerType();
+ bool srcIsPtr = SrcType->isAnyPointerType() ||
+ SrcType->isBlockPointerType();
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.
@@ -1143,9 +1161,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_Success;
}
- // Note: Clang treats enumeration types as integral types. If this is ever
- // changed for C++, the additional check here will be redundant.
- if (DestType->isIntegralType() && !DestType->isEnumeralType()) {
+ if (DestType->isIntegralType(Self.Context)) {
assert(srcIsPtr && "One type must be a pointer");
// C++ 5.2.10p4: A pointer can be explicitly converted to any integral
// type large enough to hold it.
@@ -1158,7 +1174,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_Success;
}
- if (SrcType->isIntegralType() || SrcType->isEnumeralType()) {
+ if (SrcType->isIntegralOrEnumerationType()) {
assert(destIsPtr && "One type must be a pointer");
// C++ 5.2.10p5: A value of integral or enumeration type can be explicitly
// converted to a pointer.
@@ -1178,11 +1194,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
msg = diag::err_bad_cxx_cast_const_away;
return TC_Failed;
}
+
+ // Cannot convert between block pointers and Objective-C object pointers.
+ if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) ||
+ (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType()))
+ return TC_NotApplicable;
+
+ // Any pointer can be cast to an Objective-C pointer type with a C-style
+ // cast.
if (CStyle && DestType->isObjCObjectPointerType()) {
Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
return TC_Success;
}
-
+
// Not casting away constness, so the only remaining check is for compatible
// pointer categories.
Kind = CastExpr::CK_BitCast;
@@ -1211,7 +1235,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange;
return TC_Success;
}
-
+
// C++ 5.2.10p7: A pointer to an object can be explicitly converted to
// a pointer to an object of different type.
// Void pointers are not specified, but supported by every compiler out there.
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index c0ec9e9..f56573a 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -96,7 +96,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
// injected class name of the named class template, we're entering
// into that class template definition.
QualType Injected
- = ClassTemplate->getInjectedClassNameSpecialization(Context);
+ = ClassTemplate->getInjectedClassNameSpecialization();
if (Context.hasSameType(Injected, ContextType))
return ClassTemplate->getTemplatedDecl();
@@ -458,8 +458,10 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
Diag(ND->getLocation(), diag::note_previous_decl)
<< ND->getDeclName();
- } else
+ } else {
Found.clear();
+ Found.setLookupName(&II);
+ }
}
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 4f3f41b..7a39f05 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -26,7 +26,10 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "clang/Basic/TargetBuiltins.h"
+#include "clang/Basic/TargetInfo.h"
#include <limits>
using namespace clang;
@@ -199,21 +202,119 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__sync_bool_compare_and_swap:
case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_lock_release:
- if (SemaBuiltinAtomicOverloaded(TheCall))
- return ExprError();
- break;
-
- // Target specific builtins start here.
+ return SemaBuiltinAtomicOverloaded(move(TheCallResult));
+ }
+
+ // Since the target specific builtins for each arch overlap, only check those
+ // of the arch we are compiling for.
+ if (BuiltinID >= Builtin::FirstTSBuiltin) {
+ switch (Context.Target.getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall))
+ return ExprError();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return move(TheCallResult);
+}
+
+bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ switch (BuiltinID) {
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr: {
llvm::APSInt Result;
if (SemaBuiltinConstantArg(TheCall, 2, Result))
- return ExprError();
+ return true;
break;
}
}
+ return false;
+}
- return move(TheCallResult);
+// Get the valid immediate range for the specified NEON type code.
+static unsigned RFT(unsigned t, bool shift = false) {
+ bool quad = t & 0x10;
+
+ switch (t & 0x7) {
+ case 0: // i8
+ return shift ? 7 : (8 << (int)quad) - 1;
+ case 1: // i16
+ return shift ? 15 : (4 << (int)quad) - 1;
+ case 2: // i32
+ return shift ? 31 : (2 << (int)quad) - 1;
+ case 3: // i64
+ return shift ? 63 : (1 << (int)quad) - 1;
+ case 4: // f32
+ assert(!shift && "cannot shift float types!");
+ return (2 << (int)quad) - 1;
+ case 5: // poly8
+ assert(!shift && "cannot shift polynomial types!");
+ return (8 << (int)quad) - 1;
+ case 6: // poly16
+ assert(!shift && "cannot shift polynomial types!");
+ return (4 << (int)quad) - 1;
+ case 7: // float16
+ assert(!shift && "cannot shift float types!");
+ return (4 << (int)quad) - 1;
+ }
+ return 0;
+}
+
+bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ llvm::APSInt Result;
+
+ unsigned mask = 0;
+ unsigned TV = 0;
+ switch (BuiltinID) {
+#define GET_NEON_OVERLOAD_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_OVERLOAD_CHECK
+ }
+
+ // For NEON intrinsics which are overloaded on vector element type, validate
+ // the immediate which specifies which variant to emit.
+ if (mask) {
+ unsigned ArgNo = TheCall->getNumArgs()-1;
+ if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
+ return true;
+
+ TV = Result.getLimitedValue(32);
+ if ((TV > 31) || (mask & (1 << TV)) == 0)
+ return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code)
+ << TheCall->getArg(ArgNo)->getSourceRange();
+ }
+
+ // For NEON intrinsics which take an immediate value as part of the
+ // instruction, range check them here.
+ unsigned i = 0, l = 0, u = 0;
+ switch (BuiltinID) {
+ default: return false;
+#define GET_NEON_IMMEDIATE_CHECK
+#include "clang/Basic/arm_neon.inc"
+#undef GET_NEON_IMMEDIATE_CHECK
+ };
+
+ // Check that the immediate argument is actually a constant.
+ if (SemaBuiltinConstantArg(TheCall, i, Result))
+ return true;
+
+ // Range check against the upper/lower values for this isntruction.
+ unsigned Val = Result.getZExtValue();
+ if (Val < l || Val > (u + l))
+ return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
+ << llvm::utostr(l) << llvm::utostr(u+l)
+ << TheCall->getArg(i)->getSourceRange();
+
+ return false;
}
/// CheckFunctionCall - Check a direct function call for various correctness
@@ -279,32 +380,40 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
///
/// This function goes through and does final semantic checking for these
/// builtins,
-bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
+Sema::OwningExprResult
+Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
+ CallExpr *TheCall = (CallExpr *)TheCallResult.get();
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
// Ensure that we have at least one argument to do type inference from.
- if (TheCall->getNumArgs() < 1)
- return Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_few_args_at_least)
- << 0 << 1 << TheCall->getNumArgs()
- << TheCall->getCallee()->getSourceRange();
+ if (TheCall->getNumArgs() < 1) {
+ Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1 << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return ExprError();
+ }
// Inspect the first argument of the atomic builtin. This should always be
// a pointer type, whose element is an integral scalar or pointer type.
// Because it is a pointer type, we don't have to worry about any implicit
// casts here.
+ // FIXME: We don't allow floating point scalars as input.
Expr *FirstArg = TheCall->getArg(0);
- if (!FirstArg->getType()->isPointerType())
- return Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
- << FirstArg->getType() << FirstArg->getSourceRange();
+ if (!FirstArg->getType()->isPointerType()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
- QualType ValType = FirstArg->getType()->getAs<PointerType>()->getPointeeType();
+ QualType ValType =
+ FirstArg->getType()->getAs<PointerType>()->getPointeeType();
if (!ValType->isIntegerType() && !ValType->isPointerType() &&
- !ValType->isBlockPointerType())
- return Diag(DRE->getLocStart(),
- diag::err_atomic_builtin_must_be_pointer_intptr)
- << FirstArg->getType() << FirstArg->getSourceRange();
+ !ValType->isBlockPointerType()) {
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
+ }
// We need to figure out which concrete builtin this maps onto. For example,
// __sync_fetch_and_add with a 2 byte object turns into
@@ -342,8 +451,9 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
case 8: SizeIndex = 3; break;
case 16: SizeIndex = 4; break;
default:
- return Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
- << FirstArg->getType() << FirstArg->getSourceRange();
+ Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size)
+ << FirstArg->getType() << FirstArg->getSourceRange();
+ return ExprError();
}
// Each of these builtins has one pointer argument, followed by some number of
@@ -383,12 +493,12 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
// Now that we know how many fixed arguments we expect, first check that we
// have at least that many.
- if (TheCall->getNumArgs() < 1+NumFixed)
- return Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_few_args_at_least)
- << 0 << 1+NumFixed << TheCall->getNumArgs()
- << TheCall->getCallee()->getSourceRange();
-
+ if (TheCall->getNumArgs() < 1+NumFixed) {
+ Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least)
+ << 0 << 1+NumFixed << TheCall->getNumArgs()
+ << TheCall->getCallee()->getSourceRange();
+ return ExprError();
+ }
// Get the decl for the concrete builtin from this, we can tell what the
// concrete integer type we should convert to is.
@@ -400,6 +510,8 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
TUScope, false, DRE->getLocStart()));
const FunctionProtoType *BuiltinFT =
NewBuiltinDecl->getType()->getAs<FunctionProtoType>();
+
+ QualType OrigValType = ValType;
ValType = BuiltinFT->getArgType(0)->getAs<PointerType>()->getPointeeType();
// If the first type needs to be converted (e.g. void** -> int*), do it now.
@@ -426,7 +538,7 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
CXXBaseSpecifierArray BasePath;
if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
- return true;
+ return ExprError();
// Okay, we have something that *can* be converted to the right type. Check
// to see if there is a potentially weird extension going on here. This can
@@ -448,10 +560,30 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
UsualUnaryConversions(PromotedCall);
TheCall->setCallee(PromotedCall);
-
// Change the result type of the call to match the result type of the decl.
- TheCall->setType(NewBuiltinDecl->getResultType());
- return false;
+ TheCall->setType(NewBuiltinDecl->getCallResultType());
+
+ // If the value type was converted to an integer when processing the
+ // arguments (e.g. void* -> int), we need to convert the result back.
+ if (!Context.hasSameUnqualifiedType(ValType, OrigValType)) {
+ Expr *E = TheCallResult.takeAs<Expr>();
+
+ assert(ValType->isIntegerType() &&
+ "We always convert atomic operation values to integers.");
+ // FIXME: Handle floating point value type here too.
+ CastExpr::CastKind Kind;
+ if (OrigValType->isIntegerType())
+ Kind = CastExpr::CK_IntegralCast;
+ else if (OrigValType->hasPointerRepresentation())
+ Kind = CastExpr::CK_IntegralToPointer;
+ else
+ llvm_unreachable("Unhandled original value type!");
+
+ ImpCastExprToType(E, OrigValType, Kind);
+ return Owned(E);
+ }
+
+ return move(TheCallResult);
}
@@ -511,7 +643,7 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) {
BlockScopeInfo *CurBlock = getCurBlock();
bool isVariadic;
if (CurBlock)
- isVariadic = CurBlock->isVariadic;
+ isVariadic = CurBlock->TheDecl->isVariadic();
else if (FunctionDecl *FD = getCurFunctionDecl())
isVariadic = FD->isVariadic();
else
@@ -633,45 +765,54 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything.
Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
- if (TheCall->getNumArgs() < 3)
+ if (TheCall->getNumArgs() < 2)
return ExprError(Diag(TheCall->getLocEnd(),
diag::err_typecheck_call_too_few_args_at_least)
- << 0 /*function call*/ << 3 << TheCall->getNumArgs()
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
<< TheCall->getSourceRange());
- unsigned numElements = std::numeric_limits<unsigned>::max();
+ // Determine which of the following types of shufflevector we're checking:
+ // 1) unary, vector mask: (lhs, mask)
+ // 2) binary, vector mask: (lhs, rhs, mask)
+ // 3) binary, scalar mask: (lhs, rhs, index, ..., index)
+ QualType resType = TheCall->getArg(0)->getType();
+ unsigned numElements = 0;
+
if (!TheCall->getArg(0)->isTypeDependent() &&
!TheCall->getArg(1)->isTypeDependent()) {
- QualType FAType = TheCall->getArg(0)->getType();
- QualType SAType = TheCall->getArg(1)->getType();
-
- if (!FAType->isVectorType() || !SAType->isVectorType()) {
+ QualType LHSType = TheCall->getArg(0)->getType();
+ QualType RHSType = TheCall->getArg(1)->getType();
+
+ if (!LHSType->isVectorType() || !RHSType->isVectorType()) {
Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector)
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd());
return ExprError();
}
-
- if (!Context.hasSameUnqualifiedType(FAType, SAType)) {
+
+ numElements = LHSType->getAs<VectorType>()->getNumElements();
+ unsigned numResElements = TheCall->getNumArgs() - 2;
+
+ // Check to see if we have a call with 2 vector arguments, the unary shuffle
+ // with mask. If so, verify that RHS is an integer vector type with the
+ // same number of elts as lhs.
+ if (TheCall->getNumArgs() == 2) {
+ if (!RHSType->isIntegerType() ||
+ RHSType->getAs<VectorType>()->getNumElements() != numElements)
+ Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
+ << SourceRange(TheCall->getArg(1)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd());
+ numResElements = numElements;
+ }
+ else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
<< SourceRange(TheCall->getArg(0)->getLocStart(),
TheCall->getArg(1)->getLocEnd());
return ExprError();
- }
-
- numElements = FAType->getAs<VectorType>()->getNumElements();
- if (TheCall->getNumArgs() != numElements+2) {
- if (TheCall->getNumArgs() < numElements+2)
- return ExprError(Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_few_args)
- << 0 /*function call*/
- << numElements+2 << TheCall->getNumArgs()
- << TheCall->getSourceRange());
- return ExprError(Diag(TheCall->getLocEnd(),
- diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/
- << numElements+2 << TheCall->getNumArgs()
- << TheCall->getSourceRange());
+ } else if (numElements != numResElements) {
+ QualType eltType = LHSType->getAs<VectorType>()->getElementType();
+ resType = Context.getVectorType(eltType, numResElements,
+ VectorType::NotAltiVec);
}
}
@@ -680,9 +821,11 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
TheCall->getArg(i)->isValueDependent())
continue;
- llvm::APSInt Result;
- if (SemaBuiltinConstantArg(TheCall, i, Result))
- return ExprError();
+ llvm::APSInt Result(32);
+ if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_nonconstant_argument)
+ << TheCall->getArg(i)->getSourceRange());
if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
return ExprError(Diag(TheCall->getLocStart(),
@@ -698,7 +841,7 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
}
return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(),
- exprs.size(), exprs[0]->getType(),
+ exprs.size(), resType,
TheCall->getCallee()->getLocStart(),
TheCall->getRParenLoc()));
}
@@ -1081,15 +1224,23 @@ public:
unsigned specifierLen);
private:
SourceRange getFormatStringRange();
- SourceRange getFormatSpecifierRange(const char *startSpecifier,
- unsigned specifierLen);
+ CharSourceRange getFormatSpecifierRange(const char *startSpecifier,
+ unsigned specifierLen);
SourceLocation getLocationOfByte(const char *x);
bool HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned k,
const char *startSpecifier, unsigned specifierLen);
- void HandleFlags(const analyze_printf::FormatSpecifier &FS,
- llvm::StringRef flag, llvm::StringRef cspec,
- const char *startSpecifier, unsigned specifierLen);
+ void HandleInvalidAmount(const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::OptionalAmount &Amt,
+ unsigned type,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleFlag(const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleIgnoredFlag(const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::OptionalFlag &ignoredFlag,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier, unsigned specifierLen);
const Expr *getDataArg(unsigned i) const;
};
@@ -1099,10 +1250,15 @@ SourceRange CheckPrintfHandler::getFormatStringRange() {
return OrigFormatExpr->getSourceRange();
}
-SourceRange CheckPrintfHandler::
+CharSourceRange CheckPrintfHandler::
getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
- return SourceRange(getLocationOfByte(startSpecifier),
- getLocationOfByte(startSpecifier+specifierLen-1));
+ SourceLocation Start = getLocationOfByte(startSpecifier);
+ SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1);
+
+ // Advance the end SourceLocation by one due to half-open ranges.
+ End = End.getFileLocWithOffset(1);
+
+ return CharSourceRange::getCharRange(Start, End);
}
SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) {
@@ -1174,16 +1330,6 @@ const Expr *CheckPrintfHandler::getDataArg(unsigned i) const {
return TheCall->getArg(FirstDataArg + i);
}
-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);
-}
-
bool
CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
unsigned k, const char *startSpecifier,
@@ -1228,6 +1374,62 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
return true;
}
+void CheckPrintfHandler::HandleInvalidAmount(
+ const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::OptionalAmount &Amt,
+ unsigned type,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+ switch (Amt.getHowSpecified()) {
+ case analyze_printf::OptionalAmount::Constant:
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_printf_nonsensical_optional_amount)
+ << type
+ << CS.toString()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getFormatSpecifierRange(Amt.getStart(),
+ Amt.getConstantLength()));
+ break;
+
+ default:
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_printf_nonsensical_optional_amount)
+ << type
+ << CS.toString()
+ << getFormatSpecifierRange(startSpecifier, specifierLen);
+ break;
+ }
+}
+
+void CheckPrintfHandler::HandleFlag(const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ // Warn about pointless flag with a fixit removal.
+ const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+ S.Diag(getLocationOfByte(flag.getPosition()),
+ diag::warn_printf_nonsensical_flag)
+ << flag.toString() << CS.toString()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getFormatSpecifierRange(flag.getPosition(), 1));
+}
+
+void CheckPrintfHandler::HandleIgnoredFlag(
+ const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::OptionalFlag &ignoredFlag,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ // Warn about ignored flag with a fixit removal.
+ S.Diag(getLocationOfByte(ignoredFlag.getPosition()),
+ diag::warn_printf_ignored_flag)
+ << ignoredFlag.toString() << flag.toString()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getFormatSpecifierRange(
+ ignoredFlag.getPosition(), 1));
+}
+
bool
CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
&FS,
@@ -1282,34 +1484,57 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
return HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen);
}
- // Are we using '%n'? Issue a warning about this being
- // a possible security issue.
+ // Check for invalid use of field width
+ if (!FS.hasValidFieldWidth()) {
+ HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0,
+ startSpecifier, specifierLen);
+ }
+
+ // Check for invalid use of precision
+ if (!FS.hasValidPrecision()) {
+ HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1,
+ startSpecifier, specifierLen);
+ }
+
+ // Check each flag does not conflict with any other component.
+ if (!FS.hasValidLeadingZeros())
+ HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen);
+ if (!FS.hasValidPlusPrefix())
+ HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen);
+ if (!FS.hasValidSpacePrefix())
+ HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen);
+ if (!FS.hasValidAlternativeForm())
+ HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen);
+ if (!FS.hasValidLeftJustified())
+ HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen);
+
+ // Check that flags are not ignored by another flag
+ if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+'
+ HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(),
+ startSpecifier, specifierLen);
+ if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-'
+ HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(),
+ startSpecifier, specifierLen);
+
+ // Check the length modifier is valid with the given conversion specifier.
+ const LengthModifier &LM = FS.getLengthModifier();
+ if (!FS.hasValidLengthModifier())
+ S.Diag(getLocationOfByte(LM.getStart()),
+ diag::warn_printf_nonsensical_length)
+ << LM.toString() << CS.toString()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getFormatSpecifierRange(LM.getStart(),
+ LM.getLength()));
+
+ // Are we using '%n'?
if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) {
+ // Issue a warning about this being a possible security issue.
S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back)
<< getFormatSpecifierRange(startSpecifier, specifierLen);
// Continue checking the other format specifiers.
return true;
}
- 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);
- }
-
// The remaining checks depend on the data arguments.
if (HasVAListArg)
return true;
@@ -1344,11 +1569,32 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
if (ATR.matchesType(S.Context, ICE->getSubExpr()->getType()))
return true;
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_conversion_argument_type_mismatch)
- << ATR.getRepresentativeType(S.Context) << Ex->getType()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
- << Ex->getSourceRange();
+ // We may be able to offer a FixItHint if it is a supported type.
+ FormatSpecifier fixedFS = FS;
+ bool success = fixedFS.fixType(Ex->getType());
+
+ if (success) {
+ // Get the fix string from the fixed format specifier
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream os(buf);
+ fixedFS.toString(os);
+
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange()
+ << FixItHint::CreateReplacement(
+ getFormatSpecifierRange(startSpecifier, specifierLen),
+ os.str());
+ }
+ else {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeType(S.Context) << Ex->getType()
+ << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange();
+ }
}
return true;
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index d8c1a5c..8286110 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -119,10 +119,19 @@ namespace {
/// nested-name-specifiers that would otherwise be filtered out.
bool AllowNestedNameSpecifiers;
+ /// \brief If set, the type that we would prefer our resulting value
+ /// declarations to have.
+ ///
+ /// Closely matching the preferred type gives a boost to a result's
+ /// priority.
+ CanQualType PreferredType;
+
/// \brief A list of shadow maps, which is used to model name hiding at
/// different levels of, e.g., the inheritance hierarchy.
std::list<ShadowMap> ShadowMaps;
+ void AdjustResultPriorityForPreferredType(Result &R);
+
public:
explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
: SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { }
@@ -147,6 +156,11 @@ namespace {
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
+ /// \brief Specify the preferred type.
+ void setPreferredType(QualType T) {
+ PreferredType = SemaRef.Context.getCanonicalType(T);
+ }
+
/// \brief Specify whether nested-name-specifiers are allowed.
void allowNestedNameSpecifiers(bool Allow = true) {
AllowNestedNameSpecifiers = Allow;
@@ -212,6 +226,7 @@ namespace {
///
//@{
bool IsOrdinaryName(NamedDecl *ND) const;
+ bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
bool IsOrdinaryNonValueName(NamedDecl *ND) const;
bool IsNestedNameSpecifier(NamedDecl *ND) const;
bool IsEnum(NamedDecl *ND) const;
@@ -222,6 +237,7 @@ namespace {
bool IsType(NamedDecl *ND) const;
bool IsMember(NamedDecl *ND) const;
bool IsObjCIvar(NamedDecl *ND) const;
+ bool IsObjCMessageReceiver(NamedDecl *ND) const;
//@}
};
}
@@ -355,8 +371,6 @@ getRequiredQualification(ASTContext &Context,
Result = NestedNameSpecifier::Create(Context, Result,
false,
Context.getTypeDeclType(TD).getTypePtr());
- else
- assert(Parent->isTranslationUnit());
}
return Result;
}
@@ -458,6 +472,134 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
return false;
}
+enum SimplifiedTypeClass {
+ STC_Arithmetic,
+ STC_Array,
+ STC_Block,
+ STC_Function,
+ STC_ObjectiveC,
+ STC_Other,
+ STC_Pointer,
+ STC_Record,
+ STC_Void
+};
+
+/// \brief A simplified classification of types used to determine whether two
+/// types are "similar enough" when adjusting priorities.
+static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) {
+ switch (T->getTypeClass()) {
+ case Type::Builtin:
+ switch (cast<BuiltinType>(T)->getKind()) {
+ case BuiltinType::Void:
+ return STC_Void;
+
+ case BuiltinType::NullPtr:
+ return STC_Pointer;
+
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ case BuiltinType::UndeducedAuto:
+ return STC_Other;
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return STC_ObjectiveC;
+
+ default:
+ return STC_Arithmetic;
+ }
+ return STC_Other;
+
+ case Type::Complex:
+ return STC_Arithmetic;
+
+ case Type::Pointer:
+ return STC_Pointer;
+
+ case Type::BlockPointer:
+ return STC_Block;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ return STC_Array;
+
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ return STC_Arithmetic;
+
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ return STC_Function;
+
+ case Type::Record:
+ return STC_Record;
+
+ case Type::Enum:
+ return STC_Arithmetic;
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ return STC_ObjectiveC;
+
+ default:
+ return STC_Other;
+ }
+}
+
+/// \brief Get the type that a given expression will have if this declaration
+/// is used as an expression in its "typical" code-completion form.
+static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+ return C.getTypeDeclType(Type);
+ if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+ return C.getObjCInterfaceType(Iface);
+
+ QualType T;
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+ T = Function->getCallResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ T = Method->getSendResultType();
+ else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+ T = FunTmpl->getTemplatedDecl()->getCallResultType();
+ else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+ T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
+ else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+ T = Property->getType();
+ else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+ T = Value->getType();
+ else
+ return QualType();
+
+ return T.getNonReferenceType();
+}
+
+void ResultBuilder::AdjustResultPriorityForPreferredType(Result &R) {
+ QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
+ if (T.isNull())
+ return;
+
+ CanQualType TC = SemaRef.Context.getCanonicalType(T);
+ // Check for exactly-matching types (modulo qualifiers).
+ if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
+ R.Priority /= CCF_ExactTypeMatch;
+ // Check for nearly-matching types, based on classification of each.
+ else if ((getSimplifiedTypeClass(PreferredType)
+ == getSimplifiedTypeClass(TC)) &&
+ !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
+ R.Priority /= CCF_SimilarTypeMatch;
+}
+
void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
assert(!ShadowMaps.empty() && "Must enter into a results scope");
@@ -542,8 +684,9 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
- }
-
+ } else if (!PreferredType.isNull())
+ AdjustResultPriorityForPreferredType(R);
+
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
@@ -616,6 +759,9 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
if (InBaseClass)
R.Priority += CCD_InBaseClass;
+ if (!PreferredType.isNull())
+ AdjustResultPriorityForPreferredType(R);
+
// Insert this result into the set of results.
Results.push_back(R);
}
@@ -645,9 +791,11 @@ void ResultBuilder::ExitScope() {
/// \brief Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
unsigned IDNS = Decl::IDNS_Ordinary;
if (SemaRef.getLangOptions().CPlusPlus)
- IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
return true;
@@ -655,14 +803,33 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
}
/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup but is not a type name.
+bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+ return false;
+
+ unsigned IDNS = Decl::IDNS_Ordinary;
+ if (SemaRef.getLangOptions().CPlusPlus)
+ IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
+ else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
+ return true;
+
+ return ND->getIdentifierNamespace() & IDNS;
+}
+
+/// \brief Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
+ ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+
unsigned IDNS = Decl::IDNS_Ordinary;
if (SemaRef.getLangOptions().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
return (ND->getIdentifierNamespace() & IDNS) &&
- !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND);
+ !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
+ !isa<ObjCPropertyDecl>(ND);
}
/// \brief Determines whether the given declaration is suitable as the
@@ -732,6 +899,49 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const {
isa<ObjCPropertyDecl>(ND);
}
+static bool isObjCReceiverType(ASTContext &C, QualType T) {
+ T = C.getCanonicalType(T);
+ switch (T->getTypeClass()) {
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ return true;
+
+ case Type::Builtin:
+ switch (cast<BuiltinType>(T)->getKind()) {
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+
+ default:
+ break;
+ }
+
+ if (!C.getLangOptions().CPlusPlus)
+ return false;
+
+ // FIXME: We could perform more analysis here to determine whether a
+ // particular class type has any conversions to Objective-C types. For now,
+ // just accept all class types.
+ return T->isDependentType() || T->isRecordType();
+}
+
+bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
+ QualType T = getDeclUsageType(SemaRef.Context, ND);
+ if (T.isNull())
+ return false;
+
+ T = SemaRef.Context.getBaseElementType(T);
+ return isObjCReceiverType(SemaRef.Context, T);
+}
+
+
/// \rief Determines whether the given declaration is an Objective-C
/// instance variable.
bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
@@ -788,27 +998,26 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Results.AddResult(Result("class", CCP_Type));
Results.AddResult(Result("wchar_t", CCP_Type));
- if (Results.includeCodePatterns()) {
- // typename qualified-id
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typename");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("qualified-id");
- Results.AddResult(Result(Pattern));
- }
+ // typename qualified-id
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("typename");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("qualifier");
+ Pattern->AddTextChunk("::");
+ Pattern->AddPlaceholderChunk("name");
+ Results.AddResult(Result(Pattern));
if (LangOpts.CPlusPlus0x) {
Results.AddResult(Result("auto", CCP_Type));
Results.AddResult(Result("char16_t", CCP_Type));
Results.AddResult(Result("char32_t", CCP_Type));
- if (Results.includeCodePatterns()) {
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("decltype");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression-or-type");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
- }
+
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("decltype");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
}
}
@@ -819,14 +1028,18 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
// Results.AddResult(Result("_Decimal64"));
// Results.AddResult(Result("_Decimal128"));
- if (Results.includeCodePatterns()) {
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typeof");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression-or-type");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
- }
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("typeof");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Pattern));
+
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("typeof");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
}
}
@@ -887,6 +1100,44 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts,
bool NeedAt);
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
+static void AddTypedefResult(ResultBuilder &Results) {
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("typedef");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("name");
+ Results.AddResult(CodeCompleteConsumer::Result(Pattern));
+}
+
+static bool WantTypesInContext(Action::CodeCompletionContext CCC,
+ const LangOptions &LangOpts) {
+ if (LangOpts.CPlusPlus)
+ return true;
+
+ switch (CCC) {
+ case Action::CCC_Namespace:
+ case Action::CCC_Class:
+ case Action::CCC_ObjCInstanceVariableList:
+ case Action::CCC_Template:
+ case Action::CCC_MemberTemplate:
+ case Action::CCC_Statement:
+ case Action::CCC_RecoveryInFunction:
+ return true;
+
+ case Action::CCC_ObjCInterface:
+ case Action::CCC_ObjCImplementation:
+ case Action::CCC_Expression:
+ case Action::CCC_Condition:
+ return false;
+
+ case Action::CCC_ForInit:
+ return LangOpts.ObjC1 || LangOpts.C99;
+ }
+
+ return false;
+}
+
/// \brief Add language constructs that show up for "ordinary" names.
static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
Scope *S,
@@ -895,25 +1146,29 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
typedef CodeCompleteConsumer::Result Result;
switch (CCC) {
case Action::CCC_Namespace:
- if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
- // namespace <identifier> { }
- CodeCompletionString *Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("namespace");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
- Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
- Pattern->AddPlaceholderChunk("declarations");
- Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
- Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
- Results.AddResult(Result(Pattern));
-
+ if (SemaRef.getLangOptions().CPlusPlus) {
+ CodeCompletionString *Pattern = 0;
+
+ if (Results.includeCodePatterns()) {
+ // namespace <identifier> { declarations }
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("namespace");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("identifier");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+ Pattern->AddPlaceholderChunk("declarations");
+ Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+ Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Pattern));
+ }
+
// namespace identifier = identifier ;
Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk("namespace");
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
+ Pattern->AddPlaceholderChunk("name");
Pattern->AddChunk(CodeCompletionString::CK_Equal);
- Pattern->AddPlaceholderChunk("identifier");
+ Pattern->AddPlaceholderChunk("namespace");
Results.AddResult(Result(Pattern));
// Using directives
@@ -933,43 +1188,49 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
Pattern->AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Pattern));
- // Explicit template instantiation
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("template");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("declaration");
- Results.AddResult(Result(Pattern));
+ if (Results.includeCodePatterns()) {
+ // Explicit template instantiation
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("template");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("declaration");
+ Results.AddResult(Result(Pattern));
+ }
}
if (SemaRef.getLangOptions().ObjC1)
AddObjCTopLevelResults(Results, true);
+ AddTypedefResult(Results);
// Fall through
case Action::CCC_Class:
- if (Results.includeCodePatterns())
- Results.AddResult(Result("typedef"));
-
- if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
+ if (SemaRef.getLangOptions().CPlusPlus) {
// Using declaration
CodeCompletionString *Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk("using");
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("qualified-id");
+ Pattern->AddPlaceholderChunk("qualifier");
+ Pattern->AddTextChunk("::");
+ Pattern->AddPlaceholderChunk("name");
Results.AddResult(Result(Pattern));
- // using typename qualified-id; (only in a dependent context)
+ // using typename qualifier::name (only in a dependent context)
if (SemaRef.CurContext->isDependentContext()) {
Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk("using");
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
Pattern->AddTextChunk("typename");
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("qualified-id");
+ Pattern->AddPlaceholderChunk("qualifier");
+ Pattern->AddTextChunk("::");
+ Pattern->AddPlaceholderChunk("name");
Results.AddResult(Result(Pattern));
}
if (CCC == Action::CCC_Class) {
+ AddTypedefResult(Results);
+
// public:
Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk("public");
@@ -1025,8 +1286,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
case Action::CCC_RecoveryInFunction:
case Action::CCC_Statement: {
- if (Results.includeCodePatterns())
- Results.AddResult(Result("typedef"));
+ AddTypedefResult(Results);
CodeCompletionString *Pattern = 0;
if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
@@ -1081,10 +1341,11 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
}
// Switch-specific statements.
- if (!SemaRef.getSwitchStack().empty() && Results.includeCodePatterns()) {
+ if (!SemaRef.getSwitchStack().empty()) {
// case expression:
Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk("case");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
Pattern->AddPlaceholderChunk("expression");
Pattern->AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Pattern));
@@ -1178,23 +1439,21 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
}
Results.AddResult(Result(Pattern));
- if (Results.includeCodePatterns()) {
- // goto identifier ;
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("goto");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
- Results.AddResult(Result(Pattern));
+ // goto identifier ;
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("goto");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("label");
+ Results.AddResult(Result(Pattern));
- // Using directives
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("using");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddTextChunk("namespace");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
- Results.AddResult(Result(Pattern));
- }
+ // Using directives
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("using");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("namespace");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("identifier");
+ Results.AddResult(Result(Pattern));
}
// Fall through (for statement expressions).
@@ -1215,132 +1474,133 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
Results.AddResult(Result("true"));
Results.AddResult(Result("false"));
- if (Results.includeCodePatterns()) {
- // dynamic_cast < type-id > ( expression )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("dynamic_cast");
- Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
- Pattern->AddPlaceholderChunk("type-id");
- Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
-
- // static_cast < type-id > ( expression )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("static_cast");
- Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
- Pattern->AddPlaceholderChunk("type-id");
- Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ // dynamic_cast < type-id > ( expression )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("dynamic_cast");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
+
+ // static_cast < type-id > ( expression )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("static_cast");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
- // reinterpret_cast < type-id > ( expression )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("reinterpret_cast");
- Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
- Pattern->AddPlaceholderChunk("type-id");
- Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ // reinterpret_cast < type-id > ( expression )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("reinterpret_cast");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
- // const_cast < type-id > ( expression )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("const_cast");
- Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
- Pattern->AddPlaceholderChunk("type-id");
- Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ // const_cast < type-id > ( expression )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("const_cast");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
- // typeid ( expression-or-type )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("typeid");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression-or-type");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ // typeid ( expression-or-type )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("typeid");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression-or-type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
- // new T ( ... )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("new");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("type-id");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expressions");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
+ // new T ( ... )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("new");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expressions");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
- // new T [ ] ( ... )
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("new");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("type-id");
- Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
- Pattern->AddPlaceholderChunk("size");
- Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expressions");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
-
- // delete expression
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("delete");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("expression");
- Results.AddResult(Result(Pattern));
+ // new T [ ] ( ... )
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("new");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("type");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
+ Pattern->AddPlaceholderChunk("size");
+ Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expressions");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
- // delete [] expression
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("delete");
- Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
- Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("expression");
- Results.AddResult(Result(Pattern));
+ // delete expression
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("delete");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Pattern));
- // throw expression
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("throw");
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("expression");
- Results.AddResult(Result(Pattern));
- }
+ // delete [] expression
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("delete");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
+ Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Pattern));
+
+ // throw expression
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("throw");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("expression");
+ Results.AddResult(Result(Pattern));
// FIXME: Rethrow?
}
if (SemaRef.getLangOptions().ObjC1) {
// Add "super", if we're in an Objective-C class with a superclass.
- if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
- if (Method->getClassInterface()->getSuperClass())
- Results.AddResult(Result("super"));
-
+ if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
+ // The interface can be NULL.
+ if (ObjCInterfaceDecl *ID = Method->getClassInterface())
+ if (ID->getSuperClass())
+ Results.AddResult(Result("super"));
+ }
+
AddObjCExpressionResults(Results, true);
}
- if (Results.includeCodePatterns()) {
- // sizeof expression
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk("sizeof");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression-or-type");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Results.AddResult(Result(Pattern));
- }
+ // sizeof expression
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("sizeof");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression-or-type");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Result(Pattern));
break;
}
}
- AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
+ if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
+ AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
if (SemaRef.getLangOptions().CPlusPlus)
Results.AddResult(Result("operator"));
@@ -1702,9 +1962,9 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Keyword += II->getName().str();
Keyword += ":";
- if (Idx < StartParameter || AllParametersAreInformative) {
+ if (Idx < StartParameter || AllParametersAreInformative)
Result->AddInformativeChunk(Keyword);
- } else if (Idx == StartParameter)
+ else if (Idx == StartParameter)
Result->AddTypedTextChunk(Keyword);
else
Result->AddTextChunk(Keyword);
@@ -1719,14 +1979,18 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
Arg = "(" + Arg + ")";
if (IdentifierInfo *II = (*P)->getIdentifier())
Arg += II->getName().str();
- if (AllParametersAreInformative)
+ if (DeclaringEntity)
+ Result->AddTextChunk(Arg);
+ else if (AllParametersAreInformative)
Result->AddInformativeChunk(Arg);
else
Result->AddPlaceholderChunk(Arg);
}
if (Method->isVariadic()) {
- if (AllParametersAreInformative)
+ if (DeclaringEntity)
+ Result->AddTextChunk(", ...");
+ else if (AllParametersAreInformative)
Result->AddInformativeChunk(", ...");
else
Result->AddPlaceholderChunk(", ...");
@@ -1921,12 +2185,25 @@ namespace {
};
}
-static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results) {
+static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
+ bool TargetTypeIsPointer = false) {
+ typedef CodeCompleteConsumer::Result Result;
+
Results.EnterNewScope();
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
- M != MEnd; ++M)
- Results.AddResult(M->first);
+ M != MEnd; ++M) {
+ unsigned Priority = CCP_Macro;
+
+ // Treat the "nil" and "NULL" macros as null pointer constants.
+ if (M->first->isStr("nil") || M->first->isStr("NULL")) {
+ Priority = CCP_Constant;
+ if (TargetTypeIsPointer)
+ Priority = Priority / CCF_SimilarTypeMatch;
+ }
+
+ Results.AddResult(Result(M->first, Priority));
+ }
Results.ExitScope();
}
@@ -1966,7 +2243,10 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
case CCC_Statement:
case CCC_ForInit:
case CCC_Condition:
- Results.setFilter(&ResultBuilder::IsOrdinaryName);
+ if (WantTypesInContext(CompletionContext, getLangOptions()))
+ Results.setFilter(&ResultBuilder::IsOrdinaryName);
+ else
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
break;
case CCC_RecoveryInFunction:
@@ -1986,6 +2266,36 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+/// \brief Perform code-completion in an expression context when we know what
+/// type we're looking for.
+void Sema::CodeCompleteExpression(Scope *S, QualType T) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ if (WantTypesInContext(CCC_Expression, getLangOptions()))
+ Results.setFilter(&ResultBuilder::IsOrdinaryName);
+ else
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+ Results.setPreferredType(T.getNonReferenceType());
+
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+
+ Results.EnterNewScope();
+ AddOrdinaryNameResults(CCC_Expression, S, *this, Results);
+ Results.ExitScope();
+
+ bool PreferredTypeIsPointer = false;
+ if (!T.isNull())
+ PreferredTypeIsPointer = T->isAnyPointerType() ||
+ T->isMemberPointerType() || T->isBlockPointerType();
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results, PreferredTypeIsPointer);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+
static void AddObjCProperties(ObjCContainerDecl *Container,
bool AllowCategories,
DeclContext *CurContext,
@@ -2254,6 +2564,17 @@ namespace {
};
}
+static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
+ if (NumArgs && !Args)
+ return true;
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (!Args[I])
+ return true;
+
+ return false;
+}
+
void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
ExprTy **ArgsIn, unsigned NumArgs) {
if (!CodeCompleter)
@@ -2268,7 +2589,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
Expr **Args = (Expr **)ArgsIn;
// Ignore type-dependent call expressions entirely.
- if (Fn->isTypeDependent() ||
+ if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
CodeCompleteOrdinaryName(S, CCC_Expression);
return;
@@ -2292,7 +2613,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
if (FDecl) {
- if (!FDecl->getType()->getAs<FunctionProtoType>())
+ if (!getLangOptions().CPlusPlus ||
+ !FDecl->getType()->getAs<FunctionProtoType>())
Results.push_back(ResultCandidate(FDecl));
else
// FIXME: access?
@@ -2302,6 +2624,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
}
}
+ QualType ParamType;
+
if (!CandidateSet.empty()) {
// Sort the overload candidate set by placing the best overloads first.
std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
@@ -2314,14 +2638,85 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
if (Cand->Viable)
Results.push_back(ResultCandidate(Cand->Function));
}
+
+ // From the viable candidates, try to determine the type of this parameter.
+ for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+ if (const FunctionType *FType = Results[I].getFunctionType())
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
+ if (NumArgs < Proto->getNumArgs()) {
+ if (ParamType.isNull())
+ ParamType = Proto->getArgType(NumArgs);
+ else if (!Context.hasSameUnqualifiedType(
+ ParamType.getNonReferenceType(),
+ Proto->getArgType(NumArgs).getNonReferenceType())) {
+ ParamType = QualType();
+ break;
+ }
+ }
+ }
+ } else {
+ // Try to determine the parameter type from the type of the expression
+ // being called.
+ QualType FunctionType = Fn->getType();
+ if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
+ FunctionType = Ptr->getPointeeType();
+ else if (const BlockPointerType *BlockPtr
+ = FunctionType->getAs<BlockPointerType>())
+ FunctionType = BlockPtr->getPointeeType();
+ else if (const MemberPointerType *MemPtr
+ = FunctionType->getAs<MemberPointerType>())
+ FunctionType = MemPtr->getPointeeType();
+
+ if (const FunctionProtoType *Proto
+ = FunctionType->getAs<FunctionProtoType>()) {
+ if (NumArgs < Proto->getNumArgs())
+ ParamType = Proto->getArgType(NumArgs);
+ }
}
- CodeCompleteOrdinaryName(S, CCC_Expression);
+ if (ParamType.isNull())
+ CodeCompleteOrdinaryName(S, CCC_Expression);
+ else
+ CodeCompleteExpression(S, ParamType);
+
if (!Results.empty())
CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
Results.size());
}
+void Sema::CodeCompleteInitializer(Scope *S, DeclPtrTy D) {
+ ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D.getAs<Decl>());
+ if (!VD) {
+ CodeCompleteOrdinaryName(S, CCC_Expression);
+ return;
+ }
+
+ CodeCompleteExpression(S, VD->getType());
+}
+
+void Sema::CodeCompleteReturn(Scope *S) {
+ QualType ResultType;
+ if (isa<BlockDecl>(CurContext)) {
+ if (BlockScopeInfo *BSI = getCurBlock())
+ ResultType = BSI->ReturnType;
+ } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
+ ResultType = Function->getResultType();
+ else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
+ ResultType = Method->getResultType();
+
+ if (ResultType.isNull())
+ CodeCompleteOrdinaryName(S, CCC_Expression);
+ else
+ CodeCompleteExpression(S, ResultType);
+}
+
+void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
+ if (LHS)
+ CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
+ else
+ CodeCompleteOrdinaryName(S, CCC_Expression);
+}
+
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext) {
if (!SS.getScopeRep() || !CodeCompleter)
@@ -2460,9 +2855,6 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
static void AddObjCImplementationResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
- if (!Results.includeCodePatterns())
- return;
-
typedef CodeCompleteConsumer::Result Result;
// Since we have an implementation, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
@@ -2488,9 +2880,6 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
- if (!Results.includeCodePatterns())
- return;
-
typedef CodeCompleteConsumer::Result Result;
// Since we have an interface or protocol, we can end it.
@@ -2509,9 +2898,6 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts,
}
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
- if (!Results.includeCodePatterns())
- return;
-
typedef CodeCompleteConsumer::Result Result;
CodeCompletionString *Pattern = 0;
@@ -2519,31 +2905,33 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("identifier");
- Results.AddResult(Result(Pattern));
-
- // @interface name
- // FIXME: Could introduce the whole pattern, including superclasses and
- // such.
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("class");
+ Pattern->AddPlaceholderChunk("name");
Results.AddResult(Result(Pattern));
- // @protocol name
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("protocol");
- Results.AddResult(Result(Pattern));
+ if (Results.includeCodePatterns()) {
+ // @interface name
+ // FIXME: Could introduce the whole pattern, including superclasses and
+ // such.
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("class");
+ Results.AddResult(Result(Pattern));
- // @implementation name
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddPlaceholderChunk("class");
- Results.AddResult(Result(Pattern));
+ // @protocol name
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("protocol");
+ Results.AddResult(Result(Pattern));
+
+ // @implementation name
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("class");
+ Results.AddResult(Result(Pattern));
+ }
// @compatibility_alias name
Pattern = new CodeCompletionString;
@@ -2571,9 +2959,6 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
}
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
- if (!Results.includeCodePatterns())
- return;
-
typedef CodeCompleteConsumer::Result Result;
CodeCompletionString *Pattern = 0;
@@ -2603,31 +2988,30 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
}
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
- if (!Results.includeCodePatterns())
- return;
-
typedef CodeCompleteConsumer::Result Result;
CodeCompletionString *Pattern = 0;
- // @try { statements } @catch ( declaration ) { statements } @finally
- // { statements }
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
- Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
- Pattern->AddPlaceholderChunk("statements");
- Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
- Pattern->AddTextChunk("@catch");
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("parameter");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
- Pattern->AddPlaceholderChunk("statements");
- Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
- Pattern->AddTextChunk("@finally");
- Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
- Pattern->AddPlaceholderChunk("statements");
- Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
- Results.AddResult(Result(Pattern));
+ if (Results.includeCodePatterns()) {
+ // @try { statements } @catch ( declaration ) { statements } @finally
+ // { statements }
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+ Pattern->AddPlaceholderChunk("statements");
+ Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+ Pattern->AddTextChunk("@catch");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("parameter");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+ Pattern->AddPlaceholderChunk("statements");
+ Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+ Pattern->AddTextChunk("@finally");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+ Pattern->AddPlaceholderChunk("statements");
+ Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Pattern));
+ }
// @throw
Pattern = new CodeCompletionString;
@@ -2636,25 +3020,24 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
Pattern->AddPlaceholderChunk("expression");
Results.AddResult(Result(Pattern));
- // @synchronized ( expression ) { statements }
- Pattern = new CodeCompletionString;
- Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
- Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
- Pattern->AddPlaceholderChunk("expression");
- Pattern->AddChunk(CodeCompletionString::CK_RightParen);
- Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
- Pattern->AddPlaceholderChunk("statements");
- Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
- Results.AddResult(Result(Pattern));
+ if (Results.includeCodePatterns()) {
+ // @synchronized ( expression ) { statements }
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("expression");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+ Pattern->AddPlaceholderChunk("statements");
+ Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+ Results.AddResult(Result(Pattern));
+ }
}
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
- if (!Results.includeCodePatterns())
- return;
-
typedef CodeCompleteConsumer::Result Result;
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
@@ -3021,6 +3404,31 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
.Default(0);
}
+void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ // Find anything that looks like it could be a message receiver.
+ Results.setFilter(&ResultBuilder::IsObjCMessageReceiver);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ Results.EnterNewScope();
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+
+ // If we are in an Objective-C method inside a class that has a superclass,
+ // add "super" as an option.
+ if (ObjCMethodDecl *Method = getCurMethodDecl())
+ if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
+ if (Iface->getSuperClass())
+ Results.AddResult(Result("super"));
+
+ Results.ExitScope();
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+
+}
+
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) {
@@ -3113,9 +3521,9 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
// If we have an external source, load the entire class method
// pool from the PCH file.
if (ExternalSource) {
- for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N;
- ++I) {
- Selector Sel = ExternalSource->GetSelector(I);
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || FactoryMethodPool.count(Sel) ||
InstanceMethodPool.count(Sel))
continue;
@@ -3214,9 +3622,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
// If we have an external source, load the entire class method
// pool from the PCH file.
if (ExternalSource) {
- for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N;
- ++I) {
- Selector Sel = ExternalSource->GetSelector(I);
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || InstanceMethodPool.count(Sel) ||
FactoryMethodPool.count(Sel))
continue;
@@ -3550,14 +3958,11 @@ static void FindImplementableMethods(ASTContext &Context,
// Add methods from any class extensions (but not from categories;
// those should go into category implementations).
- for (ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
- Cat = Cat->getNextClassCategory()) {
- if (!Cat->IsClassExtension())
- continue;
-
- FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
+ for (const ObjCCategoryDecl *Cat = IFace->getFirstClassExtension(); Cat;
+ Cat = Cat->getNextClassExtension())
+ FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
+ WantInstanceMethods, ReturnType,
IsInImplementation, KnownMethods);
- }
}
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
@@ -3714,7 +4119,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
Pattern->AddTextChunk("...");
}
- if (IsInImplementation) {
+ if (IsInImplementation && Results.includeCodePatterns()) {
// We will be defining the method here, so add a compound statement.
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
@@ -3739,3 +4144,70 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+
+void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ TypeTy *ReturnTy,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
+ llvm::DenseMap<Selector, ObjCMethodList> &Pool
+ = IsInstanceMethod? InstanceMethodPool : FactoryMethodPool;
+
+ // If we have an external source, load the entire class method
+ // pool from the PCH file.
+ if (ExternalSource) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
+ if (Sel.isNull() || InstanceMethodPool.count(Sel) ||
+ FactoryMethodPool.count(Sel))
+ continue;
+
+ ReadMethodPool(Sel, IsInstanceMethod);
+ }
+ }
+
+ // Build the set of methods we can see.
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ if (ReturnTy)
+ Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
+
+ Results.EnterNewScope();
+ for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = Pool.begin(),
+ MEnd = Pool.end();
+ M != MEnd;
+ ++M) {
+ for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method;
+ MethList = MethList->Next) {
+ if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
+ NumSelIdents))
+ continue;
+
+ if (AtParameterName) {
+ // Suggest parameter names we've seen before.
+ if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
+ ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
+ if (Param->getIdentifier()) {
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(Param->getIdentifier()->getName());
+ Results.AddResult(Pattern);
+ }
+ }
+
+ continue;
+ }
+
+ Result R(MethList->Method, 0);
+ R.StartParameter = NumSelIdents;
+ R.AllParametersAreInformative = false;
+ R.DeclaringEntity = true;
+ Results.MaybeAddResult(R, CurContext);
+ }
+ }
+
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index af02099..9c683f7 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -87,8 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
if (!isClassName)
return 0;
- // We know from the grammar that this name refers to a type, so build a
- // DependentNameType node to describe the type.
+ // We know from the grammar that this name refers to a type,
+ // so build a dependent node to describe the type.
return CheckTypenameType(ETK_None,
(NestedNameSpecifier *)SS->getScopeRep(), II,
SourceLocation(), SS->getRange(), NameLoc
@@ -196,12 +196,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
T = Context.getObjCInterfaceType(IDecl);
- } else if (UnresolvedUsingTypenameDecl *UUDecl =
- dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) {
- // FIXME: preserve source structure information.
- T = Context.getDependentNameType(ETK_None,
- UUDecl->getTargetNestedNameSpecifier(),
- &II);
} else {
// If it's not plausibly a type, suppress diagnostics.
Result.suppressDiagnostics();
@@ -313,7 +307,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
<< (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
- SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get();
+ SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc).get();
} else {
assert(SS && SS->isInvalid() &&
"Invalid scope specifier has already been diagnosed");
@@ -959,7 +953,7 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
return Sema::CXXCopyAssignment;
}
-/// canREdefineFunction - checks if a function can be redefined. Currently,
+/// canRedefineFunction - checks if a function can be redefined. Currently,
/// only extern inline functions can be redefined, and even then only in
/// GNU89 mode.
static bool canRedefineFunction(const FunctionDecl *FD,
@@ -1063,13 +1057,27 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
}
// FIXME: diagnose the other way around?
- if (OldType->getNoReturnAttr() &&
- !NewType->getNoReturnAttr()) {
+ if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) {
NewQType = Context.getNoReturnType(NewQType);
New->setType(NewQType);
assert(NewQType.isCanonical());
}
+ // Merge regparm attribute.
+ if (OldType->getRegParmType() != NewType->getRegParmType()) {
+ if (NewType->getRegParmType()) {
+ Diag(New->getLocation(), diag::err_regparm_mismatch)
+ << NewType->getRegParmType()
+ << OldType->getRegParmType();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ NewQType = Context.getRegParmType(NewQType, OldType->getRegParmType());
+ New->setType(NewQType);
+ assert(NewQType.isCanonical());
+ }
+
if (getLangOptions().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
@@ -1446,6 +1454,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setInvalidDecl();
return;
}
+ // c99 6.2.2 P4.
+ // For an identifier declared with the storage-class specifier extern in a
+ // scope in which a prior declaration of that identifier is visible, if
+ // the prior declaration specifies internal or external linkage, the linkage
+ // of the identifier at the later declaration is the same as the linkage
+ // specified at the prior declaration.
+ // FIXME. revisit this code.
+ if (New->hasExternalStorage() &&
+ Old->getLinkage() == InternalLinkage &&
+ New->getDeclContext() == Old->getDeclContext())
+ New->setStorageClass(Old->getStorageClass());
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
@@ -1520,6 +1539,14 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
return DeclPtrTy::make(Tag);
}
+ if (getLangOptions().CPlusPlus &&
+ DS.getStorageClassSpec() != DeclSpec::SCS_typedef)
+ if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag))
+ if (Enum->enumerator_begin() == Enum->enumerator_end() &&
+ !Enum->getIdentifier() && !Enum->isInvalidDecl())
+ Diag(Enum->getLocation(), diag::ext_no_declarators)
+ << DS.getSourceRange();
+
if (!DS.isMissingDeclaratorOk() &&
DS.getTypeSpecType() != DeclSpec::TST_error) {
// Warn about typedefs of enums without names, since this is an
@@ -1770,6 +1797,8 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
<< (int)Record->isUnion();
Invalid = true;
}
+ } else if (isa<AccessSpecDecl>(*Mem)) {
+ // Any access specifier is fine.
} else {
// We have something that isn't a non-static data
// member. Complain about it.
@@ -1795,8 +1824,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
// Mock up a declarator.
Declarator Dc(DS, Declarator::TypeNameContext);
- TypeSourceInfo *TInfo = 0;
- GetTypeForDeclarator(Dc, S, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
assert(TInfo && "couldn't build declarator info for anonymous struct/union");
// Create a declaration for this anonymous struct/union.
@@ -2091,8 +2119,8 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
NamedDecl *New;
- TypeSourceInfo *TInfo = 0;
- QualType R = GetTypeForDeclarator(D, S, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType R = TInfo->getType();
LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
ForRedeclaration);
@@ -2342,6 +2370,12 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+ if (D.getName().Kind != UnqualifiedId::IK_Identifier) {
+ Diag(D.getName().StartLocation, diag::err_typedef_not_identifier)
+ << D.getName().getSourceRange();
+ return 0;
+ }
+
TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo);
if (!NewTD) return 0;
@@ -2537,6 +2571,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Match up the template parameter lists with the scope specifier, then
// determine whether we have a template or a template specialization.
bool isExplicitSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
@@ -2545,6 +2580,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateParamLists.size(),
/*never a friend*/ false,
isExplicitSpecialization)) {
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
if (TemplateParams->size() > 0) {
// There is no such thing as a variable template.
Diag(D.getIdentifierLoc(), diag::err_template_variable)
@@ -2573,6 +2611,12 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
SetNestedNameSpecifier(NewVD, D);
+ if (NumMatchedTemplateParamLists > 0) {
+ NewVD->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**)TemplateParamLists.release());
+ }
+
if (D.getDeclSpec().isThreadSpecified()) {
if (NewVD->hasLocalStorage())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global);
@@ -2831,6 +2875,23 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,
return NewVD->setInvalidDecl();
}
+ // Function pointers and references cannot have qualified function type, only
+ // function pointer-to-members can do that.
+ QualType Pointee;
+ unsigned PtrOrRef = 0;
+ if (const PointerType *Ptr = T->getAs<PointerType>())
+ Pointee = Ptr->getPointeeType();
+ else if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
+ Pointee = Ref->getPointeeType();
+ PtrOrRef = 1;
+ }
+ if (!Pointee.isNull() && Pointee->isFunctionProtoType() &&
+ Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) {
+ Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer)
+ << PtrOrRef;
+ return NewVD->setInvalidDecl();
+ }
+
if (!Previous.empty()) {
Redeclaration = true;
MergeVarDecl(NewVD, Previous);
@@ -2858,7 +2919,7 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
// FIXME: Do we care about other names here too?
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
- // We really want to find the base class constructor here.
+ // We really want to find the base class destructor here.
QualType T = Data->S->Context.getTypeDeclType(BaseRecord);
CanQualType CT = Data->S->Context.getCanonicalType(T);
@@ -2868,8 +2929,9 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
for (Path.Decls = BaseRecord->lookup(Name);
Path.Decls.first != Path.Decls.second;
++Path.Decls.first) {
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) {
- if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD))
+ NamedDecl *D = *Path.Decls.first;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false))
return true;
}
}
@@ -2992,7 +3054,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
// This is a C++ destructor declaration.
if (DC->isRecord()) {
- R = CheckDestructorDeclarator(D, SC);
+ R = CheckDestructorDeclarator(D, R, SC);
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
@@ -3093,6 +3155,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
FunctionTemplateDecl *FunctionTemplate = 0;
bool isExplicitSpecialization = false;
bool isFunctionTemplateSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(
D.getDeclSpec().getSourceRange().getBegin(),
@@ -3101,6 +3164,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TemplateParamLists.size(),
isFriend,
isExplicitSpecialization)) {
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
if (TemplateParams->size() > 0) {
// This is a function template
@@ -3140,11 +3206,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< FixItHint::CreateInsertion(InsertLoc, "<>");
}
}
+ }
- // FIXME: Free this memory properly.
- TemplateParamLists.release();
+ if (NumMatchedTemplateParamLists > 0) {
+ NewFD->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**)TemplateParamLists.release());
}
-
+
// C++ [dcl.fct.spec]p5:
// The virtual specifier shall only be used in declarations of
// nonstatic class member functions that appear within a
@@ -3272,14 +3341,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Synthesize a parameter for each argument type.
for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
AE = FT->arg_type_end(); AI != AE; ++AI) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD,
- D.getIdentifierLoc(), 0,
- *AI,
- Context.getTrivialTypeSourceInfo(*AI,
- D.getIdentifierLoc()),
- VarDecl::None,
- VarDecl::None, 0);
- Param->setImplicit();
+ ParmVarDecl *Param =
+ BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
Params.push_back(Param);
}
} else {
@@ -3456,7 +3519,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Redeclaration && Previous.isSingleResult()) {
const FunctionDecl *Def;
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
- if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) {
+ if (PrevFD && PrevFD->hasBody(Def) && D.hasAttributes()) {
Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
Diag(Def->getLocation(), diag::note_previous_definition);
}
@@ -3582,13 +3645,10 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
- switch (CheckOverload(NewFD, Previous, OldDecl)) {
+ switch (CheckOverload(S, NewFD, Previous, OldDecl,
+ /*NewIsUsingDecl*/ false)) {
case Ovl_Match:
Redeclaration = true;
- if (isa<UsingShadowDecl>(OldDecl) && CurContext->isRecord()) {
- HideUsingShadowDecl(S, cast<UsingShadowDecl>(OldDecl));
- Redeclaration = false;
- }
break;
case Ovl_NonFunction:
@@ -3647,7 +3707,7 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
CXXRecordDecl *Record = Destructor->getParent();
QualType ClassType = Context.getTypeDeclType(Record);
- // FIXME: Shouldn't we be able to perform thisc heck even when the class
+ // FIXME: Shouldn't we be able to perform this check even when the class
// type is dependent? Both gcc and edg can handle that.
if (!ClassType->isDependentType()) {
DeclarationName Name
@@ -3943,7 +4003,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
QualType T = VDecl->getType();
if (!T->isDependentType() &&
(!Context.getCanonicalType(T).isConstQualified() ||
- !T->isIntegralType())) {
+ !T->isIntegralOrEnumerationType())) {
Diag(VDecl->getLocation(), diag::err_member_initialization)
<< VDecl->getDeclName() << Init->getSourceRange();
VDecl->setInvalidDecl();
@@ -3954,7 +4014,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// can specify a constant-initializer which shall be an
// integral constant expression (5.19).
if (!Init->isTypeDependent() &&
- !Init->getType()->isIntegralType()) {
+ !Init->getType()->isIntegralOrEnumerationType()) {
// We have a non-dependent, non-integral or enumeration type.
Diag(Init->getSourceRange().getBegin(),
diag::err_in_class_initializer_non_integral_type)
@@ -4264,9 +4324,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
- TypeSourceInfo *TInfo = 0;
TagDecl *OwnedDecl = 0;
- QualType parmDeclType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl);
+ QualType parmDeclType = TInfo->getType();
if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
// C++ [dcl.fct]p6:
@@ -4331,6 +4391,18 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
return DeclPtrTy::make(New);
}
+/// \brief Synthesizes a variable for a parameter arising from a
+/// typedef.
+ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T) {
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0,
+ T, Context.getTrivialTypeSourceInfo(T, Loc),
+ VarDecl::None, VarDecl::None, 0);
+ Param->setImplicit();
+ return Param;
+}
+
ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
@@ -4489,7 +4561,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// But don't complain if we're in GNU89 mode and the previous definition
// was an extern inline function.
const FunctionDecl *Definition;
- if (FD->getBody(Definition) &&
+ if (FD->hasBody(Definition) &&
!canRedefineFunction(Definition, getLangOptions())) {
Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName();
Diag(Definition->getLocation(), diag::note_previous_definition);
@@ -4964,6 +5036,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Check explicit specializations more carefully.
bool isExplicitSpecialization = false;
+ unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
if (TUK != TUK_Reference) {
if (TemplateParameterList *TemplateParams
= MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
@@ -4971,6 +5044,9 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
TemplateParameterLists.size(),
TUK == TUK_Friend,
isExplicitSpecialization)) {
+ // All but one template parameter lists have been matching.
+ --NumMatchedTemplateParamLists;
+
if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).
@@ -4988,8 +5064,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
isExplicitSpecialization = true;
}
}
-
- TemplateParameterLists.release();
}
DeclContext *SearchDC = CurContext;
@@ -5231,7 +5305,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// for the consumer of this Decl to know it doesn't own it.
// For our current ASTs this shouldn't be a problem, but will
// need to be changed with DeclGroups.
- if (TUK == TUK_Reference || TUK == TUK_Friend)
+ if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) ||
+ TUK == TUK_Friend)
return DeclPtrTy::make(PrevTagDecl);
// Diagnose attempts to redefine a tag.
@@ -5364,10 +5439,17 @@ CreateNewDecl:
New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc,
cast_or_null<EnumDecl>(PrevDecl));
// If this is an undefined enum, warn.
- if (TUK != TUK_Definition && !Invalid) {
- unsigned DK = getLangOptions().CPlusPlus? diag::err_forward_ref_enum
- : diag::ext_forward_ref_enum;
- Diag(Loc, DK);
+ if (TUK != TUK_Definition && !Invalid) {
+ TagDecl *Def;
+ if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
+ Diag(Loc, diag::ext_forward_ref_enum_def)
+ << New;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ } else {
+ Diag(Loc,
+ getLangOptions().CPlusPlus? diag::err_forward_ref_enum
+ : diag::ext_forward_ref_enum);
+ }
}
} else {
// struct/union/class
@@ -5392,6 +5474,11 @@ CreateNewDecl:
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier*>(SS.getScopeRep());
New->setQualifierInfo(NNS, SS.getRange());
+ if (NumMatchedTemplateParamLists > 0) {
+ New->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
}
else
Invalid = true;
@@ -5547,7 +5634,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
// C99 6.7.2.1p4 - verify the field type.
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
- if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) {
+ if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) {
// Handle incomplete types with specific error.
if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete))
return true;
@@ -5629,8 +5716,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
SourceLocation Loc = DeclStart;
if (II) Loc = D.getIdentifierLoc();
- TypeSourceInfo *TInfo = 0;
- QualType T = GetTypeForDeclarator(D, S, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
@@ -5740,6 +5827,24 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
ZeroWidth = false;
}
+ // Check that 'mutable' is consistent with the type of the declaration.
+ if (!InvalidDecl && Mutable) {
+ unsigned DiagID = 0;
+ if (T->isReferenceType())
+ DiagID = diag::err_mutable_reference;
+ else if (T.isConstQualified())
+ DiagID = diag::err_mutable_const;
+
+ if (DiagID) {
+ SourceLocation ErrLoc = Loc;
+ if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid())
+ ErrLoc = D->getDeclSpec().getStorageClassSpecLoc();
+ Diag(ErrLoc, DiagID);
+ Mutable = false;
+ InvalidDecl = true;
+ }
+ }
+
FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo,
BitWidth, Mutable);
if (InvalidDecl)
@@ -5761,41 +5866,42 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
-
- if (!RDecl->hasTrivialConstructor())
- CXXRecord->setHasTrivialConstructor(false);
- if (!RDecl->hasTrivialCopyConstructor())
- CXXRecord->setHasTrivialCopyConstructor(false);
- if (!RDecl->hasTrivialCopyAssignment())
- CXXRecord->setHasTrivialCopyAssignment(false);
- if (!RDecl->hasTrivialDestructor())
- CXXRecord->setHasTrivialDestructor(false);
-
- // C++ 9.5p1: An object of a class with a non-trivial
- // constructor, a non-trivial copy constructor, a non-trivial
- // destructor, or a non-trivial copy assignment operator
- // cannot be a member of a union, nor can an array of such
- // objects.
- // TODO: C++0x alters this restriction significantly.
- if (Record->isUnion()) {
- // We check for copy constructors before constructors
- // because otherwise we'll never get complaints about
- // copy constructors.
-
- CXXSpecialMember member = CXXInvalid;
+ if (RDecl->getDefinition()) {
+ if (!RDecl->hasTrivialConstructor())
+ CXXRecord->setHasTrivialConstructor(false);
if (!RDecl->hasTrivialCopyConstructor())
- member = CXXCopyConstructor;
- else if (!RDecl->hasTrivialConstructor())
- member = CXXConstructor;
- else if (!RDecl->hasTrivialCopyAssignment())
- member = CXXCopyAssignment;
- else if (!RDecl->hasTrivialDestructor())
- member = CXXDestructor;
-
- if (member != CXXInvalid) {
- Diag(Loc, diag::err_illegal_union_member) << Name << member;
- DiagnoseNontrivial(RT, member);
- NewFD->setInvalidDecl();
+ CXXRecord->setHasTrivialCopyConstructor(false);
+ if (!RDecl->hasTrivialCopyAssignment())
+ CXXRecord->setHasTrivialCopyAssignment(false);
+ if (!RDecl->hasTrivialDestructor())
+ CXXRecord->setHasTrivialDestructor(false);
+
+ // C++ 9.5p1: An object of a class with a non-trivial
+ // constructor, a non-trivial copy constructor, a non-trivial
+ // destructor, or a non-trivial copy assignment operator
+ // cannot be a member of a union, nor can an array of such
+ // objects.
+ // TODO: C++0x alters this restriction significantly.
+ if (Record->isUnion()) {
+ // We check for copy constructors before constructors
+ // because otherwise we'll never get complaints about
+ // copy constructors.
+
+ CXXSpecialMember member = CXXInvalid;
+ if (!RDecl->hasTrivialCopyConstructor())
+ member = CXXCopyConstructor;
+ else if (!RDecl->hasTrivialConstructor())
+ member = CXXConstructor;
+ else if (!RDecl->hasTrivialCopyAssignment())
+ member = CXXCopyAssignment;
+ else if (!RDecl->hasTrivialDestructor())
+ member = CXXDestructor;
+
+ if (member != CXXInvalid) {
+ Diag(Loc, diag::err_illegal_union_member) << Name << member;
+ DiagnoseNontrivial(RT, member);
+ NewFD->setInvalidDecl();
+ }
}
}
}
@@ -5842,7 +5948,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
typedef CXXRecordDecl::ctor_iterator ctor_iter;
for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
const FunctionDecl *body = 0;
- ci->getBody(body);
+ ci->hasBody(body);
if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) {
SourceLocation CtorLoc = ci->getLocation();
Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
@@ -5876,7 +5982,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
case CXXDestructor:
if (RD->hasUserDeclaredDestructor()) {
- SourceLocation DtorLoc = RD->getDestructor(Context)->getLocation();
+ SourceLocation DtorLoc = LookupDestructor(RD)->getLocation();
Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member;
return;
}
@@ -5985,8 +6091,8 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
// FIXME: Unnamed fields can be handled in various different ways, for
// example, unnamed unions inject all members into the struct namespace!
- TypeSourceInfo *TInfo = 0;
- QualType T = GetTypeForDeclarator(D, S, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
if (BitWidth) {
// 6.7.2.1p3, 6.7.2.1p4
@@ -6188,6 +6294,12 @@ void Sema::ActOnFields(Scope* S,
(FD->getType()->isObjCObjectPointerType() ||
FD->getType().isObjCGCStrong()))
Record->setHasObjectMember(true);
+ else if (Context.getAsArrayType(FD->getType())) {
+ QualType BaseType = Context.getBaseElementType(FD->getType());
+ if (Record && BaseType->isRecordType() &&
+ BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
+ Record->setHasObjectMember(true);
+ }
// Keep track of the number of named members.
if (FD->getIdentifier())
++NumNamedMembers;
@@ -6241,7 +6353,7 @@ void Sema::ActOnFields(Scope* S,
static bool isRepresentableIntegerValue(ASTContext &Context,
llvm::APSInt &Value,
QualType T) {
- assert(T->isIntegralType() && "Integral type required!");
+ assert(T->isIntegralType(Context) && "Integral type required!");
unsigned BitWidth = Context.getIntWidth(T);
if (Value.isUnsigned() || Value.isNonNegative())
@@ -6255,7 +6367,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context,
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!");
+ assert(T->isIntegralType(Context) && "Integral type required!");
const unsigned NumTypes = 4;
QualType SignedIntegralTypes[NumTypes] = {
Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index c6dcc3b..3b82f58 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -913,7 +913,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
isDef = (!VD->hasExternalStorage() || VD->getInit());
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- isDef = FD->getBody();
+ isDef = FD->hasBody();
} else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
// We ignore weak import on properties and methods
return;
@@ -1180,6 +1180,54 @@ static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
return InvalidFormat;
}
+/// Handle __attribute__((init_priority(priority))) attributes based on
+/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
+static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ if (!S.getLangOptions().CPlusPlus) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return;
+ }
+
+ if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) {
+ S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
+ Attr.setInvalid();
+ return;
+ }
+ QualType T = dyn_cast<VarDecl>(d)->getType();
+ if (S.Context.getAsArrayType(T))
+ T = S.Context.getBaseElementType(T);
+ if (!T->getAs<RecordType>()) {
+ S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
+ Attr.setInvalid();
+ return;
+ }
+
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ Attr.setInvalid();
+ return;
+ }
+ Expr *priorityExpr = static_cast<Expr *>(Attr.getArg(0));
+
+ llvm::APSInt priority(32);
+ if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
+ !priorityExpr->isIntegerConstantExpr(priority, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "init_priority" << priorityExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ unsigned prioritynum = priority.getZExtValue();
+ if (prioritynum < 101 || prioritynum > 65535) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range)
+ << priorityExpr->getSourceRange();
+ Attr.setInvalid();
+ return;
+ }
+ d->addAttr(::new (S.Context) InitPriorityAttr(prioritynum));
+}
+
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1362,9 +1410,10 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
FieldDecl *FirstField = *Field;
QualType FirstType = FirstField->getType();
- if (FirstType->isFloatingType() || FirstType->isVectorType()) {
+ if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
S.Diag(FirstField->getLocation(),
- diag::warn_transparent_union_attribute_floating);
+ diag::warn_transparent_union_attribute_floating)
+ << FirstType->isVectorType() << FirstType;
return;
}
@@ -1410,7 +1459,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString()));
}
-static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() > 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
@@ -1421,30 +1470,36 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// than GNU's, and should error out when it is used to specify a
// weaker alignment, rather than being silently ignored.
- unsigned Align = 0;
if (Attr.getNumArgs() == 0) {
// FIXME: This should be the target specific maximum alignment.
// (For now we just use 128 bits which is the maximum on X86).
- Align = 128;
- d->addAttr(::new (S.Context) AlignedAttr(Align));
+ D->addAttr(::new (S.Context) AlignedAttr(128));
+ return;
+ }
+
+ S.AddAlignedAttr(Attr.getLoc(), D, static_cast<Expr *>(Attr.getArg(0)));
+}
+
+void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
+ if (E->isTypeDependent() || E->isValueDependent()) {
+ // Save dependent expressions in the AST to be instantiated.
+ D->addAttr(::new (Context) AlignedAttr(E));
return;
}
- Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
llvm::APSInt Alignment(32);
- if (alignmentExpr->isTypeDependent() || alignmentExpr->isValueDependent() ||
- !alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "aligned" << alignmentExpr->getSourceRange();
+ if (!E->isIntegerConstantExpr(Alignment, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_not_int)
+ << "aligned" << E->getSourceRange();
return;
}
if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
- S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two)
- << alignmentExpr->getSourceRange();
+ Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two)
+ << E->getSourceRange();
return;
}
- d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
+ D->addAttr(::new (Context) AlignedAttr(Alignment.getZExtValue() * 8));
}
/// HandleModeAttr - This attribute modifies the width of a decl with primitive
@@ -1525,7 +1580,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
else if (IntegerMode) {
- if (!OldTy->isIntegralType())
+ if (!OldTy->isIntegralOrEnumerationType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
} else if (ComplexMode) {
if (!OldTy->isComplexType())
@@ -1650,6 +1705,23 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) NoInlineAttr());
}
+static void HandleNoInstrumentFunctionAttr(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 (!isa<FunctionDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) NoInstrumentFunctionAttr());
+}
+
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
@@ -1951,6 +2023,9 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_reqd_wg_size:
HandleReqdWorkGroupSize(D, Attr, S); break;
+ case AttributeList::AT_init_priority:
+ HandleInitPriorityAttr(D, Attr, S); break;
+
case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
@@ -1979,9 +2054,11 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break;
case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break;
case AttributeList::IgnoredAttribute:
- case AttributeList::AT_no_instrument_function: // Interacts with -pg.
// Just ignore
break;
+ case AttributeList::AT_no_instrument_function: // Interacts with -pg.
+ HandleNoInstrumentFunctionAttr(D, Attr, S);
+ break;
case AttributeList::AT_stdcall:
case AttributeList::AT_cdecl:
case AttributeList::AT_fastcall:
@@ -1992,7 +2069,8 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
// Ask target about the attribute.
const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored)
+ << Attr.getName();
break;
}
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 148d146..bd97df2 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -871,6 +871,17 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
// C++ class member Handling
//===----------------------------------------------------------------------===//
+/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
+Sema::DeclPtrTy
+Sema::ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc, SourceLocation ColonLoc) {
+ assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
+ AccessSpecDecl* ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
+ ASLoc, ColonLoc);
+ CurContext->addHiddenDecl(ASDecl);
+ return DeclPtrTy::make(ASDecl);
+}
+
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
/// bitfield width if there is one and 'InitExpr' specifies the initializer if
@@ -886,10 +897,18 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Expr *Init = static_cast<Expr*>(InitExpr);
SourceLocation Loc = D.getIdentifierLoc();
- bool isFunc = D.isFunctionDeclarator();
-
+ assert(isa<CXXRecordDecl>(CurContext));
assert(!DS.isFriendSpecified());
+ bool isFunc = false;
+ if (D.isFunctionDeclarator())
+ isFunc = true;
+ else if (D.getNumTypeObjects() == 0 &&
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename) {
+ QualType TDType = GetTypeFromParser(DS.getTypeRep());
+ isFunc = TDType->isFunctionType();
+ }
+
// C++ 9.2p6: A member shall not be declared to have automatic storage
// duration (auto, register) or with the extern storage-class-specifier.
// C++ 7.1.1p8: The mutable specifier can be applied only to names of class
@@ -911,22 +930,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// FIXME: It would be nicer if the keyword was ignored only for this
// declarator. Otherwise we could get follow-up errors.
D.getMutableDeclSpec().ClearStorageClassSpecs();
- } else {
- QualType T = GetTypeForDeclarator(D, S);
- diag::kind err = static_cast<diag::kind>(0);
- if (T->isReferenceType())
- err = diag::err_mutable_reference;
- else if (T.isConstQualified())
- err = diag::err_mutable_const;
- if (err != 0) {
- if (DS.getStorageClassSpecLoc().isValid())
- Diag(DS.getStorageClassSpecLoc(), err);
- else
- Diag(DS.getThreadSpecLoc(), err);
- // FIXME: It would be nicer if the keyword was ignored only for this
- // declarator. Otherwise we could get follow-up errors.
- D.getMutableDeclSpec().ClearStorageClassSpecs();
- }
}
break;
default:
@@ -938,18 +941,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
D.getMutableDeclSpec().ClearStorageClassSpecs();
}
- if (!isFunc &&
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename &&
- D.getNumTypeObjects() == 0) {
- // Check also for this case:
- //
- // typedef int f();
- // f a;
- //
- QualType TDType = GetTypeFromParser(DS.getTypeRep());
- isFunc = TDType->isFunctionType();
- }
-
bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
!isFunc);
@@ -1148,6 +1139,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
return true;
R.clear();
+ R.setLookupName(MemberOrBase);
}
}
@@ -1226,18 +1218,25 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
/// containing the field that is being initialized. Returns true if there is an
/// uninitialized field was used an updates the SourceLocation parameter; false
/// otherwise.
-static bool InitExprContainsUninitializedFields(const Stmt* S,
- const FieldDecl* LhsField,
- SourceLocation* L) {
- const MemberExpr* ME = dyn_cast<MemberExpr>(S);
- if (ME) {
- const NamedDecl* RhsField = ME->getMemberDecl();
+static bool InitExprContainsUninitializedFields(const Stmt *S,
+ const FieldDecl *LhsField,
+ SourceLocation *L) {
+ if (isa<CallExpr>(S)) {
+ // Do not descend into function calls or constructors, as the use
+ // of an uninitialized field may be valid. One would have to inspect
+ // the contents of the function/ctor to determine if it is safe or not.
+ // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
+ // may be safe, depending on what the function/ctor does.
+ return false;
+ }
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
+ const NamedDecl *RhsField = ME->getMemberDecl();
if (RhsField == LhsField) {
// Initializing a field with itself. Throw a warning.
// But wait; there are exceptions!
// Exception #1: The field may not belong to this record.
// e.g. Foo(const Foo& rhs) : A(rhs.A) {}
- const Expr* base = ME->getBase();
+ const Expr *base = ME->getBase();
if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) {
// Even though the field matches, it does not belong to this record.
return false;
@@ -1248,21 +1247,16 @@ static bool InitExprContainsUninitializedFields(const Stmt* S,
return true;
}
}
- bool found = false;
- for (Stmt::const_child_iterator it = S->child_begin();
- it != S->child_end() && found == false;
- ++it) {
- if (isa<CallExpr>(S)) {
- // Do not descend into function calls or constructors, as the use
- // of an uninitialized field may be valid. One would have to inspect
- // the contents of the function/ctor to determine if it is safe or not.
- // i.e. Pass-by-value is never safe, but pass-by-reference and pointers
- // may be safe, depending on what the function/ctor does.
+ for (Stmt::const_child_iterator it = S->child_begin(), e = S->child_end();
+ it != e; ++it) {
+ if (!*it) {
+ // An expression such as 'member(arg ?: "")' may trigger this.
continue;
}
- found = InitExprContainsUninitializedFields(*it, LhsField, L);
+ if (InitExprContainsUninitializedFields(*it, LhsField, L))
+ return true;
}
- return found;
+ return false;
}
Sema::MemInitResult
@@ -1375,8 +1369,48 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent();
- SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
- if (BaseType->isDependentType() || HasDependentArg) {
+ SourceLocation BaseLoc
+ = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
+
+ if (!BaseType->isDependentType() && !BaseType->isRecordType())
+ return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+ << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
+
+ // 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.
+ bool Dependent = BaseType->isDependentType() || HasDependentArg;
+
+ // Check for direct and virtual base classes.
+ const CXXBaseSpecifier *DirectBaseSpec = 0;
+ const CXXBaseSpecifier *VirtualBaseSpec = 0;
+ if (!Dependent) {
+ FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+ VirtualBaseSpec);
+
+ // C++ [base.class.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.
+ if (!DirectBaseSpec && !VirtualBaseSpec) {
+ // If the class has any dependent bases, then it's possible that
+ // one of those types will resolve to the same type as
+ // BaseType. Therefore, just treat this as a dependent base
+ // class initialization. FIXME: Should we try to check the
+ // initialization anyway? It seems odd.
+ if (ClassDecl->hasAnyDependentBases())
+ Dependent = true;
+ else
+ return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+ << BaseType << Context.getTypeDeclType(ClassDecl)
+ << BaseTInfo->getTypeLoc().getLocalSourceRange();
+ }
+ }
+
+ if (Dependent) {
// Can't check initialization for a base of dependent type or when
// any of the arguments are type-dependent expressions.
OwningExprResult BaseInit
@@ -1396,23 +1430,6 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
BaseInit.takeAs<Expr>(),
RParenLoc);
}
-
- if (!BaseType->isRecordType())
- return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
- << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
-
- // 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
@@ -1421,14 +1438,6 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
if (DirectBaseSpec && VirtualBaseSpec)
return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
- // 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 << Context.getTypeDeclType(ClassDecl)
- << BaseTInfo->getTypeLoc().getLocalSourceRange();
CXXBaseSpecifier *BaseSpec
= const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
@@ -1571,8 +1580,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
if (Field->isInvalidDecl())
return true;
+ SourceLocation Loc = Constructor->getLocation();
+
if (ImplicitInitKind == IIK_Copy) {
- SourceLocation Loc = Constructor->getLocation();
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
@@ -1680,7 +1690,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
if (FieldBaseElementType->isRecordType()) {
InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
InitializationKind InitKind =
- InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationKind::CreateDefault(Loc);
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
Sema::OwningExprResult MemberInit =
@@ -1692,10 +1702,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
CXXMemberInit =
new (SemaRef.Context) CXXBaseOrMemberInitializer(SemaRef.Context,
- Field, SourceLocation(),
- SourceLocation(),
+ Field, Loc, Loc,
MemberInit.takeAs<Expr>(),
- SourceLocation());
+ Loc);
return false;
}
@@ -1744,38 +1753,67 @@ struct BaseAndFieldInfo {
};
}
+static void RecordFieldInitializer(BaseAndFieldInfo &Info,
+ FieldDecl *Top, FieldDecl *Field,
+ CXXBaseOrMemberInitializer *Init) {
+ // If the member doesn't need to be initialized, Init will still be null.
+ if (!Init)
+ return;
+
+ Info.AllToInit.push_back(Init);
+ if (Field != Top) {
+ Init->setMember(Top);
+ Init->setAnonUnionMember(Field);
+ }
+}
+
static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
FieldDecl *Top, FieldDecl *Field) {
- // Overwhelmingly common case: we have a direct initializer for this field.
+ // Overwhelmingly common case: we have a direct initializer for this field.
if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(Field)) {
- Info.AllToInit.push_back(Init);
-
- if (Field != Top) {
- Init->setMember(Top);
- Init->setAnonUnionMember(Field);
- }
+ RecordFieldInitializer(Info, Top, Field, Init);
return false;
}
if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) {
const RecordType *FieldClassType = Field->getType()->getAs<RecordType>();
assert(FieldClassType && "anonymous struct/union without record type");
-
- // Walk through the members, tying in any initializers for fields
- // we find. The earlier semantic checks should prevent redundant
- // initialization of union members, given the requirement that
- // union members never have non-trivial default constructors.
-
- // TODO: in C++0x, it might be legal to have union members with
- // non-trivial default constructors in unions. Revise this
- // implementation then with the appropriate semantics.
CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
- for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
- EA = FieldClassDecl->field_end(); FA != EA; FA++)
- if (CollectFieldInitializer(Info, Top, *FA))
- return true;
+
+ // Even though union members never have non-trivial default
+ // constructions in C++03, we still build member initializers for aggregate
+ // record types which can be union members, and C++0x allows non-trivial
+ // default constructors for union members, so we ensure that only one
+ // member is initialized for these.
+ if (FieldClassDecl->isUnion()) {
+ // First check for an explicit initializer for one field.
+ for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+ EA = FieldClassDecl->field_end(); FA != EA; FA++) {
+ if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(*FA)) {
+ RecordFieldInitializer(Info, Top, *FA, Init);
+
+ // Once we've initialized a field of an anonymous union, the union
+ // field in the class is also initialized, so exit immediately.
+ return false;
+ }
+ }
+
+ // Fallthrough and construct a default initializer for the union as
+ // a whole, which can call its default constructor if such a thing exists
+ // (C++0x perhaps). FIXME: It's not clear that this is the correct
+ // behavior going forward with C++0x, when anonymous unions there are
+ // finalized, we should revisit this.
+ } else {
+ // For structs, we simply descend through to initialize all members where
+ // necessary.
+ for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
+ EA = FieldClassDecl->field_end(); FA != EA; FA++) {
+ if (CollectFieldInitializer(Info, Top, *FA))
+ return true;
+ }
+ }
}
// Don't try to build an implicit initializer if there were semantic
@@ -1787,15 +1825,8 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
CXXBaseOrMemberInitializer *Init = 0;
if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init))
return true;
-
- // If the member doesn't need to be initialized, Init will still be null.
- if (!Init) return false;
- Info.AllToInit.push_back(Init);
- if (Top != Field) {
- Init->setMember(Top);
- Init->setAnonUnionMember(Field);
- }
+ RecordFieldInitializer(Info, Top, Field, Init);
return false;
}
@@ -2199,7 +2230,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
if (FieldClassDecl->hasTrivialDestructor())
continue;
- CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context);
+ CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
CheckDestructorAccess(Field->getLocation(), Dtor,
PDiag(diag::err_access_dtor_field)
<< Field->getDeclName()
@@ -2225,7 +2256,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
if (BaseClassDecl->hasTrivialDestructor())
continue;
- CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+ CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
// FIXME: caret should be on the start of the class name
CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor,
@@ -2252,7 +2283,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
if (BaseClassDecl->hasTrivialDestructor())
continue;
- CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context);
+ CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
CheckDestructorAccess(ClassDecl->getLocation(), Dtor,
PDiag(diag::err_access_dtor_vbase)
<< VBase->getType());
@@ -2326,6 +2357,10 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
+ // Keep a set of seen pure methods so we won't diagnose the same method
+ // more than once.
+ llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods;
+
for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
MEnd = FinalOverriders.end();
M != MEnd;
@@ -2345,6 +2380,9 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
if (!SO->second.front().Method->isPure())
continue;
+ if (!SeenPureMethods.insert(SO->second.front().Method))
+ continue;
+
Diag(SO->second.front().Method->getLocation(),
diag::note_pure_virtual_function)
<< SO->second.front().Method->getDeclName();
@@ -2422,12 +2460,12 @@ namespace {
/// \brief Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
-void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
+void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!Record || Record->isInvalidDecl())
return;
if (!Record->isDependentType())
- AddImplicitlyDeclaredMembersToClass(S, Record);
+ AddImplicitlyDeclaredMembersToClass(Record);
if (Record->isInvalidDecl())
return;
@@ -2546,268 +2584,101 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
(DeclPtrTy*)FieldCollector->getCurFields(),
FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList);
- CheckCompletedCXXClass(S,
- dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>()));
+ CheckCompletedCXXClass(
+ dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>()));
+}
+
+namespace {
+ /// \brief Helper class that collects exception specifications for
+ /// implicitly-declared special member functions.
+ class ImplicitExceptionSpecification {
+ ASTContext &Context;
+ bool AllowsAllExceptions;
+ llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
+ llvm::SmallVector<QualType, 4> Exceptions;
+
+ public:
+ explicit ImplicitExceptionSpecification(ASTContext &Context)
+ : Context(Context), AllowsAllExceptions(false) { }
+
+ /// \brief Whether the special member function should have any
+ /// exception specification at all.
+ bool hasExceptionSpecification() const {
+ return !AllowsAllExceptions;
+ }
+
+ /// \brief Whether the special member function should have a
+ /// throw(...) exception specification (a Microsoft extension).
+ bool hasAnyExceptionSpecification() const {
+ return false;
+ }
+
+ /// \brief The number of exceptions in the exception specification.
+ unsigned size() const { return Exceptions.size(); }
+
+ /// \brief The set of exceptions in the exception specification.
+ const QualType *data() const { return Exceptions.data(); }
+
+ /// \brief Note that
+ void CalledDecl(CXXMethodDecl *Method) {
+ // If we already know that we allow all exceptions, do nothing.
+ if (AllowsAllExceptions || !Method)
+ return;
+
+ const FunctionProtoType *Proto
+ = Method->getType()->getAs<FunctionProtoType>();
+
+ // If this function can throw any exceptions, make a note of that.
+ if (!Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec()) {
+ AllowsAllExceptions = true;
+ ExceptionsSeen.clear();
+ Exceptions.clear();
+ return;
+ }
+
+ // Record the exceptions in this function's exception specification.
+ for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+ EEnd = Proto->exception_end();
+ E != EEnd; ++E)
+ if (ExceptionsSeen.insert(Context.getCanonicalType(*E)))
+ Exceptions.push_back(*E);
+ }
+ };
}
+
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
/// special functions, such as the default constructor, copy
/// constructor, or destructor, to the given C++ class (C++
/// [special]p1). This routine can only be executed just before the
/// definition of the class is complete.
-///
-/// The scope, if provided, is the class scope.
-void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
- CXXRecordDecl *ClassDecl) {
- CanQualType ClassType
- = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
-
- // FIXME: Implicit declarations have exception specifications, which are
- // the union of the specifications of the implicitly called functions.
-
- if (!ClassDecl->hasUserDeclaredConstructor()) {
- // C++ [class.ctor]p5:
- // A default constructor for a class X is a constructor of class X
- // that can be called without an argument. If there is no
- // user-declared constructor for class X, a default constructor is
- // implicitly declared. An implicitly-declared default constructor
- // is an inline public member of its class.
- DeclarationName Name
- = Context.DeclarationNames.getCXXConstructorName(ClassType);
- CXXConstructorDecl *DefaultCon =
- CXXConstructorDecl::Create(Context, ClassDecl,
- ClassDecl->getLocation(), Name,
- Context.getFunctionType(Context.VoidTy,
- 0, 0, false, 0,
- /*FIXME*/false, false,
- 0, 0,
- FunctionType::ExtInfo()),
- /*TInfo=*/0,
- /*isExplicit=*/false,
- /*isInline=*/true,
- /*isImplicitlyDeclared=*/true);
- DefaultCon->setAccess(AS_public);
- DefaultCon->setImplicit();
- DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
- if (S)
- PushOnScopeChains(DefaultCon, S, true);
- else
- ClassDecl->addDecl(DefaultCon);
- }
+void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
+ if (!ClassDecl->hasUserDeclaredConstructor())
+ ++ASTContext::NumImplicitDefaultConstructors;
- if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
- // C++ [class.copy]p4:
- // If the class definition does not explicitly declare a copy
- // constructor, one is declared implicitly.
-
- // C++ [class.copy]p5:
- // The implicitly-declared copy constructor for a class X will
- // have the form
- //
- // X::X(const X&)
- //
- // if
- bool HasConstCopyConstructor = true;
-
- // -- each direct or virtual base class B of X has a copy
- // constructor whose first parameter is of type const B& or
- // const volatile B&, and
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
- HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) {
- const CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- HasConstCopyConstructor
- = BaseClassDecl->hasConstCopyConstructor(Context);
- }
-
- // -- for all the nonstatic data members of X that are of a
- // class type M (or array thereof), each such class type
- // has a copy constructor whose first parameter is of type
- // const M& or const volatile M&.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
- HasConstCopyConstructor && Field != ClassDecl->field_end();
- ++Field) {
- QualType FieldType = (*Field)->getType();
- if (const ArrayType *Array = Context.getAsArrayType(FieldType))
- FieldType = Array->getElementType();
- if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- const CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- HasConstCopyConstructor
- = FieldClassDecl->hasConstCopyConstructor(Context);
- }
- }
-
- // Otherwise, the implicitly declared copy constructor will have
- // the form
- //
- // X::X(X&)
- QualType ArgType = ClassType;
- if (HasConstCopyConstructor)
- ArgType = ArgType.withConst();
- ArgType = Context.getLValueReferenceType(ArgType);
-
- // An implicitly-declared copy constructor is an inline public
- // member of its class.
- DeclarationName Name
- = Context.DeclarationNames.getCXXConstructorName(ClassType);
- CXXConstructorDecl *CopyConstructor
- = CXXConstructorDecl::Create(Context, ClassDecl,
- ClassDecl->getLocation(), Name,
- Context.getFunctionType(Context.VoidTy,
- &ArgType, 1,
- false, 0,
- /*FIXME: hasExceptionSpec*/false,
- false, 0, 0,
- FunctionType::ExtInfo()),
- /*TInfo=*/0,
- /*isExplicit=*/false,
- /*isInline=*/true,
- /*isImplicitlyDeclared=*/true);
- CopyConstructor->setAccess(AS_public);
- CopyConstructor->setImplicit();
- CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
-
- // Add the parameter to the constructor.
- ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
- ClassDecl->getLocation(),
- /*IdentifierInfo=*/0,
- ArgType, /*TInfo=*/0,
- VarDecl::None,
- VarDecl::None, 0);
- CopyConstructor->setParams(&FromParam, 1);
- if (S)
- PushOnScopeChains(CopyConstructor, S, true);
- else
- ClassDecl->addDecl(CopyConstructor);
- }
+ if (!ClassDecl->hasUserDeclaredCopyConstructor())
+ ++ASTContext::NumImplicitCopyConstructors;
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
- // Note: The following rules are largely analoguous to the copy
- // constructor rules. Note that virtual bases are not taken into account
- // for determining the argument type of the operator. Note also that
- // operators taking an object instead of a reference are allowed.
- //
- // C++ [class.copy]p10:
- // If the class definition does not explicitly declare a copy
- // assignment operator, one is declared implicitly.
- // The implicitly-defined copy assignment operator for a class X
- // will have the form
- //
- // X& X::operator=(const X&)
- //
- // if
- bool HasConstCopyAssignment = true;
-
- // -- each direct base class B of X has a copy assignment operator
- // whose parameter is of type const B&, const volatile B& or B,
- // and
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
- HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
- assert(!Base->getType()->isDependentType() &&
- "Cannot generate implicit members for class with dependent bases.");
- const CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- const CXXMethodDecl *MD = 0;
- HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context,
- MD);
- }
-
- // -- for all the nonstatic data members of X that are of a class
- // type M (or array thereof), each such class type has a copy
- // assignment operator whose parameter is of type const M&,
- // const volatile M& or M.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
- HasConstCopyAssignment && Field != ClassDecl->field_end();
- ++Field) {
- QualType FieldType = (*Field)->getType();
- if (const ArrayType *Array = Context.getAsArrayType(FieldType))
- FieldType = Array->getElementType();
- if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- const CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- const CXXMethodDecl *MD = 0;
- HasConstCopyAssignment
- = FieldClassDecl->hasConstCopyAssignment(Context, MD);
- }
- }
-
- // Otherwise, the implicitly declared copy assignment operator will
- // have the form
- //
- // X& X::operator=(X&)
- QualType ArgType = ClassType;
- QualType RetType = Context.getLValueReferenceType(ArgType);
- if (HasConstCopyAssignment)
- ArgType = ArgType.withConst();
- ArgType = Context.getLValueReferenceType(ArgType);
-
- // An implicitly-declared copy assignment operator is an inline public
- // member of its class.
- DeclarationName Name =
- Context.DeclarationNames.getCXXOperatorName(OO_Equal);
- CXXMethodDecl *CopyAssignment =
- CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
- Context.getFunctionType(RetType, &ArgType, 1,
- false, 0,
- /*FIXME: hasExceptionSpec*/false,
- false, 0, 0,
- FunctionType::ExtInfo()),
- /*TInfo=*/0, /*isStatic=*/false,
- /*StorageClassAsWritten=*/FunctionDecl::None,
- /*isInline=*/true);
- CopyAssignment->setAccess(AS_public);
- CopyAssignment->setImplicit();
- CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
- CopyAssignment->setCopyAssignment(true);
-
- // Add the parameter to the operator.
- ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
- ClassDecl->getLocation(),
- /*Id=*/0,
- ArgType, /*TInfo=*/0,
- VarDecl::None,
- VarDecl::None, 0);
- CopyAssignment->setParams(&FromParam, 1);
-
- // Don't call addedAssignmentOperator. There is no way to distinguish an
- // implicit from an explicit assignment operator.
- if (S)
- PushOnScopeChains(CopyAssignment, S, true);
- else
- ClassDecl->addDecl(CopyAssignment);
- AddOverriddenMethods(ClassDecl, CopyAssignment);
+ ++ASTContext::NumImplicitCopyAssignmentOperators;
+
+ // If we have a dynamic class, then the copy assignment operator may be
+ // virtual, so we have to declare it immediately. This ensures that, e.g.,
+ // it shows up in the right place in the vtable and that we diagnose
+ // problems with the implicit exception specification.
+ if (ClassDecl->isDynamicClass())
+ DeclareImplicitCopyAssignment(ClassDecl);
}
if (!ClassDecl->hasUserDeclaredDestructor()) {
- // C++ [class.dtor]p2:
- // If a class has no user-declared destructor, a destructor is
- // declared implicitly. An implicitly-declared destructor is an
- // inline public member of its class.
- QualType Ty = Context.getFunctionType(Context.VoidTy,
- 0, 0, false, 0,
- /*FIXME: hasExceptionSpec*/false,
- false, 0, 0, FunctionType::ExtInfo());
-
- DeclarationName Name
- = Context.DeclarationNames.getCXXDestructorName(ClassType);
- CXXDestructorDecl *Destructor
- = CXXDestructorDecl::Create(Context, ClassDecl,
- ClassDecl->getLocation(), Name, Ty,
- /*isInline=*/true,
- /*isImplicitlyDeclared=*/true);
- Destructor->setAccess(AS_public);
- Destructor->setImplicit();
- Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
- if (S)
- PushOnScopeChains(Destructor, S, true);
- else
- ClassDecl->addDecl(Destructor);
-
- // This could be uniqued if it ever proves significant.
- Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
+ ++ASTContext::NumImplicitDestructors;
- AddOverriddenMethods(ClassDecl, Destructor);
+ // If we have a dynamic class, then the destructor may be virtual, so we
+ // have to declare the destructor immediately. This ensures that, e.g., it
+ // shows up in the right place in the vtable and that we diagnose problems
+ // with the implicit exception specification.
+ if (ClassDecl->isDynamicClass())
+ DeclareImplicitDestructor(ClassDecl);
}
}
@@ -2952,9 +2823,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
// Rebuild the function type "R" without any type qualifiers (in
// case any of the errors above fired) and with "void" as the
- // return type, since constructors don't have return types. We
- // *always* have to do this, because GetTypeForDeclarator will
- // put in a result type of "int" when none was specified.
+ // return type, since constructors don't have return types.
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
Proto->getNumArgs(),
@@ -2990,8 +2859,11 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
QualType ClassTy = Context.getTagDeclType(ClassDecl);
if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
+ const char *ConstRef
+ = Constructor->getParamDecl(0)->getIdentifier() ? "const &"
+ : " const &";
Diag(ParamLoc, diag::err_constructor_byvalue_arg)
- << FixItHint::CreateInsertion(ParamLoc, " const &");
+ << FixItHint::CreateInsertion(ParamLoc, ConstRef);
// FIXME: Rather that making the constructor invalid, we should endeavor
// to fix the type.
@@ -3026,6 +2898,8 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
return true;
+
+ MarkDeclarationReferenced(Loc, OperatorDelete);
Destructor->setOperatorDelete(OperatorDelete);
}
@@ -3046,7 +2920,7 @@ FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
/// emit diagnostics and set the declarator to invalid. Even if this happens,
/// will be updated to reflect a well-formed type for the destructor and
/// returned.
-QualType Sema::CheckDestructorDeclarator(Declarator &D,
+QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
FunctionDecl::StorageClass& SC) {
// C++ [class.dtor]p1:
// [...] A typedef-name that names a class is a class-name
@@ -3054,11 +2928,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D,
// be used as the identifier in the declarator for a destructor
// declaration.
QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
- if (isa<TypedefType>(DeclaratorType)) {
+ if (isa<TypedefType>(DeclaratorType))
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
<< DeclaratorType;
- D.setInvalidType();
- }
// C++ [class.dtor]p2:
// A destructor is used to destroy objects of its class type. A
@@ -3072,9 +2944,10 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D,
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
- << SourceRange(D.getIdentifierLoc());
+ << SourceRange(D.getIdentifierLoc())
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
+
SC = FunctionDecl::None;
- D.setInvalidType();
}
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
// Destructors don't have return types, but the parser will
@@ -3122,11 +2995,17 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D,
// Rebuild the function type "R" without any type qualifiers or
// parameters (in case any of the errors above fired) and with
// "void" as the return type, since destructors don't have return
- // types. We *always* have to do this, because GetTypeForDeclarator
- // will put in a result type of "int" when none was specified.
- // FIXME: Exceptions!
+ // types.
+ const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
+ if (!Proto)
+ return QualType();
+
return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0,
- false, false, 0, 0, FunctionType::ExtInfo());
+ Proto->hasExceptionSpec(),
+ Proto->hasAnyExceptionSpec(),
+ Proto->getNumExceptions(),
+ Proto->exception_begin(),
+ Proto->getExtInfo());
}
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
@@ -3434,6 +3313,21 @@ void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) {
PopDeclContext();
}
+/// \brief Retrieve the special "std" namespace, which may require us to
+/// implicitly define the namespace.
+NamespaceDecl *Sema::getStdNamespace() {
+ if (!StdNamespace) {
+ // The "std" namespace has not yet been defined, so build one implicitly.
+ StdNamespace = NamespaceDecl::Create(Context,
+ Context.getTranslationUnitDecl(),
+ SourceLocation(),
+ &PP.getIdentifierTable().get("std"));
+ StdNamespace->setImplicit(true);
+ }
+
+ return StdNamespace;
+}
+
Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
SourceLocation UsingLoc,
SourceLocation NamespcLoc,
@@ -3447,13 +3341,49 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
UsingDirectiveDecl *UDir = 0;
-
+ NestedNameSpecifier *Qualifier = 0;
+ if (SS.isSet())
+ Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
if (R.isAmbiguous())
return DeclPtrTy();
+ if (R.empty()) {
+ // Allow "using namespace std;" or "using namespace ::std;" even if
+ // "std" hasn't been defined yet, for GCC compatibility.
+ if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
+ NamespcName->isStr("std")) {
+ Diag(IdentLoc, diag::ext_using_undefined_std);
+ R.addDecl(getStdNamespace());
+ R.resolveKind();
+ }
+ // Otherwise, attempt typo correction.
+ else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
+ CTC_NoKeywords, 0)) {
+ if (R.getAsSingle<NamespaceDecl>() ||
+ R.getAsSingle<NamespaceAliasDecl>()) {
+ if (DeclContext *DC = computeDeclContext(SS, false))
+ Diag(IdentLoc, diag::err_using_directive_member_suggest)
+ << NamespcName << DC << Corrected << SS.getRange()
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+ else
+ Diag(IdentLoc, diag::err_using_directive_suggest)
+ << NamespcName << Corrected
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+ Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)
+ << Corrected;
+
+ NamespcName = Corrected.getAsIdentifierInfo();
+ } else {
+ R.clear();
+ R.setLookupName(NamespcName);
+ }
+ }
+ }
+
if (!R.empty()) {
NamedDecl *Named = R.getFoundDecl();
assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
@@ -3566,6 +3496,28 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
return DeclPtrTy::make(UD);
}
+/// \brief Determine whether a using declaration considers the given
+/// declarations as "equivalent", e.g., if they are redeclarations of
+/// the same entity or are both typedefs of the same type.
+static bool
+IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
+ bool &SuppressRedeclaration) {
+ if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
+ SuppressRedeclaration = false;
+ return true;
+ }
+
+ if (TypedefDecl *TD1 = dyn_cast<TypedefDecl>(D1))
+ if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) {
+ SuppressRedeclaration = true;
+ return Context.hasSameType(TD1->getUnderlyingType(),
+ TD2->getUnderlyingType());
+ }
+
+ return false;
+}
+
+
/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
@@ -3632,8 +3584,9 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
- if (D->getCanonicalDecl() == Target->getCanonicalDecl())
- return false;
+ bool Result;
+ if (IsEquivalentForUsingDecl(Context, D, Target, Result))
+ return Result;
(isa<TagDecl>(D) ? Tag : NonTag) = D;
}
@@ -3646,7 +3599,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
FD = cast<FunctionDecl>(Target);
NamedDecl *OldDecl = 0;
- switch (CheckOverload(FD, Previous, OldDecl)) {
+ switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
case Ovl_Overload:
return false;
@@ -3656,11 +3609,6 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// We found a decl with the exact signature.
case Ovl_Match:
- if (isa<UsingShadowDecl>(OldDecl)) {
- // Silently ignore the possible conflict.
- return false;
- }
-
// If we're in a record, we want to hide the target, so we
// return true (without a diagnostic) to tell the caller not to
// build a shadow decl.
@@ -4162,8 +4110,33 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
return DeclPtrTy();
if (R.empty()) {
- Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
- return DeclPtrTy();
+ if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
+ CTC_NoKeywords, 0)) {
+ if (R.getAsSingle<NamespaceDecl>() ||
+ R.getAsSingle<NamespaceAliasDecl>()) {
+ if (DeclContext *DC = computeDeclContext(SS, false))
+ Diag(IdentLoc, diag::err_using_directive_member_suggest)
+ << Ident << DC << Corrected << SS.getRange()
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+ else
+ Diag(IdentLoc, diag::err_using_directive_suggest)
+ << Ident << Corrected
+ << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());
+
+ Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)
+ << Corrected;
+
+ Ident = Corrected.getAsIdentifierInfo();
+ } else {
+ R.clear();
+ R.setLookupName(Ident);
+ }
+ }
+
+ if (R.empty()) {
+ Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
+ return DeclPtrTy();
+ }
}
NamespaceAliasDecl *AliasDecl =
@@ -4200,10 +4173,108 @@ namespace {
};
}
+CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
+ CXXRecordDecl *ClassDecl) {
+ // C++ [class.ctor]p5:
+ // A default constructor for a class X is a constructor of class X
+ // that can be called without an argument. If there is no
+ // user-declared constructor for class X, a default constructor is
+ // implicitly declared. An implicitly-declared default constructor
+ // is an inline public member of its class.
+ assert(!ClassDecl->hasUserDeclaredConstructor() &&
+ "Should not build implicit default constructor!");
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have an
+ // exception-specification. [...]
+ ImplicitExceptionSpecification ExceptSpec(Context);
+
+ // Direct base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+ BEnd = ClassDecl->bases_end();
+ B != BEnd; ++B) {
+ if (B->isVirtual()) // Handled below.
+ continue;
+
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = BaseClassDecl->getDefaultConstructor())
+ ExceptSpec.CalledDecl(Constructor);
+ }
+ }
+
+ // Virtual base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+ BEnd = ClassDecl->vbases_end();
+ B != BEnd; ++B) {
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+ if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = BaseClassDecl->getDefaultConstructor())
+ ExceptSpec.CalledDecl(Constructor);
+ }
+ }
+
+ // Field destructors.
+ for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+ FEnd = ClassDecl->field_end();
+ F != FEnd; ++F) {
+ if (const RecordType *RecordTy
+ = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!FieldClassDecl->hasDeclaredDefaultConstructor())
+ ExceptSpec.CalledDecl(
+ DeclareImplicitDefaultConstructor(FieldClassDecl));
+ else if (CXXConstructorDecl *Constructor
+ = FieldClassDecl->getDefaultConstructor())
+ ExceptSpec.CalledDecl(Constructor);
+ }
+ }
+
+
+ // Create the actual constructor declaration.
+ CanQualType ClassType
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXConstructorName(ClassType);
+ CXXConstructorDecl *DefaultCon
+ = CXXConstructorDecl::Create(Context, ClassDecl,
+ ClassDecl->getLocation(), Name,
+ Context.getFunctionType(Context.VoidTy,
+ 0, 0, false, 0,
+ ExceptSpec.hasExceptionSpecification(),
+ ExceptSpec.hasAnyExceptionSpecification(),
+ ExceptSpec.size(),
+ ExceptSpec.data(),
+ FunctionType::ExtInfo()),
+ /*TInfo=*/0,
+ /*isExplicit=*/false,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
+ DefaultCon->setAccess(AS_public);
+ DefaultCon->setImplicit();
+ DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+
+ // Note that we have declared this constructor.
+ ClassDecl->setDeclaredDefaultConstructor(true);
+ ++ASTContext::NumImplicitDefaultConstructorsDeclared;
+
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(DefaultCon, S, false);
+ ClassDecl->addDecl(DefaultCon);
+
+ return DefaultCon;
+}
+
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
- !Constructor->isUsed()) &&
+ !Constructor->isUsed(false)) &&
"DefineImplicitDefaultConstructor - call it for implicit default ctor");
CXXRecordDecl *ClassDecl = Constructor->getParent();
@@ -4222,9 +4293,90 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
}
}
+CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
+ // C++ [class.dtor]p2:
+ // If a class has no user-declared destructor, a destructor is
+ // declared implicitly. An implicitly-declared destructor is an
+ // inline public member of its class.
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have
+ // an exception-specification.
+ ImplicitExceptionSpecification ExceptSpec(Context);
+
+ // Direct base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(),
+ BEnd = ClassDecl->bases_end();
+ B != BEnd; ++B) {
+ if (B->isVirtual()) // Handled below.
+ continue;
+
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(
+ LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+ }
+
+ // Virtual base-class destructors.
+ for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
+ BEnd = ClassDecl->vbases_end();
+ B != BEnd; ++B) {
+ if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
+ ExceptSpec.CalledDecl(
+ LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
+ }
+
+ // Field destructors.
+ for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
+ FEnd = ClassDecl->field_end();
+ F != FEnd; ++F) {
+ if (const RecordType *RecordTy
+ = Context.getBaseElementType(F->getType())->getAs<RecordType>())
+ ExceptSpec.CalledDecl(
+ LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
+ }
+
+ // Create the actual destructor declaration.
+ QualType Ty = Context.getFunctionType(Context.VoidTy,
+ 0, 0, false, 0,
+ ExceptSpec.hasExceptionSpecification(),
+ ExceptSpec.hasAnyExceptionSpecification(),
+ ExceptSpec.size(),
+ ExceptSpec.data(),
+ FunctionType::ExtInfo());
+
+ CanQualType ClassType
+ = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXDestructorName(ClassType);
+ CXXDestructorDecl *Destructor
+ = CXXDestructorDecl::Create(Context, ClassDecl,
+ ClassDecl->getLocation(), Name, Ty,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
+ Destructor->setAccess(AS_public);
+ Destructor->setImplicit();
+ Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
+
+ // Note that we have declared this destructor.
+ ClassDecl->setDeclaredDestructor(true);
+ ++ASTContext::NumImplicitDestructorsDeclared;
+
+ // Introduce this destructor into its scope.
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(Destructor, S, false);
+ ClassDecl->addDecl(Destructor);
+
+ // This could be uniqued if it ever proves significant.
+ Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
+
+ AddOverriddenMethods(ClassDecl, Destructor);
+
+ return Destructor;
+}
+
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
CXXDestructorDecl *Destructor) {
- assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
+ assert((Destructor->isImplicit() && !Destructor->isUsed(false)) &&
"DefineImplicitDestructor - call it for implicit default dtor");
CXXRecordDecl *ClassDecl = Destructor->getParent();
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
@@ -4448,12 +4600,197 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
Loc, move(Copy));
}
+/// \brief Determine whether the given class has a copy assignment operator
+/// that accepts a const-qualified argument.
+static bool hasConstCopyAssignment(Sema &S, const CXXRecordDecl *CClass) {
+ CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(CClass);
+
+ if (!Class->hasDeclaredCopyAssignment())
+ S.DeclareImplicitCopyAssignment(Class);
+
+ QualType ClassType = S.Context.getCanonicalType(S.Context.getTypeDeclType(Class));
+ DeclarationName OpName
+ = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = Class->lookup(OpName); Op != OpEnd; ++Op) {
+ // C++ [class.copy]p9:
+ // A user-declared copy assignment operator is a non-static non-template
+ // member function of class X with exactly one parameter of type X, X&,
+ // const X&, volatile X& or const volatile X&.
+ const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);
+ if (!Method)
+ continue;
+
+ if (Method->isStatic())
+ continue;
+ if (Method->getPrimaryTemplate())
+ continue;
+ const FunctionProtoType *FnType =
+ Method->getType()->getAs<FunctionProtoType>();
+ assert(FnType && "Overloaded operator has no prototype.");
+ // Don't assert on this; an invalid decl might have been left in the AST.
+ if (FnType->getNumArgs() != 1 || FnType->isVariadic())
+ continue;
+ bool AcceptsConst = true;
+ QualType ArgType = FnType->getArgType(0);
+ if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()){
+ ArgType = Ref->getPointeeType();
+ // Is it a non-const lvalue reference?
+ if (!ArgType.isConstQualified())
+ AcceptsConst = false;
+ }
+ if (!S.Context.hasSameUnqualifiedType(ArgType, ClassType))
+ continue;
+
+ // We have a single argument of type cv X or cv X&, i.e. we've found the
+ // copy assignment operator. Return whether it accepts const arguments.
+ return AcceptsConst;
+ }
+ assert(Class->isInvalidDecl() &&
+ "No copy assignment operator declared in valid code.");
+ return false;
+}
+
+CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
+ // Note: The following rules are largely analoguous to the copy
+ // constructor rules. Note that virtual bases are not taken into account
+ // for determining the argument type of the operator. Note also that
+ // operators taking an object instead of a reference are allowed.
+
+
+ // C++ [class.copy]p10:
+ // If the class definition does not explicitly declare a copy
+ // assignment operator, one is declared implicitly.
+ // The implicitly-defined copy assignment operator for a class X
+ // will have the form
+ //
+ // X& X::operator=(const X&)
+ //
+ // if
+ bool HasConstCopyAssignment = true;
+
+ // -- each direct base class B of X has a copy assignment operator
+ // whose parameter is of type const B&, const volatile B& or B,
+ // and
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ HasConstCopyAssignment && Base != BaseEnd; ++Base) {
+ assert(!Base->getType()->isDependentType() &&
+ "Cannot generate implicit members for class with dependent bases.");
+ const CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ HasConstCopyAssignment = hasConstCopyAssignment(*this, BaseClassDecl);
+ }
+
+ // -- for all the nonstatic data members of X that are of a class
+ // type M (or array thereof), each such class type has a copy
+ // assignment operator whose parameter is of type const M&,
+ // const volatile M& or M.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ HasConstCopyAssignment && Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ const CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ HasConstCopyAssignment = hasConstCopyAssignment(*this, FieldClassDecl);
+ }
+ }
+
+ // Otherwise, the implicitly declared copy assignment operator will
+ // have the form
+ //
+ // X& X::operator=(X&)
+ QualType ArgType = Context.getTypeDeclType(ClassDecl);
+ QualType RetType = Context.getLValueReferenceType(ArgType);
+ if (HasConstCopyAssignment)
+ ArgType = ArgType.withConst();
+ ArgType = Context.getLValueReferenceType(ArgType);
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have an
+ // exception-specification. [...]
+ ImplicitExceptionSpecification ExceptSpec(Context);
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ Base != BaseEnd; ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (!BaseClassDecl->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(BaseClassDecl);
+
+ if (CXXMethodDecl *CopyAssign
+ = BaseClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment))
+ ExceptSpec.CalledDecl(CopyAssign);
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+
+ if (!FieldClassDecl->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(FieldClassDecl);
+
+ if (CXXMethodDecl *CopyAssign
+ = FieldClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment))
+ ExceptSpec.CalledDecl(CopyAssign);
+ }
+ }
+
+ // An implicitly-declared copy assignment operator is an inline public
+ // member of its class.
+ DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+ CXXMethodDecl *CopyAssignment
+ = CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
+ Context.getFunctionType(RetType, &ArgType, 1,
+ false, 0,
+ ExceptSpec.hasExceptionSpecification(),
+ ExceptSpec.hasAnyExceptionSpecification(),
+ ExceptSpec.size(),
+ ExceptSpec.data(),
+ FunctionType::ExtInfo()),
+ /*TInfo=*/0, /*isStatic=*/false,
+ /*StorageClassAsWritten=*/FunctionDecl::None,
+ /*isInline=*/true);
+ CopyAssignment->setAccess(AS_public);
+ CopyAssignment->setImplicit();
+ CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
+ CopyAssignment->setCopyAssignment(true);
+
+ // Add the parameter to the operator.
+ ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
+ ClassDecl->getLocation(),
+ /*Id=*/0,
+ ArgType, /*TInfo=*/0,
+ VarDecl::None,
+ VarDecl::None, 0);
+ CopyAssignment->setParams(&FromParam, 1);
+
+ // Note that we have added this copy-assignment operator.
+ ClassDecl->setDeclaredCopyAssignment(true);
+ ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
+
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(CopyAssignment, S, false);
+ ClassDecl->addDecl(CopyAssignment);
+
+ AddOverriddenMethods(ClassDecl, CopyAssignment);
+ return CopyAssignment;
+}
+
void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *CopyAssignOperator) {
assert((CopyAssignOperator->isImplicit() &&
CopyAssignOperator->isOverloadedOperator() &&
CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
- !CopyAssignOperator->isUsed()) &&
+ !CopyAssignOperator->isUsed(false)) &&
"DefineImplicitCopyAssignment called for wrong function");
CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
@@ -4554,6 +4891,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// \brief Reference to the __builtin_memcpy function.
Expr *BuiltinMemCpyRef = 0;
+ // \brief Reference to the __builtin_objc_memmove_collectable function.
+ Expr *CollectableMemCpyRef = 0;
// Assign non-static members.
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -4630,9 +4969,35 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Take the address of the field references for "from" and "to".
From = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(From));
To = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(To));
-
+
+ bool NeedsCollectableMemCpy =
+ (BaseType->isRecordType() &&
+ BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
+
+ if (NeedsCollectableMemCpy) {
+ if (!CollectableMemCpyRef) {
+ // Create a reference to the __builtin_objc_memmove_collectable function.
+ LookupResult R(*this,
+ &Context.Idents.get("__builtin_objc_memmove_collectable"),
+ Loc, LookupOrdinaryName);
+ LookupName(R, TUScope, true);
+
+ FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
+ if (!CollectableMemCpy) {
+ // Something went horribly wrong earlier, and we will have
+ // complained about it.
+ Invalid = true;
+ continue;
+ }
+
+ CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
+ CollectableMemCpy->getType(),
+ Loc, 0).takeAs<Expr>();
+ assert(CollectableMemCpyRef && "Builtin reference cannot fail");
+ }
+ }
// Create a reference to the __builtin_memcpy builtin function.
- if (!BuiltinMemCpyRef) {
+ else if (!BuiltinMemCpyRef) {
LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
LookupOrdinaryName);
LookupName(R, TUScope, true);
@@ -4658,10 +5023,18 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
llvm::SmallVector<SourceLocation, 4> Commas; // FIXME: Silly
Commas.push_back(Loc);
Commas.push_back(Loc);
- OwningExprResult Call = ActOnCallExpr(/*Scope=*/0,
- Owned(BuiltinMemCpyRef->Retain()),
- Loc, move_arg(CallArgs),
- Commas.data(), Loc);
+ OwningExprResult Call = ExprError();
+ if (NeedsCollectableMemCpy)
+ Call = ActOnCallExpr(/*Scope=*/0,
+ Owned(CollectableMemCpyRef->Retain()),
+ Loc, move_arg(CallArgs),
+ Commas.data(), Loc);
+ else
+ Call = ActOnCallExpr(/*Scope=*/0,
+ Owned(BuiltinMemCpyRef->Retain()),
+ Loc, move_arg(CallArgs),
+ Commas.data(), Loc);
+
assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
Statements.push_back(Call.takeAs<Expr>());
continue;
@@ -4712,12 +5085,185 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CopyAssignOperator->setBody(Body.takeAs<Stmt>());
}
+CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
+ CXXRecordDecl *ClassDecl) {
+ // C++ [class.copy]p4:
+ // If the class definition does not explicitly declare a copy
+ // constructor, one is declared implicitly.
+
+ // C++ [class.copy]p5:
+ // The implicitly-declared copy constructor for a class X will
+ // have the form
+ //
+ // X::X(const X&)
+ //
+ // if
+ bool HasConstCopyConstructor = true;
+
+ // -- each direct or virtual base class B of X has a copy
+ // constructor whose first parameter is of type const B& or
+ // const volatile B&, and
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ HasConstCopyConstructor && Base != BaseEnd;
+ ++Base) {
+ // Virtual bases are handled below.
+ if (Base->isVirtual())
+ continue;
+
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ HasConstCopyConstructor
+ = BaseClassDecl->hasConstCopyConstructor(Context);
+ }
+
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+ BaseEnd = ClassDecl->vbases_end();
+ HasConstCopyConstructor && Base != BaseEnd;
+ ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ HasConstCopyConstructor
+ = BaseClassDecl->hasConstCopyConstructor(Context);
+ }
+
+ // -- for all the nonstatic data members of X that are of a
+ // class type M (or array thereof), each such class type
+ // has a copy constructor whose first parameter is of type
+ // const M& or const volatile M&.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ HasConstCopyConstructor && Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(FieldClassDecl);
+
+ HasConstCopyConstructor
+ = FieldClassDecl->hasConstCopyConstructor(Context);
+ }
+ }
+
+ // Otherwise, the implicitly declared copy constructor will have
+ // the form
+ //
+ // X::X(X&)
+ QualType ClassType = Context.getTypeDeclType(ClassDecl);
+ QualType ArgType = ClassType;
+ if (HasConstCopyConstructor)
+ ArgType = ArgType.withConst();
+ ArgType = Context.getLValueReferenceType(ArgType);
+
+ // C++ [except.spec]p14:
+ // An implicitly declared special member function (Clause 12) shall have an
+ // exception-specification. [...]
+ ImplicitExceptionSpecification ExceptSpec(Context);
+ unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ Base != BaseEnd;
+ ++Base) {
+ // Virtual bases are handled below.
+ if (Base->isVirtual())
+ continue;
+
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ if (CXXConstructorDecl *CopyConstructor
+ = BaseClassDecl->getCopyConstructor(Context, Quals))
+ ExceptSpec.CalledDecl(CopyConstructor);
+ }
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+ BaseEnd = ClassDecl->vbases_end();
+ Base != BaseEnd;
+ ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(BaseClassDecl);
+
+ if (CXXConstructorDecl *CopyConstructor
+ = BaseClassDecl->getCopyConstructor(Context, Quals))
+ ExceptSpec.CalledDecl(CopyConstructor);
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd;
+ ++Field) {
+ QualType FieldType = Context.getBaseElementType((*Field)->getType());
+ if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(FieldClassDecl);
+
+ if (CXXConstructorDecl *CopyConstructor
+ = FieldClassDecl->getCopyConstructor(Context, Quals))
+ ExceptSpec.CalledDecl(CopyConstructor);
+ }
+ }
+
+ // An implicitly-declared copy constructor is an inline public
+ // member of its class.
+ DeclarationName Name
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType));
+ CXXConstructorDecl *CopyConstructor
+ = CXXConstructorDecl::Create(Context, ClassDecl,
+ ClassDecl->getLocation(), Name,
+ Context.getFunctionType(Context.VoidTy,
+ &ArgType, 1,
+ false, 0,
+ ExceptSpec.hasExceptionSpecification(),
+ ExceptSpec.hasAnyExceptionSpecification(),
+ ExceptSpec.size(),
+ ExceptSpec.data(),
+ FunctionType::ExtInfo()),
+ /*TInfo=*/0,
+ /*isExplicit=*/false,
+ /*isInline=*/true,
+ /*isImplicitlyDeclared=*/true);
+ CopyConstructor->setAccess(AS_public);
+ CopyConstructor->setImplicit();
+ CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
+
+ // Note that we have declared this constructor.
+ ClassDecl->setDeclaredCopyConstructor(true);
+ ++ASTContext::NumImplicitCopyConstructorsDeclared;
+
+ // Add the parameter to the constructor.
+ ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
+ ClassDecl->getLocation(),
+ /*IdentifierInfo=*/0,
+ ArgType, /*TInfo=*/0,
+ VarDecl::None,
+ VarDecl::None, 0);
+ CopyConstructor->setParams(&FromParam, 1);
+ if (Scope *S = getScopeForContext(ClassDecl))
+ PushOnScopeChains(CopyConstructor, S, false);
+ ClassDecl->addDecl(CopyConstructor);
+
+ return CopyConstructor;
+}
+
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *CopyConstructor,
unsigned TypeQuals) {
assert((CopyConstructor->isImplicit() &&
CopyConstructor->isCopyConstructor(TypeQuals) &&
- !CopyConstructor->isUsed()) &&
+ !CopyConstructor->isUsed(false)) &&
"DefineImplicitCopyConstructor - call it for implicit copy ctor");
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
@@ -4810,7 +5356,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() &&
!ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) {
- CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context);
+ CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
MarkDeclarationReferenced(VD->getLocation(), Destructor);
CheckDestructorAccess(VD->getLocation(), Destructor,
PDiag(diag::err_access_dtor_var)
@@ -5477,8 +6023,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
/// handler.
Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
- TypeSourceInfo *TInfo = 0;
- QualType ExDeclType = GetTypeForDeclarator(D, S, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType ExDeclType = TInfo->getType();
bool Invalid = D.isInvalidType();
IdentifierInfo *II = D.getIdentifier();
@@ -5632,14 +6178,11 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
Declarator TheDeclarator(DS, Declarator::MemberContext);
- TypeSourceInfo *TSI;
- QualType T = GetTypeForDeclarator(TheDeclarator, S, &TSI);
+ TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
+ QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
return DeclPtrTy();
- if (!TSI)
- TSI = Context.getTrivialTypeSourceInfo(T, DS.getSourceRange().getBegin());
-
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
// poorly written.
@@ -5701,8 +6244,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
SourceLocation Loc = D.getIdentifierLoc();
- TypeSourceInfo *TInfo = 0;
- QualType T = GetTypeForDeclarator(D, S, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
// C++ [class.friend]p1
// A friend of a class is a function or class....
@@ -5759,13 +6302,18 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
LookupQualifiedName(Previous, DC);
- // If searching in that context implicitly found a declaration in
- // a different context, treat it like it wasn't found at all.
+ // Ignore things found implicitly in the wrong scope.
// TODO: better diagnostics for this case. Suggesting the right
// qualified scope would be nice...
- // FIXME: getRepresentativeDecl() is not right here at all
- if (Previous.empty() ||
- !Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) {
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+ if (!D->getDeclContext()->getLookupContext()->Equals(DC))
+ F.erase();
+ }
+ F.done();
+
+ if (Previous.empty()) {
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
return DeclPtrTy();
@@ -6061,9 +6609,9 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class of condition decl.");
- TypeSourceInfo *TInfo = 0;
TagDecl *OwnedTag = 0;
- QualType Ty = GetTypeForDeclarator(D, S, &TInfo, &OwnedTag);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag);
+ QualType Ty = TInfo->getType();
if (Ty->isFunctionType()) { // The declarator shall not specify a function...
// We exit without creating a CXXConditionDeclExpr because a FunctionDecl
@@ -6127,7 +6675,7 @@ bool Sema::DefineUsedVTables() {
if (const CXXMethodDecl *KeyFunction
= Context.getKeyFunction(DynamicClasses[I])) {
const FunctionDecl *Definition = 0;
- if (KeyFunction->getBody(Definition))
+ if (KeyFunction->hasBody(Definition))
MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true);
}
}
@@ -6150,7 +6698,7 @@ bool Sema::DefineUsedVTables() {
// defined in another translation unit, we don't need to emit the
// vtable even though we're using it.
const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
- if (KeyFunction && !KeyFunction->getBody()) {
+ if (KeyFunction && !KeyFunction->hasBody()) {
switch (KeyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
@@ -6198,7 +6746,7 @@ bool Sema::DefineUsedVTables() {
// Optionally warn if we're emitting a weak vtable.
if (Class->getLinkage() == ExternalLinkage &&
Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
- if (!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined()))
+ if (!KeyFunction || (KeyFunction->hasBody() && KeyFunction->isInlined()))
Diag(Class->getLocation(), diag::warn_weak_vtable) << Class;
}
}
@@ -6279,8 +6827,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
= Context.getBaseElementType(Field->getType())
->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (CXXDestructorDecl *Destructor
- = const_cast<CXXDestructorDecl*>(RD->getDestructor(Context))) {
+ if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
MarkDeclarationReferenced(Field->getLocation(), Destructor);
CheckDestructorAccess(Field->getLocation(), Destructor,
PDiag(diag::err_access_dtor_ivar)
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 3b05f5a..21aeb59 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -414,7 +414,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc) {
- ObjCCategoryDecl *CDecl = 0;
+ ObjCCategoryDecl *CDecl;
ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
/// Check that class of this category is already completely declared.
@@ -429,28 +429,21 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
return DeclPtrTy::make(CDecl);
}
- if (!CategoryName) {
- // Class extensions require a special treatment. Use an existing one.
- // Note that 'getClassExtension()' can return NULL.
- CDecl = IDecl->getClassExtension();
- if (IDecl->getImplementation()) {
- Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
- Diag(IDecl->getImplementation()->getLocation(),
- diag::note_implementation_declared);
- }
+ if (!CategoryName && IDecl->getImplementation()) {
+ Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
+ Diag(IDecl->getImplementation()->getLocation(),
+ diag::note_implementation_declared);
}
- if (!CDecl) {
- CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
- ClassLoc, CategoryLoc, CategoryName);
- // FIXME: PushOnScopeChains?
- CurContext->addDecl(CDecl);
+ CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc,
+ ClassLoc, CategoryLoc, CategoryName);
+ // FIXME: PushOnScopeChains?
+ CurContext->addDecl(CDecl);
- CDecl->setClassInterface(IDecl);
- // Insert first use of class extension to the list of class's categories.
- if (!CategoryName)
- CDecl->insertNextClassCategory();
- }
+ CDecl->setClassInterface(IDecl);
+ // Insert 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);
@@ -969,13 +962,11 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
InsMap, ClsMap, I);
// Check class extensions (unnamed categories)
- for (ObjCCategoryDecl *Categories = I->getCategoryList();
- Categories; Categories = Categories->getNextClassCategory()) {
- if (Categories->IsClassExtension()) {
- ImplMethodsVsClassMethods(S, IMPDecl, Categories, IncompleteImpl);
- break;
- }
- }
+ for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension();
+ Categories; Categories = Categories->getNextClassExtension())
+ ImplMethodsVsClassMethods(S, IMPDecl,
+ const_cast<ObjCCategoryDecl*>(Categories),
+ IncompleteImpl);
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
// For extended class, unimplemented methods in its protocols will
// be reported in the primary class.
@@ -1775,9 +1766,9 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
if (getLangOptions().CPlusPlus)
CheckExtraCXXDefaultArguments(D);
- TypeSourceInfo *TInfo = 0;
TagDecl *OwnedDecl = 0;
- QualType ExceptionType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl);
+ QualType ExceptionType = TInfo->getType();
if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) {
// Objective-C++: Types shall not be defined in exception types.
@@ -1821,7 +1812,8 @@ void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
}
// Find ivars to construct/destruct in class extension.
- if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) {
+ for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
+ CDecl = CDecl->getNextClassExtension()) {
for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
E = CDecl->ivar_end(); I != E; ++I) {
ObjCIvarDecl *Iv = (*I);
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 7d73fe4..34a479a 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -249,6 +249,10 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
SourceLocation NewLoc,
bool *MissingExceptionSpecification,
bool *MissingEmptyExceptionSpecification) {
+ // Just completely ignore this under -fno-exceptions.
+ if (!getLangOptions().Exceptions)
+ return false;
+
if (MissingExceptionSpecification)
*MissingExceptionSpecification = false;
@@ -318,6 +322,11 @@ bool Sema::CheckExceptionSpecSubset(
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Superset, SourceLocation SuperLoc,
const FunctionProtoType *Subset, SourceLocation SubLoc) {
+
+ // Just auto-succeed under -fno-exceptions.
+ if (!getLangOptions().Exceptions)
+ return false;
+
// FIXME: As usual, we could be more specific in our error messages, but
// that better waits until we've got types with source locations.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f745352..ce3bf11 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -388,7 +388,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
if (Literal.Pascal) StrTy = Context.UnsignedCharTy;
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
- if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings )
+ if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings)
StrTy.addConst();
// Get an array type for the string, according to C99 6.4.5. This includes
@@ -677,26 +677,6 @@ static void DecomposeUnqualifiedId(Sema &SemaRef,
}
}
-/// Decompose the given template name into a list of lookup results.
-///
-/// The unqualified ID must name a non-dependent template, which can
-/// be more easily tested by checking whether DecomposeUnqualifiedId
-/// found template arguments.
-static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) {
- assert(Id.getKind() == UnqualifiedId::IK_TemplateId);
- TemplateName TName =
- Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
-
- if (TemplateDecl *TD = TName.getAsTemplateDecl())
- R.addDecl(TD);
- else if (OverloadedTemplateStorage *OT = TName.getAsOverloadedTemplate())
- for (OverloadedTemplateStorage::iterator I = OT->begin(), E = OT->end();
- I != E; ++I)
- R.addDecl(*I);
-
- 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.
@@ -889,8 +869,8 @@ static void DiagnoseInstanceReference(Sema &SemaRef,
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
-bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS,
- LookupResult &R, CorrectTypoContext CTC) {
+bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectTypoContext CTC) {
DeclarationName Name = R.getLookupName();
unsigned diagnostic = diag::err_undeclared_var_use;
@@ -906,7 +886,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS,
// unqualified lookup. This is useful when (for example) the
// original lookup would not have found something because it was a
// dependent name.
- for (DeclContext *DC = SS.isEmpty()? CurContext : 0;
+ for (DeclContext *DC = SS.isEmpty() ? CurContext : 0;
DC; DC = DC->getParent()) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
@@ -923,11 +903,29 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS,
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
- if (isInstance)
+ if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
- else
+
+ UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
+ CallsUndergoingInstantiation.back()->getCallee());
+ CXXMethodDecl *DepMethod = cast<CXXMethodDecl>(
+ CurMethod->getInstantiatedFromMemberFunction());
+ QualType DepThisType = DepMethod->getThisType(Context);
+ CXXThisExpr *DepThis = new (Context) CXXThisExpr(R.getNameLoc(),
+ DepThisType, false);
+ TemplateArgumentListInfo TList;
+ if (ULE->hasExplicitTemplateArgs())
+ ULE->copyTemplateArgumentsInto(TList);
+ CXXDependentScopeMemberExpr *DepExpr =
+ CXXDependentScopeMemberExpr::Create(
+ Context, DepThis, DepThisType, true, SourceLocation(),
+ ULE->getQualifier(), ULE->getQualifierRange(), NULL, Name,
+ R.getNameLoc(), &TList);
+ CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+ } else {
Diag(R.getNameLoc(), diagnostic) << Name;
+ }
// Do we really want to note all of these?
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
@@ -941,7 +939,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS,
// We didn't find anything, so try to correct for a typo.
DeclarationName Corrected;
- if (S && (Corrected = CorrectTypo(R, S, &SS, false, CTC))) {
+ if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) {
if (!R.empty()) {
if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {
if (SS.isEmpty())
@@ -1746,8 +1744,29 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// Variable will be bound by-copy, make it const within the closure.
ExprTy.addConst();
- return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false,
- constAdded));
+ QualType T = VD->getType();
+ BlockDeclRefExpr *BDRE = new (Context) BlockDeclRefExpr(VD,
+ ExprTy, Loc, false,
+ constAdded);
+ if (getLangOptions().CPlusPlus) {
+ if (!T->isDependentType() && !T->isReferenceType()) {
+ Expr *E = new (Context)
+ DeclRefExpr(const_cast<ValueDecl*>(BDRE->getDecl()), T,
+ SourceLocation());
+
+ OwningExprResult Res = PerformCopyInitialization(
+ InitializedEntity::InitializeBlock(VD->getLocation(),
+ T, false),
+ SourceLocation(),
+ Owned(E));
+ if (!Res.isInvalid()) {
+ Res = MaybeCreateCXXExprWithTemporaries(move(Res));
+ Expr *Init = Res.takeAs<Expr>();
+ BDRE->setCopyConstructorExpr(Init);
+ }
+ }
+ }
+ return Owned(BDRE);
}
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
@@ -2560,13 +2579,23 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
static bool
LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
SourceRange BaseRange, const RecordType *RTy,
- SourceLocation OpLoc, CXXScopeSpec &SS) {
+ SourceLocation OpLoc, CXXScopeSpec &SS,
+ bool HasTemplateArgs) {
RecordDecl *RDecl = RTy->getDecl();
if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
<< BaseRange))
return true;
+ if (HasTemplateArgs) {
+ // LookupTemplateName doesn't expect these both to exist simultaneously.
+ QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
+
+ bool MOUS;
+ SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS);
+ return false;
+ }
+
DeclContext *DC = RDecl;
if (SS.isSet()) {
// If the member name was a qualified-id, look into the
@@ -2610,6 +2639,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
return false;
} else {
R.clear();
+ R.setLookupName(Name);
}
return false;
@@ -2640,14 +2670,14 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
if (LookupMemberExprInRecord(*this, R, SourceRange(),
RecordTy->getAs<RecordType>(),
- OpLoc, SS))
+ OpLoc, SS, TemplateArgs != 0))
return ExprError();
// Explicit member accesses.
} else {
OwningExprResult Result =
LookupMemberExpr(R, Base, IsArrow, OpLoc,
- SS, /*ObjCImpDecl*/ DeclPtrTy());
+ SS, /*ObjCImpDecl*/ DeclPtrTy(), TemplateArgs != 0);
if (Result.isInvalid()) {
Owned(Base);
@@ -2860,7 +2890,7 @@ Sema::OwningExprResult
Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
bool &IsArrow, SourceLocation OpLoc,
CXXScopeSpec &SS,
- DeclPtrTy ObjCImpDecl) {
+ DeclPtrTy ObjCImpDecl, bool HasTemplateArgs) {
assert(BaseExpr && "no base expression");
// Perform default conversions.
@@ -2893,6 +2923,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
OwningExprResult NewBase
= ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc,
MultiExprArg(*this, 0, 0), 0, Loc);
+ BaseExpr = 0;
if (NewBase.isInvalid())
return ExprError();
@@ -2973,7 +3004,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
QualType PType;
if (Getter)
- PType = Getter->getResultType();
+ PType = Getter->getSendResultType();
else
// Get the expression type from Setter's incoming parameter.
PType = (*(Setter->param_end() -1))->getType();
@@ -3037,7 +3068,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(),
- RTy, OpLoc, SS))
+ RTy, OpLoc, SS, HasTemplateArgs))
return ExprError();
return Owned((Expr*) 0);
}
@@ -3069,6 +3100,9 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
IV->getNameAsString());
Diag(IV->getLocation(), diag::note_previous_decl)
<< IV->getDeclName();
+ } else {
+ Res.clear();
+ Res.setLookupName(Member);
}
}
@@ -3146,7 +3180,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
return ExprError();
return Owned(ObjCMessageExpr::Create(Context,
- OMD->getResultType().getNonReferenceType(),
+ OMD->getSendResultType(),
OpLoc, BaseExpr, Sel,
OMD, NULL, 0, MemberLoc));
}
@@ -3239,44 +3273,24 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
TemplateArgs);
} else {
LookupResult R(*this, Name, NameLoc, LookupMemberName);
- if (TemplateArgs) {
- // Re-use the lookup done for the template name.
- DecomposeTemplateName(R, Id);
-
- // Re-derive the naming class.
- if (SS.isSet()) {
- NestedNameSpecifier *Qualifier
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- if (const Type *Ty = Qualifier->getAsType())
- if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
- R.setNamingClass(NamingClass);
- } else {
- QualType BaseType = Base->getType();
- if (const PointerType *Ptr = BaseType->getAs<PointerType>())
- BaseType = Ptr->getPointeeType();
- if (CXXRecordDecl *NamingClass = BaseType->getAsCXXRecordDecl())
- R.setNamingClass(NamingClass);
- }
- } else {
- Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
- SS, ObjCImpDecl);
+ Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
+ SS, ObjCImpDecl, TemplateArgs != 0);
- if (Result.isInvalid()) {
- Owned(Base);
- return ExprError();
- }
+ if (Result.isInvalid()) {
+ Owned(Base);
+ return ExprError();
+ }
- if (Result.get()) {
- // The only way a reference to a destructor can be used is to
- // immediately call it, which falls into this case. If the
- // next token is not a '(', produce a diagnostic and build the
- // call now.
- if (!HasTrailingLParen &&
- Id.getKind() == UnqualifiedId::IK_DestructorName)
- return DiagnoseDtorReference(NameLoc, move(Result));
+ if (Result.get()) {
+ // The only way a reference to a destructor can be used is to
+ // immediately call it, which falls into this case. If the
+ // next token is not a '(', produce a diagnostic and build the
+ // call now.
+ if (!HasTrailingLParen &&
+ Id.getKind() == UnqualifiedId::IK_DestructorName)
+ return DiagnoseDtorReference(NameLoc, move(Result));
- return move(Result);
- }
+ return move(Result);
}
Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(),
@@ -3304,9 +3318,10 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
MultiLevelTemplateArgumentList ArgList
= getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
- InstantiatingTemplate Inst(*this, CallLoc, Param,
- ArgList.getInnermost().getFlatArgumentList(),
- ArgList.getInnermost().flat_size());
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = ArgList.getInnermost();
+ InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
+ Innermost.second);
OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
if (Result.isInvalid())
@@ -3560,7 +3575,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
BO->getOpcode() == BinaryOperator::PtrMemI) {
if (const FunctionProtoType *FPT
= BO->getType()->getAs<FunctionProtoType>()) {
- QualType ResultTy = FPT->getResultType().getNonReferenceType();
+ QualType ResultTy = FPT->getCallResultType(Context);
ExprOwningPtr<CXXMemberCallExpr>
TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
@@ -3650,7 +3665,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
return ExprError();
// We know the result type of the call, set it.
- TheCall->setType(FuncT->getResultType().getNonReferenceType());
+ TheCall->setType(FuncT->getCallResultType(Context));
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs,
@@ -3663,7 +3678,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
const FunctionDecl *Def = 0;
- if (FDecl->getBody(Def) && NumArgs != Def->param_size()) {
+ if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
const FunctionProtoType *Proto =
Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) {
@@ -3893,12 +3908,13 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
if (!castType->isArithmeticType()) {
QualType castExprType = castExpr->getType();
- if (!castExprType->isIntegralType() && castExprType->isArithmeticType())
+ if (!castExprType->isIntegralType(Context) &&
+ castExprType->isArithmeticType())
return Diag(castExpr->getLocStart(),
diag::err_cast_pointer_from_non_pointer_int)
<< castExprType << castExpr->getSourceRange();
} else if (!castExpr->getType()->isArithmeticType()) {
- if (!castType->isIntegralType() && castType->isArithmeticType())
+ if (!castType->isIntegralType(Context) && castType->isArithmeticType())
return Diag(castExpr->getLocStart(),
diag::err_cast_pointer_to_non_pointer_int)
<< castType << castExpr->getSourceRange();
@@ -4021,15 +4037,26 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
TypeSourceInfo *TInfo) {
ParenListExpr *PE = (ParenListExpr *)Op.get();
QualType Ty = TInfo->getType();
+ bool isAltiVecLiteral = false;
- // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')'
- // then handle it as such.
+ // Check for an altivec literal,
+ // i.e. all the elements are integer constants.
if (getLangOptions().AltiVec && Ty->isVectorType()) {
if (PE->getNumExprs() == 0) {
Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer);
return ExprError();
}
+ if (PE->getNumExprs() == 1) {
+ if (!PE->getExpr(0)->getType()->isVectorType())
+ isAltiVecLiteral = true;
+ }
+ else
+ isAltiVecLiteral = true;
+ }
+ // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')'
+ // then handle it as such.
+ if (isAltiVecLiteral) {
llvm::SmallVector<Expr *, 8> initExprs;
for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i)
initExprs.push_back(PE->getExpr(i));
@@ -4634,7 +4661,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
if (lhsType->isExtVectorType()) {
if (rhsType->isExtVectorType())
return lhsType == rhsType ? Compatible : Incompatible;
- if (!rhsType->isVectorType() && rhsType->isArithmeticType())
+ if (rhsType->isArithmeticType())
return Compatible;
}
@@ -4932,7 +4959,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
// Handle the case of an ext vector and scalar.
if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) {
QualType EltTy = LV->getElementType();
- if (EltTy->isIntegralType() && rhsType->isIntegralType()) {
+ if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) {
if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) {
ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast);
if (swapped) std::swap(rex, lex);
@@ -5263,6 +5290,16 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return LHSTy;
}
+static bool IsWithinTemplateSpecialization(Decl *D) {
+ if (DeclContext *DC = D->getDeclContext()) {
+ if (isa<ClassTemplateSpecializationDecl>(DC))
+ return true;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
+ return FD->isFunctionTemplateSpecialization();
+ }
+ return false;
+}
+
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
unsigned OpaqueOpc, bool isRelational) {
@@ -5272,30 +5309,55 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
return CheckVectorCompareOperands(lex, rex, Loc, isRelational);
- // C99 6.5.8p3 / C99 6.5.9p4
- if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
- UsualArithmeticConversions(lex, rex);
- else {
- UsualUnaryConversions(lex);
- UsualUnaryConversions(rex);
- }
QualType lType = lex->getType();
QualType rType = rex->getType();
- if (!lType->isFloatingType()
- && !(lType->isBlockPointerType() && isRelational)) {
+ if (!lType->hasFloatingRepresentation() &&
+ !(lType->isBlockPointerType() && isRelational)) {
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
- // NOTE: Don't warn about comparisons of enum constants. These can arise
- // from macro expansions, and are usually quite deliberate.
+ //
+ // NOTE: Don't warn about comparison expressions resulting from macro
+ // expansion. Also don't warn about comparisons which are only self
+ // comparisons within a template specialization. The warnings should catch
+ // obvious cases in the definition of the template anyways. The idea is to
+ // warn when the typed comparison operator will always evaluate to the same
+ // result.
Expr *LHSStripped = lex->IgnoreParens();
Expr *RHSStripped = rex->IgnoreParens();
- if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped))
- if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped))
- if (DRL->getDecl() == DRR->getDecl() &&
- !isa<EnumConstantDecl>(DRL->getDecl()))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison));
+ if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
+ if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
+ if (DRL->getDecl() == DRR->getDecl() && !Loc.isMacroID() &&
+ !IsWithinTemplateSpecialization(DRL->getDecl())) {
+ DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ << 0 // self-
+ << (Opc == BinaryOperator::EQ
+ || Opc == BinaryOperator::LE
+ || Opc == BinaryOperator::GE));
+ } else if (lType->isArrayType() && rType->isArrayType() &&
+ !DRL->getDecl()->getType()->isReferenceType() &&
+ !DRR->getDecl()->getType()->isReferenceType()) {
+ // what is it always going to eval to?
+ char always_evals_to;
+ switch(Opc) {
+ case BinaryOperator::EQ: // e.g. array1 == array2
+ always_evals_to = 0; // false
+ break;
+ case BinaryOperator::NE: // e.g. array1 != array2
+ always_evals_to = 1; // true
+ break;
+ default:
+ // best we can say is 'a constant'
+ always_evals_to = 2; // e.g. array1 <= array2
+ break;
+ }
+ DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ << 1 // array
+ << always_evals_to);
+ }
+ }
+ }
if (isa<CastExpr>(LHSStripped))
LHSStripped = LHSStripped->IgnoreParenCasts();
@@ -5338,6 +5400,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
}
}
+ // C99 6.5.8p3 / C99 6.5.9p4
+ if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+ UsualArithmeticConversions(lex, rex);
+ else {
+ UsualUnaryConversions(lex);
+ UsualUnaryConversions(rex);
+ }
+
+ lType = lex->getType();
+ rType = rex->getType();
+
// The result of comparisons is 'bool' in C++, 'int' in C.
QualType ResultTy = getLangOptions().CPlusPlus ? Context.BoolTy:Context.IntTy;
@@ -5346,7 +5419,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return ResultTy;
} else {
// Check for comparisons of floating point operands using != and ==.
- if (lType->isFloatingType() && rType->isFloatingType())
+ if (lType->hasFloatingRepresentation())
CheckFloatComparison(Loc,lex,rex);
if (lType->isArithmeticType() && rType->isArithmeticType())
@@ -5358,9 +5431,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
bool RHSIsNull = rex->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull);
- // All of the following pointer related warnings are GCC extensions, except
- // when handling null pointer constants. One day, we can consider making them
- // errors (when -pedantic-errors is enabled).
+ // All of the following pointer-related warnings are GCC extensions, except
+ // when handling null pointer constants.
if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
QualType LCanPointeeTy =
Context.getCanonicalType(lType->getAs<PointerType>()->getPointeeType());
@@ -5374,10 +5446,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
// Valid unless comparison between non-null pointer and function pointer
// This is a gcc extension compatibility comparison.
+ // In a SFINAE context, we treat this as a hard error to maintain
+ // conformance with the C++ standard.
if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
&& !LHSIsNull && !RHSIsNull) {
- Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
+ Diag(Loc,
+ isSFINAEContext()?
+ diag::err_typecheck_comparison_of_fptr_to_void
+ : diag::ext_typecheck_comparison_of_fptr_to_void)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
+
+ if (isSFINAEContext())
+ return QualType();
+
ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
return ResultTy;
}
@@ -5541,40 +5622,36 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return ResultTy;
}
}
- if (lType->isAnyPointerType() && rType->isIntegerType()) {
+ if ((lType->isAnyPointerType() && rType->isIntegerType()) ||
+ (lType->isIntegerType() && rType->isAnyPointerType())) {
unsigned DiagID = 0;
- if (RHSIsNull) {
- if (isRelational)
+ bool isError = false;
+ if ((LHSIsNull && lType->isIntegerType()) ||
+ (RHSIsNull && rType->isIntegerType())) {
+ if (isRelational && !getLangOptions().CPlusPlus)
DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
- } else if (isRelational)
+ } else if (isRelational && !getLangOptions().CPlusPlus)
DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
- else
+ else if (getLangOptions().CPlusPlus) {
+ DiagID = diag::err_typecheck_comparison_of_pointer_integer;
+ isError = true;
+ } else
DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
if (DiagID) {
Diag(Loc, DiagID)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ if (isError)
+ return QualType();
}
- ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
- return ResultTy;
- }
- if (lType->isIntegerType() && rType->isAnyPointerType()) {
- unsigned DiagID = 0;
- if (LHSIsNull) {
- if (isRelational)
- DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
- } else if (isRelational)
- DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
+
+ if (lType->isIntegerType())
+ ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
else
- DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
-
- if (DiagID) {
- Diag(Loc, DiagID)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
- }
- ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
return ResultTy;
}
+
// Handle block pointers.
if (!isRelational && RHSIsNull
&& lType->isBlockPointerType() && rType->isIntegerType()) {
@@ -5608,16 +5685,20 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
- if (!lType->isFloatingType()) {
+ if (!lType->hasFloatingRepresentation()) {
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison));
+ DiagRuntimeBehavior(Loc,
+ PDiag(diag::warn_comparison_always)
+ << 0 // self-
+ << 2 // "a constant"
+ );
}
// Check for comparisons of floating point operands using != and ==.
- if (!isRelational && lType->isFloatingType()) {
- assert (rType->isFloatingType());
+ if (!isRelational && lType->hasFloatingRepresentation()) {
+ assert (rType->hasFloatingRepresentation());
CheckFloatComparison(Loc,lex,rex);
}
@@ -5663,25 +5744,14 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
return Context.IntTy;
}
+ // The following is safe because we only use this method for
+ // non-overloadable operands.
+
// C++ [expr.log.and]p1
// C++ [expr.log.or]p1
- // The operands are both implicitly converted to type bool (clause 4).
- StandardConversionSequence LHS;
- if (!IsStandardConversion(lex, Context.BoolTy,
- /*InOverloadResolution=*/false, LHS))
- return InvalidOperands(Loc, lex, rex);
-
- if (PerformImplicitConversion(lex, Context.BoolTy, LHS,
- AA_Passing, /*IgnoreBaseAccess=*/false))
- return InvalidOperands(Loc, lex, rex);
-
- StandardConversionSequence RHS;
- if (!IsStandardConversion(rex, Context.BoolTy,
- /*InOverloadResolution=*/false, RHS))
- return InvalidOperands(Loc, lex, rex);
-
- if (PerformImplicitConversion(rex, Context.BoolTy, RHS,
- AA_Passing, /*IgnoreBaseAccess=*/false))
+ // The operands are both contextually converted to type bool.
+ if (PerformContextuallyConvertToBool(lex) ||
+ PerformContextuallyConvertToBool(rex))
return InvalidOperands(Loc, lex, rex);
// C++ [expr.log.and]p2
@@ -5786,11 +5856,22 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
QualType LHSType = LHS->getType();
QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType;
-
AssignConvertType ConvTy;
if (CompoundType.isNull()) {
+ QualType LHSTy(LHSType);
// Simple assignment "x = y".
- ConvTy = CheckSingleAssignmentConstraints(LHSType, RHS);
+ if (const ObjCImplicitSetterGetterRefExpr *OISGE =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(LHS)) {
+ // If using property-dot syntax notation for assignment, and there is a
+ // setter, RHS expression is being passed to the setter argument. So,
+ // type conversion (and comparison) is RHS to setter's argument type.
+ if (const ObjCMethodDecl *SetterMD = OISGE->getSetterMethod()) {
+ ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
+ LHSTy = (*P)->getType();
+ }
+ }
+
+ ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
// Special case of NSObject attributes on c-style pointer types.
if (ConvTy == IncompatiblePointer &&
((Context.isObjCNSObjectType(LHSType) &&
@@ -5829,6 +5910,23 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
RHS, AA_Assigning))
return QualType();
+
+ // Check to see if the destination operand is a dereferenced null pointer. If
+ // so, and if not volatile-qualified, this is undefined behavior that the
+ // optimizer will delete, so warn about it. People sometimes try to use this
+ // to get a deterministic trap and are surprised by clang's behavior. This
+ // only handles the pattern "*null = whatever", which is a very syntactic
+ // check.
+ if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts()))
+ if (UO->getOpcode() == UnaryOperator::Deref &&
+ UO->getSubExpr()->IgnoreParenCasts()->
+ isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
+ !UO->getType().isVolatileQualified()) {
+ Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null)
+ << UO->getSubExpr()->getSourceRange();
+ Diag(UO->getOperatorLoc(), diag::note_indirection_through_null);
+ }
+
// C99 6.5.16p3: The type of an assignment expression is the type of the
// left operand unless the left operand has qualified type, in which case
// it is the unqualified version of the type of the left operand.
@@ -5841,6 +5939,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
// C99 6.5.17
QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
+ DiagnoseUnusedExprResult(LHS);
+
// Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions.
// C++ does not perform this conversion (C++ [expr.comma]p1).
if (!getLangOptions().CPlusPlus)
@@ -6025,13 +6125,17 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
return Context.getMemberPointerType(op->getType(),
Context.getTypeDeclType(cast<RecordDecl>(dcl->getDeclContext()))
.getTypePtr());
- } else if (lval == Expr::LV_ClassTemporary) {
+ }
+
+ if (lval == Expr::LV_ClassTemporary) {
Diag(OpLoc, isSFINAEContext()? diag::err_typecheck_addrof_class_temporary
: diag::ext_typecheck_addrof_class_temporary)
<< op->getType() << op->getSourceRange();
if (isSFINAEContext())
return QualType();
- } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
+ } else if (isa<ObjCSelectorExpr>(op))
+ return Context.getPointerType(op->getType());
+ else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
if (!op->getType()->isFunctionType()) {
@@ -6112,26 +6216,32 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
return Context.getPointerType(op->getType());
}
+/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) {
if (Op->isTypeDependent())
return Context.DependentTy;
UsualUnaryConversions(Op);
- QualType Ty = Op->getType();
-
- // Note that per both C89 and C99, this is always legal, even if ptype is an
- // incomplete type or void. It would be possible to warn about dereferencing
- // a void pointer, but it's completely well-defined, and such a warning is
- // unlikely to catch any mistakes.
- if (const PointerType *PT = Ty->getAs<PointerType>())
- return PT->getPointeeType();
-
- if (const ObjCObjectPointerType *OPT = Ty->getAs<ObjCObjectPointerType>())
- return OPT->getPointeeType();
-
- Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
- << Ty << Op->getSourceRange();
- return QualType();
+ QualType OpTy = Op->getType();
+ QualType Result;
+
+ // Note that per both C89 and C99, indirection is always legal, even if OpTy
+ // is an incomplete type or void. It would be possible to warn about
+ // dereferencing a void pointer, but it's completely well-defined, and such a
+ // warning is unlikely to catch any mistakes.
+ if (const PointerType *PT = OpTy->getAs<PointerType>())
+ Result = PT->getPointeeType();
+ else if (const ObjCObjectPointerType *OPT =
+ OpTy->getAs<ObjCObjectPointerType>())
+ Result = OPT->getPointeeType();
+
+ if (Result.isNull()) {
+ Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
+ << OpTy << Op->getSourceRange();
+ return QualType();
+ }
+
+ return Result;
}
static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode(
@@ -6479,7 +6589,8 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
resultType = Input->getType();
if (resultType->isDependentType())
break;
- if (resultType->isArithmeticType()) // C99 6.5.3.3p1
+ if (resultType->isArithmeticType() || // C99 6.5.3.3p1
+ resultType->isVectorType())
break;
else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7
resultType->isEnumeralType())
@@ -6980,83 +7091,99 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
PushBlockScope(BlockScope, Block);
CurContext->addDecl(Block);
- PushDeclContext(BlockScope, Block);
+ if (BlockScope)
+ PushDeclContext(BlockScope, Block);
+ else
+ CurContext = Block;
}
void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
BlockScopeInfo *CurBlock = getCurBlock();
- if (ParamInfo.getNumTypeObjects() == 0
- || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) {
- ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
- QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
-
- if (T->isArrayType()) {
- Diag(ParamInfo.getSourceRange().getBegin(),
- diag::err_block_returns_array);
- return;
- }
-
- // The parameter list is optional, if there was none, assume ().
- if (!T->isFunctionType())
- T = Context.getFunctionType(T, 0, 0, false, 0, false, false, 0, 0,
- FunctionType::ExtInfo());
+ TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
+ CurBlock->TheDecl->setSignatureAsWritten(Sig);
+ QualType T = Sig->getType();
+
+ bool isVariadic;
+ QualType RetTy;
+ if (const FunctionType *Fn = T->getAs<FunctionType>()) {
+ CurBlock->FunctionType = T;
+ RetTy = Fn->getResultType();
+ isVariadic =
+ !isa<FunctionProtoType>(Fn) || cast<FunctionProtoType>(Fn)->isVariadic();
+ } else {
+ RetTy = T;
+ isVariadic = false;
+ }
- CurBlock->hasPrototype = true;
- CurBlock->isVariadic = false;
- // Check for a valid sentinel attribute on this block.
- if (CurBlock->TheDecl->getAttr<SentinelAttr>()) {
- Diag(ParamInfo.getAttributes()->getLoc(),
- diag::warn_attribute_sentinel_not_variadic) << 1;
- // FIXME: remove the attribute.
- }
- QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType();
+ CurBlock->TheDecl->setIsVariadic(isVariadic);
- // Do not allow returning a objc interface by-value.
- if (RetTy->isObjCObjectType()) {
- Diag(ParamInfo.getSourceRange().getBegin(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
- return;
- }
+ // Don't allow returning an array by value.
+ if (RetTy->isArrayType()) {
+ Diag(ParamInfo.getSourceRange().getBegin(), diag::err_block_returns_array);
+ return;
+ }
- CurBlock->ReturnType = RetTy;
+ // Don't allow returning a objc interface by value.
+ if (RetTy->isObjCObjectType()) {
+ Diag(ParamInfo.getSourceRange().getBegin(),
+ diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
return;
}
- // Analyze arguments to block.
- assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function &&
- "Not a function declarator!");
- DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun;
-
- CurBlock->hasPrototype = FTI.hasPrototype;
- CurBlock->isVariadic = true;
-
- // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes
- // no arguments, not a function that takes a single void argument.
- if (FTI.hasPrototype &&
- FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- (!FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType().getCVRQualifiers()&&
- FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType())) {
- // 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) {
- ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ // Context.DependentTy is used as a placeholder for a missing block
+ // return type. TODO: what should we do with declarators like:
+ // ^ * { ... }
+ // If the answer is "apply template argument deduction"....
+ if (RetTy != Context.DependentTy)
+ CurBlock->ReturnType = RetTy;
+
+ // Push block parameters from the declarator if we had them.
+ llvm::SmallVector<ParmVarDecl*, 8> Params;
+ if (isa<FunctionProtoType>(T)) {
+ FunctionProtoTypeLoc TL = cast<FunctionProtoTypeLoc>(Sig->getTypeLoc());
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ ParmVarDecl *Param = TL.getArg(I);
if (Param->getIdentifier() == 0 &&
!Param->isImplicit() &&
!Param->isInvalidDecl() &&
!getLangOptions().CPlusPlus)
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
- CurBlock->Params.push_back(Param);
+ Params.push_back(Param);
+ }
+
+ // Fake up parameter variables if we have a typedef, like
+ // ^ fntype { ... }
+ } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
+ for (FunctionProtoType::arg_type_iterator
+ I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) {
+ ParmVarDecl *Param =
+ BuildParmVarDeclForTypedef(CurBlock->TheDecl,
+ ParamInfo.getSourceRange().getBegin(),
+ *I);
+ Params.push_back(Param);
}
- CurBlock->isVariadic = FTI.isVariadic;
}
- CurBlock->TheDecl->setParams(CurBlock->Params.data(),
- CurBlock->Params.size());
- CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
+
+ // Set the parameters on the block decl.
+ if (!Params.empty())
+ CurBlock->TheDecl->setParams(Params.data(), Params.size());
+
+ // Finally we can process decl attributes.
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+ if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ Diag(ParamInfo.getAttributes()->getLoc(),
+ diag::warn_attribute_sentinel_not_variadic) << 1;
+ // FIXME: remove the attribute.
+ }
+
+ // Put the parameter variables in scope. We can bail out immediately
+ // if we don't have any.
+ if (Params.empty())
+ return;
+
bool ShouldCheckShadow =
Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored;
@@ -7072,25 +7199,6 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
PushOnScopeChains(*AI, CurBlock->TheScope);
}
}
-
- // Check for a valid sentinel attribute on this block.
- if (!CurBlock->isVariadic &&
- CurBlock->TheDecl->getAttr<SentinelAttr>()) {
- Diag(ParamInfo.getAttributes()->getLoc(),
- diag::warn_attribute_sentinel_not_variadic) << 1;
- // FIXME: remove the attribute.
- }
-
- // Analyze the return type.
- QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
- QualType RetTy = T->getAs<FunctionType>()->getResultType();
-
- // Do not allow returning a objc interface by-value.
- if (RetTy->isObjCObjectType()) {
- Diag(ParamInfo.getSourceRange().getBegin(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
- } else if (!RetTy->isDependentType())
- CurBlock->ReturnType = RetTy;
}
/// ActOnBlockError - If there is an error parsing a block, this callback
@@ -7111,29 +7219,59 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
Diag(CaretLoc, diag::err_blocks_disable);
BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back());
-
+
PopDeclContext();
QualType RetTy = Context.VoidTy;
if (!BSI->ReturnType.isNull())
RetTy = BSI->ReturnType;
- llvm::SmallVector<QualType, 8> ArgTypes;
- for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
- ArgTypes.push_back(BSI->Params[i]->getType());
-
bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>();
QualType BlockTy;
- if (!BSI->hasPrototype)
- BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0,
- FunctionType::ExtInfo(NoReturn, 0, CC_Default));
- else
- BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(),
- BSI->isVariadic, 0, false, false, 0, 0,
- FunctionType::ExtInfo(NoReturn, 0, CC_Default));
+
+ // If the user wrote a function type in some form, try to use that.
+ if (!BSI->FunctionType.isNull()) {
+ const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>();
+
+ FunctionType::ExtInfo Ext = FTy->getExtInfo();
+ if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
+
+ // Turn protoless block types into nullary block types.
+ if (isa<FunctionNoProtoType>(FTy)) {
+ BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0,
+ false, false, 0, 0, Ext);
+
+ // Otherwise, if we don't need to change anything about the function type,
+ // preserve its sugar structure.
+ } else if (FTy->getResultType() == RetTy &&
+ (!NoReturn || FTy->getNoReturnAttr())) {
+ BlockTy = BSI->FunctionType;
+
+ // Otherwise, make the minimal modifications to the function type.
+ } else {
+ const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
+ BlockTy = Context.getFunctionType(RetTy,
+ FPT->arg_type_begin(),
+ FPT->getNumArgs(),
+ FPT->isVariadic(),
+ /*quals*/ 0,
+ FPT->hasExceptionSpec(),
+ FPT->hasAnyExceptionSpec(),
+ FPT->getNumExceptions(),
+ FPT->exception_begin(),
+ Ext);
+ }
+
+ // If we don't have a function type, just build one from nothing.
+ } else {
+ BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0,
+ false, false, 0, 0,
+ FunctionType::ExtInfo(NoReturn, 0, CC_Default));
+ }
// FIXME: Check that return/parameter types are complete/non-abstract
- DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end());
+ DiagnoseUnusedParameters(BSI->TheDecl->param_begin(),
+ BSI->TheDecl->param_end());
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
@@ -7445,7 +7583,7 @@ Sema::PopExpressionEvaluationContext() {
void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
assert(D && "No declaration?");
- if (D->isUsed())
+ if (D->isUsed(false))
return;
// Mark a parameter or variable declaration "used", regardless of whether we're in a
@@ -7488,24 +7626,24 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
unsigned TypeQuals;
if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
- if (!Constructor->isUsed())
+ if (!Constructor->isUsed(false))
DefineImplicitDefaultConstructor(Loc, Constructor);
} else if (Constructor->isImplicit() &&
Constructor->isCopyConstructor(TypeQuals)) {
- if (!Constructor->isUsed())
+ if (!Constructor->isUsed(false))
DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
}
MarkVTableUsed(Loc, Constructor->getParent());
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
- if (Destructor->isImplicit() && !Destructor->isUsed())
+ if (Destructor->isImplicit() && !Destructor->isUsed(false))
DefineImplicitDestructor(Loc, Destructor);
if (Destructor->isVirtual())
MarkVTableUsed(Loc, Destructor->getParent());
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
- if (!MethodDecl->isUsed())
+ if (!MethodDecl->isUsed(false))
DefineImplicitCopyAssignment(Loc, MethodDecl);
} else if (MethodDecl->isVirtual())
MarkVTableUsed(Loc, MethodDecl->getParent());
@@ -7569,45 +7707,46 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
}
namespace {
- // Mark all of the declarations referenced
+ // Mark all of the declarations referenced
// FIXME: Not fully implemented yet! We need to have a better understanding
- // of when we're entering
+ // of when we're entering
class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> {
Sema &S;
SourceLocation Loc;
-
+
public:
typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited;
-
+
MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
-
- bool VisitTemplateArgument(const TemplateArgument &Arg);
- bool VisitRecordType(RecordType *T);
+
+ bool TraverseTemplateArgument(const TemplateArgument &Arg);
+ bool TraverseRecordType(RecordType *T);
};
}
-bool MarkReferencedDecls::VisitTemplateArgument(const TemplateArgument &Arg) {
+bool MarkReferencedDecls::TraverseTemplateArgument(
+ const TemplateArgument &Arg) {
if (Arg.getKind() == TemplateArgument::Declaration) {
S.MarkDeclarationReferenced(Loc, Arg.getAsDecl());
}
-
- return Inherited::VisitTemplateArgument(Arg);
+
+ return Inherited::TraverseTemplateArgument(Arg);
}
-bool MarkReferencedDecls::VisitRecordType(RecordType *T) {
+bool MarkReferencedDecls::TraverseRecordType(RecordType *T) {
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
const TemplateArgumentList &Args = Spec->getTemplateArgs();
- return VisitTemplateArguments(Args.getFlatArgumentList(),
- Args.flat_size());
+ return TraverseTemplateArguments(Args.getFlatArgumentList(),
+ Args.flat_size());
}
- return false;
+ return true;
}
void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
MarkReferencedDecls Marker(*this, Loc);
- Marker.Visit(Context.getCanonicalType(T));
+ Marker.TraverseType(Context.getCanonicalType(T));
}
/// \brief Emit a diagnostic that describes an effect on the run-time behavior
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 97de96a..a5abfe8 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
@@ -52,6 +53,8 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
// }
//
// See also PR6358 and PR6359.
+ // For this reason, we're currently only doing the C++03 version of this
+ // code; the C++0x version has to wait until we get a proper spec.
QualType SearchType;
DeclContext *LookupCtx = 0;
bool isDependent = false;
@@ -68,50 +71,33 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
bool AlreadySearched = false;
bool LookAtPrefix = true;
- if (!getLangOptions().CPlusPlus0x) {
- // C++ [basic.lookup.qual]p6:
- // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
- // the type-names are looked up as types in the scope designated by the
- // nested-name-specifier. In a qualified-id of the form:
- //
- // ::[opt] nested-name-specifier ̃ class-name
- //
- // where the nested-name-specifier designates a namespace scope, and in
- // a qualified-id of the form:
- //
- // ::opt nested-name-specifier class-name :: ̃ class-name
- //
- // the class-names are looked up as types in the scope designated by
- // the nested-name-specifier.
- //
- // Here, we check the first case (completely) and determine whether the
- // code below is permitted to look at the prefix of the
- // nested-name-specifier (as we do in C++0x).
- DeclContext *DC = computeDeclContext(SS, EnteringContext);
- if (DC && DC->isFileContext()) {
- AlreadySearched = true;
- LookupCtx = DC;
- isDependent = false;
- } else if (DC && isa<CXXRecordDecl>(DC))
- LookAtPrefix = false;
- }
-
- // C++0x [basic.lookup.qual]p6:
- // If a pseudo-destructor-name (5.2.4) contains a
- // nested-name-specifier, the type-names are looked up as types
- // in the scope designated by the nested-name-specifier. Similarly, in
- // a qualified-id of the form:
+ // C++ [basic.lookup.qual]p6:
+ // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier,
+ // the type-names are looked up as types in the scope designated by the
+ // nested-name-specifier. In a qualified-id of the form:
+ //
+ // ::[opt] nested-name-specifier ̃ class-name
//
- // :: [opt] nested-name-specifier[opt] class-name :: ~class-name
+ // where the nested-name-specifier designates a namespace scope, and in
+ // a qualified-id of the form:
//
- // the second class-name is looked up in the same scope as the first.
+ // ::opt nested-name-specifier class-name :: ̃ class-name
//
- // To implement this, we look at the prefix of the
- // nested-name-specifier we were given, and determine the lookup
- // context from that.
+ // the class-names are looked up as types in the scope designated by
+ // the nested-name-specifier.
//
- // We also fold in the second case from the C++03 rules quoted further
- // above.
+ // Here, we check the first case (completely) and determine whether the
+ // code below is permitted to look at the prefix of the
+ // nested-name-specifier.
+ DeclContext *DC = computeDeclContext(SS, EnteringContext);
+ if (DC && DC->isFileContext()) {
+ AlreadySearched = true;
+ LookupCtx = DC;
+ isDependent = false;
+ } else if (DC && isa<CXXRecordDecl>(DC))
+ LookAtPrefix = false;
+
+ // The second case from the C++03 rules quoted further above.
NestedNameSpecifier *Prefix = 0;
if (AlreadySearched) {
// Nothing left to do.
@@ -120,11 +106,6 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
PrefixSS.setScopeRep(Prefix);
LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
isDependent = isDependentScopeSpecifier(PrefixSS);
- } else if (getLangOptions().CPlusPlus0x &&
- (LookupCtx = computeDeclContext(SS, EnteringContext))) {
- if (!LookupCtx->isTranslationUnit())
- LookupCtx = LookupCtx->getParent();
- isDependent = LookupCtx && LookupCtx->isDependentContext();
} else if (ObjectTypePtr) {
LookupCtx = computeDeclContext(SearchType);
isDependent = SearchType->isDependentType();
@@ -284,7 +265,10 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
// that is the operand of typeid are always ignored.
// If the type of the type-id is a class type or a reference to a class
// type, the class shall be completely-defined.
- QualType T = Operand->getType().getNonReferenceType();
+ Qualifiers Quals;
+ QualType T
+ = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(),
+ Quals);
if (T->getAs<RecordType>() &&
RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid))
return ExprError();
@@ -328,9 +312,11 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
// cv-qualified type, the result of the typeid expression refers to a
// std::type_info object representing the cv-unqualified referenced
// type.
- if (T.hasQualifiers()) {
- ImpCastExprToType(E, T.getUnqualifiedType(), CastExpr::CK_NoOp,
- E->isLvalue(Context));
+ Qualifiers Quals;
+ QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
+ if (!Context.hasSameType(T, UnqualT)) {
+ T = UnqualT;
+ ImpCastExprToType(E, UnqualT, CastExpr::CK_NoOp, E->isLvalue(Context));
Operand.release();
Operand = Owned(E);
}
@@ -453,11 +439,28 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
return true;
E = Res.takeAs<Expr>();
+ // If the exception has class type, we need additional handling.
+ const RecordType *RecordTy = Ty->getAs<RecordType>();
+ if (!RecordTy)
+ return false;
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+
// If we are throwing a polymorphic class type or pointer thereof,
// exception handling will make use of the vtable.
- if (const RecordType *RecordTy = Ty->getAs<RecordType>())
- MarkVTableUsed(ThrowLoc, cast<CXXRecordDecl>(RecordTy->getDecl()));
-
+ MarkVTableUsed(ThrowLoc, RD);
+
+ // If the class has a non-trivial destructor, we must be able to call it.
+ if (RD->hasTrivialDestructor())
+ return false;
+
+ CXXDestructorDecl *Destructor
+ = const_cast<CXXDestructorDecl*>(LookupDestructor(RD));
+ if (!Destructor)
+ return false;
+
+ MarkDeclarationReferenced(E->getExprLoc(), Destructor);
+ CheckDestructorAccess(E->getExprLoc(), Destructor,
+ PDiag(diag::err_access_dtor_exception) << Ty);
return false;
}
@@ -543,27 +546,19 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
RParenLoc));
}
- if (const RecordType *RT = Ty->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
-
- if (NumExprs > 1 || !Record->hasTrivialConstructor() ||
- !Record->hasTrivialDestructor()) {
- 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
- // doesn't have a user-declared default constructor.
+ if (Ty->isRecordType()) {
+ 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);
}
// C++ [expr.type.conv]p1:
@@ -582,7 +577,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
// rvalue of the specified type, which is value-initialized.
//
exprs.release();
- return Owned(new (Context) CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc));
+ return Owned(new (Context) CXXScalarValueInitExpr(Ty, TyBeginLoc, RParenLoc));
}
@@ -594,7 +589,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
Action::OwningExprResult
Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
- SourceLocation PlacementRParen, bool ParenTypeId,
+ SourceLocation PlacementRParen, SourceRange TypeIdParens,
Declarator &D, SourceLocation ConstructorLParen,
MultiExprArg ConstructorArgs,
SourceLocation ConstructorRParen) {
@@ -610,17 +605,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
<< D.getSourceRange());
- if (ParenTypeId) {
- // Can't have dynamic array size when the type-id is in parentheses.
- Expr *NumElts = (Expr *)Chunk.Arr.NumElts;
- if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() &&
- !NumElts->isIntegerConstantExpr(Context)) {
- Diag(D.getTypeObject(0).Loc, diag::err_new_paren_array_nonconst)
- << NumElts->getSourceRange();
- return ExprError();
- }
- }
-
ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts);
D.DropFirstTypeObject();
}
@@ -644,19 +628,20 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
//FIXME: Store TypeSourceInfo in CXXNew expression.
- TypeSourceInfo *TInfo = 0;
- QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &TInfo);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0);
+ QualType AllocType = TInfo->getType();
if (D.isInvalidType())
return ExprError();
-
+
+ SourceRange R = TInfo->getTypeLoc().getSourceRange();
return BuildCXXNew(StartLoc, UseGlobal,
PlacementLParen,
move(PlacementArgs),
PlacementRParen,
- ParenTypeId,
+ TypeIdParens,
AllocType,
D.getSourceRange().getBegin(),
- D.getSourceRange(),
+ R,
Owned(ArraySize),
ConstructorLParen,
move(ConstructorArgs),
@@ -668,7 +653,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
SourceLocation PlacementLParen,
MultiExprArg PlacementArgs,
SourceLocation PlacementRParen,
- bool ParenTypeId,
+ SourceRange TypeIdParens,
QualType AllocType,
SourceLocation TypeLoc,
SourceRange TypeRange,
@@ -697,11 +682,29 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
// or enumeration type with a non-negative value."
Expr *ArraySize = (Expr *)ArraySizeE.get();
if (ArraySize && !ArraySize->isTypeDependent()) {
+
QualType SizeType = ArraySize->getType();
- if (!SizeType->isIntegralType() && !SizeType->isEnumeralType())
- return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
- diag::err_array_size_not_integral)
- << SizeType << ArraySize->getSourceRange());
+
+ OwningExprResult ConvertedSize
+ = ConvertToIntegralOrEnumerationType(StartLoc, move(ArraySizeE),
+ PDiag(diag::err_array_size_not_integral),
+ PDiag(diag::err_array_size_incomplete_type)
+ << ArraySize->getSourceRange(),
+ PDiag(diag::err_array_size_explicit_conversion),
+ PDiag(diag::note_array_size_conversion),
+ PDiag(diag::err_array_size_ambiguous_conversion),
+ PDiag(diag::note_array_size_conversion),
+ PDiag(getLangOptions().CPlusPlus0x? 0
+ : diag::ext_array_size_conversion));
+ if (ConvertedSize.isInvalid())
+ return ExprError();
+
+ ArraySize = ConvertedSize.takeAs<Expr>();
+ ArraySizeE = Owned(ArraySize);
+ SizeType = ArraySize->getType();
+ if (!SizeType->isIntegralOrEnumerationType())
+ return ExprError();
+
// Let's see if this is a constant < 0. If so, we reject it out of hand.
// We don't care about special rules, so we tell the machinery it's not
// evaluated - it gives us a result in more cases.
@@ -714,6 +717,14 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
diag::err_typecheck_negative_array_size)
<< ArraySize->getSourceRange());
+ } else if (TypeIdParens.isValid()) {
+ // Can't have dynamic array size when the type-id is in parentheses.
+ Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
+ << ArraySize->getSourceRange()
+ << FixItHint::CreateRemoval(TypeIdParens.getBegin())
+ << FixItHint::CreateRemoval(TypeIdParens.getEnd());
+
+ TypeIdParens = SourceRange();
}
}
@@ -828,13 +839,15 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
PlacementArgs.release();
ConstructorArgs.release();
ArraySizeE.release();
+
+ // FIXME: The TypeSourceInfo should also be included in CXXNewExpr.
return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
- PlaceArgs, NumPlaceArgs, ParenTypeId,
+ PlaceArgs, NumPlaceArgs, TypeIdParens,
ArraySize, Constructor, Init,
ConsArgs, NumConsArgs, OperatorDelete,
ResultType, StartLoc,
Init ? ConstructorRParen :
- SourceLocation()));
+ TypeRange.getEnd()));
}
/// CheckAllocatedType - Checks that a type is suitable as the allocated type
@@ -1181,20 +1194,11 @@ void Sema::DeclareGlobalNewDelete() {
// "std" or "bad_alloc" as necessary to form the exception specification.
// However, we do not make these implicit declarations visible to name
// lookup.
- if (!StdNamespace) {
- // The "std" namespace has not yet been defined, so build one implicitly.
- StdNamespace = NamespaceDecl::Create(Context,
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- &PP.getIdentifierTable().get("std"));
- StdNamespace->setImplicit(true);
- }
-
if (!StdBadAlloc) {
// The "std::bad_alloc" class has not yet been declared, so build it
// implicitly.
StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
- StdNamespace,
+ getStdNamespace(),
SourceLocation(),
&PP.getIdentifierTable().get("bad_alloc"),
SourceLocation(), 0);
@@ -1291,11 +1295,15 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
if (Found.isAmbiguous())
return true;
+ Found.suppressDiagnostics();
+
for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
F != FEnd; ++F) {
if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
if (Delete->isUsualDeallocationFunction()) {
Operator = Delete;
+ CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
+ F.getPair());
return false;
}
}
@@ -1436,7 +1444,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError();
if (!RD->hasTrivialDestructor())
- if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context))
+ if (const CXXDestructorDecl *Dtor = LookupDestructor(RD))
MarkDeclarationReferenced(StartLoc,
const_cast<CXXDestructorDecl*>(Dtor));
}
@@ -1517,7 +1525,7 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
// be converted to an rvalue of type "pointer to char"; a wide
// string literal can be converted to an rvalue of type "pointer
// to wchar_t" (C++ 4.2p2).
- if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From))
+ if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From->IgnoreParens()))
if (const PointerType *ToPtrType = ToType->getAs<PointerType>())
if (const BuiltinType *ToPointeeType
= ToPtrType->getPointeeType()->getAs<BuiltinType>()) {
@@ -1776,7 +1784,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
break;
case ICK_Floating_Integral:
- if (ToType->isFloatingType())
+ if (ToType->isRealFloatingType())
ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating);
else
ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral);
@@ -1973,7 +1981,7 @@ QualType Sema::CheckPointerToMemberOperands(
BasePath);
}
- if (isa<CXXZeroInitValueExpr>(rex->IgnoreParens())) {
+ if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) {
// Diagnose use of pointer-to-member type which when used as
// the functional cast in a pointer-to-member expression.
Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
@@ -2583,6 +2591,16 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (FTy->getResultType()->isReferenceType())
return Owned(E);
}
+ else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ QualType Ty = ME->getType();
+ if (const PointerType *PT = Ty->getAs<PointerType>())
+ Ty = PT->getPointeeType();
+ else if (const BlockPointerType *BPT = Ty->getAs<BlockPointerType>())
+ Ty = BPT->getPointeeType();
+ if (Ty->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.
@@ -2590,11 +2608,9 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (RD->hasTrivialDestructor())
return Owned(E);
- CXXTemporary *Temp = CXXTemporary::Create(Context,
- RD->getDestructor(Context));
+ CXXTemporary *Temp = CXXTemporary::Create(Context, LookupDestructor(RD));
ExprTemporaries.push_back(Temp);
- if (CXXDestructorDecl *Destructor =
- const_cast<CXXDestructorDecl*>(RD->getDestructor(Context))) {
+ if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
MarkDeclarationReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_temp)
@@ -2819,7 +2835,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
if (ScopeTypeInfo) {
QualType ScopeType = ScopeTypeInfo->getType();
if (!ScopeType->isDependentType() && !ObjectType->isDependentType() &&
- !Context.hasSameType(ScopeType, ObjectType)) {
+ !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) {
Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(),
diag::err_pseudo_dtor_type_mismatch)
@@ -2891,7 +2907,8 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
// record types and dependent types matter.
void *ObjectTypePtrForLookup = 0;
if (!SS.isSet()) {
- ObjectTypePtrForLookup = (void *)ObjectType->getAs<RecordType>();
+ ObjectTypePtrForLookup = const_cast<RecordType*>(
+ ObjectType->getAs<RecordType>());
if (!ObjectTypePtrForLookup && ObjectType->isDependentType())
ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr();
}
@@ -3012,7 +3029,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
MemberExpr *ME =
new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
SourceLocation(), Method->getType());
- QualType ResultType = Method->getResultType().getNonReferenceType();
+ QualType ResultType = Method->getCallResultType();
MarkDeclarationReferenced(Exp->getLocStart(), Method);
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType,
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 695a1be..9f43471 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -207,7 +207,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
return false;
}
- ReturnType = Method->getResultType().getNonReferenceType();
+ ReturnType = Method->getSendResultType();
unsigned NumNamedArgs = Sel.getNumArgs();
// Method might have more arguments than selector indicates. This is due
@@ -346,7 +346,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))
- ResTy = Getter->getResultType();
+ ResTy = Getter->getSendResultType();
return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
MemberLoc, BaseExpr));
}
@@ -402,7 +402,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (Getter) {
QualType PType;
- PType = Getter->getResultType();
+ PType = Getter->getSendResultType();
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
Setter, MemberLoc, BaseExpr));
}
@@ -510,7 +510,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
QualType PType;
if (Getter)
- PType = Getter->getResultType();
+ PType = Getter->getSendResultType();
else {
for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
E = Setter->param_end(); PI != E; ++PI)
@@ -1007,6 +1007,12 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false,
LBracLoc, RBracLoc, ReturnType))
return ExprError();
+
+ if (!ReturnType->isVoidType()) {
+ if (RequireCompleteType(LBracLoc, ReturnType,
+ diag::err_illegal_message_expr_incomplete_type))
+ return ExprError();
+ }
// Construct the appropriate ObjCMessageExpr instance.
Expr *Result;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 20f0c79..7536289 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -877,10 +877,15 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
StructuredList, StructuredIndex);
++numEltsInit;
} else {
+ QualType VecType;
const VectorType *IVT = IType->getAs<VectorType>();
unsigned numIElts = IVT->getNumElements();
- QualType VecType = SemaRef.Context.getExtVectorType(elementType,
- numIElts);
+
+ if (IType->isExtVectorType())
+ VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
+ else
+ VecType = SemaRef.Context.getVectorType(elementType, numIElts,
+ IVT->getAltiVecSpecific());
CheckSubElementType(ElementEntity, IList, VecType, Index,
StructuredList, StructuredIndex);
numEltsInit += numIElts;
@@ -1114,7 +1119,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
// Emit warnings for missing struct field initializers.
- if (CheckForMissingFields && Field != FieldEnd &&
+ if (InitializedSomething && CheckForMissingFields && Field != FieldEnd &&
!Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) {
// It is possible we have one or more unnamed bitfields remaining.
// Find first (if any) named field and emit warning.
@@ -1956,6 +1961,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_Base:
case EK_ArrayElement:
case EK_VectorElement:
+ case EK_BlockElement:
return DeclarationName();
}
@@ -1977,6 +1983,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_Base:
case EK_ArrayElement:
case EK_VectorElement:
+ case EK_BlockElement:
return 0;
}
@@ -1998,6 +2005,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Base:
case EK_ArrayElement:
case EK_VectorElement:
+ case EK_BlockElement:
break;
}
@@ -2195,7 +2203,7 @@ static void TryListInitialization(Sema &S,
// FIXME: We only perform rudimentary checking of list
// initializations at this point, then assume that any list
// initialization of an array, aggregate, or scalar will be
- // well-formed. We we actually "perform" list initialization, we'll
+ // well-formed. When we actually "perform" list initialization, we'll
// do all of the necessary checking. C++0x initializer lists will
// force us to perform more checking here.
Sequence.setSequenceKind(InitializationSequence::ListInitialization);
@@ -2236,8 +2244,6 @@ static void TryListInitialization(Sema &S,
/// \brief Try a reference initialization that involves calling a conversion
/// function.
-///
-/// FIXME: look intos DRs 656, 896
static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -2271,11 +2277,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
- DeclarationName ConstructorName
- = S.Context.DeclarationNames.getCXXConstructorName(
- S.Context.getCanonicalType(T1).getUnqualifiedType());
DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName);
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -2328,7 +2331,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if (ConvTemplate)
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
- Conv = cast<CXXConversionDecl>(*I);
+ Conv = cast<CXXConversionDecl>(D);
// If the conversion function doesn't return a reference type,
// it can't be considered for this conversion unless we're allowed to
@@ -2398,14 +2401,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
return OR_Success;
}
-/// \brief Attempt reference initialization (C++0x [dcl.init.list])
+/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
static void TryReferenceInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr *Initializer,
InitializationSequence &Sequence) {
Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
-
+
QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
Qualifiers T1Quals;
@@ -2414,7 +2417,7 @@ static void TryReferenceInitialization(Sema &S,
Qualifiers T2Quals;
QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals);
SourceLocation DeclLoc = Initializer->getLocStart();
-
+
// If the initializer is the address of an overloaded function, try
// to resolve the overloaded function. If all goes well, T2 is the
// type of the resulting function.
@@ -2428,29 +2431,33 @@ static void TryReferenceInitialization(Sema &S,
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
return;
}
-
+
Sequence.AddAddressOverloadResolutionStep(Fn, Found);
cv2T2 = Fn->getType();
T2 = cv2T2.getUnqualifiedType();
}
-
+
// Compute some basic properties of the types and the initializer.
bool isLValueRef = DestType->isLValueReferenceType();
bool isRValueRef = !isLValueRef;
bool DerivedToBase = false;
- Expr::isLvalueResult InitLvalue = Initializer->isLvalue(S.Context);
+ Expr::Classification InitCategory = Initializer->Classify(S.Context);
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase);
-
+
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression of type
// "cv2 T2" as follows:
//
// - If the reference is an lvalue reference and the initializer
// expression
+ // Note the analogous bullet points for rvlaue refs to functions. Because
+ // there are no function rvalues in C++, rvalue refs to functions are treated
+ // like lvalue refs.
OverloadingResult ConvOvlResult = OR_Success;
- if (isLValueRef) {
- if (InitLvalue == Expr::LV_Valid &&
+ bool T1Function = T1->isFunctionType();
+ if (isLValueRef || T1Function) {
+ if (InitCategory.isLValue() &&
RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
// - is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
@@ -2478,10 +2485,13 @@ static void TryReferenceInitialization(Sema &S,
// with "cv3 T3" (this conversion is selected by enumerating the
// applicable conversion functions (13.3.1.6) and choosing the best
// one through overload resolution (13.3)),
- if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType()) {
+ // If we have an rvalue ref to function type here, the rhs must be
+ // an rvalue.
+ if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
+ (isLValueRef || InitCategory.isRValue())) {
ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
Initializer,
- /*AllowRValues=*/false,
+ /*AllowRValues=*/isRValueRef,
Sequence);
if (ConvOvlResult == OR_Success)
return;
@@ -2492,19 +2502,20 @@ static void TryReferenceInitialization(Sema &S,
}
}
}
-
+
// - Otherwise, the reference shall be an lvalue reference to a
// 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.
+ // be an rvalue or have a function type.
+ // We handled the function type stuff above.
if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) ||
- (isRValueRef && InitLvalue != Expr::LV_Valid))) {
+ (isRValueRef && InitCategory.isRValue()))) {
if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
ConvOvlResult);
else if (isLValueRef)
- Sequence.SetFailed(InitLvalue == Expr::LV_Valid
+ Sequence.SetFailed(InitCategory.isLValue()
? (RefRelationship == Sema::Ref_Related
? InitializationSequence::FK_ReferenceInitDropsQualifiers
: InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
@@ -2512,15 +2523,15 @@ static void TryReferenceInitialization(Sema &S,
else
Sequence.SetFailed(
InitializationSequence::FK_RValueReferenceBindingToLValue);
-
+
return;
}
-
- // - If T1 and T2 are class types and
- if (T1->isRecordType() && T2->isRecordType()) {
+
+ // - [If T1 is not a function type], if T2 is a class type and
+ if (!T1Function && T2->isRecordType()) {
// - the initializer expression is an rvalue and "cv1 T1" is
// reference-compatible with "cv2 T2", or
- if (InitLvalue != Expr::LV_Valid &&
+ if (InitCategory.isRValue() &&
RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
// The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
// compiler the freedom to perform a copy here or bind to the
@@ -2543,7 +2554,7 @@ static void TryReferenceInitialization(Sema &S,
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
return;
}
-
+
// - T1 is not reference-related to T2 and the initializer expression
// can be implicitly converted to an rvalue of type "cv3 T3" (this
// conversion is selected by enumerating the applicable conversion
@@ -2576,15 +2587,17 @@ static void TryReferenceInitialization(Sema &S,
// from the initializer expression using the rules for a non-reference
// copy initialization (8.5). The reference is then bound to the
// temporary. [...]
+
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
- ImplicitConversionSequence ICS
- = S.TryImplicitConversion(Initializer, cv1T1,
- /*SuppressUserConversions=*/false, AllowExplicit,
- /*FIXME:InOverloadResolution=*/false);
-
- if (ICS.isBad()) {
+
+ InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+
+ if (S.TryImplicitConversion(Sequence, TempEntity, Initializer,
+ /*SuppressUserConversions*/ false,
+ AllowExplicit,
+ /*FIXME:InOverloadResolution=*/false)) {
// FIXME: Use the conversion function set stored in ICS to turn
// this into an overloading ambiguity diagnostic. However, we need
// to keep that set as an OverloadCandidateSet rather than as some
@@ -2609,8 +2622,6 @@ static void TryReferenceInitialization(Sema &S,
return;
}
- // Perform the actual conversion.
- Sequence.AddConversionSequenceStep(ICS, cv1T1);
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
return;
}
@@ -2661,11 +2672,8 @@ static void TryConstructorInitialization(Sema &S,
CXXRecordDecl *DestRecordDecl
= cast<CXXRecordDecl>(DestRecordType->getDecl());
- DeclarationName ConstructorName
- = S.Context.DeclarationNames.getCXXConstructorName(
- S.Context.getCanonicalType(DestType).getUnqualifiedType());
DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -2764,8 +2772,7 @@ static void TryValueInitialization(Sema &S,
// zero-initialized and, if T’s implicitly-declared default
// constructor is non-trivial, that constructor is called.
if ((ClassDecl->getTagKind() == TTK_Class ||
- ClassDecl->getTagKind() == TTK_Struct) &&
- !ClassDecl->hasTrivialConstructor()) {
+ ClassDecl->getTagKind() == TTK_Struct)) {
Sequence.AddZeroInitializationStep(Entity.getType());
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
}
@@ -2841,15 +2848,11 @@ static void TryUserDefinedConversion(Sema &S,
// Try to complete the type we're converting to.
if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
- DeclarationName ConstructorName
- = S.Context.DeclarationNames.getCXXConstructorName(
- S.Context.getCanonicalType(DestType).getUnqualifiedType());
DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
- bool SuppressUserConversions = false;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
@@ -2858,17 +2861,8 @@ static void TryUserDefinedConversion(Sema &S,
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
- else {
+ else
Constructor = cast<CXXConstructorDecl>(D);
-
- // If we're performing copy initialization using a copy constructor,
- // we suppress user-defined conversions on the arguments.
- // FIXME: Move constructors?
- if (Kind.getKind() == InitializationKind::IK_Copy &&
- Constructor->isCopyConstructor())
- SuppressUserConversions = true;
-
- }
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
@@ -2876,11 +2870,11 @@ static void TryUserDefinedConversion(Sema &S,
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet,
- SuppressUserConversions);
+ /*SuppressUserConversions=*/true);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
&Initializer, 1, CandidateSet,
- SuppressUserConversions);
+ /*SuppressUserConversions=*/true);
}
}
}
@@ -2948,7 +2942,7 @@ static void TryUserDefinedConversion(Sema &S,
}
// Add the user-defined conversion step that calls the conversion function.
- QualType ConvType = Function->getResultType().getNonReferenceType();
+ QualType ConvType = Function->getCallResultType();
if (ConvType->getAs<RecordType>()) {
// If we're converting to a class type, there may be an copy if
// the resulting temporary object (possible to create an object of
@@ -2973,25 +2967,22 @@ static void TryUserDefinedConversion(Sema &S,
}
}
-/// \brief Attempt an implicit conversion (C++ [conv]) converting from one
-/// non-class type to another.
-static void TryImplicitConversion(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- Expr *Initializer,
- InitializationSequence &Sequence) {
+bool Sema::TryImplicitConversion(InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *Initializer,
+ bool SuppressUserConversions,
+ bool AllowExplicitConversions,
+ bool InOverloadResolution) {
ImplicitConversionSequence ICS
- = S.TryImplicitConversion(Initializer, Entity.getType(),
- /*SuppressUserConversions=*/true,
- /*AllowExplicit=*/false,
- /*InOverloadResolution=*/false);
-
- if (ICS.isBad()) {
- Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
- return;
- }
-
+ = TryImplicitConversion(Initializer, Entity.getType(),
+ SuppressUserConversions,
+ AllowExplicitConversions,
+ InOverloadResolution);
+ if (ICS.isBad()) return true;
+
+ // Perform the actual conversion.
Sequence.AddConversionSequenceStep(ICS, Entity.getType());
+ return false;
}
InitializationSequence::InitializationSequence(Sema &S,
@@ -3125,8 +3116,13 @@ InitializationSequence::InitializationSequence(Sema &S,
// conversions (Clause 4) will be used, if necessary, to convert the
// initializer expression to the cv-unqualified version of the
// destination type; no user-defined conversions are considered.
- setSequenceKind(StandardConversion);
- TryImplicitConversion(S, Entity, Kind, Initializer, *this);
+ if (S.TryImplicitConversion(*this, Entity, Initializer,
+ /*SuppressUserConversions*/ true,
+ /*AllowExplicitConversions*/ false,
+ /*InOverloadResolution*/ false))
+ SetFailed(InitializationSequence::FK_ConversionFailed);
+ else
+ setSequenceKind(StandardConversion);
}
InitializationSequence::~InitializationSequence() {
@@ -3168,6 +3164,7 @@ getAssignmentAction(const InitializedEntity &Entity) {
case InitializedEntity::EK_Member:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_BlockElement:
return Sema::AA_Initializing;
}
@@ -3186,6 +3183,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Base:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_BlockElement:
return false;
case InitializedEntity::EK_Parameter:
@@ -3205,6 +3203,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_BlockElement:
return false;
case InitializedEntity::EK_Variable:
@@ -3289,6 +3288,7 @@ static Sema::OwningExprResult CopyObject(Sema &S,
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_BlockElement:
Loc = CurInitExpr->getLocStart();
break;
}
@@ -3298,12 +3298,9 @@ static Sema::OwningExprResult CopyObject(Sema &S,
return move(CurInit);
// Perform overload resolution using the class's copy constructors.
- DeclarationName ConstructorName
- = S.Context.DeclarationNames.getCXXConstructorName(
- S.Context.getCanonicalType(S.Context.getTypeDeclType(Class)));
DeclContext::lookup_iterator Con, ConEnd;
OverloadCandidateSet CandidateSet(Loc);
- for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName);
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
Con != ConEnd; ++Con) {
// Only consider copy constructors.
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
@@ -3324,12 +3321,16 @@ static Sema::OwningExprResult CopyObject(Sema &S,
break;
case OR_No_Viable_Function:
- S.Diag(Loc, diag::err_temp_copy_no_viable)
+ S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext()
+ ? diag::ext_rvalue_to_reference_temp_copy_no_viable
+ : diag::err_temp_copy_no_viable)
<< (int)Entity.getKind() << CurInitExpr->getType()
<< CurInitExpr->getSourceRange();
S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates,
&CurInitExpr, 1);
- return S.ExprError();
+ if (!IsExtraneousCopy || S.isSFINAEContext())
+ return S.ExprError();
+ return move(CurInit);
case OR_Ambiguous:
S.Diag(Loc, diag::err_temp_copy_ambiguous)
@@ -3353,7 +3354,7 @@ static Sema::OwningExprResult CopyObject(Sema &S,
CurInit.release(); // Ownership transferred into MultiExprArg, below.
S.CheckConstructorAccess(Loc, Constructor, Entity,
- Best->FoundDecl.getAccess());
+ Best->FoundDecl.getAccess(), IsExtraneousCopy);
if (IsExtraneousCopy) {
// If this is a totally extraneous copy for C++03 reference
@@ -3699,8 +3700,8 @@ InitializationSequence::Perform(Sema &S,
CurInitExpr = static_cast<Expr *>(CurInit.get());
QualType T = CurInitExpr->getType();
if (const RecordType *Record = T->getAs<RecordType>()) {
- CXXDestructorDecl *Destructor
- = cast<CXXRecordDecl>(Record->getDecl())->getDestructor(S.Context);
+ CXXDestructorDecl *Destructor
+ = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
@@ -3836,7 +3837,7 @@ InitializationSequence::Perform(Sema &S,
} else if (Kind.getKind() == InitializationKind::IK_Value &&
S.getLangOptions().CPlusPlus &&
!Kind.isImplicitValueInit()) {
- CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type,
+ CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(Step->Type,
Kind.getRange().getBegin(),
Kind.getRange().getEnd()));
} else {
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index a9064ed..44c36a7 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -66,7 +66,10 @@ public:
EK_Base,
/// \brief The entity being initialized is an element of a vector.
/// or vector.
- EK_VectorElement
+ EK_VectorElement,
+ /// \brief The entity being initialized is a field of block descriptor for
+ /// the copied-in c++ object.
+ EK_BlockElement
};
private:
@@ -166,6 +169,11 @@ public:
return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
}
+ static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO);
+ }
+
/// \brief Create the initialization entity for an exception object.
static InitializedEntity InitializeException(SourceLocation ThrowLoc,
QualType Type, bool NRVO) {
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 4555a86..2e65183 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -447,11 +447,114 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
return false;
}
+/// \brief Determine whether we can declare a special member function within
+/// the class at this point.
+static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
+ const CXXRecordDecl *Class) {
+ // We need to have a definition for the class.
+ if (!Class->getDefinition() || Class->isDependentContext())
+ return false;
+
+ // We can't be in the middle of defining the class.
+ if (const RecordType *RecordTy
+ = Context.getTypeDeclType(Class)->getAs<RecordType>())
+ return !RecordTy->isBeingDefined();
+
+ return false;
+}
+
+void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
+ if (!CanDeclareSpecialMemberFunction(Context, Class))
+ return;
+
+ // If the default constructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredDefaultConstructor())
+ DeclareImplicitDefaultConstructor(Class);
+
+ // If the copy constructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+
+ // If the copy assignment operator has not yet been declared, do so now.
+ if (!Class->hasDeclaredCopyAssignment())
+ DeclareImplicitCopyAssignment(Class);
+
+ // If the destructor has not yet been declared, do so now.
+ if (!Class->hasDeclaredDestructor())
+ DeclareImplicitDestructor(Class);
+}
+
+/// \brief Determine whether this is the name of an implicitly-declared
+/// special member function.
+static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ return true;
+
+ case DeclarationName::CXXOperatorName:
+ return Name.getCXXOverloadedOperator() == OO_Equal;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/// \brief If there are any implicit member functions with the given name
+/// that need to be declared in the given declaration context, do so.
+static void DeclareImplicitMemberFunctionsWithName(Sema &S,
+ DeclarationName Name,
+ const DeclContext *DC) {
+ if (!DC)
+ return;
+
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record)) {
+ if (!Record->hasDeclaredDefaultConstructor())
+ S.DeclareImplicitDefaultConstructor(
+ const_cast<CXXRecordDecl *>(Record));
+ if (!Record->hasDeclaredCopyConstructor())
+ S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record));
+ }
+ break;
+
+ case DeclarationName::CXXDestructorName:
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record))
+ S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record));
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ if (Name.getCXXOverloadedOperator() != OO_Equal)
+ break;
+
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
+ if (Record->getDefinition() && !Record->hasDeclaredCopyAssignment() &&
+ CanDeclareSpecialMemberFunction(S.Context, Record))
+ S.DeclareImplicitCopyAssignment(const_cast<CXXRecordDecl *>(Record));
+ break;
+
+ default:
+ break;
+ }
+}
+
// 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(Sema &S, LookupResult &R, const DeclContext *DC) {
bool Found = false;
+ // Lazily declare C++ special member functions.
+ if (S.getLangOptions().CPlusPlus)
+ DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC);
+
+ // Perform lookup into this declaration context.
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
NamedDecl *D = *I;
@@ -640,6 +743,17 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
DeclarationName Name = R.getLookupName();
+ // If this is the name of an implicitly-declared special member function,
+ // go through the scope stack to implicitly declare
+ if (isImplicitlyDeclaredMemberFunctionName(Name)) {
+ for (Scope *PreS = S; PreS; PreS = PreS->getParent())
+ if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity()))
+ DeclareImplicitMemberFunctionsWithName(*this, Name, DC);
+ }
+
+ // Implicitly declare member functions with the name we're looking for, if in
+ // fact we are in a scope where it matters.
+
Scope *Initial = S;
IdentifierResolver::iterator
I = IdResolver.begin(Name),
@@ -1127,7 +1241,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// If this isn't a C++ class, we aren't allowed to look into base
// classes, we're done.
CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
- if (!LookupRec)
+ if (!LookupRec || !LookupRec->getDefinition())
return false;
// If we're performing qualified name lookup into a dependent class,
@@ -1416,11 +1530,22 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) {
return true;
}
+namespace {
+ struct AssociatedLookup {
+ AssociatedLookup(Sema &S,
+ Sema::AssociatedNamespaceSet &Namespaces,
+ Sema::AssociatedClassSet &Classes)
+ : S(S), Namespaces(Namespaces), Classes(Classes) {
+ }
+
+ Sema &S;
+ Sema::AssociatedNamespaceSet &Namespaces;
+ Sema::AssociatedClassSet &Classes;
+ };
+}
+
static void
-addAssociatedClassesAndNamespaces(QualType T,
- ASTContext &Context,
- Sema::AssociatedNamespaceSet &AssociatedNamespaces,
- Sema::AssociatedClassSet &AssociatedClasses);
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
DeclContext *Ctx) {
@@ -1439,10 +1564,8 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
// \brief Add the associated classes and namespaces for argument-dependent
// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
static void
-addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
- ASTContext &Context,
- Sema::AssociatedNamespaceSet &AssociatedNamespaces,
- Sema::AssociatedClassSet &AssociatedClasses) {
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
+ const TemplateArgument &Arg) {
// C++ [basic.lookup.koenig]p2, last bullet:
// -- [...] ;
switch (Arg.getKind()) {
@@ -1453,9 +1576,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
// [...] the namespaces and classes associated with the types of the
// template arguments provided for template type parameters (excluding
// template template parameters)
- addAssociatedClassesAndNamespaces(Arg.getAsType(), Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
break;
case TemplateArgument::Template: {
@@ -1467,9 +1588,9 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
= dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
DeclContext *Ctx = ClassTemplate->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
- AssociatedClasses.insert(EnclosingClass);
+ Result.Classes.insert(EnclosingClass);
// Add the associated namespace for this class.
- CollectEnclosingNamespace(AssociatedNamespaces, Ctx);
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
}
break;
}
@@ -1485,9 +1606,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
PEnd = Arg.pack_end();
P != PEnd; ++P)
- addAssociatedClassesAndNamespaces(*P, Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ addAssociatedClassesAndNamespaces(Result, *P);
break;
}
}
@@ -1496,10 +1615,13 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
// argument-dependent lookup with an argument of class type
// (C++ [basic.lookup.koenig]p2).
static void
-addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
- ASTContext &Context,
- Sema::AssociatedNamespaceSet &AssociatedNamespaces,
- Sema::AssociatedClassSet &AssociatedClasses) {
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
+ CXXRecordDecl *Class) {
+
+ // Just silently ignore anything whose name is __va_list_tag.
+ if (Class->getDeclName() == Result.S.VAListTagName)
+ return;
+
// C++ [basic.lookup.koenig]p2:
// [...]
// -- If T is a class type (including unions), its associated
@@ -1511,13 +1633,13 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
// Add the class of which it is a member, if any.
DeclContext *Ctx = Class->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
- AssociatedClasses.insert(EnclosingClass);
+ Result.Classes.insert(EnclosingClass);
// Add the associated namespace for this class.
- CollectEnclosingNamespace(AssociatedNamespaces, Ctx);
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
// Add the class itself. If we've already seen this class, we don't
// need to visit base classes.
- if (!AssociatedClasses.insert(Class))
+ if (!Result.Classes.insert(Class))
return;
// -- If T is a template-id, its associated namespaces and classes are
@@ -1533,15 +1655,13 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
= dyn_cast<ClassTemplateSpecializationDecl>(Class)) {
DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
- AssociatedClasses.insert(EnclosingClass);
+ Result.Classes.insert(EnclosingClass);
// Add the associated namespace for this class.
- CollectEnclosingNamespace(AssociatedNamespaces, Ctx);
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
- addAssociatedClassesAndNamespaces(TemplateArgs[I], Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]);
}
// Only recurse into base classes for complete types.
@@ -1573,10 +1693,10 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
if (!BaseType)
continue;
CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (AssociatedClasses.insert(BaseDecl)) {
+ if (Result.Classes.insert(BaseDecl)) {
// Find the associated namespace for this base class.
DeclContext *BaseCtx = BaseDecl->getDeclContext();
- CollectEnclosingNamespace(AssociatedNamespaces, BaseCtx);
+ CollectEnclosingNamespace(Result.Namespaces, BaseCtx);
// Make sure we visit the bases of this base class.
if (BaseDecl->bases_begin() != BaseDecl->bases_end())
@@ -1590,10 +1710,7 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
// argument-dependent lookup with an argument of type T
// (C++ [basic.lookup.koenig]p2).
static void
-addAssociatedClassesAndNamespaces(QualType T,
- ASTContext &Context,
- Sema::AssociatedNamespaceSet &AssociatedNamespaces,
- Sema::AssociatedClassSet &AssociatedClasses) {
+addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
// C++ [basic.lookup.koenig]p2:
//
// For each argument type T in the function call, there is a set
@@ -1604,109 +1721,137 @@ addAssociatedClassesAndNamespaces(QualType T,
// argument). Typedef names and using-declarations used to specify
// the types do not contribute to this set. The sets of namespaces
// and classes are determined in the following way:
- T = Context.getCanonicalType(T).getUnqualifiedType();
- // -- If T is a pointer to U or an array of U, its associated
- // namespaces and classes are those associated with U.
- //
- // We handle this by unwrapping pointer and array types immediately,
- // to avoid unnecessary recursion.
+ llvm::SmallVector<const Type *, 16> Queue;
+ const Type *T = Ty->getCanonicalTypeInternal().getTypePtr();
+
while (true) {
- if (const PointerType *Ptr = T->getAs<PointerType>())
- T = Ptr->getPointeeType();
- else if (const ArrayType *Ptr = Context.getAsArrayType(T))
- T = Ptr->getElementType();
- else
+ switch (T->getTypeClass()) {
+
+#define TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ // T is canonical. We can also ignore dependent types because
+ // we don't need to do ADL at the definition point, but if we
+ // wanted to implement template export (or if we find some other
+ // use for associated classes and namespaces...) this would be
+ // wrong.
break;
- }
- // -- If T is a fundamental type, its associated sets of
- // namespaces and classes are both empty.
- if (T->getAs<BuiltinType>())
- return;
+ // -- If T is a pointer to U or an array of U, its associated
+ // namespaces and classes are those associated with U.
+ case Type::Pointer:
+ T = cast<PointerType>(T)->getPointeeType().getTypePtr();
+ continue;
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ T = cast<ArrayType>(T)->getElementType().getTypePtr();
+ continue;
- // -- If T is a class type (including unions), its associated
- // classes are: the class itself; the class of which it is a
- // member, if any; and its direct and indirect base
- // classes. Its associated namespaces are the namespaces in
- // which its associated classes are defined.
- if (const RecordType *ClassType = T->getAs<RecordType>())
- if (CXXRecordDecl *ClassDecl
- = dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
- addAssociatedClassesAndNamespaces(ClassDecl, Context,
- AssociatedNamespaces,
- AssociatedClasses);
- return;
+ // -- If T is a fundamental type, its associated sets of
+ // namespaces and classes are both empty.
+ case Type::Builtin:
+ break;
+
+ // -- If T is a class type (including unions), its associated
+ // classes are: the class itself; the class of which it is a
+ // member, if any; and its direct and indirect base
+ // classes. Its associated namespaces are the namespaces in
+ // which its associated classes are defined.
+ case Type::Record: {
+ CXXRecordDecl *Class
+ = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
+ addAssociatedClassesAndNamespaces(Result, Class);
+ break;
}
- // -- If T is an enumeration type, its associated namespace is
- // the namespace in which it is defined. If it is class
- // member, its associated class is the member’s class; else
- // it has no associated class.
- if (const EnumType *EnumT = T->getAs<EnumType>()) {
- EnumDecl *Enum = EnumT->getDecl();
+ // -- If T is an enumeration type, its associated namespace is
+ // the namespace in which it is defined. If it is class
+ // member, its associated class is the member’s class; else
+ // it has no associated class.
+ case Type::Enum: {
+ EnumDecl *Enum = cast<EnumType>(T)->getDecl();
- DeclContext *Ctx = Enum->getDeclContext();
- if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
- AssociatedClasses.insert(EnclosingClass);
+ DeclContext *Ctx = Enum->getDeclContext();
+ if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.Classes.insert(EnclosingClass);
- // Add the associated namespace for this class.
- CollectEnclosingNamespace(AssociatedNamespaces, Ctx);
+ // Add the associated namespace for this class.
+ CollectEnclosingNamespace(Result.Namespaces, Ctx);
- return;
- }
+ break;
+ }
- // -- If T is a function type, its associated namespaces and
- // classes are those associated with the function parameter
- // types and those associated with the return type.
- if (const FunctionType *FnType = T->getAs<FunctionType>()) {
- // Return type
- addAssociatedClassesAndNamespaces(FnType->getResultType(),
- Context,
- AssociatedNamespaces, AssociatedClasses);
+ // -- If T is a function type, its associated namespaces and
+ // classes are those associated with the function parameter
+ // types and those associated with the return type.
+ case Type::FunctionProto: {
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ Queue.push_back(Arg->getTypePtr());
+ // fallthrough
+ }
+ case Type::FunctionNoProto: {
+ const FunctionType *FnType = cast<FunctionType>(T);
+ T = FnType->getResultType().getTypePtr();
+ continue;
+ }
- const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
- if (!Proto)
- return;
+ // -- If T is a pointer to a member function of a class X, its
+ // associated namespaces and classes are those associated
+ // with the function parameter types and return type,
+ // together with those associated with X.
+ //
+ // -- If T is a pointer to a data member of class X, its
+ // associated namespaces and classes are those associated
+ // with the member type together with those associated with
+ // X.
+ case Type::MemberPointer: {
+ const MemberPointerType *MemberPtr = cast<MemberPointerType>(T);
+
+ // Queue up the class type into which this points.
+ Queue.push_back(MemberPtr->getClass());
+
+ // And directly continue with the pointee type.
+ T = MemberPtr->getPointeeType().getTypePtr();
+ continue;
+ }
- // Argument types
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- addAssociatedClassesAndNamespaces(*Arg, Context,
- AssociatedNamespaces, AssociatedClasses);
+ // As an extension, treat this like a normal pointer.
+ case Type::BlockPointer:
+ T = cast<BlockPointerType>(T)->getPointeeType().getTypePtr();
+ continue;
- return;
- }
+ // References aren't covered by the standard, but that's such an
+ // obvious defect that we cover them anyway.
+ case Type::LValueReference:
+ case Type::RValueReference:
+ T = cast<ReferenceType>(T)->getPointeeType().getTypePtr();
+ continue;
- // -- If T is a pointer to a member function of a class X, its
- // associated namespaces and classes are those associated
- // with the function parameter types and return type,
- // together with those associated with X.
- //
- // -- If T is a pointer to a data member of class X, its
- // associated namespaces and classes are those associated
- // with the member type together with those associated with
- // X.
- if (const MemberPointerType *MemberPtr = T->getAs<MemberPointerType>()) {
- // Handle the type that the pointer to member points to.
- addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
- Context,
- AssociatedNamespaces,
- AssociatedClasses);
-
- // Handle the class type into which this points.
- if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>())
- addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
- Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ // These are fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ break;
- return;
- }
+ // These are ignored by ADL.
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ break;
+ }
- // FIXME: What about block pointers?
- // FIXME: What about Objective-C message sends?
+ if (Queue.empty()) break;
+ T = Queue.back();
+ Queue.pop_back();
+ }
}
/// \brief Find the associated classes and namespaces for
@@ -1723,6 +1868,8 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaces.clear();
AssociatedClasses.clear();
+ AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses);
+
// C++ [basic.lookup.koenig]p2:
// For each argument type T in the function call, there is a set
// of zero or more associated namespaces and a set of zero or more
@@ -1734,9 +1881,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
Expr *Arg = Args[ArgIdx];
if (Arg->getType() != Context.OverloadTy) {
- addAssociatedClassesAndNamespaces(Arg->getType(), Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ addAssociatedClassesAndNamespaces(Result, Arg->getType());
continue;
}
@@ -1752,17 +1897,11 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
Arg = unaryOp->getSubExpr();
- // TODO: avoid the copies. This should be easy when the cases
- // share a storage implementation.
- llvm::SmallVector<NamedDecl*, 8> Functions;
+ UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg);
+ if (!ULE) continue;
- if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg))
- Functions.append(ULE->decls_begin(), ULE->decls_end());
- else
- continue;
-
- for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(),
- E = Functions.end(); I != E; ++I) {
+ for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
+ I != E; ++I) {
// Look through any using declarations to find the underlying function.
NamedDecl *Fn = (*I)->getUnderlyingDecl();
@@ -1772,9 +1911,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
// Add the classes and namespaces associated with the parameter
// types and return type of this function.
- addAssociatedClassesAndNamespaces(FDecl->getType(), Context,
- AssociatedNamespaces,
- AssociatedClasses);
+ addAssociatedClassesAndNamespaces(Result, FDecl->getType());
}
}
}
@@ -1874,6 +2011,36 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
}
}
+/// \brief Look up the constructors for the given class.
+DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
+ // If the copy constructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class)) {
+ if (!Class->hasDeclaredDefaultConstructor())
+ DeclareImplicitDefaultConstructor(Class);
+ if (!Class->hasDeclaredCopyConstructor())
+ DeclareImplicitCopyConstructor(Class);
+ }
+
+ CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
+ DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
+ return Class->lookup(Name);
+}
+
+/// \brief Look for the destructor of the given class.
+///
+/// During semantic analysis, this routine should be used in lieu of
+/// CXXRecordDecl::getDestructor().
+///
+/// \returns The destructor for this class.
+CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
+ // If the destructor has not yet been declared, do so now.
+ if (CanDeclareSpecialMemberFunction(Context, Class) &&
+ !Class->hasDeclaredDestructor())
+ DeclareImplicitDestructor(Class);
+
+ return Class->getDestructor();
+}
+
void ADLResult::insert(NamedDecl *New) {
NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())];
@@ -2172,6 +2339,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
if (Visited.visitedContext(Ctx->getPrimaryContext()))
return;
+ if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
+ Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+
// Enumerate all of the results in this context.
for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
CurCtx = CurCtx->getNextContext()) {
@@ -2556,7 +2726,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS,
bool EnteringContext,
CorrectTypoContext CTC,
const ObjCObjectPointerType *OPT) {
- if (Diags.hasFatalErrorOccurred())
+ if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
return DeclarationName();
// Provide a stop gap for files that are just seriously broken. Trying
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 4c89a11..44cd271 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -41,7 +41,8 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
!(Attributes & ObjCDeclSpec::DQ_PR_copy)));
- QualType T = GetTypeForDeclarator(FD.D, S);
+ TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
+ QualType T = TSI->getType();
if (T->isReferenceType()) {
Diag(AtLoc, diag::error_reference_property);
return DeclPtrTy();
@@ -56,13 +57,13 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
FD, GetterSel, SetterSel,
isAssign, isReadWrite,
Attributes,
- isOverridingProperty, T,
+ isOverridingProperty, TSI,
MethodImplKind);
DeclPtrTy Res = DeclPtrTy::make(CreatePropertyDecl(S, ClassDecl, AtLoc, FD,
GetterSel, SetterSel,
isAssign, isReadWrite,
- Attributes, T, MethodImplKind));
+ Attributes, TSI, MethodImplKind));
// Validate the attributes on the @property.
CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
return Res;
@@ -76,7 +77,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
const bool isReadWrite,
const unsigned Attributes,
bool *isOverridingProperty,
- QualType T,
+ TypeSourceInfo *T,
tok::ObjCKeywordKind MethodImplKind) {
// Diagnose if this property is already in continuation class.
@@ -122,6 +123,10 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
CreatePropertyDecl(S, CCPrimary, AtLoc,
FD, GetterSel, SetterSel, isAssign, isReadWrite,
Attributes, T, MethodImplKind, DC);
+ // Mark written attribute as having no attribute because
+ // this is not a user-written property declaration in primary
+ // class.
+ PDecl->setPropertyAttributesAsWritten(ObjCPropertyDecl::OBJC_PR_noattr);
// A case of continuation class adding a new property in the class. This
// is not what it was meant for. However, gcc supports it and so should we.
@@ -133,7 +138,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
// The property 'PIDecl's readonly attribute will be over-ridden
// with continuation class's readwrite property attribute!
- unsigned PIkind = PIDecl->getPropertyAttributes();
+ unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
unsigned retainCopyNonatomic =
(ObjCPropertyDecl::OBJC_PR_retain |
@@ -190,11 +195,11 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
const bool isAssign,
const bool isReadWrite,
const unsigned Attributes,
- QualType T,
+ TypeSourceInfo *TInfo,
tok::ObjCKeywordKind MethodImplKind,
DeclContext *lexicalDC){
-
IdentifierInfo *PropertyId = FD.D.getIdentifier();
+ QualType T = TInfo->getType();
// Issue a warning if property is 'assign' as default and its object, which is
// gc'able conforms to NSCopying protocol
@@ -215,7 +220,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
DeclContext *DC = cast<DeclContext>(CDecl);
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
FD.D.getIdentifierLoc(),
- PropertyId, AtLoc, T);
+ PropertyId, AtLoc, TInfo);
if (ObjCPropertyDecl *prevDecl =
ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
@@ -265,6 +270,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
+ PDecl->setPropertyAttributesAsWritten(PDecl->getPropertyAttributes());
+
if (MethodImplKind == tok::objc_required)
PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
else if (MethodImplKind == tok::objc_optional)
@@ -771,7 +778,8 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
/// CollectImmediateProperties - This routine collects all properties in
/// the class and its conforming protocols; but not those it its super class.
void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
- llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) {
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
E = IDecl->prop_end(); P != E; ++P) {
@@ -781,10 +789,7 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
// scan through class's protocols.
for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
E = IDecl->protocol_end(); PI != E; ++PI)
- // Exclude property for protocols which conform to class's super-class,
- // as super-class has to implement the property.
- if (!ProtocolConformsToSuperClass(IDecl, (*PI)))
- CollectImmediateProperties((*PI), PropMap);
+ CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
if (!CATDecl->IsClassExtension())
@@ -796,20 +801,25 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
// scan through class's protocols.
for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
E = CATDecl->protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap);
+ CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
E = PDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Prop = (*P);
- ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
- if (!PropEntry)
- PropEntry = Prop;
+ ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
+ // Exclude property for protocols which conform to class's super-class,
+ // as super-class has to implement the property.
+ if (!PropertyFromSuper || PropertyFromSuper != Prop) {
+ ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
+ if (!PropEntry)
+ PropEntry = Prop;
+ }
}
// scan through protocol's protocols.
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
E = PDecl->protocol_end(); PI != E; ++PI)
- CollectImmediateProperties((*PI), PropMap);
+ CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
}
@@ -854,33 +864,6 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
}
}
-/// ProtocolConformsToSuperClass - Returns true if class's given protocol
-/// conforms to one of its super class's protocols.
-bool Sema::ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl,
- const ObjCProtocolDecl *PDecl) {
- if (const ObjCInterfaceDecl *CDecl = IDecl->getSuperClass()) {
- for (ObjCInterfaceDecl::protocol_iterator PI = CDecl->protocol_begin(),
- E = CDecl->protocol_end(); PI != E; ++PI) {
- if (ProtocolConformsToProtocol((*PI), PDecl))
- return true;
- return ProtocolConformsToSuperClass(CDecl, PDecl);
- }
- }
- return false;
-}
-
-bool Sema::ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol,
- const ObjCProtocolDecl *PDecl) {
- if (PDecl->getIdentifier() == NestedProtocol->getIdentifier())
- return true;
- // scan through protocol's protocols.
- for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); PI != E; ++PI)
- if (ProtocolConformsToProtocol(NestedProtocol, (*PI)))
- return true;
- return false;
-}
-
/// LookupPropertyDecl - Looks up a property in the current class and all
/// its protocols.
ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
@@ -952,8 +935,12 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
ObjCContainerDecl *CDecl,
const llvm::DenseSet<Selector>& InsMap) {
+ llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
+ if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
+ CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
+
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
- CollectImmediateProperties(CDecl, PropMap);
+ CollectImmediateProperties(CDecl, PropMap, SuperPropMap);
if (PropMap.empty())
return;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2754d44..ee4c479 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -155,7 +155,9 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
// check for their presence as well as checking whether FromType is
// a pointer.
if (getToType(1)->isBooleanType() &&
- (getFromType()->isPointerType() || getFromType()->isBlockPointerType() ||
+ (getFromType()->isPointerType() ||
+ getFromType()->isObjCObjectPointerType() ||
+ getFromType()->isBlockPointerType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@@ -498,19 +500,54 @@ void OverloadCandidateSet::clear() {
// identical (return types of functions are not part of the
// signature), IsOverload returns false and MatchedDecl will be set to
// point to the FunctionDecl for #2.
+//
+// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced
+// into a class by a using declaration. The rules for whether to hide
+// shadow declarations ignore some properties which otherwise figure
+// into a function template's signature.
Sema::OverloadKind
-Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old,
- NamedDecl *&Match) {
+Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
+ NamedDecl *&Match, bool NewIsUsingDecl) {
for (LookupResult::iterator I = Old.begin(), E = Old.end();
I != E; ++I) {
- NamedDecl *OldD = (*I)->getUnderlyingDecl();
+ NamedDecl *OldD = *I;
+
+ bool OldIsUsingDecl = false;
+ if (isa<UsingShadowDecl>(OldD)) {
+ OldIsUsingDecl = true;
+
+ // We can always introduce two using declarations into the same
+ // context, even if they have identical signatures.
+ if (NewIsUsingDecl) continue;
+
+ OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl();
+ }
+
+ // If either declaration was introduced by a using declaration,
+ // we'll need to use slightly different rules for matching.
+ // Essentially, these rules are the normal rules, except that
+ // function templates hide function templates with different
+ // return types or template parameter lists.
+ bool UseMemberUsingDeclRules =
+ (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord();
+
if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
- if (!IsOverload(New, OldT->getTemplatedDecl())) {
+ if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) {
+ if (UseMemberUsingDeclRules && OldIsUsingDecl) {
+ HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
+ continue;
+ }
+
Match = *I;
return Ovl_Match;
}
} else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) {
- if (!IsOverload(New, OldF)) {
+ if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
+ if (UseMemberUsingDeclRules && OldIsUsingDecl) {
+ HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
+ continue;
+ }
+
Match = *I;
return Ovl_Match;
}
@@ -534,7 +571,8 @@ Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old,
return Ovl_Overload;
}
-bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
+ bool UseUsingDeclRules) {
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
@@ -579,7 +617,10 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {
//
// We check the return type and template parameter lists for function
// templates first; the remaining checks follow.
- if (NewTemplate &&
+ //
+ // However, we don't consider either of these when deciding whether
+ // a member introduced by a shadow declaration is hidden.
+ if (!UseUsingDeclRules && NewTemplate &&
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
@@ -804,7 +845,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
return false;
// Vector splat from any arithmetic type to a vector.
- if (!FromType->isVectorType() && FromType->isArithmeticType()) {
+ if (FromType->isArithmeticType()) {
ICK = ICK_Vector_Splat;
return true;
}
@@ -960,8 +1001,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// Complex promotion (Clang extension)
SCS.Second = ICK_Complex_Promotion;
FromType = ToType.getUnqualifiedType();
- } else if ((FromType->isIntegralType() || FromType->isEnumeralType()) &&
- (ToType->isIntegralType() && !ToType->isEnumeralType())) {
+ } else if (FromType->isIntegralOrEnumerationType() &&
+ ToType->isIntegralType(Context)) {
// Integral conversions (C++ 4.7).
SCS.Second = ICK_Integral_Conversion;
FromType = ToType.getUnqualifiedType();
@@ -974,15 +1015,14 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// Complex-real conversions (C99 6.3.1.7)
SCS.Second = ICK_Complex_Real;
FromType = ToType.getUnqualifiedType();
- } else if (FromType->isFloatingType() && ToType->isFloatingType()) {
+ } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) {
// Floating point conversions (C++ 4.8).
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if ((FromType->isFloatingType() &&
- ToType->isIntegralType() && (!ToType->isBooleanType() &&
- !ToType->isEnumeralType())) ||
- ((FromType->isIntegralType() || FromType->isEnumeralType()) &&
- ToType->isFloatingType())) {
+ } else if ((FromType->isRealFloatingType() &&
+ ToType->isIntegralType(Context) && !ToType->isBooleanType()) ||
+ (FromType->isIntegralOrEnumerationType() &&
+ ToType->isRealFloatingType())) {
// Floating-integral conversions (C++ 4.9).
SCS.Second = ICK_Floating_Integral;
FromType = ToType.getUnqualifiedType();
@@ -1141,7 +1181,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
if (From)
if (FieldDecl *MemberDecl = From->getBitField()) {
APSInt BitWidth;
- if (FromType->isIntegralType() && !FromType->isEnumeralType() &&
+ if (FromType->isIntegralType(Context) &&
MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned());
ToSize = Context.getTypeSize(ToType);
@@ -1271,7 +1311,7 @@ static bool isNullPointerConstantForConversion(Expr *Expr,
// Handle value-dependent integral null pointer constants correctly.
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
if (Expr->isValueDependent() && !Expr->isTypeDependent() &&
- Expr->getType()->isIntegralType())
+ Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType())
return !InOverloadResolution;
return Expr->isNullPointerConstant(Context,
@@ -1622,6 +1662,12 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
+ if (CXXBoolLiteralExpr* LitBool
+ = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens()))
+ if (LitBool->getValue() == false)
+ Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false)
+ << ToType;
+
if (const PointerType *FromPtrType = FromType->getAs<PointerType>())
if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
QualType FromPointeeType = FromPtrType->getPointeeType(),
@@ -1779,7 +1825,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
// in multi-level pointers, subject to the following rules: [...]
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
- while (UnwrapSimilarPointerTypes(FromType, ToType)) {
+ while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -1850,12 +1896,8 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
// We're not going to find any constructors.
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
- DeclarationName ConstructorName
- = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(ToType).getUnqualifiedType());
DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd)
- = ToRecordDecl->lookup(ConstructorName);
+ for (llvm::tie(Con, ConEnd) = LookupConstructors(ToRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -2067,6 +2109,16 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
return ImplicitConversionSequence::Indistinguishable;
}
+static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
+ while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ Qualifiers Quals;
+ T1 = Context.getUnqualifiedArrayType(T1, Quals);
+ T2 = Context.getUnqualifiedArrayType(T2, Quals);
+ }
+
+ return Context.hasSameUnqualifiedType(T1, T2);
+}
+
// 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
@@ -2092,7 +2144,7 @@ compareStandardConversionSubsets(ASTContext &Context,
Result = ImplicitConversionSequence::Worse;
else
return ImplicitConversionSequence::Indistinguishable;
- } else if (!Context.hasSameType(SCS1.getToType(1), SCS2.getToType(1)))
+ } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1)))
return ImplicitConversionSequence::Indistinguishable;
if (SCS1.Third == SCS2.Third) {
@@ -2299,7 +2351,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
- while (UnwrapSimilarPointerTypes(T1, T2)) {
+ while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -2566,6 +2618,95 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
return Ref_Related;
}
+/// \brief Look for a user-defined conversion to an lvalue reference-compatible
+/// with DeclType. Return true if something definite is found.
+static bool
+FindConversionToLValue(Sema &S, ImplicitConversionSequence &ICS,
+ QualType DeclType, SourceLocation DeclLoc,
+ Expr *Init, QualType T2, bool AllowExplicit) {
+ assert(T2->isRecordType() && "Can only find conversions of record types.");
+ CXXRecordDecl *T2RecordDecl
+ = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
+
+ OverloadCandidateSet CandidateSet(DeclLoc);
+ const UnresolvedSetImpl *Conversions
+ = T2RecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate
+ = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(D);
+
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion. An rvalue reference
+ // is only acceptable if its referencee is a function type.
+ const ReferenceType *RefType =
+ Conv->getConversionType()->getAs<ReferenceType>();
+ if (RefType && (RefType->isLValueReferenceType() ||
+ RefType->getPointeeType()->isFunctionType()) &&
+ (AllowExplicit || !Conv->isExplicit())) {
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
+ Init, DeclType, CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
+ DeclType, CandidateSet);
+ }
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+ case OR_Success:
+ // C++ [over.ics.ref]p1:
+ //
+ // [...] If the parameter binds directly to the result of
+ // applying a conversion function to the argument
+ // expression, the implicit conversion sequence is a
+ // user-defined conversion sequence (13.3.3.1.2), with the
+ // second standard conversion sequence either an identity
+ // conversion or, if the conversion function returns an
+ // entity of a type that is a derived class of the parameter
+ // type, a derived-to-base Conversion.
+ if (!Best->FinalConversion.DirectBinding)
+ return false;
+
+ ICS.setUserDefined();
+ ICS.UserDefined.Before = Best->Conversions[0].Standard;
+ ICS.UserDefined.After = Best->FinalConversion;
+ ICS.UserDefined.ConversionFunction = Best->Function;
+ ICS.UserDefined.EllipsisConversion = false;
+ assert(ICS.UserDefined.After.ReferenceBinding &&
+ ICS.UserDefined.After.DirectBinding &&
+ "Expected a direct reference binding!");
+ return true;
+
+ case OR_Ambiguous:
+ ICS.setAmbiguous();
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+ Cand != CandidateSet.end(); ++Cand)
+ if (Cand->Viable)
+ ICS.Ambiguous.addConversion(Cand->Function);
+ return true;
+
+ case OR_No_Viable_Function:
+ case OR_Deleted:
+ // There was no suitable conversion, or we found a deleted
+ // conversion; continue with other checks.
+ return false;
+ }
+
+ return false;
+}
+
/// \brief Compute an implicit conversion sequence for reference
/// initialization.
static ImplicitConversionSequence
@@ -2595,149 +2736,72 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// Compute some basic properties of the types and the initializer.
bool isRValRef = DeclType->isRValueReferenceType();
bool DerivedToBase = false;
- Expr::isLvalueResult InitLvalue = Init->isLvalue(S.Context);
+ Expr::Classification InitCategory = Init->Classify(S.Context);
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
- // C++ [over.ics.ref]p3:
- // Except for an implicit object parameter, for which see 13.3.1,
- // a standard conversion sequence cannot be formed if it requires
- // binding an lvalue reference to non-const to an rvalue or
- // binding an rvalue reference to an lvalue.
- //
- // FIXME: DPG doesn't trust this code. It seems far too early to
- // abort because of a binding of an rvalue reference to an lvalue.
- if (isRValRef && InitLvalue == Expr::LV_Valid)
- return ICS;
-
- // C++0x [dcl.init.ref]p16:
+ // C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression
// of type "cv2 T2" as follows:
- // -- If the initializer expression
- // -- is an lvalue (but is not a bit-field), and "cv1 T1" is
- // reference-compatible with "cv2 T2," or
- //
- // Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
- if (InitLvalue == Expr::LV_Valid &&
- RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
- // C++ [over.ics.ref]p1:
- // When a parameter of reference type binds directly (8.5.3)
- // to an argument expression, the implicit conversion sequence
- // is the identity conversion, unless the argument expression
- // has a type that is a derived class of the parameter type,
- // in which case the implicit conversion sequence is a
- // derived-to-base Conversion (13.3.3.1).
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.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;
- ICS.Standard.CopyConstructor = 0;
-
- // Nothing more to do: the inaccessibility/ambiguity check for
- // derived-to-base conversions is suppressed when we're
- // computing the implicit conversion sequence (C++
- // [over.best.ics]p2).
- return ICS;
- }
-
- // -- has a class type (i.e., T2 is a class type), where T1 is
- // not reference-related to T2, and can be implicitly
- // converted to an lvalue of type "cv3 T3," where "cv1 T1"
- // is reference-compatible with "cv3 T3" 92) (this
- // conversion is selected by enumerating the applicable
- // conversion functions (13.3.1.6) and choosing the best
- // one through overload resolution (13.3)),
- if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
- !S.RequireCompleteType(DeclLoc, T2, 0) &&
- RefRelationship == Sema::Ref_Incompatible) {
- CXXRecordDecl *T2RecordDecl
- = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
-
- OverloadCandidateSet CandidateSet(DeclLoc);
- const UnresolvedSetImpl *Conversions
- = T2RecordDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
- NamedDecl *D = *I;
- CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
- if (isa<UsingShadowDecl>(D))
- D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
- FunctionTemplateDecl *ConvTemplate
- = dyn_cast<FunctionTemplateDecl>(D);
- CXXConversionDecl *Conv;
- if (ConvTemplate)
- Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
- else
- Conv = cast<CXXConversionDecl>(D);
-
- // If the conversion function doesn't return a reference type,
- // it can't be considered for this conversion.
- if (Conv->getConversionType()->isLValueReferenceType() &&
- (AllowExplicit || !Conv->isExplicit())) {
- if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
- Init, DeclType, CandidateSet);
- else
- S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
- DeclType, CandidateSet);
- }
- }
-
- OverloadCandidateSet::iterator Best;
- switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
- case OR_Success:
+ // -- If reference is an lvalue reference and the initializer expression
+ // The next bullet point (T1 is a function) is pretty much equivalent to this
+ // one, so it's handled here.
+ if (!isRValRef || T1->isFunctionType()) {
+ // -- is an lvalue (but is not a bit-field), and "cv1 T1" is
+ // reference-compatible with "cv2 T2," or
+ //
+ // Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
+ if (InitCategory.isLValue() &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
// C++ [over.ics.ref]p1:
- //
- // [...] If the parameter binds directly to the result of
- // applying a conversion function to the argument
- // expression, the implicit conversion sequence is a
- // user-defined conversion sequence (13.3.3.1.2), with the
- // second standard conversion sequence either an identity
- // conversion or, if the conversion function returns an
- // entity of a type that is a derived class of the parameter
- // type, a derived-to-base Conversion.
- if (!Best->FinalConversion.DirectBinding)
- break;
-
- ICS.setUserDefined();
- ICS.UserDefined.Before = Best->Conversions[0].Standard;
- ICS.UserDefined.After = Best->FinalConversion;
- ICS.UserDefined.ConversionFunction = Best->Function;
- ICS.UserDefined.EllipsisConversion = false;
- assert(ICS.UserDefined.After.ReferenceBinding &&
- ICS.UserDefined.After.DirectBinding &&
- "Expected a direct reference binding!");
- return ICS;
-
- case OR_Ambiguous:
- ICS.setAmbiguous();
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
- Cand != CandidateSet.end(); ++Cand)
- if (Cand->Viable)
- ICS.Ambiguous.addConversion(Cand->Function);
+ // When a parameter of reference type binds directly (8.5.3)
+ // to an argument expression, the implicit conversion sequence
+ // is the identity conversion, unless the argument expression
+ // has a type that is a derived class of the parameter type,
+ // in which case the implicit conversion sequence is a
+ // derived-to-base Conversion (13.3.3.1).
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+ ICS.Standard.Third = ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.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 = isRValRef;
+ ICS.Standard.CopyConstructor = 0;
+
+ // Nothing more to do: the inaccessibility/ambiguity check for
+ // derived-to-base conversions is suppressed when we're
+ // computing the implicit conversion sequence (C++
+ // [over.best.ics]p2).
return ICS;
+ }
- case OR_No_Viable_Function:
- case OR_Deleted:
- // There was no suitable conversion, or we found a deleted
- // conversion; continue with other checks.
- break;
+ // -- has a class type (i.e., T2 is a class type), where T1 is
+ // not reference-related to T2, and can be implicitly
+ // converted to an lvalue of type "cv3 T3," where "cv1 T1"
+ // is reference-compatible with "cv3 T3" 92) (this
+ // conversion is selected by enumerating the applicable
+ // conversion functions (13.3.1.6) and choosing the best
+ // one through overload resolution (13.3)),
+ if (!SuppressUserConversions && T2->isRecordType() &&
+ !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ RefRelationship == Sema::Ref_Incompatible) {
+ if (FindConversionToLValue(S, ICS, DeclType, DeclLoc,
+ Init, T2, AllowExplicit))
+ return ICS;
}
}
- // -- Otherwise, the reference shall be to a 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.
+ // -- Otherwise, the reference shall be an lvalue reference to a
+ // 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 or have a function type.
//
// We actually handle one oddity of C++ [over.ics.ref] at this
// point, which is that, due to p2 (which short-circuits reference
@@ -2746,10 +2810,26 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// reference to bind to an rvalue. Hence the check for the presence
// of "const" rather than checking for "const" being the only
// qualifier.
- if (!isRValRef && !T1.isConstQualified())
+ // This is also the point where rvalue references and lvalue inits no longer
+ // go together.
+ if ((!isRValRef && !T1.isConstQualified()) ||
+ (isRValRef && InitCategory.isLValue()))
+ return ICS;
+
+ // -- If T1 is a function type, then
+ // -- if T2 is the same type as T1, the reference is bound to the
+ // initializer expression lvalue;
+ // -- if T2 is a class type and the initializer expression can be
+ // implicitly converted to an lvalue of type T1 [...], the
+ // reference is bound to the function lvalue that is the result
+ // of the conversion;
+ // This is the same as for the lvalue case above, so it was handled there.
+ // -- otherwise, the program is ill-formed.
+ // This is the one difference to the lvalue case.
+ if (T1->isFunctionType())
return ICS;
- // -- if T2 is a class type and
+ // -- Otherwise, if T2 is a class type and
// -- the initializer expression is an rvalue and "cv1 T1"
// is reference-compatible with "cv2 T2," or
//
@@ -2768,7 +2848,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
//
// We're only checking the first case here, which is a direct
// binding in C++0x but not in C++03.
- if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
+ if (InitCategory.isRValue() && T2->isRecordType() &&
RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
@@ -3012,6 +3092,177 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
return true;
}
+/// \brief Attempt to convert the given expression to an integral or
+/// enumeration type.
+///
+/// This routine will attempt to convert an expression of class type to an
+/// integral or enumeration type, if that class type only has a single
+/// conversion to an integral or enumeration type.
+///
+/// \param Loc The source location of the construct that requires the
+/// conversion.
+///
+/// \param FromE The expression we're converting from.
+///
+/// \param NotIntDiag The diagnostic to be emitted if the expression does not
+/// have integral or enumeration type.
+///
+/// \param IncompleteDiag The diagnostic to be emitted if the expression has
+/// incomplete class type.
+///
+/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an
+/// explicit conversion function (because no implicit conversion functions
+/// were available). This is a recovery mode.
+///
+/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag,
+/// showing which conversion was picked.
+///
+/// \param AmbigDiag The diagnostic to be emitted if there is more than one
+/// conversion function that could convert to integral or enumeration type.
+///
+/// \param AmbigNote The note to be emitted with \p AmbigDiag for each
+/// usable conversion function.
+///
+/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
+/// function, which may be an extension in this case.
+///
+/// \returns The expression, converted to an integral or enumeration type if
+/// successful.
+Sema::OwningExprResult
+Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
+ const PartialDiagnostic &NotIntDiag,
+ const PartialDiagnostic &IncompleteDiag,
+ const PartialDiagnostic &ExplicitConvDiag,
+ const PartialDiagnostic &ExplicitConvNote,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &AmbigNote,
+ const PartialDiagnostic &ConvDiag) {
+ Expr *From = static_cast<Expr *>(FromE.get());
+
+ // We can't perform any more checking for type-dependent expressions.
+ if (From->isTypeDependent())
+ return move(FromE);
+
+ // If the expression already has integral or enumeration type, we're golden.
+ QualType T = From->getType();
+ if (T->isIntegralOrEnumerationType())
+ return move(FromE);
+
+ // FIXME: Check for missing '()' if T is a function type?
+
+ // If we don't have a class type in C++, there's no way we can get an
+ // expression of integral or enumeration type.
+ const RecordType *RecordTy = T->getAs<RecordType>();
+ if (!RecordTy || !getLangOptions().CPlusPlus) {
+ Diag(Loc, NotIntDiag)
+ << T << From->getSourceRange();
+ return move(FromE);
+ }
+
+ // We must have a complete class type.
+ if (RequireCompleteType(Loc, T, IncompleteDiag))
+ return move(FromE);
+
+ // Look for a conversion to an integral or enumeration type.
+ UnresolvedSet<4> ViableConversions;
+ UnresolvedSet<4> ExplicitConversions;
+ const UnresolvedSetImpl *Conversions
+ = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
+
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end();
+ I != E;
+ ++I) {
+ if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
+ if (Conversion->getConversionType().getNonReferenceType()
+ ->isIntegralOrEnumerationType()) {
+ if (Conversion->isExplicit())
+ ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
+ else
+ ViableConversions.addDecl(I.getDecl(), I.getAccess());
+ }
+ }
+
+ switch (ViableConversions.size()) {
+ case 0:
+ if (ExplicitConversions.size() == 1) {
+ DeclAccessPair Found = ExplicitConversions[0];
+ CXXConversionDecl *Conversion
+ = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+
+ // The user probably meant to invoke the given explicit
+ // conversion; use it.
+ QualType ConvTy
+ = Conversion->getConversionType().getNonReferenceType();
+ std::string TypeStr;
+ ConvTy.getAsStringInternal(TypeStr, Context.PrintingPolicy);
+
+ Diag(Loc, ExplicitConvDiag)
+ << T << ConvTy
+ << FixItHint::CreateInsertion(From->getLocStart(),
+ "static_cast<" + TypeStr + ">(")
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),
+ ")");
+ Diag(Conversion->getLocation(), ExplicitConvNote)
+ << ConvTy->isEnumeralType() << ConvTy;
+
+ // If we aren't in a SFINAE context, build a call to the
+ // explicit conversion function.
+ if (isSFINAEContext())
+ return ExprError();
+
+ CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+ From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found, Conversion);
+ FromE = Owned(From);
+ }
+
+ // We'll complain below about a non-integral condition type.
+ break;
+
+ case 1: {
+ // Apply this conversion.
+ DeclAccessPair Found = ViableConversions[0];
+ CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+
+ CXXConversionDecl *Conversion
+ = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+ QualType ConvTy
+ = Conversion->getConversionType().getNonReferenceType();
+ if (ConvDiag.getDiagID()) {
+ if (isSFINAEContext())
+ return ExprError();
+
+ Diag(Loc, ConvDiag)
+ << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
+ }
+
+ From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found,
+ cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
+ FromE = Owned(From);
+ break;
+ }
+
+ default:
+ Diag(Loc, AmbigDiag)
+ << T << From->getSourceRange();
+ for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+ CXXConversionDecl *Conv
+ = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
+ QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+ Diag(Conv->getLocation(), AmbigNote)
+ << ConvTy->isEnumeralType() << ConvTy;
+ }
+ return move(FromE);
+ }
+
+ if (!From->getType()->isIntegralOrEnumerationType())
+ Diag(Loc, NotIntDiag)
+ << From->getType() << From->getSourceRange();
+
+ return move(FromE);
+}
+
/// AddOverloadCandidate - Adds the given function to the set of
/// candidate functions, using the given function call arguments. If
/// @p SuppressUserConversions, then don't allow user-defined
@@ -4949,7 +5200,7 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
// - F1 is a non-template function and F2 is a function template
// specialization, or, if not that,
- if (Cand1.Function && !Cand1.Function->getPrimaryTemplate() &&
+ if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) &&
Cand2.Function && Cand2.Function->getPrimaryTemplate())
return true;
@@ -5230,6 +5481,46 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
return;
}
+ // Diagnose base -> derived pointer conversions.
+ unsigned BaseToDerivedConversion = 0;
+ if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) {
+ if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) {
+ if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+ FromPtrTy->getPointeeType()) &&
+ !FromPtrTy->getPointeeType()->isIncompleteType() &&
+ !ToPtrTy->getPointeeType()->isIncompleteType() &&
+ S.IsDerivedFrom(ToPtrTy->getPointeeType(),
+ FromPtrTy->getPointeeType()))
+ BaseToDerivedConversion = 1;
+ }
+ } else if (const ObjCObjectPointerType *FromPtrTy
+ = FromTy->getAs<ObjCObjectPointerType>()) {
+ if (const ObjCObjectPointerType *ToPtrTy
+ = ToTy->getAs<ObjCObjectPointerType>())
+ if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl())
+ if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl())
+ if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
+ FromPtrTy->getPointeeType()) &&
+ FromIface->isSuperClassOf(ToIface))
+ BaseToDerivedConversion = 2;
+ } else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) {
+ if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
+ !FromTy->isIncompleteType() &&
+ !ToRefTy->getPointeeType()->isIncompleteType() &&
+ S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy))
+ BaseToDerivedConversion = 3;
+ }
+
+ if (BaseToDerivedConversion) {
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_bad_base_to_derived_conv)
+ << (unsigned) FnKind << FnDesc
+ << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+ << (BaseToDerivedConversion - 1)
+ << FromTy << ToTy << I+1;
+ return;
+ }
+
// TODO: specialize more based on the kind of mismatch
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
<< (unsigned) FnKind << FnDesc
@@ -5673,7 +5964,10 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
Cands.push_back(Cand);
else if (OCD == OCD_AllCandidates) {
CompleteNonViableCandidate(*this, Cand, Args, NumArgs);
- Cands.push_back(Cand);
+ if (Cand->Function || Cand->IsSurrogate)
+ Cands.push_back(Cand);
+ // Otherwise, this a non-viable builtin candidate. We do not, in general,
+ // want to list every possible builtin candidate.
}
}
@@ -5683,17 +5977,26 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
bool ReportedAmbiguousConversions = false;
llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
+ const Diagnostic::OverloadsShown ShowOverloads = Diags.getShowOverloads();
+ unsigned CandsShown = 0;
for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
OverloadCandidate *Cand = *I;
+ // Set an arbitrary limit on the number of candidate functions we'll spam
+ // the user with. FIXME: This limit should depend on details of the
+ // candidate list.
+ if (CandsShown >= 4 && ShowOverloads == Diagnostic::Ovl_Best) {
+ break;
+ }
+ ++CandsShown;
+
if (Cand->Function)
NoteFunctionCandidate(*this, Cand, Args, NumArgs);
else if (Cand->IsSurrogate)
NoteSurrogateCandidate(*this, Cand);
-
- // This a builtin candidate. We do not, in general, want to list
- // every possible builtin candidate.
- else if (Cand->Viable) {
+ else {
+ assert(Cand->Viable &&
+ "Non-viable built-in candidates are not added to Cands.");
// Generally we only see ambiguities including viable builtin
// operators if overload resolution got screwed up by an
// ambiguous user-defined conversion.
@@ -5709,6 +6012,9 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
}
}
+
+ if (I != E)
+ Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
@@ -6159,7 +6465,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs),
CommaLocs, RParenLoc);
}
-
+
/// ResolveOverloadedCallFn - Given the call expression that calls Fn
/// (which eventually refers to the declaration Func) and the call
/// arguments Args/NumArgs, attempt to resolve the function call down
@@ -6290,6 +6596,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
}
if (Input->isTypeDependent()) {
+ if (Fns.empty())
+ return Owned(new (Context) UnaryOperator(input.takeAs<Expr>(),
+ Opc,
+ Context.DependentTy,
+ OpLoc));
+
CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
@@ -6356,7 +6668,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
// Determine the result type
- QualType ResultTy = FnDecl->getResultType().getNonReferenceType();
+ QualType ResultTy = FnDecl->getCallResultType();
// Build the actual expression node.
Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
@@ -6563,8 +6875,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Determine the result type
QualType ResultTy
- = FnDecl->getType()->getAs<FunctionType>()->getResultType();
- ResultTy = ResultTy.getNonReferenceType();
+ = FnDecl->getType()->getAs<FunctionType>()
+ ->getCallResultType(Context);
// Build the actual expression node.
Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
@@ -6720,8 +7032,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// Determine the result type
QualType ResultTy
- = FnDecl->getType()->getAs<FunctionType>()->getResultType();
- ResultTy = ResultTy.getNonReferenceType();
+ = FnDecl->getType()->getAs<FunctionType>()
+ ->getCallResultType(Context);
// Build the actual expression node.
Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
@@ -6909,7 +7221,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
ExprOwningPtr<CXXMemberCallExpr>
TheCall(this, new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
NumArgs,
- Method->getResultType().getNonReferenceType(),
+ Method->getCallResultType(),
RParenLoc));
// Check for a valid return type.
@@ -7124,7 +7436,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Once we've built TheCall, all of the expressions are properly
// owned.
- QualType ResultTy = Method->getResultType().getNonReferenceType();
+ QualType ResultTy = Method->getCallResultType();
ExprOwningPtr<CXXOperatorCallExpr>
TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
MethodArgs, NumArgs + 1,
@@ -7280,7 +7592,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
SourceLocation());
UsualUnaryConversions(FnExpr);
- QualType ResultTy = Method->getResultType().getNonReferenceType();
+ QualType ResultTy = Method->getCallResultType();
ExprOwningPtr<CXXOperatorCallExpr>
TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
&Base, 1, ResultTy, OpLoc));
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 875b160..9c8f48b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -92,12 +92,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
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 (E->getType()->isVoidType())
@@ -304,7 +298,7 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar,
DiagnoseUnusedExprResult(elseStmt);
CondResult.release();
- return Owned(new (Context) IfStmt(IfLoc, ConditionVar, ConditionExpr,
+ return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
thenStmt, ElseLoc, elseStmt));
}
@@ -400,124 +394,16 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs,
/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
/// potentially integral-promoted expression @p expr.
static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) {
- const ImplicitCastExpr *ImplicitCast =
- dyn_cast_or_null<ImplicitCastExpr>(expr);
- if (ImplicitCast != NULL) {
+ if (const CastExpr *ImplicitCast = dyn_cast<ImplicitCastExpr>(expr)) {
const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr();
QualType TypeBeforePromotion = ExprBeforePromotion->getType();
- if (TypeBeforePromotion->isIntegralType()) {
+ if (TypeBeforePromotion->isIntegralOrEnumerationType()) {
return TypeBeforePromotion;
}
}
return expr->getType();
}
-/// \brief Check (and possibly convert) the condition in a switch
-/// statement in C++.
-static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,
- Expr *&CondExpr) {
- if (CondExpr->isTypeDependent())
- return false;
-
- QualType CondType = CondExpr->getType();
-
- // C++ 6.4.2.p2:
- // The condition shall be of integral type, enumeration type, or of a class
- // type for which a single conversion function to integral or enumeration
- // type exists (12.3). If the condition is of class type, the condition is
- // converted by calling that conversion function, and the result of the
- // conversion is used in place of the original condition for the remainder
- // of this section. Integral promotions are performed.
-
- // Make sure that the condition expression has a complete type,
- // otherwise we'll never find any conversions.
- if (S.RequireCompleteType(SwitchLoc, CondType,
- S.PDiag(diag::err_switch_incomplete_class_type)
- << CondExpr->getSourceRange()))
- return true;
-
- UnresolvedSet<4> ViableConversions;
- UnresolvedSet<4> ExplicitConversions;
- if (const RecordType *RecordTy = CondType->getAs<RecordType>()) {
- const UnresolvedSetImpl *Conversions
- = cast<CXXRecordDecl>(RecordTy->getDecl())
- ->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
- if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
- if (Conversion->getConversionType().getNonReferenceType()
- ->isIntegralType()) {
- if (Conversion->isExplicit())
- ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
- else
- ViableConversions.addDecl(I.getDecl(), I.getAccess());
- }
- }
-
- switch (ViableConversions.size()) {
- case 0:
- if (ExplicitConversions.size() == 1) {
- DeclAccessPair Found = ExplicitConversions[0];
- CXXConversionDecl *Conversion =
- cast<CXXConversionDecl>(Found->getUnderlyingDecl());
- // The user probably meant to invoke the given explicit
- // conversion; use it.
- QualType ConvTy
- = Conversion->getConversionType().getNonReferenceType();
- std::string TypeStr;
- ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy);
-
- S.Diag(SwitchLoc, diag::err_switch_explicit_conversion)
- << CondType << ConvTy << CondExpr->getSourceRange()
- << FixItHint::CreateInsertion(CondExpr->getLocStart(),
- "static_cast<" + TypeStr + ">(")
- << FixItHint::CreateInsertion(
- S.PP.getLocForEndOfToken(CondExpr->getLocEnd()),
- ")");
- S.Diag(Conversion->getLocation(), diag::note_switch_conversion)
- << ConvTy->isEnumeralType() << ConvTy;
-
- // If we aren't in a SFINAE context, build a call to the
- // explicit conversion function.
- if (S.isSFINAEContext())
- return true;
-
- S.CheckMemberOperatorAccess(CondExpr->getExprLoc(),
- CondExpr, 0, Found);
- CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, Conversion);
- }
-
- // We'll complain below about a non-integral condition type.
- break;
-
- case 1: {
- // Apply this conversion.
- DeclAccessPair Found = ViableConversions[0];
- S.CheckMemberOperatorAccess(CondExpr->getExprLoc(),
- CondExpr, 0, Found);
- CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found,
- cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
- break;
- }
-
- default:
- S.Diag(SwitchLoc, diag::err_switch_multiple_conversions)
- << CondType << CondExpr->getSourceRange();
- for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
- CXXConversionDecl *Conv
- = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
- QualType ConvTy = Conv->getConversionType().getNonReferenceType();
- S.Diag(Conv->getLocation(), diag::note_switch_conversion)
- << ConvTy->isEnumeralType() << ConvTy;
- }
- return true;
- }
- }
-
- return false;
-}
-
Action::OwningStmtResult
Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond,
DeclPtrTy CondVar) {
@@ -531,21 +417,32 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond,
Cond = move(CondE);
}
- Expr *CondExpr = Cond.takeAs<Expr>();
- if (!CondExpr)
+ if (!Cond.get())
return StmtError();
- if (getLangOptions().CPlusPlus &&
- CheckCXXSwitchCondition(*this, SwitchLoc, CondExpr))
- return StmtError();
-
+ Expr *CondExpr = static_cast<Expr *>(Cond.get());
+ OwningExprResult ConvertedCond
+ = ConvertToIntegralOrEnumerationType(SwitchLoc, move(Cond),
+ PDiag(diag::err_typecheck_statement_requires_integer),
+ PDiag(diag::err_switch_incomplete_class_type)
+ << CondExpr->getSourceRange(),
+ PDiag(diag::err_switch_explicit_conversion),
+ PDiag(diag::note_switch_conversion),
+ PDiag(diag::err_switch_multiple_conversions),
+ PDiag(diag::note_switch_conversion),
+ PDiag(0));
+ if (ConvertedCond.isInvalid())
+ return StmtError();
+
+ CondExpr = ConvertedCond.takeAs<Expr>();
+
if (!CondVar.get()) {
CondExpr = MaybeCreateCXXExprWithTemporaries(CondExpr);
if (!CondExpr)
return StmtError();
}
- SwitchStmt *SS = new (Context) SwitchStmt(ConditionVar, CondExpr);
+ SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, CondExpr);
getSwitchStack().push_back(SS);
return Owned(SS);
}
@@ -584,11 +481,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// be represented by the promoted type. Therefore we need to find
// the pre-promotion type of the switch condition.
if (!CondExpr->isTypeDependent()) {
- if (!CondType->isIntegerType()) { // C99 6.8.4.2p1
- Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
- << CondType << CondExpr->getSourceRange();
+ // We have already converted the expression to an integral or enumeration
+ // type, when we started the switch statement. If we don't have an
+ // appropriate type now, just return an error.
+ if (!CondType->isIntegralOrEnumerationType())
return StmtError();
- }
if (CondExpr->isKnownToHaveBooleanValue()) {
// switch(bool_expr) {...} is often a programmer error, e.g.
@@ -838,6 +735,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
llvm::APSInt Val = (*EDI)->getInitVal();
if(Val.getBitWidth() < CondWidth)
Val.extend(CondWidth);
+ else if (Val.getBitWidth() > CondWidth)
+ Val.trunc(CondWidth);
Val.setIsSigned(CondIsSigned);
EnumVals.push_back(std::make_pair(Val, (*EDI)));
}
@@ -929,8 +828,8 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
DiagnoseUnusedExprResult(bodyStmt);
CondResult.release();
- return Owned(new (Context) WhileStmt(ConditionVar, ConditionExpr, bodyStmt,
- WhileLoc));
+ return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr,
+ bodyStmt, WhileLoc));
}
Action::OwningStmtResult
@@ -999,9 +898,10 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
first.release();
body.release();
- return Owned(new (Context) ForStmt(First, SecondResult.takeAs<Expr>(),
- ConditionVar, Third, Body,
- ForLoc, LParenLoc, RParenLoc));
+ return Owned(new (Context) ForStmt(Context, First,
+ SecondResult.takeAs<Expr>(), ConditionVar,
+ Third, Body, ForLoc, LParenLoc,
+ RParenLoc));
}
Action::OwningStmtResult
@@ -1517,14 +1417,14 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (InTy->isIntegerType() || InTy->isPointerType())
InputDomain = AD_Int;
- else if (InTy->isFloatingType())
+ else if (InTy->isRealFloatingType())
InputDomain = AD_FP;
else
InputDomain = AD_Other;
if (OutTy->isIntegerType() || OutTy->isPointerType())
OutputDomain = AD_Int;
- else if (OutTy->isFloatingType())
+ else if (OutTy->isRealFloatingType())
OutputDomain = AD_FP;
else
OutputDomain = AD_Other;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 307be9d..7cc4317 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -27,12 +27,12 @@ using namespace clang;
/// \brief Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns NULL.
-static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) {
- if (!D)
- return 0;
+static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
+ NamedDecl *Orig) {
+ NamedDecl *D = Orig->getUnderlyingDecl();
if (isa<TemplateDecl>(D))
- return D;
+ return Orig;
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
// C++ [temp.local]p1:
@@ -68,7 +68,7 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
LookupResult::Filter filter = R.makeFilter();
while (filter.hasNext()) {
NamedDecl *Orig = filter.next();
- NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl());
+ NamedDecl *Repl = isAcceptableTemplateName(C, Orig);
if (!Repl)
filter.erase();
else if (Repl != Orig) {
@@ -258,9 +258,9 @@ void Sema::LookupTemplateName(LookupResult &Found,
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,
- false, CTC_CXXCasts)) {
+ false, CTC_CXXCasts)) {
FilterAcceptableTemplateNames(Context, Found);
- if (!Found.empty() && isa<TemplateDecl>(*Found.begin())) {
+ if (!Found.empty()) {
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
<< Name << LookupCtx << Found.getLookupName() << SS.getRange()
@@ -274,10 +274,10 @@ void Sema::LookupTemplateName(LookupResult &Found,
if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
Diag(Template->getLocation(), diag::note_previous_decl)
<< Template->getDeclName();
- } else
- Found.clear();
+ }
} else {
Found.clear();
+ Found.setLookupName(Name);
}
}
@@ -303,7 +303,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
// - if the name is found in the context of the entire
// postfix-expression and does not name a class template, the name
// found in the class of the object expression is used, otherwise
- } else {
+ } else if (!Found.isSuppressingDiagnostics()) {
// - if the name found is a class template, it must refer to the same
// entity as the one found in the class of the object expression,
// otherwise the program is ill-formed.
@@ -311,8 +311,9 @@ void Sema::LookupTemplateName(LookupResult &Found,
Found.getFoundDecl()->getCanonicalDecl()
!= FoundOuter.getFoundDecl()->getCanonicalDecl()) {
Diag(Found.getNameLoc(),
- diag::err_nested_name_member_ref_lookup_ambiguous)
- << Found.getLookupName();
+ diag::ext_nested_name_member_ref_lookup_ambiguous)
+ << Found.getLookupName()
+ << ObjectType;
Diag(Found.getRepresentativeDecl()->getLocation(),
diag::note_ambig_member_ref_object_type)
<< ObjectType;
@@ -458,7 +459,9 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position) {
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ TypeTy *DefaultArg) {
assert(S->isTemplateParamScope() &&
"Template type parameter not in template parameter scope!");
bool Invalid = false;
@@ -489,42 +492,31 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
IdResolver.AddDecl(Param);
}
- return DeclPtrTy::make(Param);
-}
-
-/// ActOnTypeParameterDefault - Adds a default argument (the type
-/// Default) to the given template type parameter (TypeParam).
-void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
- SourceLocation EqualLoc,
- SourceLocation DefaultLoc,
- TypeTy *DefaultT) {
- TemplateTypeParmDecl *Parm
- = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
-
- TypeSourceInfo *DefaultTInfo;
- GetTypeFromParser(DefaultT, &DefaultTInfo);
-
- assert(DefaultTInfo && "expected source information for type");
-
- // C++0x [temp.param]p9:
- // A default template-argument may be specified for any kind of
- // template-parameter that is not a template parameter pack.
- if (Parm->isParameterPack()) {
- Diag(DefaultLoc, diag::err_template_param_pack_default_arg);
- return;
- }
-
- // C++ [temp.param]p14:
- // A template-parameter shall not be used in its own default argument.
- // FIXME: Implement this check! Needs a recursive walk over the types.
-
- // Check the template argument itself.
- if (CheckTemplateArgument(Parm, DefaultTInfo)) {
- Parm->setInvalidDecl();
- return;
+ // Handle the default argument, if provided.
+ if (DefaultArg) {
+ TypeSourceInfo *DefaultTInfo;
+ GetTypeFromParser(DefaultArg, &DefaultTInfo);
+
+ assert(DefaultTInfo && "expected source information for type");
+
+ // C++0x [temp.param]p9:
+ // A default template-argument may be specified for any kind of
+ // template-parameter that is not a template parameter pack.
+ if (Ellipsis) {
+ Diag(EqualLoc, diag::err_template_param_pack_default_arg);
+ return DeclPtrTy::make(Param);
+ }
+
+ // Check the template argument itself.
+ if (CheckTemplateArgument(Param, DefaultTInfo)) {
+ Param->setInvalidDecl();
+ return DeclPtrTy::make(Param);;
+ }
+
+ Param->setDefaultArgument(DefaultTInfo, false);
}
-
- Parm->setDefaultArgument(DefaultTInfo, false);
+
+ return DeclPtrTy::make(Param);
}
/// \brief Check that the type of a non-type template parameter is
@@ -548,7 +540,7 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
// (optionally cv-qualified) types:
//
// -- integral or enumeration type,
- if (T->isIntegralType() || T->isEnumeralType() ||
+ if (T->isIntegralOrEnumerationType() ||
// -- pointer to object or pointer to function,
(T->isPointerType() &&
(T->getAs<PointerType>()->getPointeeType()->isObjectType() ||
@@ -579,15 +571,13 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
return QualType();
}
-/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
-/// template parameter (e.g., "int Size" in "template<int Size>
-/// class Array") has been parsed. S is the current scope and D is
-/// the parsed declarator.
Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
- unsigned Position) {
- TypeSourceInfo *TInfo = 0;
- QualType T = GetTypeForDeclarator(D, S, &TInfo);
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ExprArg DefaultArg) {
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType T = TInfo->getType();
assert(S->isTemplateParamScope() &&
"Non-type template parameter not in template parameter scope!");
@@ -621,34 +611,21 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
S->AddDecl(DeclPtrTy::make(Param));
IdResolver.AddDecl(Param);
}
- return DeclPtrTy::make(Param);
-}
-
-/// \brief Adds a default argument to the given non-type template
-/// parameter.
-void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD,
- SourceLocation EqualLoc,
- ExprArg DefaultE) {
- NonTypeTemplateParmDecl *TemplateParm
- = cast<NonTypeTemplateParmDecl>(TemplateParamD.getAs<Decl>());
- Expr *Default = static_cast<Expr *>(DefaultE.get());
-
- // C++ [temp.param]p14:
- // A template-parameter shall not be used in its own default argument.
- // FIXME: Implement this check! Needs a recursive walk over the types.
-
- // Check the well-formedness of the default template argument.
- TemplateArgument Converted;
- if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default,
- Converted)) {
- TemplateParm->setInvalidDecl();
- return;
+
+ // Check the well-formedness of the default template argument, if provided.
+ if (Expr *Default = static_cast<Expr *>(DefaultArg.get())) {
+ TemplateArgument Converted;
+ if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
+ Param->setInvalidDecl();
+ return DeclPtrTy::make(Param);;
+ }
+
+ Param->setDefaultArgument(DefaultArg.takeAs<Expr>(), false);
}
-
- TemplateParm->setDefaultArgument(DefaultE.takeAs<Expr>());
+
+ return DeclPtrTy::make(Param);
}
-
/// ActOnTemplateTemplateParameter - Called when a C++ template template
/// parameter (e.g. T in template <template <typename> class T> class array)
/// has been parsed. S is the current scope.
@@ -658,7 +635,9 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
IdentifierInfo *Name,
SourceLocation NameLoc,
unsigned Depth,
- unsigned Position) {
+ unsigned Position,
+ SourceLocation EqualLoc,
+ const ParsedTemplateArgument &Default) {
assert(S->isTemplateParamScope() &&
"Template template parameter not in template parameter scope!");
@@ -668,53 +647,33 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
TmpLoc, Depth, Position, Name,
(TemplateParameterList*)Params);
- // Make sure the parameter is valid.
- // FIXME: Decl object is not currently invalidated anywhere so this doesn't
- // do anything yet. However, if the template parameter list or (eventual)
- // default value is ever invalidated, that will propagate here.
- bool Invalid = false;
- if (Invalid) {
- Param->setInvalidDecl();
- }
-
- // If the tt-param has a name, then link the identifier into the scope
- // and lookup mechanisms.
+ // If the template template parameter has a name, then link the identifier
+ // into the scope and lookup mechanisms.
if (Name) {
S->AddDecl(DeclPtrTy::make(Param));
IdResolver.AddDecl(Param);
}
- return DeclPtrTy::make(Param);
-}
-
-/// \brief Adds a default argument to the given template template
-/// parameter.
-void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &Default) {
- TemplateTemplateParmDecl *TemplateParm
- = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-
- // C++ [temp.param]p14:
- // A template-parameter shall not be used in its own default argument.
- // FIXME: Implement this check! Needs a recursive walk over the types.
-
- // Check only that we have a template template argument. We don't want to
- // try to check well-formedness now, because our template template parameter
- // might have dependent types in its template parameters, which we wouldn't
- // be able to match now.
- //
- // If none of the template template parameter's template arguments mention
- // other template parameters, we could actually perform more checking here.
- // However, it isn't worth doing.
- TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
- if (DefaultArg.getArgument().getAsTemplate().isNull()) {
- Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
- << DefaultArg.getSourceRange();
- return;
+ if (!Default.isInvalid()) {
+ // Check only that we have a template template argument. We don't want to
+ // try to check well-formedness now, because our template template parameter
+ // might have dependent types in its template parameters, which we wouldn't
+ // be able to match now.
+ //
+ // If none of the template template parameter's template arguments mention
+ // other template parameters, we could actually perform more checking here.
+ // However, it isn't worth doing.
+ TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+ if (DefaultArg.getArgument().getAsTemplate().isNull()) {
+ Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
+ << DefaultArg.getSourceRange();
+ return DeclPtrTy::make(Param);
+ }
+
+ Param->setDefaultArgument(DefaultArg, false);
}
- TemplateParm->setDefaultArgument(DefaultArg);
+ return DeclPtrTy::make(Param);
}
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
@@ -925,7 +884,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
NewClass->setDescribedClassTemplate(NewTemplate);
// Build the type for the class template declaration now.
- QualType T = NewTemplate->getInjectedClassNameSpecialization(Context);
+ QualType T = NewTemplate->getInjectedClassNameSpecialization();
T = Context.getInjectedClassNameType(NewClass, T);
assert(T->isDependentType() && "Class template type is not dependent?");
(void)T;
@@ -1144,7 +1103,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
NewNonTypeParm->getLocation(),
NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
NewNonTypeParm->getDefaultArgument()->Destroy(Context);
- NewNonTypeParm->setDefaultArgument(0);
+ NewNonTypeParm->removeDefaultArgument();
}
// Merge default arguments for non-type template parameters
@@ -1165,7 +1124,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// expression that points to a previous template template
// parameter.
NewNonTypeParm->setDefaultArgument(
- OldNonTypeParm->getDefaultArgument());
+ OldNonTypeParm->getDefaultArgument(),
+ /*Inherited=*/ true);
PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
} else if (NewNonTypeParm->hasDefaultArgument()) {
SawDefaultArgument = true;
@@ -1180,7 +1140,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
DiagnoseDefaultTemplateArgument(*this, TPC,
NewTemplateParm->getLocation(),
NewTemplateParm->getDefaultArgument().getSourceRange()))
- NewTemplateParm->setDefaultArgument(TemplateArgumentLoc());
+ NewTemplateParm->removeDefaultArgument();
// Merge default arguments for template template parameters
TemplateTemplateParmDecl *OldTemplateParm
@@ -1199,7 +1159,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// FIXME: We need to create a new kind of "default argument" expression
// that points to a previous template template parameter.
NewTemplateParm->setDefaultArgument(
- OldTemplateParm->getDefaultArgument());
+ OldTemplateParm->getDefaultArgument(),
+ /*Inherited=*/ true);
PreviousDefaultArgLoc
= OldTemplateParm->getDefaultArgument().getLocation();
} else if (NewTemplateParm->hasDefaultArgument()) {
@@ -1445,7 +1406,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
"Converted template argument list is too short!");
QualType CanonType;
- bool IsCurrentInstantiation = false;
if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
@@ -1502,7 +1462,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// class name type of the record we just found.
assert(ICNT.isCanonical());
CanonType = ICNT;
- IsCurrentInstantiation = true;
break;
}
}
@@ -1540,8 +1499,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
- return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType,
- IsCurrentInstantiation);
+ return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
}
Action::TypeResult
@@ -1687,12 +1645,18 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
/// example, given "MetaFun::template apply", the scope specifier \p
/// SS will be "MetaFun::", \p TemplateKWLoc contains the location
/// of the "template" keyword, and "apply" is the \p Name.
-Sema::TemplateTy
-Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext) {
+TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
+ SourceLocation TemplateKWLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ TypeTy *ObjectType,
+ bool EnteringContext,
+ TemplateTy &Result) {
+ if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(TemplateKWLoc, diag::ext_template_outside_of_template)
+ << FixItHint::CreateRemoval(TemplateKWLoc);
+
DeclContext *LookupCtx = 0;
if (SS.isSet())
LookupCtx = computeDeclContext(SS, EnteringContext);
@@ -1714,26 +1678,25 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
// the "template" keyword prior to a template-name that was not a
// dependent name. C++ DR468 relaxed this requirement (the
// "template" keyword is now permitted). We follow the C++0x
- // rules, even in C++03 mode, retroactively applying the DR.
- TemplateTy Template;
+ // rules, even in C++03 mode with a warning, retroactively applying the DR.
bool MemberOfUnknownSpecialization;
TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
- EnteringContext, Template,
+ EnteringContext, Result,
MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
isa<CXXRecordDecl>(LookupCtx) &&
cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
- // This is a dependent template.
+ // This is a dependent template. Handle it below.
} else if (TNK == TNK_Non_template) {
Diag(Name.getSourceRange().getBegin(),
diag::err_template_kw_refers_to_non_template)
<< GetNameFromUnqualifiedId(Name)
<< Name.getSourceRange()
<< TemplateKWLoc;
- return TemplateTy();
+ return TNK_Non_template;
} else {
// We found something; return it.
- return Template;
+ return TNK;
}
}
@@ -1742,12 +1705,14 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
switch (Name.getKind()) {
case UnqualifiedId::IK_Identifier:
- return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
- Name.Identifier));
+ Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Name.Identifier));
+ return TNK_Dependent_template_name;
case UnqualifiedId::IK_OperatorFunctionId:
- return TemplateTy::make(Context.getDependentTemplateName(Qualifier,
+ Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
+ return TNK_Dependent_template_name;
case UnqualifiedId::IK_LiteralOperatorId:
assert(false && "We don't support these; Parse shouldn't have allowed propagation");
@@ -1761,7 +1726,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
<< GetNameFromUnqualifiedId(Name)
<< Name.getSourceRange()
<< TemplateKWLoc;
- return TemplateTy();
+ return TNK_Non_template;
}
bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
@@ -2768,7 +2733,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// conversions (4.7) are applied.
QualType ParamType = InstantiatedParamType;
QualType ArgType = Arg->getType();
- if (ParamType->isIntegralType() || ParamType->isEnumeralType()) {
+ if (ParamType->isIntegralOrEnumerationType()) {
// C++ [temp.arg.nontype]p1:
// A template-argument for a non-type, non-template
// template-parameter shall be one of:
@@ -2778,7 +2743,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- the name of a non-type template-parameter; or
SourceLocation NonConstantLoc;
llvm::APSInt Value;
- if (!ArgType->isIntegralType() && !ArgType->isEnumeralType()) {
+ if (!ArgType->isIntegralOrEnumerationType()) {
Diag(Arg->getSourceRange().getBegin(),
diag::err_template_arg_not_integral_or_enumeral)
<< ArgType << Arg->getSourceRange();
@@ -3237,9 +3202,32 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
return false;
}
- if (isa<TemplateTypeParmDecl>(*OldParm)) {
- // Okay; all template type parameters are equivalent (since we
- // know we're at the same index).
+ if (TemplateTypeParmDecl *OldTTP
+ = dyn_cast<TemplateTypeParmDecl>(*OldParm)) {
+ // Template type parameters are equivalent if either both are template
+ // type parameter packs or neither are (since we know we're at the same
+ // index).
+ TemplateTypeParmDecl *NewTTP = cast<TemplateTypeParmDecl>(*NewParm);
+ if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) {
+ // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
+ // allow one to match a template parameter pack in the template
+ // parameter list of a template template parameter to one or more
+ // template parameters in the template parameter list of the
+ // corresponding template template argument.
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
+ if (TemplateArgLoc.isValid()) {
+ Diag(TemplateArgLoc,
+ diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_parameter_pack_non_pack;
+ }
+ Diag(NewTTP->getLocation(), NextDiag)
+ << 0 << NewTTP->isParameterPack();
+ Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here)
+ << 0 << OldTTP->isParameterPack();
+ }
+ return false;
+ }
} else if (NonTypeTemplateParmDecl *OldNTTP
= dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) {
// The types of non-type template parameters must agree.
@@ -3640,6 +3628,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TemplateParameterLists.size(),
TUK == TUK_Friend,
isExplicitSpecialization);
+ unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
+ if (TemplateParams)
+ --NumMatchedTemplateParamLists;
+
if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true;
@@ -3660,7 +3652,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Diag(NTTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec)
<< DefArg->getSourceRange();
- NTTP->setDefaultArgument(0);
+ NTTP->removeDefaultArgument();
DefArg->Destroy(Context);
}
} else {
@@ -3669,7 +3661,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Diag(TTP->getDefaultArgument().getLocation(),
diag::err_default_arg_in_partial_spec)
<< TTP->getDefaultArgument().getSourceRange();
- TTP->setDefaultArgument(TemplateArgumentLoc());
+ TTP->removeDefaultArgument();
}
}
}
@@ -3831,6 +3823,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial,
SequenceNumber);
SetNestedNameSpecifier(Partial, SS);
+ if (NumMatchedTemplateParamLists > 0) {
+ Partial->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
if (PrevPartial) {
ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial);
@@ -3888,6 +3885,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted,
PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
+ if (NumMatchedTemplateParamLists > 0) {
+ Specialization->setTemplateParameterListsInfo(Context,
+ NumMatchedTemplateParamLists,
+ (TemplateParameterList**) TemplateParameterLists.release());
+ }
if (PrevDecl) {
ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
@@ -3955,8 +3957,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TypeSourceInfo *WrittenTy
= Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
TemplateArgs, CanonType);
- if (TUK != TUK_Friend)
+ if (TUK != TUK_Friend) {
Specialization->setTypeAsWritten(WrittenTy);
+ if (TemplateParams)
+ Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc());
+ }
TemplateArgsIn.release();
// C++ [temp.expl.spec]p9:
@@ -4050,7 +4055,7 @@ static void StripImplicitInstantiation(NamedDecl *D) {
/// \param PrevPointOfInstantiation if valid, indicates where the previus
/// declaration was instantiated (either implicitly or explicitly).
///
-/// \param SuppressNew will be set to true to indicate that the new
+/// \param HasNoEffect will be set to true to indicate that the new
/// specialization or instantiation has no effect and should be ignored.
///
/// \returns true if there was an error that should prevent the introduction of
@@ -4061,8 +4066,8 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
NamedDecl *PrevDecl,
TemplateSpecializationKind PrevTSK,
SourceLocation PrevPointOfInstantiation,
- bool &SuppressNew) {
- SuppressNew = false;
+ bool &HasNoEffect) {
+ HasNoEffect = false;
switch (NewTSK) {
case TSK_Undeclared:
@@ -4119,7 +4124,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
switch (PrevTSK) {
case TSK_ExplicitInstantiationDeclaration:
// This explicit instantiation declaration is redundant (that's okay).
- SuppressNew = true;
+ HasNoEffect = true;
return false;
case TSK_Undeclared:
@@ -4134,7 +4139,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// of a template appears after a declaration of an explicit
// specialization for that template, the explicit instantiation has no
// effect.
- SuppressNew = true;
+ HasNoEffect = true;
return false;
case TSK_ExplicitInstantiationDefinition:
@@ -4148,7 +4153,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
diag::note_explicit_instantiation_definition_here);
assert(PrevPointOfInstantiation.isValid() &&
"Explicit instantiation without point of instantiation?");
- SuppressNew = true;
+ HasNoEffect = true;
return false;
}
break;
@@ -4177,7 +4182,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
Diag(PrevDecl->getLocation(),
diag::note_previous_template_specialization);
}
- SuppressNew = true;
+ HasNoEffect = true;
return false;
case TSK_ExplicitInstantiationDeclaration:
@@ -4194,7 +4199,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
<< PrevDecl;
Diag(PrevPointOfInstantiation,
diag::note_previous_explicit_instantiation);
- SuppressNew = true;
+ HasNoEffect = true;
return false;
}
break;
@@ -4343,14 +4348,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
- bool SuppressNew = false;
+ bool HasNoEffect = false;
if (!isFriend &&
CheckSpecializationInstantiationRedecl(FD->getLocation(),
TSK_ExplicitSpecialization,
Specialization,
SpecInfo->getTemplateSpecializationKind(),
SpecInfo->getPointOfInstantiation(),
- SuppressNew))
+ HasNoEffect))
return true;
// Mark the prior declaration as an explicit specialization, so that later
@@ -4477,13 +4482,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
// use occurs; no diagnostic is required.
assert(MSInfo && "Member specialization info missing?");
- bool SuppressNew = false;
+ bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
TSK_ExplicitSpecialization,
Instantiation,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
- SuppressNew))
+ HasNoEffect))
return true;
// Check the scope of this explicit specialization.
@@ -4544,13 +4549,21 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
}
/// \brief Check the scope of an explicit instantiation.
-static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
+///
+/// \returns true if a serious error occurs, false otherwise.
+static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
SourceLocation InstLoc,
bool WasQualifiedName) {
DeclContext *ExpectedContext
= D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext();
DeclContext *CurContext = S.CurContext->getLookupContext();
+ if (CurContext->isRecord()) {
+ S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
+ << D;
+ return true;
+ }
+
// C++0x [temp.explicit]p2:
// An explicit instantiation shall appear in an enclosing namespace of its
// template.
@@ -4571,7 +4584,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
: diag::warn_explicit_instantiation_out_of_scope_0x)
<< D;
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
- return;
+ return false;
}
// C++0x [temp.explicit]p2:
@@ -4580,10 +4593,10 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
// its template is declared or, if that namespace is inline (7.3.1), any
// namespace from its enclosing namespace set.
if (WasQualifiedName)
- return;
+ return false;
if (CurContext->Equals(ExpectedContext))
- return;
+ return false;
S.Diag(InstLoc,
S.getLangOptions().CPlusPlus0x?
@@ -4591,6 +4604,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
: diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
<< D << ExpectedContext;
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+ return false;
}
/// \brief Determine whether the given scope specifier has a template-id in it.
@@ -4685,42 +4699,46 @@ Sema::ActOnExplicitInstantiation(Scope *S,
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ TemplateSpecializationKind PrevDecl_TSK
+ = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
+
// C++0x [temp.explicit]p2:
// [...] An explicit instantiation shall appear in an enclosing
// namespace of its template. [...]
//
// This is C++ DR 275.
- CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
- SS.isSet());
+ if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
+ SS.isSet()))
+ return true;
ClassTemplateSpecializationDecl *Specialization = 0;
bool ReusedDecl = false;
+ bool HasNoEffect = false;
if (PrevDecl) {
- bool SuppressNew = false;
if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
- PrevDecl,
- PrevDecl->getSpecializationKind(),
+ PrevDecl, PrevDecl_TSK,
PrevDecl->getPointOfInstantiation(),
- SuppressNew))
+ HasNoEffect))
return DeclPtrTy::make(PrevDecl);
- if (SuppressNew)
- return DeclPtrTy::make(PrevDecl);
-
- if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation ||
- PrevDecl->getSpecializationKind() == TSK_Undeclared) {
+ // Even though HasNoEffect == true means that this explicit instantiation
+ // has no effect on semantics, we go on to put its syntax in the AST.
+
+ if (PrevDecl_TSK == TSK_ImplicitInstantiation ||
+ PrevDecl_TSK == TSK_Undeclared) {
// Since the only prior class template specialization with these
// arguments was referenced but not declared, reuse that
- // declaration node as our own, updating its source location to
- // reflect our new declaration.
+ // declaration node as our own, updating the source location
+ // for the template name to reflect our new declaration.
+ // (Other source locations will be updated later.)
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
PrevDecl = 0;
ReusedDecl = true;
}
}
-
+
if (!Specialization) {
// Create a new class template specialization declaration node for
// this explicit specialization.
@@ -4732,15 +4750,16 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Converted, PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
- if (PrevDecl) {
- // Remove the previous declaration from the folding set, since we want
- // to introduce a new declaration.
- ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
- ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
- }
-
- // Insert the new specialization.
- ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
+ if (!HasNoEffect) {
+ if (PrevDecl) {
+ // Remove the previous declaration from the folding set, since we want
+ // to introduce a new declaration.
+ ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
+ ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ }
+ // Insert the new specialization.
+ ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
+ }
}
// Build the fully-sugared type for this explicit instantiation as
@@ -4757,12 +4776,21 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setTypeAsWritten(WrittenTy);
TemplateArgsIn.release();
- if (!ReusedDecl) {
- // Add the explicit instantiation into its lexical context. However,
- // since explicit instantiations are never found by name lookup, we
- // just put it into the declaration context directly.
- Specialization->setLexicalDeclContext(CurContext);
- CurContext->addDecl(Specialization);
+ // Set source locations for keywords.
+ Specialization->setExternLoc(ExternLoc);
+ Specialization->setTemplateKeywordLoc(TemplateLoc);
+
+ // Add the explicit instantiation into its lexical context. However,
+ // since explicit instantiations are never found by name lookup, we
+ // just put it into the declaration context directly.
+ Specialization->setLexicalDeclContext(CurContext);
+ CurContext->addDecl(Specialization);
+
+ // Syntax is now OK, so return if it has no other effect on semantics.
+ if (HasNoEffect) {
+ // Set the template specialization kind.
+ Specialization->setTemplateSpecializationKind(TSK);
+ return DeclPtrTy::make(Specialization);
}
// C++ [temp.explicit]p3:
@@ -4777,8 +4805,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->getDefinition());
if (!Def)
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
- else if (TSK == TSK_ExplicitInstantiationDefinition)
+ else if (TSK == TSK_ExplicitInstantiationDefinition) {
MarkVTableUsed(TemplateNameLoc, Specialization, true);
+ Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
+ }
// Instantiate the members of this class template specialization.
Def = cast_or_null<ClassTemplateSpecializationDecl>(
@@ -4795,6 +4825,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
}
+ // Set the template specialization kind.
+ Specialization->setTemplateSpecializationKind(TSK);
return DeclPtrTy::make(Specialization);
}
@@ -4847,7 +4879,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
//
// C++98 has the same restriction, just worded differently.
if (!ScopeSpecifierHasTemplateId(SS))
- Diag(TemplateLoc, diag::err_explicit_instantiation_without_qualified_id)
+ Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id)
<< Record << SS.getRange();
// C++0x [temp.explicit]p2:
@@ -4872,15 +4904,15 @@ Sema::ActOnExplicitInstantiation(Scope *S,
PrevDecl = Record;
if (PrevDecl) {
MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
- bool SuppressNew = false;
+ bool HasNoEffect = false;
assert(MSInfo && "No member specialization information?");
if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
PrevDecl,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
- SuppressNew))
+ HasNoEffect))
return true;
- if (SuppressNew)
+ if (HasNoEffect)
return TagD;
}
@@ -4947,7 +4979,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
S = S->getParent();
// Determine the type of the declaration.
- QualType R = GetTypeForDeclarator(D, S, 0);
+ TypeSourceInfo *T = GetTypeForDeclarator(D, S);
+ QualType R = T->getType();
if (R.isNull())
return true;
@@ -5019,7 +5052,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// C++98 has the same restriction, just worded differently.
if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
Diag(D.getIdentifierLoc(),
- diag::err_explicit_instantiation_without_qualified_id)
+ diag::ext_explicit_instantiation_without_qualified_id)
<< Prev << D.getCXXScopeSpec().getRange();
// Check the scope of this explicit instantiation.
@@ -5028,13 +5061,13 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// Verify that it is okay to explicitly instantiate here.
MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
assert(MSInfo && "Missing static data member specialization info?");
- bool SuppressNew = false;
+ bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
- SuppressNew))
+ HasNoEffect))
return true;
- if (SuppressNew)
+ if (HasNoEffect)
return DeclPtrTy();
// Instantiate static data member.
@@ -5131,17 +5164,17 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
PrevDecl = Specialization;
if (PrevDecl) {
- bool SuppressNew = false;
+ bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
PrevDecl,
PrevDecl->getTemplateSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
- SuppressNew))
+ HasNoEffect))
return true;
// FIXME: We may still want to build some representation of this
// explicit specialization.
- if (SuppressNew)
+ if (HasNoEffect)
return DeclPtrTy();
}
@@ -5163,7 +5196,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
D.getCXXScopeSpec().isSet() &&
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
Diag(D.getIdentifierLoc(),
- diag::err_explicit_instantiation_without_qualified_id)
+ diag::ext_explicit_instantiation_without_qualified_id)
<< Specialization << D.getCXXScopeSpec().getRange();
CheckExplicitInstantiationScope(*this,
@@ -5200,31 +5233,20 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
return Context.getDependentNameType(Kwd, NNS, Name).getAsOpaquePtr();
}
-static void FillTypeLoc(DependentNameTypeLoc TL,
- SourceLocation TypenameLoc,
- SourceRange QualifierRange,
- SourceLocation NameLoc) {
- TL.setKeywordLoc(TypenameLoc);
- TL.setQualifierRange(QualifierRange);
- TL.setNameLoc(NameLoc);
-}
-
-static void FillTypeLoc(ElaboratedTypeLoc TL,
- SourceLocation TypenameLoc,
- SourceRange QualifierRange) {
- // FIXME: inner locations.
- TL.setKeywordLoc(TypenameLoc);
- TL.setQualifierRange(QualifierRange);
-}
-
Sema::TypeResult
-Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
- const IdentifierInfo &II, SourceLocation IdLoc) {
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, const IdentifierInfo &II,
+ SourceLocation IdLoc) {
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
if (!NNS)
return true;
+ if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+ << FixItHint::CreateRemoval(TypenameLoc);
+
QualType T = CheckTypenameType(ETK_Typename, NNS, II,
TypenameLoc, SS.getRange(), IdLoc);
if (T.isNull())
@@ -5233,44 +5255,82 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
- // FIXME: fill inner type loc
- FillTypeLoc(TL, TypenameLoc, SS.getRange(), IdLoc);
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+ TL.setNameLoc(IdLoc);
} else {
ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
- // FIXME: fill inner type loc
- FillTypeLoc(TL, TypenameLoc, SS.getRange());
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+ cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
}
return CreateLocInfoType(T, TSI).getAsOpaquePtr();
}
Sema::TypeResult
-Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
- SourceLocation TemplateLoc, TypeTy *Ty) {
- QualType T = GetTypeFromParser(Ty);
+Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+ TypeTy *Ty) {
+ if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(TypenameLoc, diag::ext_typename_outside_of_template)
+ << FixItHint::CreateRemoval(TypenameLoc);
+
+ TypeSourceInfo *InnerTSI = 0;
+ QualType T = GetTypeFromParser(Ty, &InnerTSI);
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- const TemplateSpecializationType *TemplateId
- = T->getAs<TemplateSpecializationType>();
- assert(TemplateId && "Expected a template specialization type");
+
+ assert(isa<TemplateSpecializationType>(T) &&
+ "Expected a template specialization type");
if (computeDeclContext(SS, false)) {
// If we can compute a declaration context, then the "typename"
// keyword was superfluous. Just build an ElaboratedType to keep
// track of the nested-name-specifier.
+
+ // Push the inner type, preserving its source locations if possible.
+ TypeLocBuilder Builder;
+ if (InnerTSI)
+ Builder.pushFullCopy(InnerTSI->getTypeLoc());
+ else
+ Builder.push<TemplateSpecializationTypeLoc>(T).initialize(TemplateLoc);
+
T = Context.getElaboratedType(ETK_Typename, NNS, T);
- TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
- ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc());
- // FIXME: fill inner type loc
- FillTypeLoc(TL, TypenameLoc, SS.getRange());
+ ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
+
+ TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
return CreateLocInfoType(T, TSI).getAsOpaquePtr();
}
- T = Context.getDependentNameType(ETK_Typename, NNS, TemplateId);
+ // TODO: it's really silly that we make a template specialization
+ // type earlier only to drop it again here.
+ TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
+ DependentTemplateName *DTN =
+ TST->getTemplateName().getAsDependentTemplateName();
+ assert(DTN && "dependent template has non-dependent name?");
+ T = Context.getDependentTemplateSpecializationType(ETK_Typename, NNS,
+ DTN->getIdentifier(),
+ TST->getNumArgs(),
+ TST->getArgs());
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
- DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc());
- // FIXME: fill inner type loc
- FillTypeLoc(TL, TypenameLoc, SS.getRange(), TemplateLoc);
+ DependentTemplateSpecializationTypeLoc TL =
+ cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc());
+ if (InnerTSI) {
+ TemplateSpecializationTypeLoc TSTL =
+ cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc());
+ TL.setLAngleLoc(TSTL.getLAngleLoc());
+ TL.setRAngleLoc(TSTL.getRAngleLoc());
+ for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I)
+ TL.setArgLocInfo(I, TSTL.getArgLocInfo(I));
+ } else {
+ TL.initializeLocal(SourceLocation());
+ }
+ TL.setKeywordLoc(TypenameLoc);
+ TL.setQualifierRange(SS.getRange());
return CreateLocInfoType(T, TSI).getAsOpaquePtr();
}
@@ -5297,7 +5357,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// the "typename" keyword itself is superfluous. In C++03, the
// program is actually ill-formed. However, DR 382 (in C++0x CD1)
// allows such extraneous "typename" keywords, and we retroactively
- // apply this DR to C++03 code. In any case we continue.
+ // apply this DR to C++03 code with only a warning. In any case we continue.
if (RequireCompleteDeclContext(SS, Ctx))
return QualType();
@@ -5317,7 +5377,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
return Context.getDependentNameType(Keyword, NNS, &II);
case LookupResult::Found:
- if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
+ if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
// We found a type. Build an ElaboratedType, since the
// typename-specifier was just sugar.
return Context.getElaboratedType(ETK_Typename, NNS,
@@ -5399,87 +5459,9 @@ namespace {
Sema::OwningExprResult TransformExpr(Expr *E) {
return getSema().Owned(E->Retain());
}
-
- /// \brief Transforms a typename type by determining whether the type now
- /// refers to a member of the current instantiation, and then
- /// type-checking and building an ElaboratedType (when possible).
- QualType TransformDependentNameType(TypeLocBuilder &TLB,
- DependentNameTypeLoc TL,
- QualType ObjectType);
};
}
-QualType
-CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB,
- DependentNameTypeLoc TL,
- QualType ObjectType) {
- DependentNameType *T = TL.getTypePtr();
-
- NestedNameSpecifier *NNS
- = TransformNestedNameSpecifier(T->getQualifier(),
- TL.getQualifierRange(),
- ObjectType);
- if (!NNS)
- return QualType();
-
- // If the nested-name-specifier did not change, and we cannot compute the
- // context corresponding to the nested-name-specifier, then this
- // typename type will not change; exit early.
- CXXScopeSpec SS;
- SS.setRange(TL.getQualifierRange());
- SS.setScopeRep(NNS);
-
- QualType Result;
- if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0)
- Result = QualType(T, 0);
-
- // Rebuild the typename type, which will probably turn into a
- // ElaboratedType.
- else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
- QualType NewTemplateId
- = TransformType(QualType(TemplateId, 0));
- if (NewTemplateId.isNull())
- return QualType();
-
- if (NNS == T->getQualifier() &&
- NewTemplateId == QualType(TemplateId, 0))
- Result = QualType(T, 0);
- else
- Result = getDerived().RebuildDependentNameType(T->getKeyword(),
- NNS, NewTemplateId);
- } else
- Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
- T->getIdentifier(),
- TL.getKeywordLoc(),
- TL.getQualifierRange(),
- TL.getNameLoc());
-
- if (Result.isNull())
- return QualType();
-
- if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) {
- QualType NamedT = ElabT->getNamedType();
- if (isa<TemplateSpecializationType>(NamedT)) {
- TemplateSpecializationTypeLoc NamedTLoc
- = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
- // FIXME: fill locations
- NamedTLoc.initializeLocal(TL.getNameLoc());
- } else {
- TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
- }
- ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
- NewTL.setKeywordLoc(TL.getKeywordLoc());
- NewTL.setQualifierRange(TL.getQualifierRange());
- }
- else {
- DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
- NewTL.setKeywordLoc(TL.getKeywordLoc());
- NewTL.setQualifierRange(TL.getQualifierRange());
- NewTL.setNameLoc(TL.getNameLoc());
- }
- return Result;
-}
-
/// \brief Rebuilds a type within the context of the current instantiation.
///
/// The type \p T is part of the type of an out-of-line member definition of
diff --git a/lib/Sema/SemaTemplate.h b/lib/Sema/SemaTemplate.h
index ca59e27..b3f4651 100644
--- a/lib/Sema/SemaTemplate.h
+++ b/lib/Sema/SemaTemplate.h
@@ -36,10 +36,14 @@ namespace clang {
/// When instantiating X<int>::Y<17>::f, the multi-level template argument
/// list will contain a template argument list (int) at depth 0 and a
/// template argument list (17) at depth 1.
- struct MultiLevelTemplateArgumentList {
+ class MultiLevelTemplateArgumentList {
+ public:
+ typedef std::pair<const TemplateArgument *, unsigned> ArgList;
+
+ private:
/// \brief The template argument lists, stored from the innermost template
/// argument list (first) to the outermost template argument list (last).
- llvm::SmallVector<const TemplateArgumentList *, 4> TemplateArgumentLists;
+ llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
public:
/// \brief Construct an empty set of template argument lists.
@@ -48,7 +52,7 @@ namespace clang {
/// \brief Construct a single-level template argument list.
explicit
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
- TemplateArgumentLists.push_back(&TemplateArgs);
+ addOuterTemplateArguments(&TemplateArgs);
}
/// \brief Determine the number of levels in this template argument
@@ -58,8 +62,8 @@ namespace clang {
/// \brief Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
- assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
- return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index);
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
}
/// \brief Determine whether there is a non-NULL template argument at the
@@ -69,7 +73,7 @@ namespace clang {
bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
- if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size())
+ if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
return false;
return !(*this)(Depth, Index).isNull();
@@ -78,12 +82,21 @@ namespace clang {
/// \brief Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
- TemplateArgumentLists.push_back(TemplateArgs);
+ TemplateArgumentLists.push_back(
+ ArgList(TemplateArgs->getFlatArgumentList(),
+ TemplateArgs->flat_size()));
+ }
+
+ /// \brief Add a new outmost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
}
/// \brief Retrieve the innermost template argument list.
- const TemplateArgumentList &getInnermost() const {
- return *TemplateArgumentLists.front();
+ const ArgList &getInnermost() const {
+ return TemplateArgumentLists.front();
}
};
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 88ceeca..403d554 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2624,6 +2624,18 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
OnlyDeduced, Depth, Used);
break;
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *Spec
+ = cast<DependentTemplateSpecializationType>(T);
+ if (!OnlyDeduced)
+ MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(),
+ OnlyDeduced, Depth, Used);
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth,
+ Used);
+ break;
+ }
+
case Type::TypeOf:
if (!OnlyDeduced)
MarkUsedTemplateParameters(SemaRef,
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 1adf594..6db0916 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -63,7 +63,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
// We're done when we hit an explicit specialization.
- if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization)
+ if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
+ !isa<ClassTemplatePartialSpecializationDecl>(Spec))
break;
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
@@ -104,6 +105,15 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
RelativeToPrimary = false;
continue;
}
+ } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
+ if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
+ QualType T = ClassTemplate->getInjectedClassNameSpecialization();
+ const TemplateSpecializationType *TST
+ = cast<TemplateSpecializationType>(Context.getCanonicalType(T));
+ Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs());
+ if (ClassTemplate->isMemberSpecialization())
+ break;
+ }
}
Ctx = Ctx->getParent();
@@ -620,6 +630,14 @@ namespace {
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL,
QualType ObjectType);
+
+ Sema::OwningExprResult TransformCallExpr(CallExpr *CE) {
+ getSema().CallsUndergoingInstantiation.push_back(CE);
+ OwningExprResult Result =
+ TreeTransform<TemplateInstantiator>::TransformCallExpr(CE);
+ getSema().CallsUndergoingInstantiation.pop_back();
+ return move(Result);
+ }
};
}
@@ -1216,7 +1234,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
0);
- CheckCompletedCXXClass(/*Scope=*/0, Instantiation);
+ CheckCompletedCXXClass(Instantiation);
if (Instantiation->isInvalidDecl())
Invalid = true;
@@ -1434,7 +1452,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
SuppressNew)
continue;
- if (Function->getBody())
+ if (Function->hasBody())
continue;
if (TSK == TSK_ExplicitInstantiationDefinition) {
@@ -1444,7 +1462,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
// specialization and is only an explicit instantiation definition
// of members whose definition is visible at the point of
// instantiation.
- if (!Pattern->getBody())
+ if (!Pattern->hasBody())
continue;
Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 834b86d..2fd3528 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -42,12 +42,13 @@ namespace {
// FIXME: Once we get closer to completion, replace these manually-written
// declarations with automatically-generated ones from
- // clang/AST/DeclNodes.def.
+ // clang/AST/DeclNodes.inc.
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
Decl *VisitTypedefDecl(TypedefDecl *D);
Decl *VisitVarDecl(VarDecl *D);
+ Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
@@ -142,14 +143,29 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
return false;
}
-// FIXME: Is this too simple?
+// FIXME: Is this still too simple?
void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
- for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
+ for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
TmplAttr = TmplAttr->getNext()) {
-
+ // FIXME: This should be generalized to more than just the AlignedAttr.
+ if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
+ if (Aligned->isDependent()) {
+ // The alignment expression is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Action::Unevaluated);
+
+ OwningExprResult Result = SemaRef.SubstExpr(Aligned->getAlignmentExpr(),
+ TemplateArgs);
+ if (!Result.isInvalid())
+ // FIXME: Is this the correct source location?
+ SemaRef.AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(),
+ New, Result.takeAs<Expr>());
+ continue;
+ }
+ }
+
// FIXME: Is cloning correct for all attributes?
Attr *NewAttr = TmplAttr->clone(SemaRef.Context);
-
New->addAttr(NewAttr);
}
}
@@ -360,7 +376,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
Var->setLexicalDeclContext(D->getLexicalDeclContext());
Var->setAccess(D->getAccess());
- Var->setUsed(D->isUsed());
+
+ if (!D->isStaticDataMember())
+ Var->setUsed(D->isUsed(false));
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
@@ -373,15 +391,16 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
if (D->isOutOfLine()) {
- D->getLexicalDeclContext()->addDecl(Var);
+ if (!D->isStaticDataMember())
+ D->getLexicalDeclContext()->addDecl(Var);
Owner->makeDeclVisibleInContext(Var);
} else {
Owner->addDecl(Var);
-
if (Owner->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
}
-
+ InstantiateAttrs(D, Var);
+
// Link instantiations of static data members back to the template from
// which they were instantiated.
if (Var->isStaticDataMember())
@@ -436,6 +455,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
return Var;
}
+Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) {
+ AccessSpecDecl* AD
+ = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner,
+ D->getAccessSpecifierLoc(), D->getColonLoc());
+ Owner->addHiddenDecl(AD);
+ return AD;
+}
+
Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
bool Invalid = false;
TypeSourceInfo *DI = D->getTypeSourceInfo();
@@ -793,7 +820,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Trigger creation of the type for the instantiation.
SemaRef.Context.getInjectedClassNameType(RecordInst,
- Inst->getInjectedClassNameSpecialization(SemaRef.Context));
+ Inst->getInjectedClassNameSpecialization());
// Finish handling of friends.
if (isFriend) {
@@ -951,9 +978,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
void *InsertPos = 0;
if (FunctionTemplate && !TemplateParams) {
llvm::FoldingSetNodeID ID;
- FunctionTemplateSpecializationInfo::Profile(ID,
- TemplateArgs.getInnermost().getFlatArgumentList(),
- TemplateArgs.getInnermost().flat_size(),
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
+ FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
+ Innermost.second,
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
@@ -1062,8 +1090,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
} else if (FunctionTemplate) {
// Record this function template specialization.
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
Function->setFunctionTemplateSpecialization(FunctionTemplate,
- &TemplateArgs.getInnermost(),
+ new (SemaRef.Context) TemplateArgumentList(SemaRef.Context,
+ Innermost.first,
+ Innermost.second),
InsertPos);
} else if (isFriend && D->isThisDeclarationADefinition()) {
// TODO: should we remember this connection regardless of whether
@@ -1154,7 +1186,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
D->isThisDeclarationADefinition()) {
// Check for a function body.
const FunctionDecl *Definition = 0;
- if (Function->getBody(Definition) &&
+ if (Function->hasBody(Definition) &&
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
<< Function->getDeclName();
@@ -1170,7 +1202,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
((*R)->getFriendObjectKind() != Decl::FOK_None)) {
if (const FunctionDecl *RPattern
= (*R)->getTemplateInstantiationPattern())
- if (RPattern->getBody(RPattern)) {
+ if (RPattern->hasBody(RPattern)) {
SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
<< Function->getDeclName();
SemaRef.Diag((*R)->getLocation(), diag::note_previous_definition);
@@ -1200,9 +1232,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// template. Check whether there is already a function template
// specialization for this particular set of template arguments.
llvm::FoldingSetNodeID ID;
- FunctionTemplateSpecializationInfo::Profile(ID,
- TemplateArgs.getInnermost().getFlatArgumentList(),
- TemplateArgs.getInnermost().flat_size(),
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
+ FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
+ Innermost.second,
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
@@ -1347,8 +1380,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method->setDescribedFunctionTemplate(FunctionTemplate);
} else if (FunctionTemplate) {
// Record this function template specialization.
+ std::pair<const TemplateArgument *, unsigned> Innermost
+ = TemplateArgs.getInnermost();
Method->setFunctionTemplateSpecialization(FunctionTemplate,
- &TemplateArgs.getInnermost(),
+ new (SemaRef.Context) TemplateArgumentList(SemaRef.Context,
+ Innermost.first,
+ Innermost.second),
InsertPos);
} else if (!isFriend) {
// Record that this is an instantiation of a member function.
@@ -1485,7 +1522,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (Invalid)
Param->setInvalidDecl();
- Param->setDefaultArgument(D->getDefaultArgument());
+ Param->setDefaultArgument(D->getDefaultArgument(), false);
// Introduce this template parameter's instantiation into the instantiation
// scope.
@@ -1513,7 +1550,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
= TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getDepth() - 1, D->getPosition(),
D->getIdentifier(), InstParams);
- Param->setDefaultArgument(D->getDefaultArgument());
+ Param->setDefaultArgument(D->getDefaultArgument(), false);
// Introduce this template parameter's instantiation into the instantiation
// scope.
@@ -1966,6 +2003,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Proto->getExtInfo()));
}
+ InstantiateAttrs(Tmpl, New);
+
return false;
}
@@ -2011,7 +2050,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
bool Recursive,
bool DefinitionRequired) {
- if (Function->isInvalidDecl() || Function->getBody())
+ if (Function->isInvalidDecl() || Function->hasBody())
return;
// Never instantiate an explicit specialization.
@@ -2568,7 +2607,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
if (ClassTemplate) {
- T = ClassTemplate->getInjectedClassNameSpecialization(Context);
+ T = ClassTemplate->getInjectedClassNameSpecialization();
} else if (ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
ClassTemplate = PartialSpec->getSpecializedTemplate();
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 35efa61..a4fc98c 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -383,8 +383,12 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
} 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());
+ VectorType::AltiVecSpecific AltiVecSpec = VectorType::AltiVec;
+ if (DS.isTypeAltiVecPixel())
+ AltiVecSpec = VectorType::Pixel;
+ else if (DS.isTypeAltiVecBool())
+ AltiVecSpec = VectorType::Bool;
+ Result = Context.getVectorType(Result, 128/typeSize, AltiVecSpec);
}
assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary &&
@@ -472,12 +476,49 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) {
return "type name";
}
+QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
+ Qualifiers Qs) {
+ // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+ // object or incomplete types shall not be restrict-qualified."
+ if (Qs.hasRestrict()) {
+ unsigned DiagID = 0;
+ QualType ProblemTy;
+
+ const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
+ if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
+ if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
+ }
+ } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
+ if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T->getAs<PointerType>()->getPointeeType();
+ }
+ } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
+ if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T->getAs<PointerType>()->getPointeeType();
+ }
+ } else if (!Ty->isDependentType()) {
+ // FIXME: this deserves a proper diagnostic
+ DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ ProblemTy = T;
+ }
+
+ if (DiagID) {
+ Diag(Loc, DiagID) << ProblemTy;
+ Qs.removeRestrict();
+ }
+ }
+
+ return Context.getQualifiedType(T, Qs);
+}
+
/// \brief Build a pointer type.
///
/// \param T The type to which we'll be building a pointer.
///
-/// \param Quals The cvr-qualifiers to be applied to the pointer type.
-///
/// \param Loc The location of the entity whose type involves this
/// pointer type or, if there is no such entity, the location of the
/// type that will have pointer type.
@@ -487,7 +528,7 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) {
///
/// \returns A suitable pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildPointerType(QualType T, unsigned Quals,
+QualType Sema::BuildPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity) {
if (T->isReferenceType()) {
// C++ 8.3.2p4: There shall be no ... pointers to references ...
@@ -496,28 +537,16 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
return QualType();
}
- Qualifiers Qs = Qualifiers::fromCVRMask(Quals);
-
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from
- // object or incomplete types shall not be restrict-qualified."
- if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) {
- Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
- << T;
- Qs.removeRestrict();
- }
-
assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
// Build the pointer type.
- return Context.getQualifiedType(Context.getPointerType(T), Qs);
+ return Context.getPointerType(T);
}
/// \brief Build a reference type.
///
/// \param T The type to which we'll be building a reference.
///
-/// \param CVR The cvr-qualifiers to be applied to the reference type.
-///
/// \param Loc The location of the entity whose type involves this
/// reference type or, if there is no such entity, the location of the
/// type that will have reference type.
@@ -528,10 +557,8 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,
/// \returns A suitable reference type, if there are no
/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
- unsigned CVR, SourceLocation Loc,
+ SourceLocation Loc,
DeclarationName Entity) {
- Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
-
bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
// C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
@@ -562,31 +589,10 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return QualType();
}
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from
- // object or incomplete types shall not be restrict-qualified."
- if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
- Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
- << T;
- Quals.removeRestrict();
- }
-
- // C++ [dcl.ref]p1:
- // [...] Cv-qualified references are ill-formed except when the
- // cv-qualifiers are introduced through the use of a typedef
- // (7.1.3) or of a template type argument (14.3), in which case
- // the cv-qualifiers are ignored.
- //
- // We diagnose extraneous cv-qualifiers for the non-typedef,
- // non-template type argument case within the parser. Here, we just
- // ignore any extraneous cv-qualifiers.
- Quals.removeConst();
- Quals.removeVolatile();
-
// Handle restrict on references.
if (LValueRef)
- return Context.getQualifiedType(
- Context.getLValueReferenceType(T, SpelledAsLValue), Quals);
- return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
+ return Context.getLValueReferenceType(T, SpelledAsLValue);
+ return Context.getRValueReferenceType(T);
}
/// \brief Build an array type.
@@ -597,9 +603,6 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
///
/// \param ArraySize Expression describing the size of the array.
///
-/// \param Quals The cvr-qualifiers to be applied to the array's
-/// element type.
-///
/// \param Loc The location of the entity whose type involves this
/// array type or, if there is no such entity, the location of the
/// type that will have array type.
@@ -815,7 +818,7 @@ QualType Sema::BuildFunctionType(QualType T,
<< T->isFunctionType() << T;
return QualType();
}
-
+
bool Invalid = false;
for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
QualType ParamType = adjustParameterType(ParamTypes[Idx]);
@@ -846,10 +849,8 @@ QualType Sema::BuildFunctionType(QualType T,
/// \returns a member pointer type, if successful, or a NULL type if there was
/// an error.
QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
- unsigned CVR, SourceLocation Loc,
+ SourceLocation Loc,
DeclarationName Entity) {
- Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
-
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (CheckDistantExceptionSpec(T)) {
@@ -863,7 +864,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
T = Context.getCanonicalType(T);
}
- // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
+ // C++ 8.3.3p3: A pointer to member shall not point to ... a member
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
@@ -877,24 +878,12 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from
- // object or incomplete types shall not be restrict-qualified."
- if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) {
- Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
- << T;
-
- // FIXME: If we're doing this as part of template instantiation,
- // we should return immediately.
- Quals.removeRestrict();
- }
-
if (!Class->isDependentType() && !Class->isRecordType()) {
Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
return QualType();
}
- return Context.getQualifiedType(
- Context.getMemberPointerType(T, Class.getTypePtr()), Quals);
+ return Context.getMemberPointerType(T, Class.getTypePtr());
}
/// \brief Build a block pointer type.
@@ -912,7 +901,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
///
/// \returns A suitable block pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
+QualType Sema::BuildBlockPointerType(QualType T,
SourceLocation Loc,
DeclarationName Entity) {
if (!T->isFunctionType()) {
@@ -920,8 +909,7 @@ QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR,
return QualType();
}
- Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
- return Context.getQualifiedType(Context.getBlockPointerType(T), Quals);
+ return Context.getBlockPointerType(T);
}
QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) {
@@ -947,9 +935,11 @@ QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) {
/// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq
/// owns the declaration of a type (e.g., the definition of a struct
/// type), then *OwnedDecl will receive the owned declaration.
-QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
- TypeSourceInfo **TInfo,
- TagDecl **OwnedDecl) {
+///
+/// The result of this call will never be null, but the associated
+/// type may be a null type if there's an unrecoverable error.
+TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
+ TagDecl **OwnedDecl) {
// Determine the type of the declarator. Not all forms of declarator
// have a type.
QualType T;
@@ -980,22 +970,18 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Constructors and destructors don't have return types. Use
// "void" instead.
T = Context.VoidTy;
-
- if (TInfo)
- ReturnTypeInfo = Context.getTrivialTypeSourceInfo(T,
- D.getName().StartLocation);
break;
case UnqualifiedId::IK_ConversionFunctionId:
// The result type of a conversion function is the type that it
// converts to.
T = GetTypeFromParser(D.getName().ConversionFunctionId,
- TInfo? &ReturnTypeInfo : 0);
+ &ReturnTypeInfo);
break;
}
if (T.isNull())
- return T;
+ return Context.getNullTypeSourceInfo();
if (T == Context.UndeducedAutoTy) {
int Error = -1;
@@ -1059,8 +1045,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (!LangOpts.Blocks)
Diag(DeclType.Loc, diag::err_blocks_disable);
- T = BuildBlockPointerType(T, DeclType.Cls.TypeQuals, D.getIdentifierLoc(),
- Name);
+ T = BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
+ if (DeclType.Cls.TypeQuals)
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
break;
case DeclaratorChunk::Pointer:
// Verify that we're not building a pointer to pointer to function with
@@ -1072,15 +1059,15 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
if (getLangOptions().ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
- T = Context.getCVRQualifiedType(T, DeclType.Ptr.TypeQuals);
+ if (DeclType.Ptr.TypeQuals)
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
}
- T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
+ T = BuildPointerType(T, DeclType.Loc, Name);
+ if (DeclType.Ptr.TypeQuals)
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
case DeclaratorChunk::Reference: {
- Qualifiers Quals;
- if (DeclType.Ref.HasRestrict) Quals.addRestrict();
-
// Verify that we're not building a reference to pointer to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -1088,8 +1075,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.setInvalidType(true);
// Build the type anyway.
}
- T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals,
- DeclType.Loc, Name);
+ T = BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
+
+ Qualifiers Quals;
+ if (DeclType.Ref.HasRestrict)
+ T = BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
break;
}
case DeclaratorChunk::Array: {
@@ -1139,6 +1129,48 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.setInvalidType(true);
}
+ // cv-qualifiers on return types are pointless except when the type is a
+ // class type in C++.
+ if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
+ (!getLangOptions().CPlusPlus ||
+ (!T->isDependentType() && !T->isRecordType()))) {
+ unsigned Quals = D.getDeclSpec().getTypeQualifiers();
+ std::string QualStr;
+ unsigned NumQuals = 0;
+ SourceLocation Loc;
+ if (Quals & Qualifiers::Const) {
+ Loc = D.getDeclSpec().getConstSpecLoc();
+ ++NumQuals;
+ QualStr = "const";
+ }
+ if (Quals & Qualifiers::Volatile) {
+ if (NumQuals == 0) {
+ Loc = D.getDeclSpec().getVolatileSpecLoc();
+ QualStr = "volatile";
+ } else
+ QualStr += " volatile";
+ ++NumQuals;
+ }
+ if (Quals & Qualifiers::Restrict) {
+ if (NumQuals == 0) {
+ Loc = D.getDeclSpec().getRestrictSpecLoc();
+ QualStr = "restrict";
+ } else
+ QualStr += " restrict";
+ ++NumQuals;
+ }
+ assert(NumQuals > 0 && "No known qualifiers?");
+
+ SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type);
+ DB << QualStr << NumQuals;
+ if (Quals & Qualifiers::Const)
+ DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc());
+ if (Quals & Qualifiers::Volatile)
+ DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc());
+ if (Quals & Qualifiers::Restrict)
+ DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc());
+ }
+
if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
@@ -1154,29 +1186,14 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef);
- if (FTI.NumArgs == 0) {
- if (getLangOptions().CPlusPlus) {
- // C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
- // function takes no arguments.
- llvm::SmallVector<QualType, 4> Exceptions;
- Exceptions.reserve(FTI.NumExceptions);
- for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
- // FIXME: Preserve type source info.
- QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty);
- // Check that the type is valid for an exception spec, and drop it
- // if not.
- if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
- Exceptions.push_back(ET);
- }
- T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals,
- FTI.hasExceptionSpec,
- FTI.hasAnyExceptionSpec,
- Exceptions.size(), Exceptions.data(),
- FunctionType::ExtInfo());
- } else if (FTI.isVariadic) {
- // We allow a zero-parameter variadic function in C if the
- // function is marked with the "overloadable"
- // attribute. Scan for this attribute now.
+ if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) {
+ // Simple void foo(), where the incoming T is the result type.
+ T = Context.getFunctionNoProtoType(T);
+ } else {
+ // We allow a zero-parameter variadic function in C if the
+ // function is marked with the "overloadable" attribute. Scan
+ // for this attribute now.
+ if (!FTI.NumArgs && FTI.isVariadic && !getLangOptions().CPlusPlus) {
bool Overloadable = false;
for (const AttributeList *Attrs = D.getAttributes();
Attrs; Attrs = Attrs->getNext()) {
@@ -1188,21 +1205,20 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (!Overloadable)
Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
- T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, 0,
- false, false, 0, 0,
- FunctionType::ExtInfo());
- } else {
- // Simple void foo(), where the incoming T is the result type.
- T = Context.getFunctionNoProtoType(T);
}
- } else if (FTI.ArgInfo[0].Param == 0) {
- // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
- Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
- D.setInvalidType(true);
- } else {
+
+ if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
+ // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
+ // definition.
+ Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
+ D.setInvalidType(true);
+ break;
+ }
+
// Otherwise, we have a function with an argument list that is
// potentially variadic.
llvm::SmallVector<QualType, 16> ArgTys;
+ ArgTys.reserve(FTI.NumArgs);
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
ParmVarDecl *Param =
@@ -1278,13 +1294,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
case DeclaratorChunk::MemberPointer:
- // Verify that we're not building a pointer to pointer to function with
- // exception specification.
- if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
- Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
- D.setInvalidType(true);
- // Build the type anyway.
- }
// The scope spec must refer to a class, or be dependent.
QualType ClsType;
if (DeclType.Mem.Scope().isInvalid()) {
@@ -1323,11 +1332,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
if (!ClsType.isNull())
- T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
- DeclType.Loc, D.getIdentifier());
+ T = BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier());
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
+ } else if (DeclType.Mem.TypeQuals) {
+ T = BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
}
break;
}
@@ -1352,18 +1362,19 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// for a nonstatic member function, the function type to which a pointer
// to member refers, or the top-level function type of a function typedef
// declaration.
+ bool FreeFunction = (D.getContext() != Declarator::MemberContext &&
+ (!D.getCXXScopeSpec().isSet() ||
+ !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true)->isRecord()));
if (FnTy->getTypeQuals() != 0 &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
- ((D.getContext() != Declarator::MemberContext &&
- (!D.getCXXScopeSpec().isSet() ||
- !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true)
- ->isRecord())) ||
+ (FreeFunction ||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
if (D.isFunctionDeclarator())
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
else
Diag(D.getIdentifierLoc(),
- diag::err_invalid_qualified_typedef_function_type_use);
+ diag::err_invalid_qualified_typedef_function_type_use)
+ << FreeFunction;
// Strip the cv-quals from the type.
T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(),
@@ -1372,6 +1383,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
}
+ // If there's a constexpr specifier, treat it as a top-level const.
+ if (D.getDeclSpec().isConstexprSpecified()) {
+ T.addConst();
+ }
+
// Process any function attributes we might have delayed from the
// declaration-specifiers.
ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec);
@@ -1386,14 +1402,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk);
- if (TInfo) {
- if (D.isInvalidType())
- *TInfo = 0;
- else
- *TInfo = GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo);
- }
-
- return T;
+ if (T.isNull())
+ return Context.getNullTypeSourceInfo();
+ else if (D.isInvalidType())
+ return Context.getTrivialTypeSourceInfo(T);
+ return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo);
}
namespace {
@@ -1527,6 +1540,28 @@ namespace {
// FIXME: load appropriate source location.
TL.setNameLoc(DS.getTypeSpecTypeLoc());
}
+ void VisitDependentTemplateSpecializationTypeLoc(
+ DependentTemplateSpecializationTypeLoc TL) {
+ ElaboratedTypeKeyword Keyword
+ = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
+ if (Keyword == ETK_Typename) {
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ if (TInfo) {
+ TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
+ TInfo->getTypeLoc()));
+ return;
+ }
+ }
+ TL.initializeLocal(SourceLocation());
+ TL.setKeywordLoc(Keyword != ETK_None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation());
+ const CXXScopeSpec& SS = DS.getTypeSpecScope();
+ TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange());
+ // FIXME: load appropriate source location.
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ }
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
@@ -1651,53 +1686,14 @@ void LocInfoType::getAsStringInternal(std::string &Str,
" GetTypeFromParser");
}
-/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that
-/// may be similar (C++ 4.4), replaces T1 and T2 with the type that
-/// they point to and return true. If T1 and T2 aren't pointer types
-/// or pointer-to-member types, or if they are not similar at this
-/// level, returns false and leaves T1 and T2 unchanged. Top-level
-/// qualifiers on T1 and T2 are ignored. This function will typically
-/// be called in a loop that successively "unwraps" pointer and
-/// pointer-to-member types to compare them at each level.
-bool Sema::UnwrapSimilarPointerTypes(QualType& T1, QualType& T2) {
- const PointerType *T1PtrType = T1->getAs<PointerType>(),
- *T2PtrType = T2->getAs<PointerType>();
- if (T1PtrType && T2PtrType) {
- T1 = T1PtrType->getPointeeType();
- T2 = T2PtrType->getPointeeType();
- return true;
- }
-
- const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
- *T2MPType = T2->getAs<MemberPointerType>();
- if (T1MPType && T2MPType &&
- Context.getCanonicalType(T1MPType->getClass()) ==
- Context.getCanonicalType(T2MPType->getClass())) {
- T1 = T1MPType->getPointeeType();
- T2 = T2MPType->getPointeeType();
- return true;
- }
-
- if (getLangOptions().ObjC1) {
- const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(),
- *T2OPType = T2->getAs<ObjCObjectPointerType>();
- if (T1OPType && T2OPType) {
- T1 = T1OPType->getPointeeType();
- T2 = T2OPType->getPointeeType();
- return true;
- }
- }
- return false;
-}
-
Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
- TypeSourceInfo *TInfo = 0;
TagDecl *OwnedTag = 0;
- QualType T = GetTypeForDeclarator(D, S, &TInfo, &OwnedTag);
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag);
+ QualType T = TInfo->getType();
if (D.isInvalidType())
return true;
@@ -1714,9 +1710,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
<< Context.getTypeDeclType(OwnedTag);
}
- if (TInfo)
- T = CreateLocInfoType(T, TInfo);
-
+ T = CreateLocInfoType(T, TInfo);
return T.getAsOpaquePtr();
}
@@ -1934,7 +1928,8 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
/// The raw attribute should contain precisely 1 argument, the vector size for
/// the variable, measured in bytes. If curType and rawAttr are well formed,
/// this routine will return a new vector type.
-static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Sema &S) {
+static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
+ Sema &S) {
// Check the attribute arugments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
@@ -1977,7 +1972,8 @@ 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, false, false);
+ CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
+ VectorType::NotAltiVec);
}
void ProcessTypeAttributeList(Sema &S, QualType &Result,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index a18701e..132d049 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -442,7 +442,7 @@ 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,
- bool IsAltiVec, bool IsPixel);
+ VectorType::AltiVecSpecific AltiVecSpec);
/// \brief Build a new extended vector type given the element type and
/// number of elements.
@@ -533,16 +533,30 @@ public:
/// By default, builds a new DependentNameType type from the
/// nested-name-specifier and the given type. Subclasses may override
/// this routine to provide different behavior.
- QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,
- NestedNameSpecifier *NNS, QualType T) {
- if (NNS->isDependent()) {
- // If the name is still dependent, just build a new dependent name type.
- CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- if (!SemaRef.computeDeclContext(SS))
- return SemaRef.Context.getDependentNameType(Keyword, NNS,
- cast<TemplateSpecializationType>(T));
- }
+ QualType RebuildDependentTemplateSpecializationType(
+ ElaboratedTypeKeyword Keyword,
+ NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo &Args) {
+ // Rebuild the template name.
+ // TODO: avoid TemplateName abstraction
+ TemplateName InstName =
+ getDerived().RebuildTemplateName(NNS, *Name, QualType());
+
+ if (InstName.isNull())
+ return QualType();
+
+ // If it's still dependent, make a dependent specialization.
+ if (InstName.getAsDependentTemplateName())
+ return SemaRef.Context.getDependentTemplateSpecializationType(
+ Keyword, NNS, Name, Args);
+
+ // Otherwise, make an elaborated type wrapping a non-dependent
+ // specialization.
+ QualType T =
+ getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
+ if (T.isNull()) return QualType();
return SemaRef.Context.getElaboratedType(Keyword, NNS, T);
}
@@ -1160,7 +1174,9 @@ public:
SS.setScopeRep(Qualifier);
}
- QualType BaseType = ((Expr*) Base.get())->getType();
+ Expr *BaseExpr = Base.takeAs<Expr>();
+ getSema().DefaultFunctionArrayConversion(BaseExpr);
+ QualType BaseType = BaseExpr->getType();
// FIXME: this involves duplicating earlier analysis in a lot of
// cases; we should avoid this when possible.
@@ -1169,8 +1185,8 @@ public:
R.addDecl(FoundDecl);
R.resolveKind();
- return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
- OpLoc, isArrow,
+ return getSema().BuildMemberReferenceExpr(getSema().Owned(BaseExpr),
+ BaseType, OpLoc, isArrow,
SS, FirstQualifierInScope,
R, ExplicitTemplateArgs);
}
@@ -1561,7 +1577,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXZeroInitValueExpr(SourceLocation TypeStartLoc,
+ OwningExprResult RebuildCXXScalarValueInitExpr(SourceLocation TypeStartLoc,
SourceLocation LParenLoc,
QualType T,
SourceLocation RParenLoc) {
@@ -1580,7 +1596,7 @@ public:
SourceLocation PlacementLParen,
MultiExprArg PlacementArgs,
SourceLocation PlacementRParen,
- bool ParenTypeId,
+ SourceRange TypeIdParens,
QualType AllocType,
SourceLocation TypeLoc,
SourceRange TypeRange,
@@ -1592,7 +1608,7 @@ public:
PlacementLParen,
move(PlacementArgs),
PlacementRParen,
- ParenTypeId,
+ TypeIdParens,
AllocType,
TypeLoc,
TypeRange,
@@ -1815,7 +1831,8 @@ public:
Sema::LookupMemberName);
OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IvarLoc,
- SS, DeclPtrTy());
+ SS, DeclPtrTy(),
+ false);
if (Result.isInvalid())
return getSema().ExprError();
@@ -1844,7 +1861,8 @@ public:
bool IsArrow = false;
OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/PropertyLoc,
- SS, DeclPtrTy());
+ SS, DeclPtrTy(),
+ false);
if (Result.isInvalid())
return getSema().ExprError();
@@ -1892,7 +1910,8 @@ public:
Sema::LookupMemberName);
OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IsaLoc,
- SS, DeclPtrTy());
+ SS, DeclPtrTy(),
+ false);
if (Result.isInvalid())
return getSema().ExprError();
@@ -1933,7 +1952,7 @@ public:
Expr **Subs = (Expr **)SubExprs.release();
CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee,
Subs, NumSubExprs,
- Builtin->getResultType(),
+ Builtin->getCallResultType(),
RParenLoc);
OwningExprResult OwnedCall(SemaRef.Owned(TheCall));
@@ -2405,11 +2424,11 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
if (Result->isFunctionType() || Result->isReferenceType())
return Result;
- Result = SemaRef.Context.getQualifiedType(Result, Quals);
-
- TLB.push<QualifiedTypeLoc>(Result);
-
- // No location information to preserve.
+ if (!Quals.empty()) {
+ Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals);
+ TLB.push<QualifiedTypeLoc>(Result);
+ // No location information to preserve.
+ }
return Result;
}
@@ -2792,7 +2811,7 @@ QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
if (getDerived().AlwaysRebuild() ||
ElementType != T->getElementType()) {
Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(),
- T->isAltiVec(), T->isPixel());
+ T->getAltiVecSpecific());
if (Result.isNull())
return QualType();
}
@@ -3298,46 +3317,23 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
if (!NNS)
return QualType();
- QualType Result;
-
- if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
- QualType NewTemplateId
- = getDerived().TransformType(QualType(TemplateId, 0));
- if (NewTemplateId.isNull())
- return QualType();
-
- if (!getDerived().AlwaysRebuild() &&
- NNS == T->getQualifier() &&
- NewTemplateId == QualType(TemplateId, 0))
- return QualType(T, 0);
-
- Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
- NewTemplateId);
- } else {
- Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
- T->getIdentifier(),
- TL.getKeywordLoc(),
- TL.getQualifierRange(),
- TL.getNameLoc());
- }
+ QualType Result
+ = getDerived().RebuildDependentNameType(T->getKeyword(), NNS,
+ T->getIdentifier(),
+ TL.getKeywordLoc(),
+ TL.getQualifierRange(),
+ TL.getNameLoc());
if (Result.isNull())
return QualType();
if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) {
QualType NamedT = ElabT->getNamedType();
- if (isa<TemplateSpecializationType>(NamedT)) {
- TemplateSpecializationTypeLoc NamedTLoc
- = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
- // FIXME: fill locations
- NamedTLoc.initializeLocal(TL.getNameLoc());
- } else {
- TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
- }
+ TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc());
+
ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
NewTL.setKeywordLoc(TL.getKeywordLoc());
NewTL.setQualifierRange(TL.getQualifierRange());
- }
- else {
+ } else {
DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result);
NewTL.setKeywordLoc(TL.getKeywordLoc());
NewTL.setQualifierRange(TL.getQualifierRange());
@@ -3347,6 +3343,62 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB,
}
template<typename Derived>
+QualType TreeTransform<Derived>::
+ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
+ DependentTemplateSpecializationTypeLoc TL,
+ QualType ObjectType) {
+ DependentTemplateSpecializationType *T = TL.getTypePtr();
+
+ NestedNameSpecifier *NNS
+ = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
+ TL.getQualifierRange(),
+ ObjectType);
+ if (!NNS)
+ return QualType();
+
+ TemplateArgumentListInfo NewTemplateArgs;
+ NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
+ NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
+
+ for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) {
+ TemplateArgumentLoc Loc;
+ if (getDerived().TransformTemplateArgument(TL.getArgLoc(I), Loc))
+ return QualType();
+ NewTemplateArgs.addArgument(Loc);
+ }
+
+ QualType Result = getDerived().RebuildDependentTemplateSpecializationType(
+ T->getKeyword(),
+ NNS,
+ T->getIdentifier(),
+ TL.getNameLoc(),
+ NewTemplateArgs);
+ if (Result.isNull())
+ return QualType();
+
+ if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) {
+ QualType NamedT = ElabT->getNamedType();
+
+ // Copy information relevant to the template specialization.
+ TemplateSpecializationTypeLoc NamedTL
+ = TLB.push<TemplateSpecializationTypeLoc>(NamedT);
+ NamedTL.setLAngleLoc(TL.getLAngleLoc());
+ NamedTL.setRAngleLoc(TL.getRAngleLoc());
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I));
+
+ // Copy information relevant to the elaborated type.
+ ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+ NewTL.setKeywordLoc(TL.getKeywordLoc());
+ NewTL.setQualifierRange(TL.getQualifierRange());
+ } else {
+ TypeLoc NewTL(Result, TL.getOpaqueData());
+ TLB.pushFullCopy(NewTL);
+ }
+ return Result;
+}
+
+template<typename Derived>
QualType
TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
ObjCInterfaceTypeLoc TL,
@@ -4146,6 +4198,10 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
if (!ND)
return SemaRef.ExprError();
+ // Set DeclContext if inside a Block.
+ if (BlockScopeInfo *CurBlock = SemaRef.getCurBlock())
+ ND->setDeclContext(CurBlock->TheDecl);
+
if (!getDerived().AlwaysRebuild() &&
Qualifier == E->getQualifier() &&
ND == E->getDecl() &&
@@ -5167,7 +5223,7 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
template<typename Derived>
Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+TreeTransform<Derived>::TransformCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
@@ -5178,10 +5234,10 @@ TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
T == E->getType())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildCXXZeroInitValueExpr(E->getTypeBeginLoc(),
- /*FIXME:*/E->getTypeBeginLoc(),
- T,
- E->getRParenLoc());
+ return getDerived().RebuildCXXScalarValueInitExpr(E->getTypeBeginLoc(),
+ /*FIXME:*/E->getTypeBeginLoc(),
+ T,
+ E->getRParenLoc());
}
template<typename Derived>
@@ -5300,7 +5356,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
/*FIXME:*/E->getLocStart(),
move_arg(PlacementArgs),
/*FIXME:*/E->getLocStart(),
- E->isParenTypeId(),
+ E->getTypeIdParens(),
AllocType,
/*FIXME:*/E->getLocStart(),
/*FIXME:*/SourceRange(),
@@ -6165,17 +6221,75 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
- // FIXME: Implement this!
- assert(false && "Cannot transform block expressions yet");
- return SemaRef.Owned(E->Retain());
+ SourceLocation CaretLoc(E->getExprLoc());
+
+ SemaRef.ActOnBlockStart(CaretLoc, /*Scope=*/0);
+ BlockScopeInfo *CurBlock = SemaRef.getCurBlock();
+ CurBlock->TheDecl->setIsVariadic(E->getBlockDecl()->isVariadic());
+ llvm::SmallVector<ParmVarDecl*, 4> Params;
+ llvm::SmallVector<QualType, 4> ParamTypes;
+
+ // Parameter substitution.
+ const BlockDecl *BD = E->getBlockDecl();
+ for (BlockDecl::param_const_iterator P = BD->param_begin(),
+ EN = BD->param_end(); P != EN; ++P) {
+ ParmVarDecl *OldParm = (*P);
+ ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm);
+ QualType NewType = NewParm->getType();
+ Params.push_back(NewParm);
+ ParamTypes.push_back(NewParm->getType());
+ }
+
+ const FunctionType *BExprFunctionType = E->getFunctionType();
+ QualType BExprResultType = BExprFunctionType->getResultType();
+ if (!BExprResultType.isNull()) {
+ if (!BExprResultType->isDependentType())
+ CurBlock->ReturnType = BExprResultType;
+ else if (BExprResultType != SemaRef.Context.DependentTy)
+ CurBlock->ReturnType = getDerived().TransformType(BExprResultType);
+ }
+
+ // Transform the body
+ OwningStmtResult Body = getDerived().TransformStmt(E->getBody());
+ if (Body.isInvalid())
+ return SemaRef.ExprError();
+ // Set the parameters on the block decl.
+ if (!Params.empty())
+ CurBlock->TheDecl->setParams(Params.data(), Params.size());
+
+ QualType FunctionType = getDerived().RebuildFunctionProtoType(
+ CurBlock->ReturnType,
+ ParamTypes.data(),
+ ParamTypes.size(),
+ BD->isVariadic(),
+ 0);
+
+ CurBlock->FunctionType = FunctionType;
+ return SemaRef.ActOnBlockStmtExpr(CaretLoc, move(Body), /*Scope=*/0);
}
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
- // FIXME: Implement this!
- assert(false && "Cannot transform block-related expressions yet");
- return SemaRef.Owned(E->Retain());
+ NestedNameSpecifier *Qualifier = 0;
+
+ ValueDecl *ND
+ = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
+ E->getDecl()));
+ if (!ND)
+ return SemaRef.ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ ND == E->getDecl()) {
+ // Mark it referenced in the new context regardless.
+ // FIXME: this is a bit instantiation-specific.
+ SemaRef.MarkDeclarationReferenced(E->getLocation(), ND);
+
+ return SemaRef.Owned(E->Retain());
+ }
+
+ return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(),
+ ND, E->getLocation(), 0);
}
//===----------------------------------------------------------------------===//
@@ -6185,14 +6299,14 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
template<typename Derived>
QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType,
SourceLocation Star) {
- return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star,
+ return SemaRef.BuildPointerType(PointeeType, Star,
getDerived().getBaseEntity());
}
template<typename Derived>
QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType,
SourceLocation Star) {
- return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star,
+ return SemaRef.BuildBlockPointerType(PointeeType, Star,
getDerived().getBaseEntity());
}
@@ -6201,7 +6315,7 @@ QualType
TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
bool WrittenAsLValue,
SourceLocation Sigil) {
- return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(),
+ return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue,
Sigil, getDerived().getBaseEntity());
}
@@ -6210,7 +6324,7 @@ QualType
TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
QualType ClassType,
SourceLocation Sigil) {
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(),
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType,
Sigil, getDerived().getBaseEntity());
}
@@ -6293,11 +6407,10 @@ TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
template<typename Derived>
QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
- unsigned NumElements,
- bool IsAltiVec, bool IsPixel) {
+ unsigned NumElements,
+ VectorType::AltiVecSpecific AltiVecSpec) {
// FIXME: semantic checking!
- return SemaRef.Context.getVectorType(ElementType, NumElements,
- IsAltiVec, IsPixel);
+ return SemaRef.Context.getVectorType(ElementType, NumElements, AltiVecSpec);
}
template<typename Derived>
@@ -6449,13 +6562,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
SS.setScopeRep(Qualifier);
UnqualifiedId Name;
Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
- return getSema().ActOnDependentTemplateName(
- /*FIXME:*/getDerived().getBaseLocation(),
- SS,
- Name,
- ObjectType.getAsOpaquePtr(),
- /*EnteringContext=*/false)
- .template getAsVal<TemplateName>();
+ Sema::TemplateTy Template;
+ getSema().ActOnDependentTemplateName(/*Scope=*/0,
+ /*FIXME:*/getDerived().getBaseLocation(),
+ SS,
+ Name,
+ ObjectType.getAsOpaquePtr(),
+ /*EnteringContext=*/false,
+ Template);
+ return Template.template getAsVal<TemplateName>();
}
template<typename Derived>
@@ -6470,13 +6585,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
Operator, SymbolLocations);
- return getSema().ActOnDependentTemplateName(
+ Sema::TemplateTy Template;
+ getSema().ActOnDependentTemplateName(/*Scope=*/0,
/*FIXME:*/getDerived().getBaseLocation(),
- SS,
- Name,
- ObjectType.getAsOpaquePtr(),
- /*EnteringContext=*/false)
- .template getAsVal<TemplateName>();
+ SS,
+ Name,
+ ObjectType.getAsOpaquePtr(),
+ /*EnteringContext=*/false,
+ Template);
+ return Template.template getAsVal<TemplateName>();
}
template<typename Derived>
OpenPOWER on IntegriCloud