summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
commit5563df30b9c8d1fe87a54baae0d6bd86642563f4 (patch)
tree3fdd91eae574e32453a4baf462961c742df2691a /lib/Sema
parente5557c18e5d41b4b62f2af8a24af20eba40b0225 (diff)
downloadFreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.zip
FreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.tar.gz
Update clang to r84949.
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp207
-rw-r--r--lib/Sema/Sema.h64
-rw-r--r--lib/Sema/SemaCXXCast.cpp16
-rw-r--r--lib/Sema/SemaChecking.cpp3
-rw-r--r--lib/Sema/SemaCodeComplete.cpp4
-rw-r--r--lib/Sema/SemaDecl.cpp81
-rw-r--r--lib/Sema/SemaDeclAttr.cpp93
-rw-r--r--lib/Sema/SemaDeclCXX.cpp13
-rw-r--r--lib/Sema/SemaExpr.cpp386
-rw-r--r--lib/Sema/SemaExprCXX.cpp239
-rw-r--r--lib/Sema/SemaExprObjC.cpp6
-rw-r--r--lib/Sema/SemaInit.cpp6
-rw-r--r--lib/Sema/SemaOverload.cpp419
-rw-r--r--lib/Sema/SemaStmt.cpp52
-rw-r--r--lib/Sema/SemaTemplate.cpp433
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp4
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp97
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp75
-rw-r--r--lib/Sema/SemaType.cpp353
-rw-r--r--lib/Sema/TreeTransform.h1038
20 files changed, 2391 insertions, 1198 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index ba05a07..fc9c14f 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -23,44 +23,134 @@
#include "clang/Basic/TargetInfo.h"
using namespace clang;
+/// Determines whether we should have an a.k.a. clause when
+/// pretty-printing a type. There are three main criteria:
+///
+/// 1) Some types provide very minimal sugar that doesn't impede the
+/// user's understanding --- for example, elaborated type
+/// specifiers. If this is all the sugar we see, we don't want an
+/// a.k.a. clause.
+/// 2) Some types are technically sugared but are much more familiar
+/// when seen in their sugared form --- for example, va_list,
+/// vector types, and the magic Objective C types. We don't
+/// want to desugar these, even if we do produce an a.k.a. clause.
+/// 3) Some types may have already been desugared previously in this diagnostic.
+/// if this is the case, doing another "aka" would just be clutter.
+///
+static bool ShouldAKA(ASTContext &Context, QualType QT,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
+ QualType &DesugaredQT) {
+ QualType InputTy = QT;
+
+ bool AKA = false;
+ QualifierCollector Qc;
+
+ while (true) {
+ const Type *Ty = Qc.strip(QT);
+
+ // Don't aka just because we saw an elaborated type...
+ if (isa<ElaboratedType>(Ty)) {
+ QT = cast<ElaboratedType>(Ty)->desugar();
+ continue;
+ }
+
+ // ...or a qualified name type...
+ if (isa<QualifiedNameType>(Ty)) {
+ QT = cast<QualifiedNameType>(Ty)->desugar();
+ continue;
+ }
+
+ // ...or a substituted template type parameter.
+ if (isa<SubstTemplateTypeParmType>(Ty)) {
+ QT = cast<SubstTemplateTypeParmType>(Ty)->desugar();
+ continue;
+ }
+
+ // Don't desugar template specializations.
+ if (isa<TemplateSpecializationType>(Ty))
+ break;
+
+ // Don't desugar magic Objective-C types.
+ if (QualType(Ty,0) == Context.getObjCIdType() ||
+ QualType(Ty,0) == Context.getObjCClassType() ||
+ QualType(Ty,0) == Context.getObjCSelType() ||
+ QualType(Ty,0) == Context.getObjCProtoType())
+ break;
+
+ // Don't desugar va_list.
+ if (QualType(Ty,0) == Context.getBuiltinVaListType())
+ break;
+
+ // Otherwise, do a single-step desugar.
+ QualType Underlying;
+ bool IsSugar = false;
+ switch (Ty->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Base)
+#define TYPE(Class, Base) \
+ case Type::Class: { \
+ const Class##Type *CTy = cast<Class##Type>(Ty); \
+ if (CTy->isSugared()) { \
+ IsSugar = true; \
+ Underlying = CTy->desugar(); \
+ } \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+
+ // If it wasn't sugared, we're done.
+ if (!IsSugar)
+ break;
+
+ // If the desugared type is a vector type, we don't want to expand
+ // it, it will turn into an attribute mess. People want their "vec4".
+ if (isa<VectorType>(Underlying))
+ break;
+
+ // Otherwise, we're tearing through something opaque; note that
+ // we'll eventually need an a.k.a. clause and keep going.
+ AKA = true;
+ QT = Underlying;
+ continue;
+ }
+
+ // If we never tore through opaque sugar, don't print aka.
+ if (!AKA) return false;
+
+ // If we did, check to see if we already desugared this type in this
+ // diagnostic. If so, don't do it again.
+ for (unsigned i = 0; i != NumPrevArgs; ++i) {
+ // TODO: Handle ak_declcontext case.
+ if (PrevArgs[i].first == Diagnostic::ak_qualtype) {
+ void *Ptr = (void*)PrevArgs[i].second;
+ QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
+ if (PrevTy == InputTy)
+ return false;
+ }
+ }
+
+ DesugaredQT = Qc.apply(QT);
+ return true;
+}
+
/// \brief Convert the given type to a string suitable for printing as part of
/// a diagnostic.
///
/// \param Context the context in which the type was allocated
/// \param Ty the type to print
-static std::string ConvertTypeToDiagnosticString(ASTContext &Context,
- QualType Ty) {
+static std::string
+ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs) {
// FIXME: Playing with std::string is really slow.
std::string S = Ty.getAsString(Context.PrintingPolicy);
- // If this is a sugared type (like a typedef, typeof, etc), then unwrap one
- // level of the sugar so that the type is more obvious to the user.
- QualType DesugaredTy = Ty.getDesugaredType();
-
- if (Ty != DesugaredTy &&
- // If the desugared type is a vector type, we don't want to expand it,
- // it will turn into an attribute mess. People want their "vec4".
- !isa<VectorType>(DesugaredTy) &&
-
- // Don't aka just because we saw an elaborated type...
- (!isa<ElaboratedType>(Ty) ||
- cast<ElaboratedType>(Ty)->desugar() != DesugaredTy) &&
-
- // ...or a qualified name type...
- (!isa<QualifiedNameType>(Ty) ||
- cast<QualifiedNameType>(Ty)->desugar() != DesugaredTy) &&
-
- // ...or a non-dependent template specialization.
- (!isa<TemplateSpecializationType>(Ty) || Ty->isDependentType()) &&
-
- // Don't desugar magic Objective-C types.
- Ty.getUnqualifiedType() != Context.getObjCIdType() &&
- Ty.getUnqualifiedType() != Context.getObjCClassType() &&
- Ty.getUnqualifiedType() != Context.getObjCSelType() &&
- Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
-
- // Not va_list.
- Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
+ // Consider producing an a.k.a. clause if removing all the direct
+ // sugar gives us something "significantly different".
+
+ QualType DesugaredTy;
+ if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) {
S = "'"+S+"' (aka '";
S += DesugaredTy.getAsString(Context.PrintingPolicy);
S += "')";
@@ -76,21 +166,27 @@ static std::string ConvertTypeToDiagnosticString(ASTContext &Context,
static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
const char *Modifier, unsigned ModLen,
const char *Argument, unsigned ArgLen,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
void *Cookie) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
std::string S;
bool NeedQuotes = true;
- if (Kind == Diagnostic::ak_qualtype) {
+
+ switch (Kind) {
+ default: assert(0 && "unknown ArgumentKind");
+ case Diagnostic::ak_qualtype: {
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for QualType argument");
QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
- S = ConvertTypeToDiagnosticString(Context, Ty);
+ S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);
NeedQuotes = false;
- } else if (Kind == Diagnostic::ak_declarationname) {
-
+ break;
+ }
+ case Diagnostic::ak_declarationname: {
DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);
S = N.getAsString();
@@ -101,7 +197,9 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
else
assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for DeclarationName argument");
- } else if (Kind == Diagnostic::ak_nameddecl) {
+ break;
+ }
+ case Diagnostic::ak_nameddecl: {
bool Qualified;
if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
Qualified = true;
@@ -110,30 +208,30 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
"Invalid modifier for NamedDecl* argument");
Qualified = false;
}
- reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S,
- Context.PrintingPolicy,
- Qualified);
- } else if (Kind == Diagnostic::ak_nestednamespec) {
+ reinterpret_cast<NamedDecl*>(Val)->
+ getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
+ break;
+ }
+ case Diagnostic::ak_nestednamespec: {
llvm::raw_string_ostream OS(S);
- reinterpret_cast<NestedNameSpecifier*> (Val)->print(OS,
- Context.PrintingPolicy);
+ reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS,
+ Context.PrintingPolicy);
NeedQuotes = false;
- } else {
- assert(Kind == Diagnostic::ak_declcontext);
+ break;
+ }
+ case Diagnostic::ak_declcontext: {
DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
- NeedQuotes = false;
- if (!DC) {
- assert(false && "Should never have a null declaration context");
- S = "unknown context";
- } else if (DC->isTranslationUnit()) {
+ assert(DC && "Should never have a null declaration context");
+
+ if (DC->isTranslationUnit()) {
// FIXME: Get these strings from some localized place
if (Context.getLangOptions().CPlusPlus)
S = "the global namespace";
else
S = "the global scope";
} else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
- S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type));
- NeedQuotes = false;
+ S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type),
+ PrevArgs, NumPrevArgs);
} else {
// FIXME: Get these strings from some localized place
NamedDecl *ND = cast<NamedDecl>(DC);
@@ -147,8 +245,10 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
S += "'";
ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);
S += "'";
- NeedQuotes = false;
}
+ NeedQuotes = false;
+ break;
+ }
}
if (NeedQuotes)
@@ -361,9 +461,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// Set the length of the array to 1 (C99 6.9.2p5).
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
- QualType T
- = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(),
- One, ArrayType::Normal, 0);
+ QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
+ One, ArrayType::Normal, 0);
VD->setType(T);
} else if (RequireCompleteType(VD->getLocation(), VD->getType(),
diag::err_tentative_def_incomplete_type))
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 80f3663..6dd081b 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -448,7 +448,7 @@ public:
//
QualType adjustParameterType(QualType T);
QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc,
- bool &IsInvalid, QualType &SourceTy);
+ bool &IsInvalid);
void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
@@ -908,6 +908,7 @@ public:
bool IsAssignmentOperator = false,
unsigned NumContextualBoolArguments = 0);
void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);
void AddArgumentDependentLookupCandidates(DeclarationName Name,
@@ -929,7 +930,7 @@ public:
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool Complain);
- void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
+ Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
void AddOverloadedCallCandidates(NamedDecl *Callee,
DeclarationName &UnqualifiedName,
@@ -2108,6 +2109,15 @@ public:
bool HasTrailingLParen);
virtual OwningExprResult
+ ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceRange TypeRange,
+ TypeTy *Type,
+ const CXXScopeSpec &SS,
+ bool HasTrailingLParen);
+
+ virtual OwningExprResult
ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
@@ -2343,6 +2353,10 @@ public:
FunctionDecl::StorageClass& SC);
DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+ bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
+ SourceLocation NameLoc, QualType &ThisType,
+ QualType &MemberType);
+
//===--------------------------------------------------------------------===//
// C++ Derived Classes
//
@@ -2515,14 +2529,17 @@ public:
DeclSpec::TST TagSpec,
SourceLocation TagLoc);
- OwningExprResult BuildTemplateIdExpr(TemplateName Template,
+ OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc);
- virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template,
+ virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+ TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
@@ -3143,6 +3160,10 @@ public:
void PerformPendingImplicitInstantiations();
+ DeclaratorInfo *SubstType(DeclaratorInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
QualType SubstType(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity);
@@ -3197,11 +3218,13 @@ public:
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
- bool Recursive = false);
+ bool Recursive = false,
+ bool DefinitionRequired = false);
void InstantiateStaticDataMemberDefinition(
SourceLocation PointOfInstantiation,
VarDecl *Var,
- bool Recursive = false);
+ bool Recursive = false,
+ bool DefinitionRequired = false);
void InstantiateMemInitializers(CXXConstructorDecl *New,
const CXXConstructorDecl *Tmpl,
@@ -3404,8 +3427,7 @@ public:
/// 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.
- void ImpCastExprToType(Expr *&Expr, QualType Type,
- CastExpr::CastKind Kind = CastExpr::CK_Unknown,
+ void ImpCastExprToType(Expr *&Expr, QualType Type, CastExpr::CastKind Kind,
bool isLvalue = false);
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
@@ -3550,6 +3572,10 @@ public:
bool PerformImplicitConversion(Expr *&From, QualType ToType,
const StandardConversionSequence& SCS,
const char *Flavor);
+
+ bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
+ const ImplicitConversionSequence& ICS,
+ const char *Flavor);
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
@@ -3659,14 +3685,16 @@ public:
// Since vectors are an extension, there are no C standard reference for this.
// We allow casting between vectors and integer datatypes of the same size.
// returns true if the cast is invalid
- bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+ bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+ CastExpr::CastKind &Kind);
// CheckExtVectorCast - check type constraints for extended vectors.
// Since vectors are an extension, there are no C standard reference for this.
// We allow casting between vectors and integer datatypes of the same size,
// or vectors and the element type of that vector.
// returns true if the cast is invalid
- bool CheckExtVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+ bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr,
+ CastExpr::CastKind &Kind);
/// CXXCheckCStyleCast - Check constraints of a C-style or function-style
/// cast under C++ semantics.
@@ -3727,22 +3755,6 @@ public:
QualType FieldTy, const Expr *BitWidth,
bool *ZeroWidth = 0);
- /// adjustFunctionParamType - Converts the type of a function parameter to a
- // type that can be passed as an argument type to
- /// ASTContext::getFunctionType.
- ///
- /// C++ [dcl.fct]p3: "...Any cv-qualifier modifying a parameter type is
- /// deleted. Such cv-qualifiers affect only the definition of the parameter
- /// within the body of the function; they do not affect the function type.
- QualType adjustFunctionParamType(QualType T) const {
- if (!Context.getLangOptions().CPlusPlus)
- return T;
- return
- T->isDependentType() ? T.getUnqualifiedType()
- : T.getDesugaredType().getUnqualifiedType();
-
- }
-
/// \name Code completion
//@{
void setCodeCompleteConsumer(CodeCompleteConsumer *CCC);
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 69d1f92..bf39604 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -175,7 +175,7 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
/// the cast checkers. Both arguments must denote pointer (possibly to member)
/// types.
-bool
+static bool
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
// Casting away constness is defined in C++ 5.2.11p8 with reference to
// C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
@@ -605,6 +605,11 @@ TryCastResult
TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,
bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
QualType OrigDestType, unsigned &msg) {
+ // We can only work with complete types. But don't complain if it doesn't work
+ if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, PDiag(0)) ||
+ Self.RequireCompleteType(OpRange.getBegin(), DestType, PDiag(0)))
+ return TC_NotApplicable;
+
// Downcast can only happen in class hierarchies, so we need classes.
if (!DestType->isRecordType() || !SrcType->isRecordType()) {
return TC_NotApplicable;
@@ -943,6 +948,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
}
// A valid member pointer cast.
+ Kind = CastExpr::CK_BitCast;
return TC_Success;
}
@@ -1044,6 +1050,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// Not casting away constness, so the only remaining check is for compatible
// pointer categories.
+ Kind = CastExpr::CK_BitCast;
if (SrcType->isFunctionPointerType()) {
if (DestType->isFunctionPointerType()) {
@@ -1085,8 +1092,10 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
- if (CastTy->isVoidType())
+ if (CastTy->isVoidType()) {
+ Kind = CastExpr::CK_ToVoid;
return false;
+ }
// If the type is dependent, we won't do any other semantic analysis now.
if (CastTy->isDependentType() || CastExpr->isTypeDependent())
@@ -1109,6 +1118,9 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
unsigned msg = diag::err_bad_cxx_cast_generic;
TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,
msg);
+ if (tcr == TC_Success)
+ Kind = CastExpr::CK_NoOp;
+
if (tcr == TC_NotApplicable) {
// ... or if that is not possible, a static_cast, ignoring const, ...
tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 92bf83f..589b0c6 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -381,8 +381,7 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
// If the first type needs to be converted (e.g. void** -> int*), do it now.
if (BuiltinFT->getArgType(0) != FirstArg->getType()) {
- ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_Unknown,
- /*isLvalue=*/false);
+ ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_BitCast);
TheCall->setArg(0, FirstArg);
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 3981b8d..3811513 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -235,8 +235,10 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
// Filter out names reserved for the implementation (C99 7.1.3,
// C++ [lib.global.names]). Users don't need to see those.
+ //
+ // FIXME: Add predicate for this.
if (Id->getLength() >= 2) {
- const char *Name = Id->getName();
+ const char *Name = Id->getNameStart();
if (Name[0] == '_' &&
(Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
return;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 606b33f..b83181b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -218,7 +218,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
<< &II << DC << SS->getRange();
else if (isDependentScopeSpecifier(*SS)) {
Diag(SS->getRange().getBegin(), diag::err_typename_missing)
- << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
+ << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
<< SourceRange(SS->getRange().getBegin(), IILoc)
<< CodeModificationHint::CreateInsertion(SS->getRange().getBegin(),
"typename ");
@@ -1059,6 +1059,8 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
/// NeverFallThrough iff we never fall off the end of the statement. We assume
/// that functions not marked noreturn will return.
Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
+ // FIXME: Eventually share this CFG object when we have other warnings based
+ // of the CFG. This can be done using AnalysisContext.
llvm::OwningPtr<CFG> cfg (CFG::buildCFG(Root, &Context));
// FIXME: They should never return 0, fix that, delete this code.
@@ -1527,14 +1529,19 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Invalid = true;
}
+ // Mock up a declarator.
+ Declarator Dc(DS, Declarator::TypeNameContext);
+ DeclaratorInfo *DInfo = 0;
+ GetTypeForDeclarator(Dc, S, &DInfo);
+ assert(DInfo && "couldn't build declarator info for anonymous struct/union");
+
// Create a declaration for this anonymous struct/union.
NamedDecl *Anon = 0;
if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {
Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(),
/*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
- // FIXME: Type source info.
- /*DInfo=*/0,
+ DInfo,
/*BitWidth=*/0, /*Mutable=*/false);
Anon->setAccess(AS_public);
if (getLangOptions().CPlusPlus)
@@ -1561,8 +1568,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
/*IdentifierInfo=*/0,
Context.getTypeDeclType(Record),
- // FIXME: Type source info.
- /*DInfo=*/0,
+ DInfo,
SC);
}
Anon->setImplicit();
@@ -1903,16 +1909,9 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
llvm::APSInt &Res = EvalResult.Val.getInt();
if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) {
- Expr* ArySizeExpr = VLATy->getSizeExpr();
- // FIXME: here we could "steal" (how?) ArySizeExpr from the VLA,
- // so as to transfer ownership to the ConstantArrayWithExpr.
- // Alternatively, we could "clone" it (how?).
- // Since we don't know how to do things above, we just use the
- // very same Expr*.
- return Context.getConstantArrayWithExprType(VLATy->getElementType(),
- Res, ArySizeExpr,
- ArrayType::Normal, 0,
- VLATy->getBracketsRange());
+ // TODO: preserve the size expression in declarator info
+ return Context.getConstantArrayType(VLATy->getElementType(),
+ Res, ArrayType::Normal, 0);
}
SizeIsNegative = true;
@@ -3331,7 +3330,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
<< Init->getSourceRange();
VDecl->setInvalidDecl();
} else if (!VDecl->getType()->isDependentType())
- ImpCastExprToType(Init, VDecl->getType());
+ ImpCastExprToType(Init, VDecl->getType(), CastExpr::CK_IntegralCast);
}
}
} else if (VDecl->isFileVarDecl()) {
@@ -3534,10 +3533,37 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
// Block scope. C99 6.7p7: If an identifier for an object is declared with
// no linkage (C99 6.2.2p6), the type for the object shall be complete...
if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) {
- if (!IDecl->isInvalidDecl() &&
- RequireCompleteType(IDecl->getLocation(), T,
- diag::err_typecheck_decl_incomplete_type))
- IDecl->setInvalidDecl();
+ if (T->isDependentType()) {
+ // If T is dependent, we should not require a complete type.
+ // (RequireCompleteType shouldn't be called with dependent types.)
+ // But we still can at least check if we've got an array of unspecified
+ // size without an initializer.
+ if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() &&
+ !IDecl->getInit()) {
+ Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)
+ << T;
+ IDecl->setInvalidDecl();
+ }
+ } else if (!IDecl->isInvalidDecl()) {
+ // If T is an incomplete array type with an initializer list that is
+ // dependent on something, its size has not been fixed. We could attempt
+ // to fix the size for such arrays, but we would still have to check
+ // here for initializers containing a C++0x vararg expansion, e.g.
+ // template <typename... Args> void f(Args... args) {
+ // int vals[] = { args };
+ // }
+ const IncompleteArrayType *IAT = T->getAs<IncompleteArrayType>();
+ Expr *Init = IDecl->getInit();
+ if (IAT && Init &&
+ (Init->isTypeDependent() || Init->isValueDependent())) {
+ // Check that the member type of the array is complete, at least.
+ if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(),
+ diag::err_typecheck_decl_incomplete_type))
+ IDecl->setInvalidDecl();
+ } else if (RequireCompleteType(IDecl->getLocation(), T,
+ diag::err_typecheck_decl_incomplete_type))
+ IDecl->setInvalidDecl();
+ }
}
// File scope. C99 6.9.2p2: A declaration of an identifier for an
// object that has file scope without an initializer, and without a
@@ -3707,12 +3733,13 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {
--i;
if (FTI.ArgInfo[i].Param == 0) {
- std::string Code = " int ";
- Code += FTI.ArgInfo[i].Ident->getName();
- Code += ";\n";
+ llvm::SmallString<256> Code;
+ llvm::raw_svector_ostream(Code) << " int "
+ << FTI.ArgInfo[i].Ident->getName()
+ << ";\n";
Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)
<< FTI.ArgInfo[i].Ident
- << CodeModificationHint::CreateInsertion(LocAfterDecls, Code);
+ << CodeModificationHint::CreateInsertion(LocAfterDecls, Code.str());
// Implicitly declare the argument as type 'int' for lack of a better
// type.
@@ -3975,9 +4002,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
}
// Extension in C99. Legal in C90, but warn about it.
- static const unsigned int BuiltinLen = strlen("__builtin_");
- if (II.getLength() > BuiltinLen &&
- std::equal(II.getName(), II.getName() + BuiltinLen, "__builtin_"))
+ if (II.getName().startswith("__builtin_"))
Diag(Loc, diag::warn_builtin_unknown) << &II;
else if (getLangOptions().C99)
Diag(Loc, diag::ext_implicit_function_decl) << &II;
@@ -5587,7 +5612,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// Adjust the Expr initializer and type.
if (ECD->getInitExpr())
ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy,
- CastExpr::CK_Unknown,
+ CastExpr::CK_IntegralCast,
ECD->getInitExpr(),
/*isLvalue=*/false));
if (getLangOptions().CPlusPlus)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 50ebb49..341d49e 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1202,6 +1202,35 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
}
+enum FormatAttrKind {
+ CFStringFormat,
+ NSStringFormat,
+ StrftimeFormat,
+ SupportedFormat,
+ InvalidFormat
+};
+
+/// getFormatAttrKind - Map from format attribute names to supported format
+/// types.
+static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
+ // Check for formats that get handled specially.
+ if (Format == "NSString")
+ return NSStringFormat;
+ if (Format == "CFString")
+ return CFStringFormat;
+ if (Format == "strftime")
+ return StrftimeFormat;
+
+ // Otherwise, check for supported formats.
+ if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
+ Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
+ Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
+ Format == "zcmn_err")
+ return SupportedFormat;
+
+ return InvalidFormat;
+}
+
/// 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) {
@@ -1226,38 +1255,15 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned NumArgs = getFunctionOrMethodNumArgs(d);
unsigned FirstIdx = 1;
- const char *Format = Attr.getParameterName()->getName();
- unsigned FormatLen = Attr.getParameterName()->getLength();
+ llvm::StringRef Format = Attr.getParameterName()->getName();
// Normalize the argument, __foo__ becomes foo.
- if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
- Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
- Format += 2;
- FormatLen -= 4;
- }
-
- bool Supported = false;
- bool is_NSString = false;
- bool is_strftime = false;
- bool is_CFString = false;
-
- switch (FormatLen) {
- default: break;
- case 5: Supported = !memcmp(Format, "scanf", 5); break;
- case 6: Supported = !memcmp(Format, "printf", 6); break;
- case 7: Supported = !memcmp(Format, "printf0", 7) ||
- !memcmp(Format, "strfmon", 7) ||
- !memcmp(Format, "cmn_err", 7); break;
- case 8:
- Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
- (is_NSString = !memcmp(Format, "NSString", 8)) ||
- !memcmp(Format, "vcmn_err", 8) ||
- !memcmp(Format, "zcmn_err", 8) ||
- (is_CFString = !memcmp(Format, "CFString", 8));
- break;
- }
+ if (Format.startswith("__") && Format.endswith("__"))
+ Format = Format.substr(2, Format.size() - 4);
- if (!Supported) {
+ // Check for supported formats.
+ FormatAttrKind Kind = getFormatAttrKind(Format);
+ if (Kind == InvalidFormat) {
S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
<< "format" << Attr.getParameterName()->getName();
return;
@@ -1296,13 +1302,13 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// make sure the format string is really a string
QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
- if (is_CFString) {
+ if (Kind == CFStringFormat) {
if (!isCFStringType(Ty, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
<< "a CFString" << IdxExpr->getSourceRange();
return;
}
- } else if (is_NSString) {
+ } else if (Kind == NSStringFormat) {
// FIXME: do we need to check if the type is NSString*? What are the
// semantics?
if (!isNSStringType(Ty, S.Context)) {
@@ -1340,7 +1346,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// strftime requires FirstArg to be 0 because it doesn't read from any
// variable the input is just the current time + the format string.
- if (is_strftime) {
+ if (Kind == StrftimeFormat) {
if (FirstArg != 0) {
S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
<< FirstArgExpr->getSourceRange();
@@ -1353,8 +1359,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen),
- Idx.getZExtValue(), FirstArg.getZExtValue()));
+ d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(),
+ FirstArg.getZExtValue()));
}
static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
@@ -1496,20 +1502,17 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
return;
}
- const char *Str = Name->getName();
- unsigned Len = Name->getLength();
+
+ llvm::StringRef Str = Attr.getParameterName()->getName();
// Normalize the attribute name, __foo__ becomes foo.
- if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
- Str[Len - 2] == '_' && Str[Len - 1] == '_') {
- Str += 2;
- Len -= 4;
- }
+ if (Str.startswith("__") && Str.endswith("__"))
+ Str = Str.substr(2, Str.size() - 4);
unsigned DestWidth = 0;
bool IntegerMode = true;
bool ComplexMode = false;
- switch (Len) {
+ switch (Str.size()) {
case 2:
switch (Str[0]) {
case 'Q': DestWidth = 8; break;
@@ -1531,13 +1534,13 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
case 4:
// FIXME: glibc uses 'word' to define register_t; this is narrower than a
// pointer on PIC16 and other embedded platforms.
- if (!memcmp(Str, "word", 4))
+ if (Str == "word")
DestWidth = S.Context.Target.getPointerWidth(0);
- if (!memcmp(Str, "byte", 4))
+ else if (Str == "byte")
DestWidth = S.Context.Target.getCharWidth();
break;
case 7:
- if (!memcmp(Str, "pointer", 7))
+ if (Str == "pointer")
DestWidth = S.Context.Target.getPointerWidth(0);
break;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 419c8a1..6d1f4ea 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1658,12 +1658,10 @@ namespace {
// Traverse the record, looking for methods.
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {
// If the method is pure virtual, add it to the methods vector.
- if (MD->isPure()) {
+ if (MD->isPure())
Methods.push_back(MD);
- continue;
- }
- // Otherwise, record all the overridden methods in our set.
+ // Record all the overridden methods in our set.
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods(); I != E; ++I) {
// Keep track of the overridden methods.
@@ -3571,7 +3569,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
if (DiagnoseUseOfDecl(Fn, DeclLoc))
return true;
- FixOverloadedFunctionReference(Init, Fn);
+ Init = FixOverloadedFunctionReference(Init, Fn);
}
T2 = Fn->getType();
@@ -3660,7 +3658,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// applicable conversion functions (13.3.1.6) and choosing
// the best one through overload resolution (13.3)),
if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
- !RequireCompleteType(SourceLocation(), T2, 0)) {
+ !RequireCompleteType(DeclLoc, T2, 0)) {
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
@@ -4283,8 +4281,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
bool invalid = false;
- QualType SourceTy;
- QualType T = ConvertDeclSpecToType(DS, Loc, invalid, SourceTy);
+ QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
if (invalid) return DeclPtrTy();
// This is definitely an error in C++98. It's probably meant to
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a946500..ae45429 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -241,12 +241,12 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
// other types are unchanged by the integer promotions.
QualType PTy = Context.isPromotableBitField(Expr);
if (!PTy.isNull()) {
- ImpCastExprToType(Expr, PTy);
+ ImpCastExprToType(Expr, PTy, CastExpr::CK_IntegralCast);
return Expr;
}
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
- ImpCastExprToType(Expr, PT);
+ ImpCastExprToType(Expr, PT, CastExpr::CK_IntegralCast);
return Expr;
}
@@ -264,7 +264,8 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) {
// If this is a 'float' (CVR qualified or typedef) promote to double.
if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
if (BT->getKind() == BuiltinType::Float)
- return ImpCastExprToType(Expr, Context.DoubleTy);
+ return ImpCastExprToType(Expr, Context.DoubleTy,
+ CastExpr::CK_FloatingCast);
UsualUnaryConversions(Expr);
}
@@ -330,8 +331,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs);
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, destType);
- ImpCastExprToType(rhsExpr, destType);
+ ImpCastExprToType(lhsExpr, destType, CastExpr::CK_Unknown);
+ ImpCastExprToType(rhsExpr, destType, CastExpr::CK_Unknown);
return destType;
}
@@ -940,95 +941,31 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
+ // FIXME: This needs to happen post-isImplicitMemberReference?
if (FieldDecl *FD = dyn_cast<FieldDecl>(D))
if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
return BuildAnonymousStructUnionMemberReference(Loc, FD);
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
- if (!MD->isStatic()) {
- // C++ [class.mfct.nonstatic]p2:
- // [...] if name lookup (3.4.1) resolves the name in the
- // id-expression to a nonstatic nontype member of class X or of
- // a base class of X, the id-expression is transformed into a
- // class member access expression (5.2.5) using (*this) (9.3.2)
- // as the postfix-expression to the left of the '.' operator.
- DeclContext *Ctx = 0;
- QualType MemberType;
- if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- Ctx = FD->getDeclContext();
- MemberType = FD->getType();
-
- if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
- MemberType = RefType->getPointeeType();
- else if (!FD->isMutable())
- MemberType
- = Context.getQualifiedType(MemberType,
- Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
- } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
- if (!Method->isStatic()) {
- Ctx = Method->getParent();
- MemberType = Method->getType();
- }
- } else if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>(D)) {
- if (CXXMethodDecl *Method
- = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())) {
- if (!Method->isStatic()) {
- Ctx = Method->getParent();
- MemberType = Context.OverloadTy;
- }
- }
- } else if (OverloadedFunctionDecl *Ovl
- = dyn_cast<OverloadedFunctionDecl>(D)) {
- // FIXME: We need an abstraction for iterating over one or more function
- // templates or functions. This code is far too repetitive!
- for (OverloadedFunctionDecl::function_iterator
- Func = Ovl->function_begin(),
- FuncEnd = Ovl->function_end();
- Func != FuncEnd; ++Func) {
- CXXMethodDecl *DMethod = 0;
- if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>(*Func))
- DMethod = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
- else
- DMethod = dyn_cast<CXXMethodDecl>(*Func);
-
- if (DMethod && !DMethod->isStatic()) {
- Ctx = DMethod->getDeclContext();
- MemberType = Context.OverloadTy;
- break;
- }
- }
- }
-
- if (Ctx && Ctx->isRecord()) {
- QualType CtxType = Context.getTagDeclType(cast<CXXRecordDecl>(Ctx));
- QualType ThisType = Context.getTagDeclType(MD->getParent());
- if ((Context.getCanonicalType(CtxType)
- == Context.getCanonicalType(ThisType)) ||
- IsDerivedFrom(ThisType, CtxType)) {
- // Build the implicit member access expression.
- Expr *This = new (Context) CXXThisExpr(SourceLocation(),
- MD->getThisType(Context));
- MarkDeclarationReferenced(Loc, D);
- if (PerformObjectMemberConversion(This, D))
- return ExprError();
-
- bool ShouldCheckUse = true;
- if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- // Don't diagnose the use of a virtual member function unless it's
- // explicitly qualified.
- if (MD->isVirtual() && (!SS || !SS->isSet()))
- ShouldCheckUse = false;
- }
+ // Cope with an implicit member access in a C++ non-static member function.
+ QualType ThisType, MemberType;
+ if (isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) {
+ Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
+ MarkDeclarationReferenced(Loc, D);
+ if (PerformObjectMemberConversion(This, D))
+ return ExprError();
- if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
- return ExprError();
- return Owned(BuildMemberExpr(Context, This, true, SS, D,
- Loc, MemberType));
- }
- }
+ bool ShouldCheckUse = true;
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ // Don't diagnose the use of a virtual member function unless it's
+ // explicitly qualified.
+ if (MD->isVirtual() && (!SS || !SS->isSet()))
+ ShouldCheckUse = false;
}
+
+ if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
+ return ExprError();
+ return Owned(BuildMemberExpr(Context, This, true, SS, D,
+ Loc, MemberType));
}
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
@@ -1813,7 +1750,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
// force the promotion here.
Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
LHSExp->getSourceRange();
- ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy));
+ ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
+ CastExpr::CK_ArrayToPointerDecay);
LHSTy = LHSExp->getType();
BaseExpr = LHSExp;
@@ -1823,7 +1761,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
// Same as previous, except for 123[f().a] case
Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
RHSExp->getSourceRange();
- ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy));
+ ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
+ CastExpr::CK_ArrayToPointerDecay);
RHSTy = RHSExp->getType();
BaseExpr = RHSExp;
@@ -1877,10 +1816,15 @@ QualType Sema::
CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
const IdentifierInfo *CompName,
SourceLocation CompLoc) {
+ // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
+ // see FIXME there.
+ //
+ // FIXME: This logic can be greatly simplified by splitting it along
+ // halving/not halving and reworking the component checking.
const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();
// The vector accessor can't exceed the number of elements.
- const char *compStr = CompName->getName();
+ const char *compStr = CompName->getNameStart();
// This flag determines whether or not the component is one of the four
// special names that indicate a subset of exactly half the elements are
@@ -1917,7 +1861,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
// Ensure no component accessor exceeds the width of the vector type it
// operates on.
if (!HalvingSwizzle) {
- compStr = CompName->getName();
+ compStr = CompName->getNameStart();
if (HexSwizzle)
compStr++;
@@ -2042,7 +1986,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
// is a reference to 'isa'.
if (BaseType != Context.ObjCIdRedefinitionType) {
BaseType = Context.ObjCIdRedefinitionType;
- ImpCastExprToType(BaseExpr, BaseType);
+ ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
}
}
assert(!BaseType.isNull() && "no type for member expression");
@@ -2100,7 +2044,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
if (BaseType->isObjCClassType() &&
BaseType != Context.ObjCClassRedefinitionType) {
BaseType = Context.ObjCClassRedefinitionType;
- ImpCastExprToType(BaseExpr, BaseType);
+ ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
}
// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
@@ -2184,6 +2128,12 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
// If the member name was a qualified-id, look into the
// nested-name-specifier.
DC = computeDeclContext(*SS, false);
+
+ if (!isa<TypeDecl>(DC)) {
+ Diag(MemberLoc, diag::err_qualified_member_nonclass)
+ << DC << SS->getRange();
+ return ExprError();
+ }
// FIXME: If DC is not computable, we should build a
// CXXUnresolvedMemberExpr.
@@ -3142,6 +3092,40 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
return Owned(E);
}
+static CastExpr::CastKind getScalarCastKind(ASTContext &Context,
+ QualType SrcTy, QualType DestTy) {
+ if (Context.getCanonicalType(SrcTy).getUnqualifiedType() ==
+ Context.getCanonicalType(DestTy).getUnqualifiedType())
+ return CastExpr::CK_NoOp;
+
+ if (SrcTy->hasPointerRepresentation()) {
+ if (DestTy->hasPointerRepresentation())
+ return CastExpr::CK_BitCast;
+ if (DestTy->isIntegerType())
+ return CastExpr::CK_PointerToIntegral;
+ }
+
+ if (SrcTy->isIntegerType()) {
+ if (DestTy->isIntegerType())
+ return CastExpr::CK_IntegralCast;
+ if (DestTy->hasPointerRepresentation())
+ return CastExpr::CK_IntegralToPointer;
+ if (DestTy->isRealFloatingType())
+ return CastExpr::CK_IntegralToFloating;
+ }
+
+ if (SrcTy->isRealFloatingType()) {
+ if (DestTy->isRealFloatingType())
+ return CastExpr::CK_FloatingCast;
+ if (DestTy->isIntegerType())
+ return CastExpr::CK_FloatingToIntegral;
+ }
+
+ // FIXME: Assert here.
+ // assert(false && "Unhandled cast combination!");
+ return CastExpr::CK_Unknown;
+}
+
/// CheckCastTypes - Check type constraints for casting between types.
bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
CastExpr::CastKind& Kind,
@@ -3157,7 +3141,11 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
// type needs to be scalar.
if (castType->isVoidType()) {
// Cast to void allows any expr type.
- } else if (!castType->isScalarType() && !castType->isVectorType()) {
+ Kind = CastExpr::CK_ToVoid;
+ return false;
+ }
+
+ if (!castType->isScalarType() && !castType->isVectorType()) {
if (Context.getCanonicalType(castType).getUnqualifiedType() ==
Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) &&
(castType->isStructureType() || castType->isUnionType())) {
@@ -3166,7 +3154,10 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
<< castType << castExpr->getSourceRange();
Kind = CastExpr::CK_NoOp;
- } else if (castType->isUnionType()) {
+ return false;
+ }
+
+ if (castType->isUnionType()) {
// GCC cast to union extension
RecordDecl *RD = castType->getAs<RecordType>()->getDecl();
RecordDecl::field_iterator Field, FieldEnd;
@@ -3183,28 +3174,36 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
<< castExpr->getType() << castExpr->getSourceRange();
Kind = CastExpr::CK_ToUnion;
- } else {
- // Reject any other conversions to non-scalar types.
- return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
- << castType << castExpr->getSourceRange();
+ return false;
}
- } else if (!castExpr->getType()->isScalarType() &&
- !castExpr->getType()->isVectorType()) {
+
+ // Reject any other conversions to non-scalar types.
+ return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
+ << castType << castExpr->getSourceRange();
+ }
+
+ if (!castExpr->getType()->isScalarType() &&
+ !castExpr->getType()->isVectorType()) {
return Diag(castExpr->getLocStart(),
diag::err_typecheck_expect_scalar_operand)
<< castExpr->getType() << castExpr->getSourceRange();
- } else if (castType->isExtVectorType()) {
- if (CheckExtVectorCast(TyR, castType, castExpr->getType()))
- return true;
- } else if (castType->isVectorType()) {
- if (CheckVectorCast(TyR, castType, castExpr->getType()))
- return true;
- } else if (castExpr->getType()->isVectorType()) {
- if (CheckVectorCast(TyR, castExpr->getType(), castType))
- return true;
- } else if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr)) {
+ }
+
+ if (castType->isExtVectorType())
+ return CheckExtVectorCast(TyR, castType, castExpr, Kind);
+
+ if (castType->isVectorType())
+ return CheckVectorCast(TyR, castType, castExpr->getType(), Kind);
+ if (castExpr->getType()->isVectorType())
+ return CheckVectorCast(TyR, castExpr->getType(), castType, Kind);
+
+ if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))
return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
- } else if (!castType->isArithmeticType()) {
+
+ if (isa<ObjCSelectorExpr>(castExpr))
+ return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
+
+ if (!castType->isArithmeticType()) {
QualType castExprType = castExpr->getType();
if (!castExprType->isIntegralType() && castExprType->isArithmeticType())
return Diag(castExpr->getLocStart(),
@@ -3216,12 +3215,13 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
diag::err_cast_pointer_to_non_pointer_int)
<< castType << castExpr->getSourceRange();
}
- if (isa<ObjCSelectorExpr>(castExpr))
- return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr);
+
+ Kind = getScalarCastKind(Context, castExpr->getType(), castType);
return false;
}
-bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) {
+bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+ CastExpr::CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
if (Ty->isVectorType() || Ty->isIntegerType()) {
@@ -3236,18 +3236,23 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) {
diag::err_invalid_conversion_between_vector_and_scalar)
<< VectorTy << Ty << R;
+ Kind = CastExpr::CK_BitCast;
return false;
}
-bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) {
+bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
+ CastExpr::CastKind &Kind) {
assert(DestTy->isExtVectorType() && "Not an extended vector type!");
-
+
+ QualType SrcTy = CastExpr->getType();
+
// If SrcTy is a VectorType, the total size must match to explicitly cast to
// an ExtVectorType.
if (SrcTy->isVectorType()) {
if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
<< DestTy << SrcTy << R;
+ Kind = CastExpr::CK_BitCast;
return false;
}
@@ -3258,6 +3263,12 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) {
return Diag(R.getBegin(),
diag::err_invalid_conversion_between_vector_and_scalar)
<< DestTy << SrcTy << R;
+
+ QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();
+ ImpCastExprToType(CastExpr, DestElemTy,
+ getScalarCastKind(Context, SrcTy, DestElemTy));
+
+ Kind = CastExpr::CK_VectorSplat;
return false;
}
@@ -3414,20 +3425,21 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!RHSTy->isVoidType())
Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void)
<< LHS->getSourceRange();
- ImpCastExprToType(LHS, Context.VoidTy);
- ImpCastExprToType(RHS, Context.VoidTy);
+ ImpCastExprToType(LHS, Context.VoidTy, CastExpr::CK_ToVoid);
+ ImpCastExprToType(RHS, Context.VoidTy, CastExpr::CK_ToVoid);
return Context.VoidTy;
}
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
// the type of the other operand."
if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(RHS, LHSTy); // promote the null to a pointer.
+ // promote the null to a pointer.
+ ImpCastExprToType(RHS, LHSTy, CastExpr::CK_Unknown);
return LHSTy;
}
if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer.
+ ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown);
return RHSTy;
}
// Handle things like Class and struct objc_class*. Here we case the result
@@ -3435,23 +3447,23 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// redefinition type if an attempt is made to access its fields.
if (LHSTy->isObjCClassType() &&
(RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
- ImpCastExprToType(RHS, LHSTy);
+ ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
return LHSTy;
}
if (RHSTy->isObjCClassType() &&
(LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
- ImpCastExprToType(LHS, RHSTy);
+ ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
return RHSTy;
}
// And the same for struct objc_object* / id
if (LHSTy->isObjCIdType() &&
(RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
- ImpCastExprToType(RHS, LHSTy);
+ ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
return LHSTy;
}
if (RHSTy->isObjCIdType() &&
(LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
- ImpCastExprToType(LHS, RHSTy);
+ ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
return RHSTy;
}
// Handle block pointer types.
@@ -3459,8 +3471,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
QualType destType = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, destType);
- ImpCastExprToType(RHS, destType);
+ ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
return destType;
}
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
@@ -3484,13 +3496,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, incompatTy);
- ImpCastExprToType(RHS, incompatTy);
+ ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
return incompatTy;
}
// The block pointer types are compatible.
- ImpCastExprToType(LHS, LHSTy);
- ImpCastExprToType(RHS, LHSTy);
+ ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
return LHSTy;
}
// Check constraints for Objective-C object pointers types.
@@ -3536,13 +3548,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
<< LHSTy << RHSTy
<< LHS->getSourceRange() << RHS->getSourceRange();
QualType incompatTy = Context.getObjCIdType();
- ImpCastExprToType(LHS, incompatTy);
- ImpCastExprToType(RHS, incompatTy);
+ ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
return incompatTy;
}
// The object pointer types are compatible.
- ImpCastExprToType(LHS, compositeType);
- ImpCastExprToType(RHS, compositeType);
+ ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast);
return compositeType;
}
// Check Objective-C object pointer types and 'void *'
@@ -3552,8 +3564,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
QualType destPointee
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
- ImpCastExprToType(LHS, destType); // add qualifiers if necessary
- ImpCastExprToType(RHS, destType); // promote to void*
+ // Add qualifiers if necessary.
+ ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
return destType;
}
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
@@ -3562,8 +3576,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
QualType destPointee
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
- ImpCastExprToType(RHS, destType); // add qualifiers if necessary
- ImpCastExprToType(LHS, destType); // promote to void*
+ // Add qualifiers if necessary.
+ ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
return destType;
}
// Check constraints for C object pointers types (C99 6.5.15p3,6).
@@ -3578,16 +3594,20 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
QualType destPointee
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
- ImpCastExprToType(LHS, destType); // add qualifiers if necessary
- ImpCastExprToType(RHS, destType); // promote to void*
+ // Add qualifiers if necessary.
+ ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
QualType destPointee
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
- ImpCastExprToType(LHS, destType); // add qualifiers if necessary
- ImpCastExprToType(RHS, destType); // promote to void*
+ // Add qualifiers if necessary.
+ ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+ // Promote to void*.
+ ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
return destType;
}
@@ -3603,8 +3623,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, incompatTy);
- ImpCastExprToType(RHS, incompatTy);
+ ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
return incompatTy;
}
// The pointer types are compatible.
@@ -3614,8 +3634,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// type.
// FIXME: Need to calculate the composite type.
// FIXME: Need to add qualifiers
- ImpCastExprToType(LHS, LHSTy);
- ImpCastExprToType(RHS, LHSTy);
+ ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
return LHSTy;
}
@@ -3623,13 +3643,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
- ImpCastExprToType(LHS, RHSTy); // promote the integer to a pointer.
+ ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer);
return RHSTy;
}
if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
- ImpCastExprToType(RHS, LHSTy); // promote the integer to a pointer.
+ ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer);
return LHSTy;
}
@@ -3728,16 +3748,16 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
// Check if the pointee types are compatible ignoring the sign.
// We explicitly check for char so that we catch "char" vs
// "unsigned char" on systems where "char" is unsigned.
- if (lhptee->isCharType()) {
+ if (lhptee->isCharType())
lhptee = Context.UnsignedCharTy;
- } else if (lhptee->isSignedIntegerType()) {
+ else if (lhptee->isSignedIntegerType())
lhptee = Context.getCorrespondingUnsignedType(lhptee);
- }
- if (rhptee->isCharType()) {
+
+ if (rhptee->isCharType())
rhptee = Context.UnsignedCharTy;
- } else if (rhptee->isSignedIntegerType()) {
+ else if (rhptee->isSignedIntegerType())
rhptee = Context.getCorrespondingUnsignedType(rhptee);
- }
+
if (lhptee == rhptee) {
// Types are compatible ignoring the sign. Qualifier incompatibility
// takes priority over sign incompatibility because the sign
@@ -4003,14 +4023,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
// 2) null pointer constant
if (FromType->isPointerType())
if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
- ImpCastExprToType(rExpr, it->getType());
+ ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_BitCast);
InitField = *it;
break;
}
if (rExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, it->getType());
+ ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_IntegralToPointer);
InitField = *it;
break;
}
@@ -4054,7 +4074,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
lhsType->isBlockPointerType())
&& rExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, lhsType);
+ ImpCastExprToType(rExpr, lhsType, CastExpr::CK_Unknown);
return Compatible;
}
@@ -4077,7 +4097,8 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// The getNonReferenceType() call makes sure that the resulting expression
// does not have reference type.
if (result != Incompatible && rExpr->getType() != lhsType)
- ImpCastExprToType(rExpr, lhsType.getNonReferenceType());
+ ImpCastExprToType(rExpr, lhsType.getNonReferenceType(),
+ CastExpr::CK_Unknown);
return result;
}
@@ -4128,7 +4149,7 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,
QualType EltTy = LV->getElementType();
if (EltTy->isIntegralType() && rhsType->isIntegralType()) {
if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) {
- ImpCastExprToType(rex, lhsType);
+ ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -4136,7 +4157,7 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,
if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&
rhsType->isRealFloatingType()) {
if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) {
- ImpCastExprToType(rex, lhsType);
+ ImpCastExprToType(rex, lhsType, CastExpr::CK_FloatingCast);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -4416,7 +4437,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
LHSTy = Context.getPromotedIntegerType(LHSTy);
}
if (!isCompAssign)
- ImpCastExprToType(lex, LHSTy);
+ ImpCastExprToType(lex, LHSTy, CastExpr::CK_IntegralCast);
UsualUnaryConversions(rex);
@@ -4567,8 +4588,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return QualType();
}
- ImpCastExprToType(lex, T);
- ImpCastExprToType(rex, T);
+ ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, T, CastExpr::CK_BitCast);
return ResultTy;
}
// C99 6.5.9p2 and C99 6.5.8p2
@@ -4593,7 +4614,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
if (LCanPointeeTy != RCanPointeeTy)
- ImpCastExprToType(rex, lType); // promote the pointer to pointer
+ ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
return ResultTy;
}
@@ -4633,8 +4654,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
return QualType();
}
- ImpCastExprToType(lex, T);
- ImpCastExprToType(rex, T);
+ ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, T, CastExpr::CK_BitCast);
return ResultTy;
}
@@ -4653,7 +4674,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType); // promote the pointer to pointer
+ ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
return ResultTy;
}
// Allow block pointers to be compared with null pointer constants.
@@ -4668,7 +4689,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType); // promote the pointer to pointer
+ ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
return ResultTy;
}
@@ -4686,14 +4707,14 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType);
+ ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
return ResultTy;
}
if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {
if (!Context.areComparableObjCPointerTypes(lType, rType))
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
- ImpCastExprToType(rex, lType);
+ ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
return ResultTy;
}
}
@@ -4711,7 +4732,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, DiagID)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType); // promote the integer to pointer
+ ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
return ResultTy;
}
if (lType->isIntegerType() && rType->isAnyPointerType()) {
@@ -4728,18 +4749,18 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, DiagID)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(lex, rType); // promote the integer to pointer
+ ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
return ResultTy;
}
// Handle block pointers.
if (!isRelational && RHSIsNull
&& lType->isBlockPointerType() && rType->isIntegerType()) {
- ImpCastExprToType(rex, lType); // promote the integer to pointer
+ ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
return ResultTy;
}
if (!isRelational && LHSIsNull
&& lType->isIntegerType() && rType->isBlockPointerType()) {
- ImpCastExprToType(lex, rType); // promote the integer to pointer
+ ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
return ResultTy;
}
return InvalidOperands(Loc, lex, rex);
@@ -4812,9 +4833,16 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
UsualUnaryConversions(lex);
UsualUnaryConversions(rex);
- if (lex->getType()->isScalarType() && rex->getType()->isScalarType())
- return Context.IntTy;
- return InvalidOperands(Loc, lex, rex);
+ if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType())
+ return InvalidOperands(Loc, lex, rex);
+
+ if (Context.getLangOptions().CPlusPlus) {
+ // C++ [expr.log.and]p2
+ // C++ [expr.log.or]p2
+ return Context.BoolTy;
+ }
+
+ return Context.IntTy;
}
/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 5f111c8..d4d031f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -411,13 +411,15 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
}
- ImpCastExprToType(ArraySize, Context.getSizeType());
+ ImpCastExprToType(ArraySize, Context.getSizeType(),
+ CastExpr::CK_IntegralCast);
}
FunctionDecl *OperatorNew = 0;
FunctionDecl *OperatorDelete = 0;
Expr **PlaceArgs = (Expr**)PlacementArgs.get();
unsigned NumPlaceArgs = PlacementArgs.size();
+
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) &&
FindAllocationFunctions(StartLoc,
@@ -448,7 +450,9 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
Expr **ConsArgs = (Expr**)ConstructorArgs.get();
const RecordType *RT;
unsigned NumConsArgs = ConstructorArgs.size();
- if (AllocType->isDependentType()) {
+
+ if (AllocType->isDependentType() ||
+ Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
// Skip all the checks.
} else if ((RT = AllocType->getAs<RecordType>()) &&
!AllocType->isAggregateType()) {
@@ -491,7 +495,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
// FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
-
+
PlacementArgs.release();
ConstructorArgs.release();
ArraySizeE.release();
@@ -1043,6 +1047,40 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
return PerformImplicitConversion(From, ToType, ICS, Flavor);
}
+/// BuildCXXDerivedToBaseExpr - This routine generates the suitable AST
+/// for the derived to base conversion of the expression 'From'. All
+/// necessary information is passed in ICS.
+bool
+Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
+ const ImplicitConversionSequence& ICS,
+ const char *Flavor) {
+ QualType BaseType =
+ QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr);
+ // Must do additional defined to base conversion.
+ QualType DerivedType =
+ QualType::getFromOpaquePtr(ICS.UserDefined.After.FromTypePtr);
+
+ From = new (Context) ImplicitCastExpr(
+ DerivedType.getNonReferenceType(),
+ CastKind,
+ From,
+ DerivedType->isLValueReferenceType());
+ From = new (Context) ImplicitCastExpr(BaseType.getNonReferenceType(),
+ CastExpr::CK_DerivedToBase, From,
+ BaseType->isLValueReferenceType());
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+ OwningExprResult FromResult =
+ BuildCXXConstructExpr(
+ ICS.UserDefined.After.CopyConstructor->getLocation(),
+ BaseType,
+ ICS.UserDefined.After.CopyConstructor,
+ MultiExprArg(*this, (void **)&From, 1));
+ if (FromResult.isInvalid())
+ return true;
+ From = FromResult.takeAs<Expr>();
+ return false;
+}
+
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType using the pre-computed implicit
/// conversion sequence ICS. Returns true if there was an error, false
@@ -1095,13 +1133,19 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
if (CastArg.isInvalid())
return true;
+
+ if (ICS.UserDefined.After.Second == ICK_Derived_To_Base &&
+ ICS.UserDefined.After.CopyConstructor) {
+ From = CastArg.takeAs<Expr>();
+ return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor);
+ }
From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(),
- CastKind, CastArg.takeAs<Expr>(),
+ CastKind, CastArg.takeAs<Expr>(),
ToType->isLValueReferenceType());
return false;
- }
-
+ }
+
case ImplicitConversionSequence::EllipsisConversion:
assert(false && "Cannot perform an ellipsis conversion");
return false;
@@ -1182,8 +1226,14 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
return true;
- FixOverloadedFunctionReference(From, Fn);
+ From = FixOverloadedFunctionReference(From, Fn);
FromType = From->getType();
+
+ // If there's already an address-of operator in the expression, we have
+ // the right type already, and the code below would just introduce an
+ // invalid additional pointer level.
+ if (FromType->isPointerType() || FromType->isMemberFunctionPointerType())
+ break;
}
FromType = Context.getPointerType(FromType);
ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay);
@@ -1205,17 +1255,33 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
break;
case ICK_Integral_Promotion:
- case ICK_Floating_Promotion:
- case ICK_Complex_Promotion:
case ICK_Integral_Conversion:
+ ImpCastExprToType(From, ToType, CastExpr::CK_IntegralCast);
+ break;
+
+ case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
+ ImpCastExprToType(From, ToType, CastExpr::CK_FloatingCast);
+ break;
+
+ case ICK_Complex_Promotion:
case ICK_Complex_Conversion:
+ ImpCastExprToType(From, ToType, CastExpr::CK_Unknown);
+ break;
+
case ICK_Floating_Integral:
+ if (ToType->isFloatingType())
+ ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating);
+ else
+ ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral);
+ break;
+
case ICK_Complex_Real:
+ ImpCastExprToType(From, ToType, CastExpr::CK_Unknown);
+ break;
+
case ICK_Compatible_Conversion:
- // FIXME: Go deeper to get the unqualified type!
- FromType = ToType.getUnqualifiedType();
- ImpCastExprToType(From, FromType);
+ ImpCastExprToType(From, ToType, CastExpr::CK_NoOp);
break;
case ICK_Pointer_Conversion: {
@@ -1245,8 +1311,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
break;
}
case ICK_Boolean_Conversion:
- FromType = Context.BoolTy;
- ImpCastExprToType(From, FromType);
+ ImpCastExprToType(From, Context.BoolTy, CastExpr::CK_Unknown);
break;
default:
@@ -1263,7 +1328,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue
// references.
ImpCastExprToType(From, ToType.getNonReferenceType(),
- CastExpr::CK_Unknown,
+ CastExpr::CK_NoOp,
ToType->isLValueReferenceType());
break;
@@ -1465,7 +1530,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
SourceLocation Loc) {
Expr *Args[2] = { LHS, RHS };
OverloadCandidateSet CandidateSet;
- Self.AddBuiltinOperatorCandidates(OO_Conditional, Args, 2, CandidateSet);
+ Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet);
OverloadCandidateSet::iterator Best;
switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
@@ -1691,12 +1756,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
const MemberPointerType *RMemPtr = RTy->getAs<MemberPointerType>();
if (LMemPtr &&
RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(RHS, LTy);
+ ImpCastExprToType(RHS, LTy, CastExpr::CK_NullToMemberPointer);
return LTy;
}
if (RMemPtr &&
LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(LHS, RTy);
+ ImpCastExprToType(LHS, RTy, CastExpr::CK_NullToMemberPointer);
return RTy;
}
if (LMemPtr && RMemPtr) {
@@ -1787,11 +1852,17 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
// one operand is a null pointer constant, the composite pointer type is
// the type of the other operand.
if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(E1, T2);
+ if (T2->isMemberPointerType())
+ ImpCastExprToType(E1, T2, CastExpr::CK_NullToMemberPointer);
+ else
+ ImpCastExprToType(E1, T2, CastExpr::CK_IntegralToPointer);
return T2;
}
if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(E2, T1);
+ if (T1->isMemberPointerType())
+ ImpCastExprToType(E2, T1, CastExpr::CK_NullToMemberPointer);
+ else
+ ImpCastExprToType(E2, T1, CastExpr::CK_IntegralToPointer);
return T1;
}
@@ -2051,6 +2122,8 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
ClassName);
else {
TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS);
+
+ // FIXME: If Base is dependent, we might not be able to resolve it here.
if (!BaseTy) {
Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
<< ClassName;
@@ -2060,25 +2133,41 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
BaseType = GetTypeFromParser(BaseTy);
}
- CanQualType CanBaseType = Context.getCanonicalType(BaseType);
- DeclarationName DtorName =
- Context.DeclarationNames.getCXXDestructorName(CanBaseType);
+ return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind,
+ SourceRange(ClassNameLoc),
+ BaseType.getAsOpaquePtr(),
+ SS, HasTrailingLParen);
+}
+Sema::OwningExprResult
+Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceRange TypeRange,
+ TypeTy *T,
+ const CXXScopeSpec &SS,
+ bool HasTrailingLParen) {
+ QualType Type = QualType::getFromOpaquePtr(T);
+ CanQualType CanType = Context.getCanonicalType(Type);
+ DeclarationName DtorName =
+ Context.DeclarationNames.getCXXDestructorName(CanType);
+
OwningExprResult Result
- = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
- DtorName, DeclPtrTy(), &SS);
+ = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,
+ TypeRange.getBegin(), DtorName, DeclPtrTy(),
+ &SS);
if (Result.isInvalid() || HasTrailingLParen)
return move(Result);
-
+
// The only way a reference to a destructor can be used is to
// immediately call them. Since the next token is not a '(', produce a
// diagnostic and build the call now.
Expr *E = (Expr *)Result.get();
- SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(E->getLocEnd());
+ SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());
Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
<< isa<CXXPseudoDestructorExpr>(E)
<< CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
-
+
return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
}
@@ -2154,9 +2243,14 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
MultiExprArg(*this, (void **)&From, 1),
CastLoc, ConstructorArgs))
return ExprError();
-
- return BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
- move_arg(ConstructorArgs));
+
+ OwningExprResult Result =
+ BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
+ move_arg(ConstructorArgs));
+ if (Result.isInvalid())
+ return ExprError();
+
+ return MaybeBindToTemporary(Result.takeAs<Expr>());
}
case CastExpr::CK_UserDefinedConversion: {
@@ -2168,7 +2262,7 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
// Create an implicit call expr that calls it.
CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method);
- return Owned(CE);
+ return MaybeBindToTemporary(CE);
}
}
}
@@ -2182,3 +2276,84 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
return Owned(FullExpr);
}
+
+/// \brief Determine whether a reference to the given declaration in the
+/// current context is an implicit member access
+/// (C++ [class.mfct.non-static]p2).
+///
+/// FIXME: Should Objective-C also use this approach?
+///
+/// \param SS if non-NULL, the C++ nested-name-specifier that precedes the
+/// name of the declaration referenced.
+///
+/// \param D the declaration being referenced from the current scope.
+///
+/// \param NameLoc the location of the name in the source.
+///
+/// \param ThisType if the reference to this declaration is an implicit member
+/// access, will be set to the type of the "this" pointer to be used when
+/// building that implicit member access.
+///
+/// \param MemberType if the reference to this declaration is an implicit
+/// member access, will be set to the type of the member being referenced
+/// (for use at the type of the resulting member access expression).
+///
+/// \returns true if this is an implicit member reference (in which case
+/// \p ThisType and \p MemberType will be set), or false if it is not an
+/// implicit member reference.
+bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
+ SourceLocation NameLoc, QualType &ThisType,
+ QualType &MemberType) {
+ // If this isn't a C++ method, then it isn't an implicit member reference.
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
+ if (!MD || MD->isStatic())
+ return false;
+
+ // C++ [class.mfct.nonstatic]p2:
+ // [...] if name lookup (3.4.1) resolves the name in the
+ // id-expression to a nonstatic nontype member of class X or of
+ // a base class of X, the id-expression is transformed into a
+ // class member access expression (5.2.5) using (*this) (9.3.2)
+ // as the postfix-expression to the left of the '.' operator.
+ DeclContext *Ctx = 0;
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ Ctx = FD->getDeclContext();
+ MemberType = FD->getType();
+
+ if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
+ MemberType = RefType->getPointeeType();
+ else if (!FD->isMutable())
+ MemberType
+ = Context.getQualifiedType(MemberType,
+ Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
+ } else {
+ for (OverloadIterator Ovl(D), OvlEnd; Ovl != OvlEnd; ++Ovl) {
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl);
+ FunctionTemplateDecl *FunTmpl = 0;
+ if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+
+ if (Method && !Method->isStatic()) {
+ Ctx = Method->getParent();
+ if (isa<CXXMethodDecl>(D) && !FunTmpl)
+ MemberType = Method->getType();
+ else
+ MemberType = Context.OverloadTy;
+ break;
+ }
+ }
+ }
+
+ if (!Ctx || !Ctx->isRecord())
+ return false;
+
+ // Determine whether the declaration(s) we found are actually in a base
+ // class. If not, this isn't an implicit member reference.
+ ThisType = MD->getThisType(Context);
+ QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx));
+ QualType ClassType
+ = Context.getTypeDeclType(cast<CXXRecordDecl>(MD->getParent()));
+ return Context.hasSameType(CtxType, ClassType) ||
+ IsDerivedFrom(ClassType, CtxType);
+}
+
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index d7e4e4a..b78c10b 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -636,7 +636,11 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// Implicitly convert integers and pointers to 'id' but emit a warning.
Diag(lbrac, diag::warn_bad_receiver_type)
<< RExpr->getType() << RExpr->getSourceRange();
- ImpCastExprToType(RExpr, Context.getObjCIdType());
+ if (ReceiverCType->isPointerType())
+ ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast);
+ else
+ ImpCastExprToType(RExpr, Context.getObjCIdType(),
+ CastExpr::CK_IntegralToPointer);
} else {
// Reject other random receiver types (e.g. structs).
Diag(lbrac, diag::err_bad_receiver_type)
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 27f0896..4746a25 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -109,9 +109,9 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
llvm::APSInt ConstVal(32);
ConstVal = StrLength;
// Return a new array type (C99 6.7.8p22).
- DeclT = S.Context.getConstantArrayWithoutExprType(IAT->getElementType(),
- ConstVal,
- ArrayType::Normal, 0);
+ DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
+ ConstVal,
+ ArrayType::Normal, 0);
return;
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 99e7b08..ebcf3ad 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1934,14 +1934,43 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
return ImplicitConversionSequence::Worse;
}
}
-
-
- // FIXME: conversion of A::* to B::* is better than conversion of
- // A::* to C::*,
-
- // FIXME: conversion of B::* to C::* is better than conversion of
- // A::* to C::*, and
-
+
+ // Ranking of member-pointer types.
+ if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
+ FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
+ ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
+ const MemberPointerType * FromMemPointer1 =
+ FromType1->getAs<MemberPointerType>();
+ const MemberPointerType * ToMemPointer1 =
+ ToType1->getAs<MemberPointerType>();
+ const MemberPointerType * FromMemPointer2 =
+ FromType2->getAs<MemberPointerType>();
+ const MemberPointerType * ToMemPointer2 =
+ ToType2->getAs<MemberPointerType>();
+ const Type *FromPointeeType1 = FromMemPointer1->getClass();
+ const Type *ToPointeeType1 = ToMemPointer1->getClass();
+ const Type *FromPointeeType2 = FromMemPointer2->getClass();
+ const Type *ToPointeeType2 = ToMemPointer2->getClass();
+ QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType();
+ QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType();
+ QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType();
+ QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
+ // conversion of A::* to B::* is better than conversion of A::* to C::*,
+ if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
+ if (IsDerivedFrom(ToPointee1, ToPointee2))
+ return ImplicitConversionSequence::Worse;
+ else if (IsDerivedFrom(ToPointee2, ToPointee1))
+ return ImplicitConversionSequence::Better;
+ }
+ // conversion of B::* to C::* is better than conversion of A::* to C::*
+ if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
+ if (IsDerivedFrom(FromPointee1, FromPointee2))
+ return ImplicitConversionSequence::Better;
+ else if (IsDerivedFrom(FromPointee2, FromPointee1))
+ return ImplicitConversionSequence::Worse;
+ }
+ }
+
if (SCS1.CopyConstructor && SCS2.CopyConstructor &&
SCS1.Second == ICK_Derived_To_Base) {
// -- conversion of C to B is better than conversion of C to A,
@@ -2539,6 +2568,18 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.Viable = false;
return;
}
+
+ // We won't go through a user-define type conversion function to convert a
+ // derived to base as such conversions are given Conversion Rank. They only
+ // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
+ QualType FromCanon
+ = Context.getCanonicalType(From->getType().getUnqualifiedType());
+ QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
+ if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
+ Candidate.Viable = false;
+ return;
+ }
+
// To determine what the conversion from the result of calling the
// conversion function to the type we're eventually trying to
@@ -2551,7 +2592,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
SourceLocation());
ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()),
- CastExpr::CK_Unknown,
+ CastExpr::CK_FunctionToPointerDecay,
&ConversionRef, false);
// Note that it is safe to allocate CallExpr on the stack here because
@@ -2723,7 +2764,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
- AddBuiltinOperatorCandidates(Op, Args, NumArgs, CandidateSet);
+ AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
}
/// \brief Add overload candidates for overloaded operators that are
@@ -2873,7 +2914,8 @@ class BuiltinCandidateTypeSet {
/// Context - The AST context in which we will build the type sets.
ASTContext &Context;
- bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty);
+ bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+ const Qualifiers &VisibleQuals);
bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty);
public:
@@ -2883,8 +2925,11 @@ public:
BuiltinCandidateTypeSet(Sema &SemaRef)
: SemaRef(SemaRef), Context(SemaRef.Context) { }
- void AddTypesConvertedFrom(QualType Ty, bool AllowUserConversions,
- bool AllowExplicitConversions);
+ void AddTypesConvertedFrom(QualType Ty,
+ SourceLocation Loc,
+ bool AllowUserConversions,
+ bool AllowExplicitConversions,
+ const Qualifiers &VisibleTypeConversionsQuals);
/// pointer_begin - First pointer type found;
iterator pointer_begin() { return PointerTypes.begin(); }
@@ -2915,7 +2960,8 @@ public:
///
/// FIXME: what to do about extended qualifiers?
bool
-BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {
+BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
+ const Qualifiers &VisibleQuals) {
// Insert this type.
if (!PointerTypes.insert(Ty))
@@ -2926,11 +2972,16 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {
QualType PointeeTy = PointerTy->getPointeeType();
unsigned BaseCVR = PointeeTy.getCVRQualifiers();
-
+ bool hasVolatile = VisibleQuals.hasVolatile();
+ bool hasRestrict = VisibleQuals.hasRestrict();
+
// Iterate through all strict supersets of BaseCVR.
for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
if ((CVR | BaseCVR) != CVR) continue;
-
+ // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere
+ // in the types.
+ if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue;
+ if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue;
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
PointerTypes.insert(Context.getPointerType(QPointeeTy));
}
@@ -2983,8 +3034,10 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
/// type.
void
BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
+ SourceLocation Loc,
bool AllowUserConversions,
- bool AllowExplicitConversions) {
+ bool AllowExplicitConversions,
+ const Qualifiers &VisibleQuals) {
// Only deal with canonical types.
Ty = Context.getCanonicalType(Ty);
@@ -3001,33 +3054,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
// Insert our type, and its more-qualified variants, into the set
// of types.
- if (!AddPointerWithMoreQualifiedTypeVariants(Ty))
+ if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
return;
-
- // Add 'cv void*' to our set of types.
- if (!Ty->isVoidType()) {
- QualType QualVoid
- = Context.getCVRQualifiedType(Context.VoidTy,
- PointeeTy.getCVRQualifiers());
- AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid));
- }
-
- // If this is a pointer to a class type, add pointers to its bases
- // (with the same level of cv-qualification as the original
- // derived class, of course).
- if (const RecordType *PointeeRec = PointeeTy->getAs<RecordType>()) {
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(PointeeRec->getDecl());
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- QualType BaseTy = Context.getCanonicalType(Base->getType());
- BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(),
- PointeeTy.getCVRQualifiers());
-
- // Add the pointer type, recursively, so that we get all of
- // the indirect base classes, too.
- AddTypesConvertedFrom(Context.getPointerType(BaseTy), false, false);
- }
- }
} else if (Ty->isMemberPointerType()) {
// Member pointers are far easier, since the pointee can't be converted.
if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty))
@@ -3036,7 +3064,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
EnumerationTypes.insert(Ty);
} else if (AllowUserConversions) {
if (const RecordType *TyRec = Ty->getAs<RecordType>()) {
- if (SemaRef.RequireCompleteType(SourceLocation(), Ty, 0)) {
+ if (SemaRef.RequireCompleteType(Loc, Ty, 0)) {
// No conversion functions in incomplete types.
return;
}
@@ -3056,8 +3084,10 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
if (ConvTemplate)
continue;
- if (AllowExplicitConversions || !Conv->isExplicit())
- AddTypesConvertedFrom(Conv->getConversionType(), false, false);
+ if (AllowExplicitConversions || !Conv->isExplicit()) {
+ AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
+ VisibleQuals);
+ }
}
}
}
@@ -3089,6 +3119,58 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
}
}
+/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers
+/// , if any, found in visible type conversion functions found in ArgExpr's
+/// type.
+static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
+ Qualifiers VRQuals;
+ const RecordType *TyRec;
+ if (const MemberPointerType *RHSMPType =
+ ArgExpr->getType()->getAs<MemberPointerType>())
+ TyRec = cast<RecordType>(RHSMPType->getClass());
+ else
+ TyRec = ArgExpr->getType()->getAs<RecordType>();
+ if (!TyRec) {
+ // Just to be safe, assume the worst case.
+ VRQuals.addVolatile();
+ VRQuals.addRestrict();
+ return VRQuals;
+ }
+
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ OverloadedFunctionDecl *Conversions =
+ ClassDecl->getVisibleConversionFunctions();
+
+ for (OverloadedFunctionDecl::function_iterator Func
+ = Conversions->function_begin();
+ Func != Conversions->function_end(); ++Func) {
+ if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*Func)) {
+ QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
+ if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
+ CanTy = ResTypeRef->getPointeeType();
+ // Need to go down the pointer/mempointer chain and add qualifiers
+ // as see them.
+ bool done = false;
+ while (!done) {
+ if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
+ CanTy = ResTypePtr->getPointeeType();
+ else if (const MemberPointerType *ResTypeMPtr =
+ CanTy->getAs<MemberPointerType>())
+ CanTy = ResTypeMPtr->getPointeeType();
+ else
+ done = true;
+ if (CanTy.isVolatileQualified())
+ VRQuals.addVolatile();
+ if (CanTy.isRestrictQualified())
+ VRQuals.addRestrict();
+ if (VRQuals.hasRestrict() && VRQuals.hasVolatile())
+ return VRQuals;
+ }
+ }
+ }
+ return VRQuals;
+}
+
/// AddBuiltinOperatorCandidates - Add the appropriate built-in
/// operator overloads to the candidate set (C++ [over.built]), based
/// on the operator @p Op and the arguments given. For example, if the
@@ -3096,6 +3178,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
/// operator+(int, int)" to cover integer addition.
void
Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet) {
// The set of "promoted arithmetic types", which are the arithmetic
@@ -3119,10 +3202,25 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy,
Context.FloatTy, Context.DoubleTy, Context.LongDoubleTy
};
-
+ assert(ArithmeticTypes[FirstPromotedIntegralType] == Context.IntTy &&
+ "Invalid first promoted integral type");
+ assert(ArithmeticTypes[LastPromotedIntegralType - 1]
+ == Context.UnsignedLongLongTy &&
+ "Invalid last promoted integral type");
+ assert(ArithmeticTypes[FirstPromotedArithmeticType] == Context.IntTy &&
+ "Invalid first promoted arithmetic type");
+ assert(ArithmeticTypes[LastPromotedArithmeticType - 1]
+ == Context.LongDoubleTy &&
+ "Invalid last promoted arithmetic type");
+
// Find all of the types that the arguments can convert to, but only
// if the operator we're looking at has built-in operator candidates
// that make use of these types.
+ Qualifiers VisibleTypeConversionsQuals;
+ VisibleTypeConversionsQuals.addConst();
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+ VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
+
BuiltinCandidateTypeSet CandidateTypes(*this);
if (Op == OO_Less || Op == OO_Greater || Op == OO_LessEqual ||
Op == OO_GreaterEqual || Op == OO_EqualEqual || Op == OO_ExclaimEqual ||
@@ -3132,10 +3230,12 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
(Op == OO_Star && NumArgs == 1) || Op == OO_Conditional) {
for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(),
+ OpLoc,
true,
(Op == OO_Exclaim ||
Op == OO_AmpAmp ||
- Op == OO_PipePipe));
+ Op == OO_PipePipe),
+ VisibleTypeConversionsQuals);
}
bool isComparison = false;
@@ -3202,14 +3302,17 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
-
- // Volatile version
- ParamTypes[0]
- = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
- if (NumArgs == 1)
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
- else
- AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
+ // heuristic to reduce number of builtin candidates in the set.
+ // Add volatile version only if there are conversions to a volatile type.
+ if (VisibleTypeConversionsQuals.hasVolatile()) {
+ // Volatile version
+ ParamTypes[0]
+ = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
+ if (NumArgs == 1)
+ AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+ else
+ AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
+ }
}
// C++ [over.built]p5:
@@ -3238,7 +3341,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
else
AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
- if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
+ if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()) {
// With volatile
ParamTypes[0]
= Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
@@ -3550,7 +3654,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
- if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
+ if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()) {
// volatile version
ParamTypes[0]
= Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
@@ -3586,10 +3691,12 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
/*IsAssigmentOperator=*/Op == OO_Equal);
// Add this built-in operator as a candidate (VQ is 'volatile').
- ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
- ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
+ if (VisibleTypeConversionsQuals.hasVolatile()) {
+ ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
+ ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
+ AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/Op == OO_Equal);
+ }
}
}
break;
@@ -3621,12 +3728,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
// Add this built-in operator as a candidate (VQ is empty).
ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
-
- // Add this built-in operator as a candidate (VQ is 'volatile').
- ParamTypes[0] = ArithmeticTypes[Left];
- ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
- ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+ if (VisibleTypeConversionsQuals.hasVolatile()) {
+ // Add this built-in operator as a candidate (VQ is 'volatile').
+ ParamTypes[0] = ArithmeticTypes[Left];
+ ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
+ ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
+ AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+ }
}
}
break;
@@ -3708,6 +3816,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
C1 = QualType(Q1.strip(PointerTy->getPointeeType()), 0);
if (!isa<RecordType>(C1))
continue;
+ // heuristic to reduce number of builtin candidates in the set.
+ // Add volatile/restrict version only if there are conversions to a
+ // volatile/restrict type.
+ if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+ continue;
}
for (BuiltinCandidateTypeSet::iterator
MemPtr = CandidateTypes.member_pointer_begin(),
@@ -3721,6 +3836,12 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
QualType ParamTypes[2] = { *Ptr, *MemPtr };
// build CV12 T&
QualType T = mptr->getPointeeType();
+ if (!VisibleTypeConversionsQuals.hasVolatile() &&
+ T.isVolatileQualified())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() &&
+ T.isRestrictQualified())
+ continue;
T = Q1.apply(T);
QualType ResultTy = Context.getLValueReferenceType(T);
AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
@@ -4061,13 +4182,20 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
} else if (OnlyViable) {
assert(Cand->Conversions.size() <= 2 &&
"builtin-binary-operator-not-binary");
- if (Cand->Conversions.size() == 1)
- Diag(OpLoc, diag::err_ovl_builtin_unary_candidate)
- << Opc << Cand->BuiltinTypes.ParamTypes[0];
- else
- Diag(OpLoc, diag::err_ovl_builtin_binary_candidate)
- << Opc << Cand->BuiltinTypes.ParamTypes[0]
- << Cand->BuiltinTypes.ParamTypes[1];
+ std::string TypeStr("operator");
+ TypeStr += Opc;
+ TypeStr += "(";
+ TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
+ if (Cand->Conversions.size() == 1) {
+ TypeStr += ")";
+ Diag(OpLoc, diag::err_ovl_builtin_unary_candidate) << TypeStr;
+ }
+ else {
+ TypeStr += ", ";
+ TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
+ TypeStr += ")";
+ Diag(OpLoc, diag::err_ovl_builtin_binary_candidate) << TypeStr;
+ }
}
else if (!Cand->Viable && !Reported) {
// Non-viability might be due to ambiguous user-defined conversions,
@@ -4150,6 +4278,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
OvlExpr = UnOp->getSubExpr()->IgnoreParens();
}
+ bool HasExplicitTemplateArgs = false;
+ const TemplateArgument *ExplicitTemplateArgs = 0;
+ unsigned NumExplicitTemplateArgs = 0;
+
// Try to dig out the overloaded function.
FunctionTemplateDecl *FunctionTemplate = 0;
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
@@ -4159,9 +4291,17 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
// FIXME: Explicit template arguments
+ } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) {
+ TemplateName Name = TIRE->getTemplateName();
+ Ovl = Name.getAsOverloadedFunctionDecl();
+ FunctionTemplate =
+ dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
+
+ HasExplicitTemplateArgs = true;
+ ExplicitTemplateArgs = TIRE->getTemplateArgs();
+ NumExplicitTemplateArgs = TIRE->getNumTemplateArgs();
}
- // FIXME: TemplateIdRefExpr?
-
+
// If there's no overloaded function declaration or function template,
// we're done.
if (!Ovl && !FunctionTemplate)
@@ -4206,8 +4346,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
FunctionDecl *Specialization = 0;
TemplateDeductionInfo Info(Context);
if (TemplateDeductionResult Result
- = DeduceTemplateArguments(FunctionTemplate, /*FIXME*/false,
- /*FIXME:*/0, /*FIXME:*/0,
+ = DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs,
+ ExplicitTemplateArgs,
+ NumExplicitTemplateArgs,
FunctionType, Specialization, Info)) {
// FIXME: make a note of the failed deduction for diagnostics.
(void)Result;
@@ -4240,8 +4381,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// If there were 0 or 1 matches, we're done.
if (Matches.empty())
return 0;
- else if (Matches.size() == 1)
- return *Matches.begin();
+ else if (Matches.size() == 1) {
+ FunctionDecl *Result = *Matches.begin();
+ MarkDeclarationReferenced(From->getLocStart(), Result);
+ return Result;
+ }
// C++ [over.over]p4:
// If more than one function is selected, [...]
@@ -4257,14 +4401,17 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// two-pass algorithm (similar to the one used to identify the
// best viable function in an overload set) that identifies the
// best function template (if it exists).
- llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(),
+ llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(),
Matches.end());
- return getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(),
- TPOC_Other, From->getLocStart(),
- PDiag(),
- PDiag(diag::err_addr_ovl_ambiguous)
- << TemplateMatches[0]->getDeclName(),
- PDiag(diag::err_ovl_template_candidate));
+ FunctionDecl *Result =
+ getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(),
+ TPOC_Other, From->getLocStart(),
+ PDiag(),
+ PDiag(diag::err_addr_ovl_ambiguous)
+ << TemplateMatches[0]->getDeclName(),
+ PDiag(diag::err_ovl_template_candidate));
+ MarkDeclarationReferenced(From->getLocStart(), Result);
+ return Result;
}
// [...] any function template specializations in the set are
@@ -4276,8 +4423,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// [...] After such eliminations, if any, there shall remain exactly one
// selected function.
- if (RemainingMatches.size() == 1)
- return RemainingMatches.front();
+ if (RemainingMatches.size() == 1) {
+ FunctionDecl *Result = RemainingMatches.front();
+ MarkDeclarationReferenced(From->getLocStart(), Result);
+ return Result;
+ }
// FIXME: We should probably return the same thing that BestViableFunction
// returns (even if we issue the diagnostics here).
@@ -4511,7 +4661,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
// Add builtin operator candidates.
- AddBuiltinOperatorCandidates(Op, &Args[0], NumArgs, CandidateSet);
+ AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
@@ -4671,7 +4821,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
// Add builtin operator candidates.
- AddBuiltinOperatorCandidates(Op, Args, 2, CandidateSet);
+ AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
@@ -4925,6 +5075,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,
CandidateSet, /*SuppressUserConversions=*/false);
+ if (RequireCompleteType(LParenLoc, Object->getType(),
+ PartialDiagnostic(diag::err_incomplete_object_call)
+ << Object->getSourceRange()))
+ return true;
+
// C++ [over.call.object]p2:
// In addition, for each conversion function declared in T of the
// form
@@ -4942,33 +5097,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
+ // FIXME: Look in base classes for more conversion operators!
+ OverloadedFunctionDecl *Conversions
+ = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+ for (OverloadedFunctionDecl::function_iterator
+ Func = Conversions->function_begin(),
+ FuncEnd = Conversions->function_end();
+ Func != FuncEnd; ++Func) {
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
- if (!RequireCompleteType(SourceLocation(), Object->getType(), 0)) {
- // FIXME: Look in base classes for more conversion operators!
- OverloadedFunctionDecl *Conversions
- = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- Func = Conversions->function_begin(),
- FuncEnd = Conversions->function_end();
- Func != FuncEnd; ++Func) {
- CXXConversionDecl *Conv;
- FunctionTemplateDecl *ConvTemplate;
- GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
-
- // Skip over templated conversion functions; they aren't
- // surrogates.
- if (ConvTemplate)
- continue;
+ // Skip over templated conversion functions; they aren't
+ // surrogates.
+ if (ConvTemplate)
+ continue;
- // Strip the reference type (if any) and then the pointer type (if
- // any) to get down to what might be a function type.
- QualType ConvType = Conv->getConversionType().getNonReferenceType();
- if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
- ConvType = ConvPtrType->getPointeeType();
+ // Strip the reference type (if any) and then the pointer type (if
+ // any) to get down to what might be a function type.
+ QualType ConvType = Conv->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ ConvType = ConvPtrType->getPointeeType();
- if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
- AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
- }
+ if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
+ AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
}
// Perform overload resolution.
@@ -5205,11 +5357,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
/// a C++ overloaded function (possibly with some parentheses and
/// perhaps a '&' around it). We have resolved the overloaded function
/// to the function declaration Fn, so patch up the expression E to
-/// refer (possibly indirectly) to Fn.
-void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
+/// refer (possibly indirectly) to Fn. Returns the new expr.
+Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
- FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
- E->setType(PE->getSubExpr()->getType());
+ Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
+ NewExpr->setType(PE->getSubExpr()->getType());
+ return NewExpr;
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&
"Can only take the address of an overloaded function");
@@ -5228,11 +5381,16 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
E->setType(Context.getMemberPointerType(Fn->getType(),
ClassType.getTypePtr()));
- return;
+ return E;
}
+ // FIXME: TemplateIdRefExpr referring to a member function template
+ // specialization!
}
- FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
- E->setType(Context.getPointerType(UnOp->getSubExpr()->getType()));
+ Expr *NewExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+ UnOp->setSubExpr(NewExpr);
+ UnOp->setType(Context.getPointerType(NewExpr->getType()));
+
+ return UnOp;
} else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
isa<FunctionTemplateDecl>(DR->getDecl())) &&
@@ -5242,9 +5400,24 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
} else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
MemExpr->setMemberDecl(Fn);
E->setType(Fn->getType());
+ } else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
+ // FIXME: We should capture the template arguments here.
+ if (NestedNameSpecifier *Qualifier = TID->getQualifier())
+ E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(),
+ TID->getTemplateNameLoc(),
+ /*FIXME?*/false, /*FIXME?*/false,
+ TID->getQualifierRange(),
+ Qualifier);
+ else
+ E = new (Context) DeclRefExpr(Fn, Fn->getType(),
+ TID->getTemplateNameLoc());
+
+ TID->Destroy(Context);
} else {
assert(false && "Invalid reference to overloaded function");
}
+
+ return E;
}
} // end namespace clang
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index e8cd6b0..1453424 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -368,6 +368,21 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,
return false;
}
+/// 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) {
+ const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr();
+ QualType TypeBeforePromotion = ExprBeforePromotion->getType();
+ if (TypeBeforePromotion->isIntegralType()) {
+ return TypeBeforePromotion;
+ }
+ }
+ return expr->getType();
+}
+
Action::OwningStmtResult
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
StmtArg Body) {
@@ -382,11 +397,30 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
Expr *CondExpr = SS->getCond();
QualType CondType = CondExpr->getType();
- if (!CondExpr->isTypeDependent() &&
- !CondType->isIntegerType()) { // C99 6.8.4.2p1
- Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
- << CondType << CondExpr->getSourceRange();
- return StmtError();
+ // C++ 6.4.2.p2:
+ // Integral promotions are performed (on the switch condition).
+ //
+ // A case value unrepresentable by the original switch condition
+ // type (before the promotion) doesn't make sense, even when it can
+ // be represented by the promoted type. Therefore we need to find
+ // the pre-promotion type of the switch condition.
+ QualType CondTypeBeforePromotion =
+ GetTypeBeforeIntegralPromotion(CondExpr);
+
+ if (!CondExpr->isTypeDependent()) {
+ if (!CondType->isIntegerType()) { // C99 6.8.4.2p1
+ Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
+ << CondType << CondExpr->getSourceRange();
+ return StmtError();
+ }
+
+ if (CondTypeBeforePromotion->isBooleanType()) {
+ // switch(bool_expr) {...} is often a programmer error, e.g.
+ // switch(n && mask) { ... } // Doh - should be "n & mask".
+ // One can always use an if statement instead of switch(bool_expr).
+ Diag(SwitchLoc, diag::warn_bool_switch_condition)
+ << CondExpr->getSourceRange();
+ }
}
// Get the bitwidth of the switched-on value before promotions. We must
@@ -395,8 +429,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
= CondExpr->isTypeDependent() || CondExpr->isValueDependent();
unsigned CondWidth
= HasDependentValue? 0
- : static_cast<unsigned>(Context.getTypeSize(CondType));
- bool CondIsSigned = CondType->isSignedIntegerType();
+ : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion));
+ bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();
// Accumulate all of the case values in a vector so that we can sort them
// and detect duplicates. This vector contains the APInt for the case after
@@ -448,7 +482,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Lo, CondType);
+ ImpCastExprToType(Lo, CondType, CastExpr::CK_IntegralCast);
CS->setLHS(Lo);
// If this is a case range, remember it in CaseRanges, otherwise CaseVals.
@@ -504,7 +538,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Hi, CondType);
+ ImpCastExprToType(Hi, CondType, CastExpr::CK_IntegralCast);
CR->setRHS(Hi);
// If the low value is bigger than the high value, the case is empty.
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ab0bbe0..0f22320 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1251,7 +1251,9 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
return ElabType.getAsOpaquePtr();
}
-Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template,
+Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
const TemplateArgument *TemplateArgs,
@@ -1261,16 +1263,36 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template,
// template arguments that we have against the template name, if the template
// name refers to a single template. That's not a terribly common case,
// though.
- return Owned(TemplateIdRefExpr::Create(Context,
- /*FIXME: New type?*/Context.OverloadTy,
- /*FIXME: Necessary?*/0,
- /*FIXME: Necessary?*/SourceRange(),
+
+ // Cope with an implicit member access in a C++ non-static member function.
+ NamedDecl *D = Template.getAsTemplateDecl();
+ if (!D)
+ D = Template.getAsOverloadedFunctionDecl();
+
+ CXXScopeSpec SS;
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+ QualType ThisType, MemberType;
+ if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc,
+ ThisType, MemberType)) {
+ Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType);
+ return Owned(MemberExpr::Create(Context, This, true,
+ Qualifier, QualifierRange,
+ D, TemplateNameLoc, true,
+ LAngleLoc, TemplateArgs,
+ NumTemplateArgs, RAngleLoc,
+ Context.OverloadTy));
+ }
+
+ return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy,
+ Qualifier, QualifierRange,
Template, TemplateNameLoc, LAngleLoc,
TemplateArgs,
NumTemplateArgs, RAngleLoc));
}
-Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,
+Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS,
+ TemplateTy TemplateD,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
@@ -1283,7 +1305,9 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
TemplateArgsIn.release();
- return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc,
+ return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
+ SS.getRange(),
+ Template, TemplateNameLoc, LAngleLoc,
TemplateArgs.data(), TemplateArgs.size(),
RAngleLoc);
}
@@ -1706,7 +1730,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
bool Invalid = false;
// See through any implicit casts we added to fix the type.
- if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+ while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
Arg = Cast->getSubExpr();
// C++0x allows nullptr, and there's no further checking to be done for that.
@@ -1808,7 +1832,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
bool Invalid = false;
// See through any implicit casts we added to fix the type.
- if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+ while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
Arg = Cast->getSubExpr();
// C++0x allows nullptr, and there's no further checking to be done for that.
@@ -1936,7 +1960,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
// This is an integral promotion or conversion.
- ImpCastExprToType(Arg, ParamType);
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_IntegralCast);
} else {
// We can't perform this conversion.
Diag(Arg->getSourceRange().getBegin(),
@@ -2025,20 +2049,23 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
} else if (ArgType->isNullPtrType() && (ParamType->isPointerType() ||
ParamType->isMemberPointerType())) {
ArgType = ParamType;
- ImpCastExprToType(Arg, ParamType);
+ if (ParamType->isMemberPointerType())
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer);
+ else
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast);
} else if (ArgType->isFunctionType() && ParamType->isPointerType()) {
ArgType = Context.getPointerType(ArgType);
- ImpCastExprToType(Arg, ArgType);
+ ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);
} else if (FunctionDecl *Fn
= ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) {
if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
return true;
- FixOverloadedFunctionReference(Arg, Fn);
+ Arg = FixOverloadedFunctionReference(Arg, Fn);
ArgType = Arg->getType();
if (ArgType->isFunctionType() && ParamType->isPointerType()) {
ArgType = Context.getPointerType(Arg->getType());
- ImpCastExprToType(Arg, ArgType);
+ ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);
}
}
@@ -2083,15 +2110,15 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (ArgType->isNullPtrType()) {
ArgType = ParamType;
- ImpCastExprToType(Arg, ParamType);
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast);
} else if (ArgType->isArrayType()) {
ArgType = Context.getArrayDecayedType(ArgType);
- ImpCastExprToType(Arg, ArgType);
+ ImpCastExprToType(Arg, ArgType, CastExpr::CK_ArrayToPointerDecay);
}
if (IsQualificationConversion(ArgType, ParamType)) {
ArgType = ParamType;
- ImpCastExprToType(Arg, ParamType);
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp);
}
if (!Context.hasSameUnqualifiedType(ArgType, ParamType)) {
@@ -2162,9 +2189,9 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
// Types match exactly: nothing more to do here.
} else if (ArgType->isNullPtrType()) {
- ImpCastExprToType(Arg, ParamType);
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer);
} else if (IsQualificationConversion(ArgType, ParamType)) {
- ImpCastExprToType(Arg, ParamType);
+ ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp);
} else {
// We can't perform this conversion.
Diag(Arg->getSourceRange().getBegin(),
@@ -3038,6 +3065,173 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
return DeclPtrTy();
}
+/// \brief Diagnose cases where we have an explicit template specialization
+/// before/after an explicit template instantiation, producing diagnostics
+/// for those cases where they are required and determining whether the
+/// new specialization/instantiation will have any effect.
+///
+/// \param S the semantic analysis object.
+///
+/// \param NewLoc the location of the new explicit specialization or
+/// instantiation.
+///
+/// \param NewTSK the kind of the new explicit specialization or instantiation.
+///
+/// \param PrevDecl the previous declaration of the entity.
+///
+/// \param PrevTSK the kind of the old explicit specialization or instantiatin.
+///
+/// \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
+/// specialization or instantiation has no effect and should be ignored.
+///
+/// \returns true if there was an error that should prevent the introduction of
+/// the new declaration into the AST, false otherwise.
+static bool
+CheckSpecializationInstantiationRedecl(Sema &S,
+ SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &SuppressNew) {
+ SuppressNew = false;
+
+ switch (NewTSK) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ assert(false && "Don't check implicit instantiations here");
+ return false;
+
+ case TSK_ExplicitSpecialization:
+ switch (PrevTSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ // Okay, we're just specializing something that is either already
+ // explicitly specialized or has merely been mentioned without any
+ // instantiation.
+ return false;
+
+ case TSK_ImplicitInstantiation:
+ if (PrevPointOfInstantiation.isInvalid()) {
+ // The declaration itself has not actually been instantiated, so it is
+ // still okay to specialize it.
+ return false;
+ }
+ // Fall through
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ assert((PrevTSK == TSK_ImplicitInstantiation ||
+ PrevPointOfInstantiation.isValid()) &&
+ "Explicit instantiation without point of instantiation?");
+
+ // C++ [temp.expl.spec]p6:
+ // If a template, a member template or the member of a class template
+ // is explicitly specialized then that specialization shall be declared
+ // before the first use of that specialization that would cause an
+ // implicit instantiation to take place, in every translation unit in
+ // which such a use occurs; no diagnostic is required.
+ S.Diag(NewLoc, diag::err_specialization_after_instantiation)
+ << PrevDecl;
+ S.Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
+ << (PrevTSK != TSK_ImplicitInstantiation);
+
+ return true;
+ }
+ break;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ switch (PrevTSK) {
+ case TSK_ExplicitInstantiationDeclaration:
+ // This explicit instantiation declaration is redundant (that's okay).
+ SuppressNew = true;
+ return false;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // We're explicitly instantiating something that may have already been
+ // implicitly instantiated; that's fine.
+ return false;
+
+ case TSK_ExplicitSpecialization:
+ // C++0x [temp.explicit]p4:
+ // For a given set of template parameters, if an explicit instantiation
+ // of a template appears after a declaration of an explicit
+ // specialization for that template, the explicit instantiation has no
+ // effect.
+ return false;
+
+ case TSK_ExplicitInstantiationDefinition:
+ // C++0x [temp.explicit]p10:
+ // If an entity is the subject of both an explicit instantiation
+ // declaration and an explicit instantiation definition in the same
+ // translation unit, the definition shall follow the declaration.
+ S.Diag(NewLoc,
+ diag::err_explicit_instantiation_declaration_after_definition);
+ S.Diag(PrevPointOfInstantiation,
+ diag::note_explicit_instantiation_definition_here);
+ assert(PrevPointOfInstantiation.isValid() &&
+ "Explicit instantiation without point of instantiation?");
+ SuppressNew = true;
+ return false;
+ }
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ switch (PrevTSK) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // We're explicitly instantiating something that may have already been
+ // implicitly instantiated; that's fine.
+ return false;
+
+ case TSK_ExplicitSpecialization:
+ // C++ DR 259, C++0x [temp.explicit]p4:
+ // For a given set of template parameters, if an explicit
+ // instantiation of a template appears after a declaration of
+ // an explicit specialization for that template, the explicit
+ // instantiation has no effect.
+ //
+ // In C++98/03 mode, we only give an extension warning here, because it
+ // is not not harmful to try to explicitly instantiate something that
+ // has been explicitly specialized.
+ if (!S.getLangOptions().CPlusPlus0x) {
+ S.Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
+ << PrevDecl;
+ S.Diag(PrevDecl->getLocation(),
+ diag::note_previous_template_specialization);
+ }
+ SuppressNew = true;
+ return false;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ // We're explicity instantiating a definition for something for which we
+ // were previously asked to suppress instantiations. That's fine.
+ return false;
+
+ case TSK_ExplicitInstantiationDefinition:
+ // C++0x [temp.spec]p5:
+ // For a given template and a given set of template-arguments,
+ // - an explicit instantiation definition shall appear at most once
+ // in a program,
+ S.Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
+ << PrevDecl;
+ S.Diag(PrevPointOfInstantiation,
+ diag::note_previous_explicit_instantiation);
+ SuppressNew = true;
+ return false;
+ }
+ break;
+ }
+
+ assert(false && "Missing specialization/instantiation case?");
+
+ return false;
+}
+
/// \brief Perform semantic analysis for the given function template
/// specialization.
///
@@ -3463,54 +3657,18 @@ Sema::ActOnExplicitInstantiation(Scope *S,
ClassTemplateSpecializationDecl *Specialization = 0;
- bool SpecializationRequiresInstantiation = true;
if (PrevDecl) {
- if (PrevDecl->getSpecializationKind()
- == TSK_ExplicitInstantiationDefinition) {
- // This particular specialization has already been declared or
- // instantiated. We cannot explicitly instantiate it.
- Diag(TemplateNameLoc, diag::err_explicit_instantiation_duplicate)
- << Context.getTypeDeclType(PrevDecl);
- Diag(PrevDecl->getLocation(),
- diag::note_previous_explicit_instantiation);
+ bool SuppressNew = false;
+ if (CheckSpecializationInstantiationRedecl(*this, TemplateNameLoc, TSK,
+ PrevDecl,
+ PrevDecl->getSpecializationKind(),
+ PrevDecl->getPointOfInstantiation(),
+ SuppressNew))
return DeclPtrTy::make(PrevDecl);
- }
-
- if (PrevDecl->getSpecializationKind() == TSK_ExplicitSpecialization) {
- // C++ DR 259, C++0x [temp.explicit]p4:
- // For a given set of template parameters, if an explicit
- // instantiation of a template appears after a declaration of
- // an explicit specialization for that template, the explicit
- // instantiation has no effect.
- if (!getLangOptions().CPlusPlus0x) {
- Diag(TemplateNameLoc,
- diag::ext_explicit_instantiation_after_specialization)
- << Context.getTypeDeclType(PrevDecl);
- Diag(PrevDecl->getLocation(),
- diag::note_previous_template_specialization);
- }
- // Create a new class template specialization declaration node
- // for this explicit specialization. This node is only used to
- // record the existence of this explicit instantiation for
- // accurate reproduction of the source code; we don't actually
- // use it for anything, since it is semantically irrelevant.
- Specialization
- = ClassTemplateSpecializationDecl::Create(Context,
- ClassTemplate->getDeclContext(),
- TemplateNameLoc,
- ClassTemplate,
- Converted, 0);
- Specialization->setLexicalDeclContext(CurContext);
- CurContext->addDecl(Specialization);
+ if (SuppressNew)
return DeclPtrTy::make(PrevDecl);
- }
-
- // If we have already (implicitly) instantiated this
- // specialization, there is less work to do.
- if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation)
- SpecializationRequiresInstantiation = false;
-
+
if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation ||
PrevDecl->getSpecializationKind() == TSK_Undeclared) {
// Since the only prior class template specialization with these
@@ -3521,7 +3679,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setLocation(TemplateNameLoc);
PrevDecl = 0;
}
- }
+ }
if (!Specialization) {
// Create a new class template specialization declaration node for
@@ -3574,11 +3732,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,
//
// This check comes when we actually try to perform the
// instantiation.
- if (SpecializationRequiresInstantiation)
+ ClassTemplateSpecializationDecl *Def
+ = cast_or_null<ClassTemplateSpecializationDecl>(
+ Specialization->getDefinition(Context));
+ if (!Def)
InstantiateClassTemplateSpecialization(Specialization, TSK);
else // Instantiate the members of this class template specialization.
- InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization,
- TSK);
+ InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
return DeclPtrTy::make(Specialization);
}
@@ -3649,17 +3809,46 @@ Sema::ActOnExplicitInstantiation(Scope *S,
//
// This is C++ DR 275.
CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
-
- if (!Record->getDefinition(Context)) {
- // If the class has a definition, instantiate it (and all of its
- // members, recursively).
- Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
- if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern,
- getTemplateInstantiationArgs(Record),
- TSK))
+
+ // Verify that it is okay to explicitly instantiate here.
+ CXXRecordDecl *PrevDecl
+ = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
+ if (!PrevDecl && Record->getDefinition(Context))
+ PrevDecl = Record;
+ if (PrevDecl) {
+ MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
+ bool SuppressNew = false;
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(*this, TemplateLoc, TSK,
+ PrevDecl,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew))
+ return true;
+ if (SuppressNew)
+ return TagD;
+ }
+
+ CXXRecordDecl *RecordDef
+ = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ if (!RecordDef) {
+ // C++ [temp.explicit]p3:
+ // A definition of a member class of a class template shall be in scope
+ // at the point of an explicit instantiation of the member class.
+ CXXRecordDecl *Def
+ = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
+ if (!Def) {
+ Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
+ << 0 << Record->getDeclName() << Record->getDeclContext();
+ Diag(Pattern->getLocation(), diag::note_forward_declaration)
+ << Pattern;
+ return true;
+ } else if (InstantiateClass(NameLoc, Record, Def,
+ getTemplateInstantiationArgs(Record),
+ TSK))
return true;
} else // Instantiate all of the members of the class.
- InstantiateClassMembers(TemplateLoc, Record,
+ InstantiateClassMembers(NameLoc, RecordDef,
getTemplateInstantiationArgs(Record), TSK);
// FIXME: We don't have any representation for explicit instantiations of
@@ -3775,11 +3964,24 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// Check the scope of this explicit instantiation.
CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
+ // Verify that it is okay to explicitly instantiate here.
+ MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing static data member specialization info?");
+ bool SuppressNew = false;
+ if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
+ Prev,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew))
+ return true;
+ if (SuppressNew)
+ return DeclPtrTy();
+
// Instantiate static data member.
- // FIXME: Check for prior specializations and such.
- Prev->setTemplateSpecializationKind(TSK);
+ Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false);
+ InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false,
+ /*DefinitionRequired=*/true);
// FIXME: Create an ExplicitInstantiation node?
return DeclPtrTy();
@@ -3850,8 +4052,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (!Specialization)
return true;
- switch (Specialization->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
+ if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
Diag(D.getIdentifierLoc(),
diag::err_explicit_instantiation_member_function_not_instantiated)
<< Specialization
@@ -3859,35 +4060,33 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
TSK_ExplicitSpecialization);
Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
return true;
+ }
+
+ FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+ if (!PrevDecl && Specialization->isThisDeclarationADefinition())
+ PrevDecl = Specialization;
- case TSK_ExplicitSpecialization:
- // C++ [temp.explicit]p4:
- // For a given set of template parameters, if an explicit instantiation
- // of a template appears after a declaration of an explicit
- // specialization for that template, the explicit instantiation has no
- // effect.
- break;
-
- case TSK_ExplicitInstantiationDefinition:
- // FIXME: Check that we aren't trying to perform an explicit instantiation
- // declaration now.
- // Fall through
-
- case TSK_ImplicitInstantiation:
- case TSK_ExplicitInstantiationDeclaration:
- // Instantiate the function, if this is an explicit instantiation
- // definition.
- if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization,
- false);
-
- Specialization->setTemplateSpecializationKind(TSK);
- break;
+ if (PrevDecl) {
+ bool SuppressNew = false;
+ if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
+ PrevDecl,
+ PrevDecl->getTemplateSpecializationKind(),
+ PrevDecl->getPointOfInstantiation(),
+ SuppressNew))
+ return true;
+
+ // FIXME: We may still want to build some representation of this
+ // explicit specialization.
+ if (SuppressNew)
+ return DeclPtrTy();
}
-
- // Check the scope of this explicit instantiation.
- FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
+ if (TSK == TSK_ExplicitInstantiationDefinition)
+ InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization,
+ false, /*DefinitionRequired=*/true);
+
+ Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+
// C++0x [temp.explicit]p2:
// If the explicit instantiation is for a member function, a member class
// or a static data member of a class template specialization, the name of
@@ -3895,6 +4094,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
+ FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl &&
D.getCXXScopeSpec().isSet() &&
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
@@ -4089,12 +4289,27 @@ namespace {
/// \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 a QualifiedNameType (when possible).
- QualType TransformTypenameType(const TypenameType *T);
+ QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
+ QualType TransformTypenameType(TypenameType *T);
};
}
QualType
-CurrentInstantiationRebuilder::TransformTypenameType(const TypenameType *T) {
+CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
+ TypenameTypeLoc TL) {
+ QualType Result = TransformTypenameType(TL.getTypePtr());
+ if (Result.isNull())
+ return QualType();
+
+ TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+QualType
+CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) {
+
NestedNameSpecifier *NNS
= TransformNestedNameSpecifier(T->getQualifier(),
/*FIXME:*/SourceRange(getBaseLocation()));
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index b981389..2a44f83 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -221,7 +221,7 @@ DeduceTemplateArguments(ASTContext &Context,
QualType Arg,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
- assert(Arg->isCanonical() && "Argument type must be canonical");
+ assert(Arg.isCanonical() && "Argument type must be canonical");
// Check whether the template argument is a dependent template-id.
// FIXME: This is untested code; it can be tested when we implement
@@ -313,7 +313,7 @@ DeduceTemplateArguments(ASTContext &Context,
/// that corresponds to T. Otherwise, returns T.
static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,
Qualifiers &Quals) {
- assert(T->isCanonical() && "Only operates on canonical types");
+ assert(T.isCanonical() && "Only operates on canonical types");
if (!isa<ArrayType>(T)) {
Quals = T.getQualifiers();
return T.getUnqualifiedType();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 24b8370..53d1580 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -400,6 +400,10 @@ namespace {
/// instantiating it.
Decl *TransformDefinition(Decl *D);
+ /// \bried Transform the first qualifier within a scope by instantiating the
+ /// declaration.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
+
/// \brief Rebuild the exception declaration and register the declaration
/// as an instantiated local.
VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T,
@@ -416,7 +420,8 @@ namespace {
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
- QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
+ QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL);
};
}
@@ -457,6 +462,31 @@ Decl *TemplateInstantiator::TransformDefinition(Decl *D) {
return Inst;
}
+NamedDecl *
+TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
+ SourceLocation Loc) {
+ // If the first part of the nested-name-specifier was a template type
+ // parameter, instantiate that type parameter down to a tag type.
+ if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
+ const TemplateTypeParmType *TTP
+ = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
+ if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType();
+ if (T.isNull())
+ return cast_or_null<NamedDecl>(TransformDecl(D));
+
+ if (const TagType *Tag = T->getAs<TagType>())
+ return Tag->getDecl();
+
+ // The resulting type is not a tag; complain.
+ getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
+ return 0;
+ }
+ }
+
+ return cast_or_null<NamedDecl>(TransformDecl(D));
+}
+
VarDecl *
TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
QualType T,
@@ -596,8 +626,9 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
}
QualType
-TemplateInstantiator::TransformTemplateTypeParmType(
- const TemplateTypeParmType *T) {
+TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL) {
+ TemplateTypeParmType *T = TL.getTypePtr();
if (T->getDepth() < TemplateArgs.getNumLevels()) {
// Replace the template type parameter with its corresponding
// template argument.
@@ -606,25 +637,42 @@ TemplateInstantiator::TransformTemplateTypeParmType(
// because we are performing instantiation from explicitly-specified
// template arguments in a function template class, but there were some
// arguments left unspecified.
- if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
- return QualType(T, 0);
+ if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
+ TemplateTypeParmTypeLoc NewTL
+ = TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
+ NewTL.setNameLoc(TL.getNameLoc());
+ return TL.getType();
+ }
assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()
== TemplateArgument::Type &&
"Template argument kind mismatch");
- return TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
+ QualType Replacement
+ = TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
+
+ // TODO: only do this uniquing once, at the start of instantiation.
+ QualType Result
+ = getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
+ SubstTemplateTypeParmTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
}
// The template type parameter comes from an inner template (e.g.,
// the template parameter list of a member template inside the
// template we are instantiating). Create a new template type
// parameter with the template "level" reduced by one.
- return getSema().Context.getTemplateTypeParmType(
- T->getDepth() - TemplateArgs.getNumLevels(),
- T->getIndex(),
- T->isParameterPack(),
- T->getName());
+ QualType Result
+ = getSema().Context.getTemplateTypeParmType(T->getDepth()
+ - TemplateArgs.getNumLevels(),
+ T->getIndex(),
+ T->isParameterPack(),
+ T->getName());
+ TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
}
/// \brief Perform substitution on the type T with a given set of template
@@ -654,6 +702,22 @@ TemplateInstantiator::TransformTemplateTypeParmType(
///
/// \returns If the instantiation succeeds, the instantiated
/// type. Otherwise, produces diagnostics and returns a NULL type.
+DeclaratorInfo *Sema::SubstType(DeclaratorInfo *T,
+ const MultiLevelTemplateArgumentList &Args,
+ SourceLocation Loc,
+ DeclarationName Entity) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
+ if (!T->getType()->isDependentType())
+ return T;
+
+ TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
+ return Instantiator.TransformType(T);
+}
+
+/// Deprecated form of the above.
QualType Sema::SubstType(QualType T,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity) {
@@ -769,6 +833,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
}
Pattern = PatternDef;
+ // \brief Record the point of instantiation.
+ if (MemberSpecializationInfo *MSInfo
+ = Instantiation->getMemberSpecializationInfo()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst)
return true;
@@ -1007,7 +1078,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
TSK_ExplicitSpecialization)
continue;
- Function->setTemplateSpecializationKind(TSK);
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
if (!Function->getBody() && TSK == TSK_ExplicitInstantiationDefinition)
@@ -1018,7 +1089,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
continue;
- Var->setTemplateSpecializationKind(TSK);
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 060cc55..be4adbc 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -123,16 +123,17 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// Do substitution on the type of the declaration
- QualType T = SemaRef.SubstType(D->getType(), TemplateArgs,
- D->getTypeSpecStartLoc(),
- D->getDeclName());
- if (T.isNull())
+ DeclaratorInfo *DI = SemaRef.SubstType(D->getDeclaratorInfo(),
+ TemplateArgs,
+ D->getTypeSpecStartLoc(),
+ D->getDeclName());
+ if (!DI)
return 0;
// Build the instantiated declaration
VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
D->getLocation(), D->getIdentifier(),
- T, D->getDeclaratorInfo(),
+ DI->getType(), DI,
D->getStorageClass());
Var->setThreadSpecified(D->isThreadSpecified());
Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
@@ -203,11 +204,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
bool Invalid = false;
- QualType T = D->getType();
- if (T->isDependentType()) {
- T = SemaRef.SubstType(T, TemplateArgs,
- D->getLocation(), D->getDeclName());
- if (!T.isNull() && T->isFunctionType()) {
+ DeclaratorInfo *DI = D->getDeclaratorInfo();
+ if (DI->getType()->isDependentType()) {
+ DI = SemaRef.SubstType(DI, TemplateArgs,
+ D->getLocation(), D->getDeclName());
+ if (!DI) {
+ DI = D->getDeclaratorInfo();
+ Invalid = true;
+ } else if (DI->getType()->isFunctionType()) {
// C++ [temp.arg.type]p3:
// If a declaration acquires a function type through a type
// dependent on a template-parameter and this causes a
@@ -215,8 +219,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
// function declarator to have function type, the program is
// ill-formed.
SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
- << T;
- T = QualType();
+ << DI->getType();
Invalid = true;
}
}
@@ -237,8 +240,8 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
BitWidth = InstantiatedBitWidth.takeAs<Expr>();
}
- FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), T,
- D->getDeclaratorInfo(),
+ FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(),
+ DI->getType(), DI,
cast<RecordDecl>(Owner),
D->getLocation(),
D->isMutable(),
@@ -1044,9 +1047,14 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
///
/// \param Recursive if true, recursively instantiates any functions that
/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where the body of the function is required. Complain if
+/// there is no such body.
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
- bool Recursive) {
+ bool Recursive,
+ bool DefinitionRequired) {
if (Function->isInvalidDecl())
return;
@@ -1075,8 +1083,24 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl)
Pattern = PatternDecl->getBody(PatternDecl);
- if (!Pattern)
+ if (!Pattern) {
+ if (DefinitionRequired) {
+ if (Function->getPrimaryTemplate())
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_func_template)
+ << Function->getPrimaryTemplate();
+ else
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << 1 << Function->getDeclName() << Function->getDeclContext();
+
+ if (PatternDecl)
+ Diag(PatternDecl->getLocation(),
+ diag::note_explicit_instantiation_here);
+ }
+
return;
+ }
// C++0x [temp.explicit]p9:
// Except for inline functions, other explicit instantiation declarations
@@ -1161,10 +1185,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
///
/// \param Recursive if true, recursively instantiates any functions that
/// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where an out-of-line definition of the member variable
+/// is required. Complain if there is no such definition.
void Sema::InstantiateStaticDataMemberDefinition(
SourceLocation PointOfInstantiation,
VarDecl *Var,
- bool Recursive) {
+ bool Recursive,
+ bool DefinitionRequired) {
if (Var->isInvalidDecl())
return;
@@ -1187,6 +1216,13 @@ void Sema::InstantiateStaticDataMemberDefinition(
// so we won't perform any instantiation. Rather, we rely on the user to
// instantiate this definition (or provide a specialization for it) in
// another translation unit.
+ if (DefinitionRequired) {
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << 2 << Var->getDeclName() << Var->getDeclContext();
+ Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+ }
+
return;
}
@@ -1225,7 +1261,10 @@ void Sema::InstantiateStaticDataMemberDefinition(
if (Var) {
Var->setPreviousDeclaration(OldVar);
- Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind());
+ MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
+ Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation());
DeclGroupRef DG(Var);
Consumer.HandleTopLevelDecl(DG);
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9603ca8..49f7119 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
@@ -51,16 +52,14 @@ QualType Sema::adjustParameterType(QualType T) {
/// object.
/// \param DS the declaration specifiers
/// \param DeclLoc The location of the declarator identifier or invalid if none.
-/// \param SourceTy QualType representing the type as written in source form.
/// \returns The type described by the declaration specifiers. This function
/// never returns null.
QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
SourceLocation DeclLoc,
- bool &isInvalid, QualType &SourceTy) {
+ bool &isInvalid) {
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
QualType Result;
- SourceTy = Result;
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_void:
@@ -105,9 +104,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
case DeclSpec::TST_unspecified:
// "<proto1,proto2>" is an objc qualified ID with a missing id.
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
- SourceTy = Context.getObjCProtocolListType(QualType(),
- (ObjCProtocolDecl**)PQ,
- DS.getNumProtocolQualifiers());
Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,
(ObjCProtocolDecl**)PQ,
DS.getNumProtocolQualifiers());
@@ -225,9 +221,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
Result = GetTypeFromParser(DS.getTypeRep());
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
- SourceTy = Context.getObjCProtocolListType(Result,
- (ObjCProtocolDecl**)PQ,
- DS.getNumProtocolQualifiers());
if (const ObjCInterfaceType *
Interface = Result->getAs<ObjCInterfaceType>()) {
// It would be nice if protocol qualifiers were only stored with the
@@ -384,8 +377,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
Result = Context.getQualifiedType(Result, Quals);
}
- if (SourceTy.isNull())
- SourceTy = Result;
return Result;
}
@@ -449,36 +440,32 @@ 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 LValueRef, unsigned CVR,
- SourceLocation Loc, DeclarationName Entity) {
+QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
+ unsigned CVR, SourceLocation Loc,
+ DeclarationName Entity) {
Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
- if (LValueRef) {
- if (const RValueReferenceType *R = T->getAs<RValueReferenceType>()) {
- // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
- // reference to a type T, and attempt to create the type "lvalue
- // reference to cv TD" creates the type "lvalue reference to T".
- // We use the qualifiers (restrict or none) of the original reference,
- // not the new ones. This is consistent with GCC.
- QualType LVRT = Context.getLValueReferenceType(R->getPointeeType());
- return Context.getQualifiedType(LVRT, T.getQualifiers());
- }
- }
- if (T->isReferenceType()) {
- // C++ [dcl.ref]p4: There shall be no references to references.
- //
- // According to C++ DR 106, references to references are only
- // diagnosed when they are written directly (e.g., "int & &"),
- // but not when they happen via a typedef:
- //
- // typedef int& intref;
- // typedef intref& intref2;
- //
- // Parser::ParseDeclaratorInternal diagnoses the case where
- // references are written directly; here, we handle the
- // collapsing of references-to-references as described in C++
- // DR 106 and amended by C++ DR 540.
- return T;
- }
+
+ bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
+
+ // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a
+ // reference to a type T, and attempt to create the type "lvalue
+ // reference to cv TD" creates the type "lvalue reference to T".
+ // We use the qualifiers (restrict or none) of the original reference,
+ // not the new ones. This is consistent with GCC.
+
+ // C++ [dcl.ref]p4: There shall be no references to references.
+ //
+ // According to C++ DR 106, references to references are only
+ // diagnosed when they are written directly (e.g., "int & &"),
+ // but not when they happen via a typedef:
+ //
+ // typedef int& intref;
+ // typedef intref& intref2;
+ //
+ // Parser::ParseDeclaratorInternal diagnoses the case where
+ // references are written directly; here, we handle the
+ // collapsing of references-to-references as described in C++
+ // DR 106 and amended by C++ DR 540.
// C++ [dcl.ref]p1:
// A declarator that specifies the type "reference to cv void"
@@ -510,7 +497,8 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,
// Handle restrict on references.
if (LValueRef)
- return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals);
+ return Context.getQualifiedType(
+ Context.getLValueReferenceType(T, SpelledAsLValue), Quals);
return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);
}
@@ -610,8 +598,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
<< ArraySize->getSourceRange();
}
}
- T = Context.getConstantArrayWithExprType(T, ConstVal, ArraySize,
- ASM, Quals, Brackets);
+ T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOptions().C99) {
@@ -717,7 +704,7 @@ QualType Sema::BuildFunctionType(QualType T,
Invalid = true;
}
- ParamTypes[Idx] = adjustFunctionParamType(ParamType);
+ ParamTypes[Idx] = ParamType;
}
if (Invalid)
@@ -856,9 +843,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// Determine the type of the declarator. Not all forms of declarator
// have a type.
QualType T;
- // The QualType referring to the type as written in source code. We can't use
- // T because it can change due to semantic analysis.
- QualType SourceTy;
switch (D.getKind()) {
case Declarator::DK_Abstract:
@@ -872,7 +856,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
T = Context.DependentTy;
} else {
bool isInvalid = false;
- T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid, SourceTy);
+ T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);
if (isInvalid)
D.setInvalidType(true);
else if (OwnedDecl && DS.isTypeSpecOwned())
@@ -891,9 +875,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
- if (SourceTy.isNull())
- SourceTy = T;
-
if (T == Context.UndeducedAutoTy) {
int Error = -1;
@@ -942,8 +923,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.getIdentifier())
Name = D.getIdentifier();
- bool ShouldBuildInfo = DInfo != 0;
-
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -952,17 +931,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
switch (DeclType.Kind) {
default: assert(0 && "Unknown decltype!");
case DeclaratorChunk::BlockPointer:
- if (ShouldBuildInfo) {
- if (SourceTy->isFunctionType())
- SourceTy
- = Context.getQualifiedType(Context.getBlockPointerType(SourceTy),
- Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals));
- else
- // If not function type Context::getBlockPointerType asserts,
- // so just give up.
- ShouldBuildInfo = false;
- }
-
// If blocks are disabled, emit an error.
if (!LangOpts.Blocks)
Diag(DeclType.Loc, diag::err_blocks_disable);
@@ -971,10 +939,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
Name);
break;
case DeclaratorChunk::Pointer:
- //FIXME: Use ObjCObjectPointer for info when appropriate.
- if (ShouldBuildInfo)
- SourceTy = Context.getQualifiedType(Context.getPointerType(SourceTy),
- Qualifiers::fromCVRMask(DeclType.Ptr.TypeQuals));
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -995,14 +959,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
Qualifiers Quals;
if (DeclType.Ref.HasRestrict) Quals.addRestrict();
- if (ShouldBuildInfo) {
- if (DeclType.Ref.LValueRef)
- SourceTy = Context.getLValueReferenceType(SourceTy);
- else
- SourceTy = Context.getRValueReferenceType(SourceTy);
- SourceTy = Context.getQualifiedType(SourceTy, Quals);
- }
-
// Verify that we're not building a reference to pointer to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -1015,11 +971,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
case DeclaratorChunk::Array: {
- if (ShouldBuildInfo)
- // We just need to get an array type, the exact type doesn't matter.
- SourceTy = Context.getIncompleteArrayType(SourceTy, ArrayType::Normal,
- DeclType.Arr.TypeQuals);
-
// Verify that we're not building an array of pointers to function with
// exception specification.
if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
@@ -1051,24 +1002,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
case DeclaratorChunk::Function: {
- if (ShouldBuildInfo) {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- llvm::SmallVector<QualType, 16> ArgTys;
-
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
- if (Param) {
- QualType ArgTy = adjustFunctionParamType(Param->getType());
-
- ArgTys.push_back(ArgTy);
- }
- }
- SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(),
- ArgTys.size(),
- FTI.isVariadic,
- FTI.TypeQuals);
- }
-
// If the function declarator has a prototype (i.e. it is not () and
// does not have a K&R-style identifier list), then the arguments are part
// of the type, otherwise the argument list is ().
@@ -1137,6 +1070,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
} 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 {
// Otherwise, we have a function with an argument list that is
// potentially variadic.
@@ -1185,7 +1119,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
}
- ArgTys.push_back(adjustFunctionParamType(ArgTy));
+ ArgTys.push_back(ArgTy);
}
llvm::SmallVector<QualType, 4> Exceptions;
@@ -1234,13 +1168,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.setInvalidType(true);
}
- if (ShouldBuildInfo) {
- QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy;
- SourceTy = Context.getQualifiedType(
- Context.getMemberPointerType(SourceTy, cls.getTypePtr()),
- Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals));
- }
-
if (!ClsType.isNull())
T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
DeclType.Loc, D.getIdentifier());
@@ -1293,106 +1220,162 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (const AttributeList *Attrs = D.getAttributes())
ProcessTypeAttributeList(T, Attrs);
- if (ShouldBuildInfo)
- *DInfo = GetDeclaratorInfoForDeclarator(D, SourceTy, Skip);
+ if (DInfo) {
+ if (D.isInvalidType())
+ *DInfo = 0;
+ else
+ *DInfo = GetDeclaratorInfoForDeclarator(D, T, Skip);
+ }
return T;
}
-static void FillTypeSpecLoc(TypeLoc TSL, const DeclSpec &DS) {
- if (TSL.isNull()) return;
+namespace {
+ class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
+ const DeclSpec &DS;
- if (TypedefLoc *TL = dyn_cast<TypedefLoc>(&TSL)) {
- TL->setNameLoc(DS.getTypeSpecTypeLoc());
+ public:
+ TypeSpecLocFiller(const DeclSpec &DS) : DS(DS) {}
- } else if (ObjCInterfaceLoc *TL = dyn_cast<ObjCInterfaceLoc>(&TSL)) {
- TL->setNameLoc(DS.getTypeSpecTypeLoc());
+ void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ Visit(TL.getUnqualifiedLoc());
+ }
+ void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+ }
+ void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ TL.setNameLoc(DS.getTypeSpecTypeLoc());
+
+ if (DS.getProtocolQualifiers()) {
+ assert(TL.getNumProtocols() > 0);
+ assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+ TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+ TL.setRAngleLoc(DS.getSourceRange().getEnd());
+ for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
+ TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
+ } else {
+ assert(TL.getNumProtocols() == 0);
+ TL.setLAngleLoc(SourceLocation());
+ TL.setRAngleLoc(SourceLocation());
+ }
+ }
+ void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
- } else if (ObjCProtocolListLoc *PLL = dyn_cast<ObjCProtocolListLoc>(&TSL)) {
- assert(PLL->getNumProtocols() == DS.getNumProtocolQualifiers());
- PLL->setLAngleLoc(DS.getProtocolLAngleLoc());
- PLL->setRAngleLoc(DS.getSourceRange().getEnd());
- for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i)
- PLL->setProtocolLoc(i, DS.getProtocolLocs()[i]);
- FillTypeSpecLoc(PLL->getBaseTypeLoc(), DS);
+ TL.setStarLoc(SourceLocation());
- } else {
- //FIXME: Other typespecs.
- DefaultTypeSpecLoc &DTL = cast<DefaultTypeSpecLoc>(TSL);
- DTL.setStartLoc(DS.getSourceRange().getBegin());
- }
-}
+ if (DS.getProtocolQualifiers()) {
+ assert(TL.getNumProtocols() > 0);
+ assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
+ TL.setHasProtocolsAsWritten(true);
+ TL.setLAngleLoc(DS.getProtocolLAngleLoc());
+ TL.setRAngleLoc(DS.getSourceRange().getEnd());
+ for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
+ TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
-/// \brief Create and instantiate a DeclaratorInfo with type source information.
-///
-/// \param T QualType referring to the type as written in source code.
-DeclaratorInfo *
-Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) {
- DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T);
- TypeLoc CurrTL = DInfo->getTypeLoc();
+ } else {
+ assert(TL.getNumProtocols() == 0);
+ TL.setHasProtocolsAsWritten(false);
+ TL.setLAngleLoc(SourceLocation());
+ TL.setRAngleLoc(SourceLocation());
+ }
- for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
- assert(!CurrTL.isNull());
-
- // Don't bother recording source locations for qualifiers.
- CurrTL = CurrTL.getUnqualifiedLoc();
+ // This might not have been written with an inner type.
+ if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
+ TL.setHasBaseTypeAsWritten(false);
+ TL.getBaseTypeLoc().initialize(SourceLocation());
+ } else {
+ TL.setHasBaseTypeAsWritten(true);
+ Visit(TL.getBaseTypeLoc());
+ }
+ }
+ void VisitTypeLoc(TypeLoc TL) {
+ // FIXME: add other typespec types and change this to an assert.
+ TL.initialize(DS.getTypeSpecTypeLoc());
+ }
+ };
- DeclaratorChunk &DeclType = D.getTypeObject(i);
- switch (DeclType.Kind) {
- default: assert(0 && "Unknown decltype!");
- case DeclaratorChunk::BlockPointer: {
- BlockPointerLoc &BPL = cast<BlockPointerLoc>(CurrTL);
- BPL.setCaretLoc(DeclType.Loc);
- break;
+ class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
+ const DeclaratorChunk &Chunk;
+
+ public:
+ DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {}
+
+ void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ llvm::llvm_unreachable("qualified type locs not expected here!");
}
- case DeclaratorChunk::Pointer: {
- //FIXME: ObjCObject pointers.
- PointerLoc &PL = cast<PointerLoc>(CurrTL);
- PL.setStarLoc(DeclType.Loc);
- break;
+
+ void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
+ TL.setCaretLoc(Chunk.Loc);
}
- case DeclaratorChunk::Reference: {
- ReferenceLoc &RL = cast<ReferenceLoc>(CurrTL);
- RL.setAmpLoc(DeclType.Loc);
- break;
+ void VisitPointerTypeLoc(PointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Pointer);
+ TL.setStarLoc(Chunk.Loc);
}
- case DeclaratorChunk::Array: {
- DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
- ArrayLoc &AL = cast<ArrayLoc>(CurrTL);
- AL.setLBracketLoc(DeclType.Loc);
- AL.setRBracketLoc(DeclType.EndLoc);
- AL.setSizeExpr(static_cast<Expr*>(ATI.NumElts));
- //FIXME: Star location for [*].
- break;
+ void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Pointer);
+ TL.setStarLoc(Chunk.Loc);
+ TL.setHasBaseTypeAsWritten(true);
+ TL.setHasProtocolsAsWritten(false);
+ TL.setLAngleLoc(SourceLocation());
+ TL.setRAngleLoc(SourceLocation());
}
- case DeclaratorChunk::Function: {
- const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- FunctionLoc &FL = cast<FunctionLoc>(CurrTL);
- FL.setLParenLoc(DeclType.Loc);
- FL.setRParenLoc(DeclType.EndLoc);
- for (unsigned i = 0, e = FTI.NumArgs, tpi = 0; i != e; ++i) {
+ void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+ TL.setStarLoc(Chunk.Loc);
+ // FIXME: nested name specifier
+ }
+ void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Reference);
+ // 'Amp' is misleading: this might have been originally
+ /// spelled with AmpAmp.
+ TL.setAmpLoc(Chunk.Loc);
+ }
+ void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Reference);
+ assert(!Chunk.Ref.LValueRef);
+ TL.setAmpAmpLoc(Chunk.Loc);
+ }
+ void VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Array);
+ TL.setLBracketLoc(Chunk.Loc);
+ TL.setRBracketLoc(Chunk.EndLoc);
+ TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
+ }
+ void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ assert(Chunk.Kind == DeclaratorChunk::Function);
+ TL.setLParenLoc(Chunk.Loc);
+ TL.setRParenLoc(Chunk.EndLoc);
+
+ const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
+ for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
- if (Param) {
- assert(tpi < FL.getNumArgs());
- FL.setArg(tpi++, Param);
- }
+ TL.setArg(tpi++, Param);
}
- break;
- //FIXME: Exception specs.
- }
- case DeclaratorChunk::MemberPointer: {
- MemberPointerLoc &MPL = cast<MemberPointerLoc>(CurrTL);
- MPL.setStarLoc(DeclType.Loc);
- //FIXME: Class location.
- break;
+ // FIXME: exception specs
}
+ void VisitTypeLoc(TypeLoc TL) {
+ llvm::llvm_unreachable("unsupported TypeLoc kind in declarator!");
}
+ };
+}
+
+/// \brief Create and instantiate a DeclaratorInfo with type source information.
+///
+/// \param T QualType referring to the type as written in source code.
+DeclaratorInfo *
+Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) {
+ DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T);
+ UnqualTypeLoc CurrTL = DInfo->getTypeLoc().getUnqualifiedLoc();
- CurrTL = CurrTL.getNextTypeLoc();
+ for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL);
+ CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
- FillTypeSpecLoc(CurrTL, D.getDeclSpec());
+ TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
return DInfo;
}
@@ -1655,6 +1638,8 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
PartialDiagnostic> Note) {
unsigned diag = PD.getDiagID();
+ // FIXME: Add this assertion to make sure we always get instantiation points.
+ // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
// checking for dependent types and type-dependent expressions.
//
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index ec5c667..7e0972f 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1,4 +1,4 @@
-//===------- TreeTransform.h - Semantic Tree Transformation ---------------===/
+//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===/
//
// The LLVM Compiler Infrastructure
//
@@ -22,9 +22,11 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
+#include "clang/AST/TypeLocBuilder.h"
#include "clang/Parse/Ownership.h"
#include "clang/Parse/Designator.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
namespace clang {
@@ -170,25 +172,30 @@ public:
/// \brief Transforms the given type into another type.
///
- /// By default, this routine transforms a type by delegating to the
- /// appropriate TransformXXXType to build a new type, then applying
- /// the qualifiers on \p T to the resulting type with AddTypeQualifiers.
- /// Subclasses may override this function (to take over all type
- /// transformations), some set of the TransformXXXType functions, or
- /// the AddTypeQualifiers function to alter the transformation.
+ /// By default, this routine transforms a type by creating a
+ /// DeclaratorInfo for it and delegating to the appropriate
+ /// function. This is expensive, but we don't mind, because
+ /// this method is deprecated anyway; all users should be
+ /// switched to storing DeclaratorInfos.
///
/// \returns the transformed type.
QualType TransformType(QualType T);
- /// \brief Transform the given type by adding the given set of qualifiers
- /// and returning the result.
+ /// \brief Transforms the given type-with-location into a new
+ /// type-with-location.
+ ///
+ /// By default, this routine transforms a type by delegating to the
+ /// appropriate TransformXXXType to build a new type. Subclasses
+ /// may override this function (to take over all type
+ /// transformations) or some set of the TransformXXXType functions
+ /// to alter the transformation.
+ DeclaratorInfo *TransformType(DeclaratorInfo *DI);
+
+ /// \brief Transform the given type-with-location into a new
+ /// type, collecting location information in the given builder
+ /// as necessary.
///
- /// FIXME: By default, this routine adds type qualifiers only to types that
- /// can have qualifiers, and silently suppresses those qualifiers that are
- /// not permitted (e.g., qualifiers on reference or function types). This
- /// is the right thing for template instantiation, but probably not for
- /// other clients.
- QualType AddTypeQualifiers(QualType T, Qualifiers Qs);
+ QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
/// \brief Transform the given statement.
///
@@ -236,6 +243,19 @@ public:
/// Subclasses may override this function to provide alternate behavior.
Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); }
+ /// \brief Transform the given declaration, which was the first part of a
+ /// nested-name-specifier in a member access expression.
+ ///
+ /// This specific declaration transformation only applies to the first
+ /// identifier in a nested-name-specifier of a member access expression, e.g.,
+ /// the \c T in \c x->T::member
+ ///
+ /// By default, invokes TransformDecl() to transform the declaration.
+ /// Subclasses may override this function to provide alternate behavior.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) {
+ return cast_or_null<NamedDecl>(getDerived().TransformDecl(D));
+ }
+
/// \brief Transform the given nested-name-specifier.
///
/// By default, transforms all of the types and declarations within the
@@ -253,7 +273,8 @@ public:
/// Identifiers and selectors are returned unmodified. Sublcasses may
/// override this function to provide alternate behavior.
DeclarationName TransformDeclarationName(DeclarationName Name,
- SourceLocation Loc);
+ SourceLocation Loc,
+ QualType ObjectType = QualType());
/// \brief Transform the given template name.
///
@@ -271,11 +292,15 @@ public:
/// override this function to provide alternate behavior.
TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT) \
- QualType Transform##CLASS##Type(const CLASS##Type *T);
-#include "clang/AST/TypeNodes.def"
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+#include "clang/AST/TypeLocNodes.def"
+ QualType
+ TransformTemplateSpecializationType(const TemplateSpecializationType *T,
+ QualType ObjectType);
+
OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
#define STMT(Node, Parent) \
@@ -316,6 +341,9 @@ public:
/// type. Subclasses may override this routine to provide different behavior.
QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType);
+ /// \brief Build a new Objective C object pointer type.
+ QualType RebuildObjCObjectPointerType(QualType PointeeType);
+
/// \brief Build a new array type given the element type, size
/// modifier, size of the array (if known), size expression, and index type
/// qualifiers.
@@ -340,29 +368,6 @@ public:
const llvm::APInt &Size,
unsigned IndexTypeQuals);
- /// \brief Build a new constant array type given the element type, size
- /// modifier, (known) size of the array, size expression, and index type
- /// qualifiers.
- ///
- /// By default, performs semantic analysis when building the array type.
- /// Subclasses may override this routine to provide different behavior.
- QualType RebuildConstantArrayWithExprType(QualType ElementType,
- ArrayType::ArraySizeModifier SizeMod,
- const llvm::APInt &Size,
- Expr *SizeExpr,
- unsigned IndexTypeQuals,
- SourceRange BracketsRange);
-
- /// \brief Build a new constant array type given the element type, size
- /// modifier, (known) size of the array, and index type qualifiers.
- ///
- /// By default, performs semantic analysis when building the array type.
- /// Subclasses may override this routine to provide different behavior.
- QualType RebuildConstantArrayWithoutExprType(QualType ElementType,
- ArrayType::ArraySizeModifier SizeMod,
- const llvm::APInt &Size,
- unsigned IndexTypeQuals);
-
/// \brief Build a new incomplete array type given the element type, size
/// modifier, and index type qualifiers.
///
@@ -427,6 +432,9 @@ public:
unsigned NumParamTypes,
bool Variadic, unsigned Quals);
+ /// \brief Build a new unprototyped function type.
+ QualType RebuildFunctionNoProtoType(QualType ResultType);
+
/// \brief Build a new typedef type.
QualType RebuildTypedefType(TypedefDecl *Typedef) {
return SemaRef.Context.getTypeDeclType(Typedef);
@@ -1429,13 +1437,16 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildTemplateIdExpr(TemplateName Template,
+ OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ TemplateName Template,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation RAngleLoc) {
- return getSema().BuildTemplateIdExpr(Template, TemplateLoc,
+ return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange,
+ Template, TemplateLoc,
LAngleLoc,
TemplateArgs, NumTemplateArgs,
RAngleLoc);
@@ -1757,7 +1768,8 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
template<typename Derived>
DeclarationName
TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc,
+ QualType ObjectType) {
if (!Name)
return Name;
@@ -1774,7 +1786,14 @@ TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
TemporaryBase Rebase(*this, Loc, Name);
- QualType T = getDerived().TransformType(Name.getCXXNameType());
+ QualType T;
+ if (!ObjectType.isNull() &&
+ isa<TemplateSpecializationType>(Name.getCXXNameType())) {
+ TemplateSpecializationType *SpecType
+ = cast<TemplateSpecializationType>(Name.getCXXNameType());
+ T = TransformTemplateSpecializationType(SpecType, ObjectType);
+ } else
+ T = getDerived().TransformType(Name.getCXXNameType());
if (T.isNull())
return DeclarationName();
@@ -1837,7 +1856,8 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
return TemplateName();
if (!getDerived().AlwaysRebuild() &&
- NNS == DTN->getQualifier())
+ NNS == DTN->getQualifier() &&
+ ObjectType.isNull())
return Name;
return getDerived().RebuildTemplateName(NNS, *DTN->getName(), ObjectType);
@@ -1935,268 +1955,369 @@ QualType TreeTransform<Derived>::TransformType(QualType T) {
if (getDerived().AlreadyTransformed(T))
return T;
- QualifierCollector Qs;
- const Type *Ty = Qs.strip(T);
+ // Temporary workaround. All of these transformations should
+ // eventually turn into transformations on TypeLocs.
+ DeclaratorInfo *DI = getSema().Context.CreateDeclaratorInfo(T);
+ DI->getTypeLoc().initialize(getDerived().getBaseLocation());
+
+ DeclaratorInfo *NewDI = getDerived().TransformType(DI);
- QualType Result;
- switch (Ty->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- Result = getDerived().Transform##CLASS##Type( \
- static_cast<const CLASS##Type*>(Ty)); \
- break;
-#include "clang/AST/TypeNodes.def"
- }
-
- if (Result.isNull() || T == Result)
- return Result;
+ if (!NewDI)
+ return QualType();
- return getDerived().AddTypeQualifiers(Result, Qs);
+ return NewDI->getType();
}
template<typename Derived>
-QualType
-TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) {
- if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType())
- return SemaRef.Context.getQualifiedType(T, Quals);
+DeclaratorInfo *TreeTransform<Derived>::TransformType(DeclaratorInfo *DI) {
+ if (getDerived().AlreadyTransformed(DI->getType()))
+ return DI;
- return T;
-}
+ TypeLocBuilder TLB;
-template<typename Derived>
-QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) {
- // Nothing to do
- return QualType(T, 0);
-}
+ TypeLoc TL = DI->getTypeLoc();
+ TLB.reserve(TL.getFullDataSize());
-template<typename Derived>
-QualType TreeTransform<Derived>::TransformFixedWidthIntType(
- const FixedWidthIntType *T) {
- // FIXME: Implement
- return QualType(T, 0);
-}
+ QualType Result = getDerived().TransformType(TLB, TL);
+ if (Result.isNull())
+ return 0;
-template<typename Derived>
-QualType TreeTransform<Derived>::TransformComplexType(const ComplexType *T) {
- // FIXME: Implement
- return QualType(T, 0);
+ return TLB.getDeclaratorInfo(SemaRef.Context, Result);
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformPointerType(const PointerType *T) {
- QualType PointeeType = getDerived().TransformType(T->getPointeeType());
- if (PointeeType.isNull())
- return QualType();
-
- if (!getDerived().AlwaysRebuild() &&
- PointeeType == T->getPointeeType())
- return QualType(T, 0);
+QualType
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+ switch (T.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: \
+ return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+#include "clang/AST/TypeLocNodes.def"
+ }
- return getDerived().RebuildPointerType(PointeeType);
+ llvm::llvm_unreachable("unhandled type loc!");
+ return QualType();
}
+/// FIXME: By default, this routine adds type qualifiers only to types
+/// that can have qualifiers, and silently suppresses those qualifiers
+/// that are not permitted (e.g., qualifiers on reference or function
+/// types). This is the right thing for template instantiation, but
+/// probably not for other clients.
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformBlockPointerType(const BlockPointerType *T) {
- QualType PointeeType = getDerived().TransformType(T->getPointeeType());
- if (PointeeType.isNull())
+TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
+ QualifiedTypeLoc T) {
+ Qualifiers Quals = T.getType().getQualifiers();
+
+ QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+ if (Result.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- PointeeType == T->getPointeeType())
- return QualType(T, 0);
+ // Silently suppress qualifiers if the result type can't be qualified.
+ // FIXME: this is the right thing for template instantiation, but
+ // probably not for other clients.
+ if (Result->isFunctionType() || Result->isReferenceType())
+ return Result;
- return getDerived().RebuildBlockPointerType(PointeeType);
+ Result = SemaRef.Context.getQualifiedType(Result, Quals);
+
+ TLB.push<QualifiedTypeLoc>(Result);
+
+ // No location information to preserve.
+
+ return Result;
+}
+
+template <class TyLoc> static inline
+QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
+ TyLoc NewT = TLB.push<TyLoc>(T.getType());
+ NewT.setNameLoc(T.getNameLoc());
+ return T.getType();
+}
+
+// Ugly metaprogramming macros because I couldn't be bothered to make
+// the equivalent template version work.
+#define TransformPointerLikeType(TypeClass) do { \
+ QualType PointeeType \
+ = getDerived().TransformType(TLB, TL.getPointeeLoc()); \
+ if (PointeeType.isNull()) \
+ return QualType(); \
+ \
+ QualType Result = TL.getType(); \
+ if (getDerived().AlwaysRebuild() || \
+ PointeeType != TL.getPointeeLoc().getType()) { \
+ Result = getDerived().Rebuild##TypeClass(PointeeType); \
+ if (Result.isNull()) \
+ return QualType(); \
+ } \
+ \
+ TypeClass##Loc NewT = TLB.push<TypeClass##Loc>(Result); \
+ NewT.setSigilLoc(TL.getSigilLoc()); \
+ \
+ return Result; \
+} while(0)
+
+// Reference collapsing forces us to transform reference types
+// differently from the other pointer-like types.
+#define TransformReferenceType(TypeClass) do { \
+ QualType PointeeType \
+ = getDerived().TransformType(TLB, TL.getPointeeLoc()); \
+ if (PointeeType.isNull()) \
+ return QualType(); \
+ \
+ QualType Result = TL.getType(); \
+ if (getDerived().AlwaysRebuild() || \
+ PointeeType != TL.getPointeeLoc().getType()) { \
+ Result = getDerived().Rebuild##TypeClass(PointeeType); \
+ if (Result.isNull()) \
+ return QualType(); \
+ } \
+ \
+ /* Workaround: rebuild doesn't always change the type */ \
+ /* FIXME: avoid losing this location information. */ \
+ if (Result == PointeeType) \
+ return Result; \
+ ReferenceTypeLoc NewTL; \
+ if (isa<LValueReferenceType>(Result)) \
+ NewTL = TLB.push<LValueReferenceTypeLoc>(Result); \
+ else \
+ NewTL = TLB.push<RValueReferenceTypeLoc>(Result); \
+ NewTL.setSigilLoc(TL.getSigilLoc()); \
+ return Result; \
+} while (0)
+
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
+ BuiltinTypeLoc T) {
+ return TransformTypeSpecType(TLB, T);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformLValueReferenceType(
- const LValueReferenceType *T) {
- QualType PointeeType = getDerived().TransformType(T->getPointeeType());
- if (PointeeType.isNull())
- return QualType();
+TreeTransform<Derived>::TransformFixedWidthIntType(TypeLocBuilder &TLB,
+ FixedWidthIntTypeLoc T) {
+ return TransformTypeSpecType(TLB, T);
+}
- if (!getDerived().AlwaysRebuild() &&
- PointeeType == T->getPointeeType())
- return QualType(T, 0);
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
+ ComplexTypeLoc T) {
+ // FIXME: recurse?
+ return TransformTypeSpecType(TLB, T);
+}
- return getDerived().RebuildLValueReferenceType(PointeeType);
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
+ PointerTypeLoc TL) {
+ TransformPointerLikeType(PointerType);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformRValueReferenceType(
- const RValueReferenceType *T) {
- QualType PointeeType = getDerived().TransformType(T->getPointeeType());
- if (PointeeType.isNull())
- return QualType();
-
- if (!getDerived().AlwaysRebuild() &&
- PointeeType == T->getPointeeType())
- return QualType(T, 0);
-
- return getDerived().RebuildRValueReferenceType(PointeeType);
+TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
+ BlockPointerTypeLoc TL) {
+ TransformPointerLikeType(BlockPointerType);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformMemberPointerType(const MemberPointerType *T) {
- QualType PointeeType = getDerived().TransformType(T->getPointeeType());
- if (PointeeType.isNull())
- return QualType();
-
- QualType ClassType = getDerived().TransformType(QualType(T->getClass(), 0));
- if (ClassType.isNull())
- return QualType();
-
- if (!getDerived().AlwaysRebuild() &&
- PointeeType == T->getPointeeType() &&
- ClassType == QualType(T->getClass(), 0))
- return QualType(T, 0);
-
- return getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
+ LValueReferenceTypeLoc TL) {
+ TransformReferenceType(LValueReferenceType);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) {
- QualType ElementType = getDerived().TransformType(T->getElementType());
- if (ElementType.isNull())
- return QualType();
-
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType())
- return QualType(T, 0);
-
- return getDerived().RebuildConstantArrayType(ElementType,
- T->getSizeModifier(),
- T->getSize(),
- T->getIndexTypeCVRQualifiers());
+TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
+ RValueReferenceTypeLoc TL) {
+ TransformReferenceType(RValueReferenceType);
}
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformConstantArrayWithExprType(
- const ConstantArrayWithExprType *T) {
- QualType ElementType = getDerived().TransformType(T->getElementType());
- if (ElementType.isNull())
- return QualType();
+TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
+ MemberPointerTypeLoc TL) {
+ MemberPointerType *T = TL.getTypePtr();
- // Array bounds are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
+ if (PointeeType.isNull())
+ return QualType();
- Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
- if (Size.isInvalid())
+ // TODO: preserve source information for this.
+ QualType ClassType
+ = getDerived().TransformType(QualType(T->getClass(), 0));
+ if (ClassType.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType() &&
- Size.get() == T->getSizeExpr())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != T->getPointeeType() ||
+ ClassType != QualType(T->getClass(), 0)) {
+ Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType);
+ if (Result.isNull())
+ return QualType();
+ }
- return getDerived().RebuildConstantArrayWithExprType(ElementType,
- T->getSizeModifier(),
- T->getSize(),
- Size.takeAs<Expr>(),
- T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
+ NewTL.setSigilLoc(TL.getSigilLoc());
+
+ return Result;
}
template<typename Derived>
QualType
-TreeTransform<Derived>::TransformConstantArrayWithoutExprType(
- const ConstantArrayWithoutExprType *T) {
- QualType ElementType = getDerived().TransformType(T->getElementType());
+TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
+ ConstantArrayTypeLoc TL) {
+ ConstantArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType())
- return QualType(T, 0);
-
- return getDerived().RebuildConstantArrayWithoutExprType(ElementType,
- T->getSizeModifier(),
- T->getSize(),
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildConstantArrayType(ElementType,
+ T->getSizeModifier(),
+ T->getSize(),
T->getIndexTypeCVRQualifiers());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+
+ Expr *Size = TL.getSizeExpr();
+ if (Size) {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
+ }
+ NewTL.setSizeExpr(Size);
+
+ return Result;
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformIncompleteArrayType(
- const IncompleteArrayType *T) {
- QualType ElementType = getDerived().TransformType(T->getElementType());
+ TypeLocBuilder &TLB,
+ IncompleteArrayTypeLoc TL) {
+ IncompleteArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildIncompleteArrayType(ElementType,
+ T->getSizeModifier(),
+ T->getIndexTypeCVRQualifiers());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+ NewTL.setSizeExpr(0);
- return getDerived().RebuildIncompleteArrayType(ElementType,
- T->getSizeModifier(),
- T->getIndexTypeCVRQualifiers());
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformVariableArrayType(
- const VariableArrayType *T) {
- QualType ElementType = getDerived().TransformType(T->getElementType());
+QualType
+TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
+ VariableArrayTypeLoc TL) {
+ VariableArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
// Array bounds are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
- Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
- if (Size.isInvalid())
+ Sema::OwningExprResult SizeResult
+ = getDerived().TransformExpr(T->getSizeExpr());
+ if (SizeResult.isInvalid())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType() &&
- Size.get() == T->getSizeExpr()) {
- Size.take();
- return QualType(T, 0);
+ Expr *Size = static_cast<Expr*>(SizeResult.get());
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType() ||
+ Size != T->getSizeExpr()) {
+ Result = getDerived().RebuildVariableArrayType(ElementType,
+ T->getSizeModifier(),
+ move(SizeResult),
+ T->getIndexTypeCVRQualifiers(),
+ T->getBracketsRange());
+ if (Result.isNull())
+ return QualType();
}
+ else SizeResult.take();
+
+ VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+ NewTL.setSizeExpr(Size);
- return getDerived().RebuildVariableArrayType(ElementType,
- T->getSizeModifier(),
- move(Size),
- T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
- const DependentSizedArrayType *T) {
- QualType ElementType = getDerived().TransformType(T->getElementType());
+QualType
+TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
+ DependentSizedArrayTypeLoc TL) {
+ DependentSizedArrayType *T = TL.getTypePtr();
+ QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
// Array bounds are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
- Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
- if (Size.isInvalid())
+ Sema::OwningExprResult SizeResult
+ = getDerived().TransformExpr(T->getSizeExpr());
+ if (SizeResult.isInvalid())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType() &&
- Size.get() == T->getSizeExpr()) {
- Size.take();
- return QualType(T, 0);
+ Expr *Size = static_cast<Expr*>(SizeResult.get());
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType() ||
+ Size != T->getSizeExpr()) {
+ Result = getDerived().RebuildDependentSizedArrayType(ElementType,
+ T->getSizeModifier(),
+ move(SizeResult),
+ T->getIndexTypeCVRQualifiers(),
+ T->getBracketsRange());
+ if (Result.isNull())
+ return QualType();
}
+ else SizeResult.take();
- return getDerived().RebuildDependentSizedArrayType(ElementType,
- T->getSizeModifier(),
- move(Size),
- T->getIndexTypeCVRQualifiers(),
- T->getBracketsRange());
+ // We might have any sort of array type now, but fortunately they
+ // all have the same location layout.
+ ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
+ NewTL.setLBracketLoc(TL.getLBracketLoc());
+ NewTL.setRBracketLoc(TL.getRBracketLoc());
+ NewTL.setSizeExpr(Size);
+
+ return Result;
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
- const DependentSizedExtVectorType *T) {
+ TypeLocBuilder &TLB,
+ DependentSizedExtVectorTypeLoc TL) {
+ DependentSizedExtVectorType *T = TL.getTypePtr();
+
+ // FIXME: ext vector locs should be nested
QualType ElementType = getDerived().TransformType(T->getElementType());
if (ElementType.isNull())
return QualType();
@@ -2208,98 +2329,201 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
if (Size.isInvalid())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType() &&
- Size.get() == T->getSizeExpr()) {
- Size.take();
- return QualType(T, 0);
- }
-
- return getDerived().RebuildDependentSizedExtVectorType(ElementType,
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ (ElementType != T->getElementType() && Size.get() != T->getSizeExpr())) {
+ Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
move(Size),
T->getAttributeLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+ else Size.take();
+
+ // Result might be dependent or not.
+ if (isa<DependentSizedExtVectorType>(Result)) {
+ DependentSizedExtVectorTypeLoc NewTL
+ = TLB.push<DependentSizedExtVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ } else {
+ ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ }
+
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformVectorType(const VectorType *T) {
+QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
+ VectorTypeLoc TL) {
+ VectorType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(T->getElementType());
if (ElementType.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildVectorType(ElementType, T->getNumElements());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildVectorType(ElementType, T->getNumElements());
+ return Result;
}
template<typename Derived>
-QualType
-TreeTransform<Derived>::TransformExtVectorType(const ExtVectorType *T) {
+QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
+ ExtVectorTypeLoc TL) {
+ VectorType *T = TL.getTypePtr();
QualType ElementType = getDerived().TransformType(T->getElementType());
if (ElementType.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- ElementType == T->getElementType())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ElementType != T->getElementType()) {
+ Result = getDerived().RebuildExtVectorType(ElementType,
+ T->getNumElements(),
+ /*FIXME*/ SourceLocation());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(),
- /*FIXME*/SourceLocation());
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformFunctionProtoType(
- const FunctionProtoType *T) {
- QualType ResultType = getDerived().TransformType(T->getResultType());
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL) {
+ FunctionProtoType *T = TL.getTypePtr();
+ QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
if (ResultType.isNull())
return QualType();
+ // Transform the parameters.
llvm::SmallVector<QualType, 4> ParamTypes;
- for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(),
- ParamEnd = T->arg_type_end();
- Param != ParamEnd; ++Param) {
- QualType P = getDerived().TransformType(*Param);
- if (P.isNull())
- return QualType();
+ llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+ ParmVarDecl *OldParm = TL.getArg(i);
+
+ QualType NewType;
+ ParmVarDecl *NewParm;
+
+ if (OldParm) {
+ DeclaratorInfo *OldDI = OldParm->getDeclaratorInfo();
+ assert(OldDI->getType() == T->getArgType(i));
+
+ DeclaratorInfo *NewDI = getDerived().TransformType(OldDI);
+ if (!NewDI)
+ return QualType();
+
+ if (NewDI == OldDI)
+ NewParm = OldParm;
+ else
+ NewParm = ParmVarDecl::Create(SemaRef.Context,
+ OldParm->getDeclContext(),
+ OldParm->getLocation(),
+ OldParm->getIdentifier(),
+ NewDI->getType(),
+ NewDI,
+ OldParm->getStorageClass(),
+ /* DefArg */ NULL);
+ NewType = NewParm->getType();
+
+ // Deal with the possibility that we don't have a parameter
+ // declaration for this parameter.
+ } else {
+ NewParm = 0;
+
+ QualType OldType = T->getArgType(i);
+ NewType = getDerived().TransformType(OldType);
+ if (NewType.isNull())
+ return QualType();
+ }
- ParamTypes.push_back(P);
+ ParamTypes.push_back(NewType);
+ ParamDecls.push_back(NewParm);
}
- if (!getDerived().AlwaysRebuild() &&
- ResultType == T->getResultType() &&
- std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin()))
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ResultType != T->getResultType() ||
+ !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) {
+ Result = getDerived().RebuildFunctionProtoType(ResultType,
+ ParamTypes.data(),
+ ParamTypes.size(),
+ T->isVariadic(),
+ T->getTypeQuals());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+ for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i)
+ NewTL.setArg(i, ParamDecls[i]);
- return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(),
- ParamTypes.size(), T->isVariadic(),
- T->getTypeQuals());
+ return Result;
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
- const FunctionNoProtoType *T) {
- // FIXME: Implement
- return QualType(T, 0);
+ TypeLocBuilder &TLB,
+ FunctionNoProtoTypeLoc TL) {
+ FunctionNoProtoType *T = TL.getTypePtr();
+ QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ ResultType != T->getResultType())
+ Result = getDerived().RebuildFunctionNoProtoType(ResultType);
+
+ FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result);
+ NewTL.setLParenLoc(TL.getLParenLoc());
+ NewTL.setRParenLoc(TL.getRParenLoc());
+
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) {
+QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
+ TypedefTypeLoc TL) {
+ TypedefType *T = TL.getTypePtr();
TypedefDecl *Typedef
= cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
if (!Typedef)
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- Typedef == T->getDecl())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Typedef != T->getDecl()) {
+ Result = getDerived().RebuildTypedefType(Typedef);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildTypedefType(Typedef);
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypeOfExprType(
- const TypeOfExprType *T) {
+QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
+ TypeOfExprTypeLoc TL) {
+ TypeOfExprType *T = TL.getTypePtr();
+
// typeof expressions are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
@@ -2307,30 +2531,50 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(
if (E.isInvalid())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- E.get() == T->getUnderlyingExpr()) {
- E.take();
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ E.get() != T->getUnderlyingExpr()) {
+ Result = getDerived().RebuildTypeOfExprType(move(E));
+ if (Result.isNull())
+ return QualType();
}
+ else E.take();
- return getDerived().RebuildTypeOfExprType(move(E));
+ TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) {
+QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
+ TypeOfTypeLoc TL) {
+ TypeOfType *T = TL.getTypePtr();
+
+ // FIXME: should be an inner type, or at least have a DeclaratorInfo.
QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
if (Underlying.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- Underlying == T->getUnderlyingType())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Underlying != T->getUnderlyingType()) {
+ Result = getDerived().RebuildTypeOfType(Underlying);
+ if (Result.isNull())
+ return QualType();
+ }
- return getDerived().RebuildTypeOfType(Underlying);
+ TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {
+QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
+ DecltypeTypeLoc TL) {
+ DecltypeType *T = TL.getTypePtr();
+
// decltype expressions are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
@@ -2338,70 +2582,130 @@ QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {
if (E.isInvalid())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- E.get() == T->getUnderlyingExpr()) {
- E.take();
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ E.get() != T->getUnderlyingExpr()) {
+ Result = getDerived().RebuildDecltypeType(move(E));
+ if (Result.isNull())
+ return QualType();
}
+ else E.take();
- return getDerived().RebuildDecltypeType(move(E));
+ DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformRecordType(const RecordType *T) {
+QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
+ RecordTypeLoc TL) {
+ RecordType *T = TL.getTypePtr();
RecordDecl *Record
- = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
+ = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
if (!Record)
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- Record == T->getDecl())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Record != T->getDecl()) {
+ Result = getDerived().RebuildRecordType(Record);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildRecordType(Record);
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) {
+QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
+ EnumTypeLoc TL) {
+ EnumType *T = TL.getTypePtr();
EnumDecl *Enum
- = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
+ = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
if (!Enum)
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- Enum == T->getDecl())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Enum != T->getDecl()) {
+ Result = getDerived().RebuildEnumType(Enum);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildEnumType(Enum);
+ return Result;
}
template <typename Derived>
-QualType TreeTransform<Derived>::TransformElaboratedType(
- const ElaboratedType *T) {
+QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
+ ElaboratedTypeLoc TL) {
+ ElaboratedType *T = TL.getTypePtr();
+
+ // FIXME: this should be a nested type.
QualType Underlying = getDerived().TransformType(T->getUnderlyingType());
if (Underlying.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- Underlying == T->getUnderlyingType())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Underlying != T->getUnderlyingType()) {
+ Result = getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildElaboratedType(Underlying, T->getTagKind());
+ return Result;
}
template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
- const TemplateTypeParmType *T) {
- // Nothing to do
- return QualType(T, 0);
+ TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL) {
+ return TransformTypeSpecType(TLB, TL);
}
template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
+ TypeLocBuilder &TLB,
+ SubstTemplateTypeParmTypeLoc TL) {
+ return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
+inline QualType
+TreeTransform<Derived>::TransformTemplateSpecializationType(
+ TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL) {
+ // TODO: figure out how make this work with an ObjectType.
+ QualType Result
+ = TransformTemplateSpecializationType(TL.getTypePtr(), QualType());
+ if (Result.isNull())
+ return QualType();
+
+ TemplateSpecializationTypeLoc NewTL
+ = TLB.push<TemplateSpecializationTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+
+ return Result;
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
- const TemplateSpecializationType *T) {
+ const TemplateSpecializationType *T,
+ QualType ObjectType) {
TemplateName Template
- = getDerived().TransformTemplateName(T->getTemplateName());
+ = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);
if (Template.isNull())
return QualType();
@@ -2426,8 +2730,10 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformQualifiedNameType(
- const QualifiedNameType *T) {
+QualType
+TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB,
+ QualifiedNameTypeLoc TL) {
+ QualifiedNameType *T = TL.getTypePtr();
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(),
SourceRange());
@@ -2438,22 +2744,33 @@ QualType TreeTransform<Derived>::TransformQualifiedNameType(
if (Named.isNull())
return QualType();
- if (!getDerived().AlwaysRebuild() &&
- NNS == T->getQualifier() &&
- Named == T->getNamedType())
- return QualType(T, 0);
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ NNS != T->getQualifier() ||
+ Named != T->getNamedType()) {
+ Result = getDerived().RebuildQualifiedNameType(NNS, Named);
+ if (Result.isNull())
+ return QualType();
+ }
+
+ QualifiedNameTypeLoc NewTL = TLB.push<QualifiedNameTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
- return getDerived().RebuildQualifiedNameType(NNS, Named);
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {
+QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
+ TypenameTypeLoc TL) {
+ TypenameType *T = TL.getTypePtr();
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(),
SourceRange(/*FIXME:*/getDerived().getBaseLocation()));
if (!NNS)
return QualType();
+ QualType Result;
+
if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
QualType NewTemplateId
= getDerived().TransformType(QualType(TemplateId, 0));
@@ -2465,31 +2782,33 @@ QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {
NewTemplateId == QualType(TemplateId, 0))
return QualType(T, 0);
- return getDerived().RebuildTypenameType(NNS, NewTemplateId);
+ Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
+ } else {
+ Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier());
}
+ if (Result.isNull())
+ return QualType();
- return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
-}
+ TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
-template<typename Derived>
-QualType TreeTransform<Derived>::TransformObjCInterfaceType(
- const ObjCInterfaceType *T) {
- // FIXME: Implement
- return QualType(T, 0);
+ return Result;
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformObjCObjectPointerType(
- const ObjCObjectPointerType *T) {
- // FIXME: Implement
- return QualType(T, 0);
+QualType
+TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
+ ObjCInterfaceTypeLoc TL) {
+ assert(false && "TransformObjCInterfaceType unimplemented");
+ return QualType();
}
template<typename Derived>
-QualType TreeTransform<Derived>::TransformObjCProtocolListType(
- const ObjCProtocolListType *T) {
- assert(false && "Should not see ObjCProtocolList types");
- return QualType(T, 0);
+QualType
+TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
+ ObjCObjectPointerTypeLoc TL) {
+ assert(false && "TransformObjCObjectPointerType unimplemented");
+ return QualType();
}
//===----------------------------------------------------------------------===//
@@ -4010,8 +4329,8 @@ Sema::OwningExprResult
TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(
UnresolvedDeclRefExpr *E) {
NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
if (!NNS)
return SemaRef.ExprError();
@@ -4040,6 +4359,14 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {
if (Template.isNull())
return SemaRef.ExprError();
+ NestedNameSpecifier *Qualifier = 0;
+ if (E->getQualifier()) {
+ Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (!Qualifier)
+ return SemaRef.ExprError();
+ }
+
llvm::SmallVector<TemplateArgument, 4> TransArgs;
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgument TransArg
@@ -4056,7 +4383,8 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {
// FIXME: It's possible that we'll find out now that the template name
// actually refers to a type, in which case the caller is actually dealing
// with a functional cast. Give a reasonable error message!
- return getDerived().RebuildTemplateIdExpr(Template, E->getTemplateNameLoc(),
+ return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(),
+ Template, E->getTemplateNameLoc(),
E->getLAngleLoc(),
TransArgs.data(),
TransArgs.size(),
@@ -4235,6 +4563,7 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
if (Base.isInvalid())
return SemaRef.ExprError();
+ // Start the member reference and compute the object's type.
Sema::TypeTy *ObjectType = 0;
Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
E->getOperatorLoc(),
@@ -4243,12 +4572,12 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
if (Base.isInvalid())
return SemaRef.ExprError();
- // FIXME: The first qualifier found might be a template type parameter,
- // in which case there is no transformed declaration to refer to (it might
- // refer to a built-in type!).
+ // Transform the first part of the nested-name-specifier that qualifies
+ // the member name.
NamedDecl *FirstQualifierInScope
- = cast_or_null<NamedDecl>(
- getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
+ = getDerived().TransformFirstQualifierInScope(
+ E->getFirstQualifierFoundInScope(),
+ E->getQualifierRange().getBegin());
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
@@ -4261,7 +4590,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(
}
DeclarationName Name
- = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc());
+ = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc(),
+ QualType::getFromOpaquePtr(ObjectType));
if (!Name)
return SemaRef.ExprError();
@@ -4504,6 +4834,14 @@ QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
template<typename Derived>
QualType
+TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType) {
+ return SemaRef.BuildPointerType(PointeeType, Qualifiers(),
+ getDerived().getBaseLocation(),
+ getDerived().getBaseEntity());
+}
+
+template<typename Derived>
+QualType
TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt *Size,
@@ -4549,29 +4887,6 @@ TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
template<typename Derived>
QualType
-TreeTransform<Derived>::RebuildConstantArrayWithExprType(QualType ElementType,
- ArrayType::ArraySizeModifier SizeMod,
- const llvm::APInt &Size,
- Expr *SizeExpr,
- unsigned IndexTypeQuals,
- SourceRange BracketsRange) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, SizeExpr,
- IndexTypeQuals, BracketsRange);
-}
-
-template<typename Derived>
-QualType
-TreeTransform<Derived>::RebuildConstantArrayWithoutExprType(
- QualType ElementType,
- ArrayType::ArraySizeModifier SizeMod,
- const llvm::APInt &Size,
- unsigned IndexTypeQuals) {
- return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0,
- IndexTypeQuals, SourceRange());
-}
-
-template<typename Derived>
-QualType
TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
unsigned IndexTypeQuals) {
@@ -4644,6 +4959,11 @@ QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
+ return SemaRef.Context.getFunctionNoProtoType(T);
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
}
OpenPOWER on IntegriCloud