aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp507
-rw-r--r--lib/AST/CXXInheritance.cpp2
-rw-r--r--lib/AST/Decl.cpp53
-rw-r--r--lib/AST/DeclTemplate.cpp2
-rw-r--r--lib/AST/DeclarationName.cpp4
-rw-r--r--lib/AST/Expr.cpp50
-rw-r--r--lib/AST/Stmt.cpp2
-rw-r--r--lib/AST/StmtDumper.cpp8
-rw-r--r--lib/AST/StmtPrinter.cpp2
-rw-r--r--lib/AST/Type.cpp91
-rw-r--r--lib/AST/TypeLoc.cpp207
-rw-r--r--lib/Analysis/AnalysisContext.cpp21
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp26
-rw-r--r--lib/Analysis/BasicStore.cpp14
-rw-r--r--lib/Analysis/CFG.cpp22
-rw-r--r--lib/Analysis/CFRefCount.cpp83
-rw-r--r--lib/Analysis/GRExprEngine.cpp105
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp15
-rw-r--r--lib/Analysis/LiveVariables.cpp15
-rw-r--r--lib/Analysis/RegionStore.cpp140
-rw-r--r--lib/Analysis/SimpleSValuator.cpp25
-rw-r--r--lib/Basic/Diagnostic.cpp51
-rw-r--r--lib/Basic/FileManager.cpp39
-rw-r--r--lib/Basic/IdentifierTable.cpp29
-rw-r--r--lib/Basic/TargetInfo.cpp52
-rw-r--r--lib/Basic/Targets.cpp39
-rw-r--r--lib/CodeGen/CGBlocks.cpp140
-rw-r--r--lib/CodeGen/CGBlocks.h20
-rw-r--r--lib/CodeGen/CGCXX.cpp15
-rw-r--r--lib/CodeGen/CGCall.cpp5
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp99
-rw-r--r--lib/CodeGen/CGDebugInfo.h2
-rw-r--r--lib/CodeGen/CGDecl.cpp5
-rw-r--r--lib/CodeGen/CGExpr.cpp121
-rw-r--r--lib/CodeGen/CGExprAgg.cpp25
-rw-r--r--lib/CodeGen/CGExprConstant.cpp6
-rw-r--r--lib/CodeGen/CGExprScalar.cpp256
-rw-r--r--lib/CodeGen/CGObjCMac.cpp199
-rw-r--r--lib/CodeGen/CGVtable.cpp71
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp6
-rw-r--r--lib/CodeGen/CodeGenFunction.h11
-rw-r--r--lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--lib/CodeGen/Mangle.cpp14
-rw-r--r--lib/CodeGen/TargetABIInfo.cpp20
-rw-r--r--lib/Driver/ToolChains.cpp25
-rw-r--r--lib/Driver/Tools.cpp45
-rw-r--r--lib/Frontend/ASTUnit.cpp35
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp5
-rw-r--r--lib/Frontend/CacheTokens.cpp24
-rw-r--r--lib/Frontend/GeneratePCH.cpp2
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp13
-rw-r--r--lib/Frontend/InitPreprocessor.cpp16
-rw-r--r--lib/Frontend/PCHReader.cpp270
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp81
-rw-r--r--lib/Frontend/PCHWriter.cpp273
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp196
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp4
-rw-r--r--lib/Frontend/RewriteMacros.cpp8
-rw-r--r--lib/Frontend/RewriteObjC.cpp18
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp6
-rw-r--r--lib/Index/ASTLocation.cpp2
-rw-r--r--lib/Index/ASTVisitor.h8
-rw-r--r--lib/Index/DeclReferenceMap.cpp8
-rw-r--r--lib/Index/Entity.cpp8
-rw-r--r--lib/Index/GlobalSelector.cpp10
-rw-r--r--lib/Index/ResolveLocation.cpp66
-rw-r--r--lib/Lex/PPDirectives.cpp2
-rw-r--r--lib/Lex/PTHLexer.cpp20
-rw-r--r--lib/Lex/Preprocessor.cpp4
-rw-r--r--lib/Lex/TokenConcatenation.cpp2
-rw-r--r--lib/Parse/AttributeList.cpp13
-rw-r--r--lib/Parse/ParseExpr.cpp42
-rw-r--r--lib/Parse/ParseExprCXX.cpp3
-rw-r--r--lib/Parse/ParseInit.cpp9
-rw-r--r--lib/Parse/ParseObjc.cpp7
-rw-r--r--lib/Parse/ParseStmt.cpp4
-rw-r--r--lib/Parse/Parser.cpp5
-rw-r--r--lib/Rewrite/RewriteRope.cpp1
-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
98 files changed, 4737 insertions, 2714 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e028186d46e5..7f5fa35842af 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -40,7 +40,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
bool FreeMem, unsigned size_reserve) :
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
- sigjmp_bufDecl(0), SourceMgr(SM), LangOpts(LOpts),
+ sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
+ SourceMgr(SM), LangOpts(LOpts),
LoadedExternalComments(false), FreeMemory(FreeMem), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
@@ -554,10 +555,6 @@ ASTContext::getTypeInfo(const Type *T) {
assert(false && "Should not see dependent types");
break;
- case Type::ObjCProtocolList:
- assert(false && "Should not see protocol list types");
- break;
-
case Type::FunctionNoProto:
case Type::FunctionProto:
// GCC extension: alignof(function) = 32 bits
@@ -571,8 +568,6 @@ ASTContext::getTypeInfo(const Type *T) {
Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
break;
- case Type::ConstantArrayWithExpr:
- case Type::ConstantArrayWithoutExpr:
case Type::ConstantArray: {
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
@@ -583,14 +578,16 @@ ASTContext::getTypeInfo(const Type *T) {
}
case Type::ExtVector:
case Type::Vector: {
- std::pair<uint64_t, unsigned> EltInfo =
- getTypeInfo(cast<VectorType>(T)->getElementType());
- Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
+ const VectorType *VT = cast<VectorType>(T);
+ std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType());
+ Width = EltInfo.first*VT->getNumElements();
Align = Width;
// If the alignment is not a power of 2, round up to the next power of 2.
// This happens for non-power-of-2 length vectors.
- // FIXME: this should probably be a target property.
- Align = 1 << llvm::Log2_32_Ceil(Align);
+ if (VT->getNumElements() & (VT->getNumElements()-1)) {
+ Align = llvm::NextPowerOf2(Align);
+ Width = llvm::RoundUpToAlignment(Width, Align);
+ }
break;
}
@@ -749,9 +746,13 @@ ASTContext::getTypeInfo(const Type *T) {
break;
}
- case Type::Elaborated: {
- return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr());
- }
+ case Type::SubstTemplateTypeParm:
+ return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
+ getReplacementType().getTypePtr());
+
+ case Type::Elaborated:
+ return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType()
+ .getTypePtr());
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
@@ -940,8 +941,14 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
/// \param T the type that will be the basis for type source info. This type
/// should refer to how the declarator was written in source code, not to
/// what type semantic analysis resolved the declarator to.
-DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T) {
- unsigned DataSize = TypeLoc::getFullDataSizeForType(T);
+DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T,
+ unsigned DataSize) {
+ if (!DataSize)
+ DataSize = TypeLoc::getFullDataSizeForType(T);
+ else
+ assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
+ "incorrect data size provided to CreateDeclaratorInfo!");
+
DeclaratorInfo *DInfo =
(DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8);
new (DInfo) DeclaratorInfo(T);
@@ -1140,7 +1147,7 @@ QualType ASTContext::getComplexType(QualType T) {
// If the pointee type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!T->isCanonical()) {
+ if (!T.isCanonical()) {
Canonical = getComplexType(getCanonicalType(T));
// Get the new insert position for the node we care about.
@@ -1177,7 +1184,7 @@ QualType ASTContext::getPointerType(QualType T) {
// If the pointee type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!T->isCanonical()) {
+ if (!T.isCanonical()) {
Canonical = getPointerType(getCanonicalType(T));
// Get the new insert position for the node we care about.
@@ -1207,7 +1214,7 @@ QualType ASTContext::getBlockPointerType(QualType T) {
// If the block pointee type isn't canonical, this won't be a canonical
// type either so fill in the canonical type field.
QualType Canonical;
- if (!T->isCanonical()) {
+ if (!T.isCanonical()) {
Canonical = getBlockPointerType(getCanonicalType(T));
// Get the new insert position for the node we care about.
@@ -1224,22 +1231,25 @@ QualType ASTContext::getBlockPointerType(QualType T) {
/// getLValueReferenceType - Return the uniqued reference to the type for an
/// lvalue reference to the specified type.
-QualType ASTContext::getLValueReferenceType(QualType T) {
+QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) {
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
- ReferenceType::Profile(ID, T);
+ ReferenceType::Profile(ID, T, SpelledAsLValue);
void *InsertPos = 0;
if (LValueReferenceType *RT =
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
+ const ReferenceType *InnerRef = T->getAs<ReferenceType>();
+
// If the referencee type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
QualType Canonical;
- if (!T->isCanonical()) {
- Canonical = getLValueReferenceType(getCanonicalType(T));
+ if (!SpelledAsLValue || InnerRef || !T.isCanonical()) {
+ QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
+ Canonical = getLValueReferenceType(getCanonicalType(PointeeType));
// Get the new insert position for the node we care about.
LValueReferenceType *NewIP =
@@ -1248,9 +1258,11 @@ QualType ASTContext::getLValueReferenceType(QualType T) {
}
LValueReferenceType *New
- = new (*this, TypeAlignment) LValueReferenceType(T, Canonical);
+ = new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
+ SpelledAsLValue);
Types.push_back(New);
LValueReferenceTypes.InsertNode(New, InsertPos);
+
return QualType(New, 0);
}
@@ -1260,18 +1272,21 @@ QualType ASTContext::getRValueReferenceType(QualType T) {
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
- ReferenceType::Profile(ID, T);
+ ReferenceType::Profile(ID, T, false);
void *InsertPos = 0;
if (RValueReferenceType *RT =
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
+ const ReferenceType *InnerRef = T->getAs<ReferenceType>();
+
// If the referencee type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
QualType Canonical;
- if (!T->isCanonical()) {
- Canonical = getRValueReferenceType(getCanonicalType(T));
+ if (InnerRef || !T.isCanonical()) {
+ QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
+ Canonical = getRValueReferenceType(getCanonicalType(PointeeType));
// Get the new insert position for the node we care about.
RValueReferenceType *NewIP =
@@ -1302,7 +1317,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) {
// If the pointee or class type isn't canonical, this won't be a canonical
// type either, so fill in the canonical type field.
QualType Canonical;
- if (!T->isCanonical()) {
+ if (!T.isCanonical()) {
Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
// Get the new insert position for the node we care about.
@@ -1342,7 +1357,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!EltTy->isCanonical()) {
+ if (!EltTy.isCanonical()) {
Canonical = getConstantArrayType(getCanonicalType(EltTy), ArySize,
ASM, EltTypeQuals);
// Get the new insert position for the node we care about.
@@ -1358,53 +1373,6 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
return QualType(New, 0);
}
-/// getConstantArrayWithExprType - Return a reference to the type for
-/// an array of the specified element type.
-QualType
-ASTContext::getConstantArrayWithExprType(QualType EltTy,
- const llvm::APInt &ArySizeIn,
- Expr *ArySizeExpr,
- ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals,
- SourceRange Brackets) {
- // Convert the array size into a canonical width matching the pointer
- // size for the target.
- llvm::APInt ArySize(ArySizeIn);
- ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace()));
-
- // Compute the canonical ConstantArrayType.
- QualType Canonical = getConstantArrayType(getCanonicalType(EltTy),
- ArySize, ASM, EltTypeQuals);
- // Since we don't unique expressions, it isn't possible to unique VLA's
- // that have an expression provided for their size.
- ConstantArrayWithExprType *New = new(*this, TypeAlignment)
- ConstantArrayWithExprType(EltTy, Canonical, ArySize, ArySizeExpr,
- ASM, EltTypeQuals, Brackets);
- Types.push_back(New);
- return QualType(New, 0);
-}
-
-/// getConstantArrayWithoutExprType - Return a reference to the type for
-/// an array of the specified element type.
-QualType
-ASTContext::getConstantArrayWithoutExprType(QualType EltTy,
- const llvm::APInt &ArySizeIn,
- ArrayType::ArraySizeModifier ASM,
- unsigned EltTypeQuals) {
- // Convert the array size into a canonical width matching the pointer
- // size for the target.
- llvm::APInt ArySize(ArySizeIn);
- ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace()));
-
- // Compute the canonical ConstantArrayType.
- QualType Canonical = getConstantArrayType(getCanonicalType(EltTy),
- ArySize, ASM, EltTypeQuals);
- ConstantArrayWithoutExprType *New = new(*this, TypeAlignment)
- ConstantArrayWithoutExprType(EltTy, Canonical, ArySize, ASM, EltTypeQuals);
- Types.push_back(New);
- return QualType(New, 0);
-}
-
/// getVariableArrayType - Returns a non-unique reference to the type for a
/// variable array of the specified element type.
QualType ASTContext::getVariableArrayType(QualType EltTy,
@@ -1484,7 +1452,7 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy,
// either, so fill in the canonical type field.
QualType Canonical;
- if (!EltTy->isCanonical()) {
+ if (!EltTy.isCanonical()) {
Canonical = getIncompleteArrayType(getCanonicalType(EltTy),
ASM, EltTypeQuals);
@@ -1520,7 +1488,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) {
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!vecType->isCanonical()) {
+ if (!vecType.isCanonical()) {
Canonical = getVectorType(getCanonicalType(vecType), NumElts);
// Get the new insert position for the node we care about.
@@ -1552,7 +1520,7 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!vecType->isCanonical()) {
+ if (!vecType.isCanonical()) {
Canonical = getExtVectorType(getCanonicalType(vecType), NumElts);
// Get the new insert position for the node we care about.
@@ -1616,7 +1584,7 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
return QualType(FT, 0);
QualType Canonical;
- if (!ResultTy->isCanonical()) {
+ if (!ResultTy.isCanonical()) {
Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
// Get the new insert position for the node we care about.
@@ -1639,12 +1607,6 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
unsigned TypeQuals, bool hasExceptionSpec,
bool hasAnyExceptionSpec, unsigned NumExs,
const QualType *ExArray, bool NoReturn) {
- if (LangOpts.CPlusPlus) {
- for (unsigned i = 0; i != NumArgs; ++i)
- assert(!ArgArray[i].hasQualifiers() &&
- "C++ arguments can't have toplevel qualifiers!");
- }
-
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
@@ -1658,11 +1620,9 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
return QualType(FTP, 0);
// Determine whether the type being created is already canonical or not.
- bool isCanonical = ResultTy->isCanonical();
- if (hasExceptionSpec)
- isCanonical = false;
+ bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical();
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
- if (!ArgArray[i]->isCanonical())
+ if (!ArgArray[i].isCanonicalAsParam())
isCanonical = false;
// If this type isn't canonical, get the canonical version of it.
@@ -1672,7 +1632,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
llvm::SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
- CanonicalArgs.push_back(getCanonicalType(ArgArray[i]));
+ CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
Canonical = getFunctionType(getCanonicalType(ResultTy),
CanonicalArgs.data(), NumArgs,
@@ -1743,6 +1703,29 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) {
return QualType(Decl->TypeForDecl, 0);
}
+/// \brief Retrieve a substitution-result type.
+QualType
+ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
+ QualType Replacement) {
+ assert(Replacement.isCanonical()
+ && "replacement types must always be canonical");
+
+ llvm::FoldingSetNodeID ID;
+ SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
+ void *InsertPos = 0;
+ SubstTemplateTypeParmType *SubstParm
+ = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!SubstParm) {
+ SubstParm = new (*this, TypeAlignment)
+ SubstTemplateTypeParmType(Parm, Replacement);
+ Types.push_back(SubstParm);
+ SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
+ }
+
+ return QualType(SubstParm, 0);
+}
+
/// \brief Retrieve the template type parameter type for a template
/// parameter or parameter pack with the given depth, index, and (optionally)
/// name.
@@ -1933,7 +1916,17 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
return LHS->getDeclName() < RHS->getDeclName();
}
-static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
+static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols,
+ unsigned NumProtocols) {
+ if (NumProtocols == 0) return true;
+
+ for (unsigned i = 1; i != NumProtocols; ++i)
+ if (!CmpProtocolNames(Protocols[i-1], Protocols[i]))
+ return false;
+ return true;
+}
+
+static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
unsigned &NumProtocols) {
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
@@ -1950,10 +1943,6 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
- // Sort the protocol list alphabetically to canonicalize it.
- if (NumProtocols)
- SortAndUniqueProtocols(Protocols, NumProtocols);
-
llvm::FoldingSetNodeID ID;
ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols);
@@ -1962,9 +1951,31 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
+ // Sort the protocol list alphabetically to canonicalize it.
+ QualType Canonical;
+ if (!InterfaceT.isCanonical() ||
+ !areSortedAndUniqued(Protocols, NumProtocols)) {
+ if (!areSortedAndUniqued(Protocols, NumProtocols)) {
+ llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols);
+ unsigned UniqueCount = NumProtocols;
+
+ std::copy(Protocols, Protocols + NumProtocols, Sorted.begin());
+ SortAndUniqueProtocols(&Sorted[0], UniqueCount);
+
+ Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
+ &Sorted[0], UniqueCount);
+ } else {
+ Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT),
+ Protocols, NumProtocols);
+ }
+
+ // Regenerate InsertPos.
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
// No Match;
ObjCObjectPointerType *QType = new (*this, TypeAlignment)
- ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols);
+ ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols);
Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
@@ -1975,10 +1986,6 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
/// specified ObjC interface decl. The list of protocols is optional.
QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
- if (NumProtocols)
- // Sort the protocol list alphabetically to canonicalize it.
- SortAndUniqueProtocols(Protocols, NumProtocols);
-
llvm::FoldingSetNodeID ID;
ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols);
@@ -1987,31 +1994,26 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
- // No Match;
- ObjCInterfaceType *QType = new (*this, TypeAlignment)
- ObjCInterfaceType(const_cast<ObjCInterfaceDecl*>(Decl),
- Protocols, NumProtocols);
- Types.push_back(QType);
- ObjCInterfaceTypes.InsertNode(QType, InsertPos);
- return QualType(QType, 0);
-}
+ // Sort the protocol list alphabetically to canonicalize it.
+ QualType Canonical;
+ if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) {
+ llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols);
+ std::copy(Protocols, Protocols + NumProtocols, Sorted.begin());
-QualType ASTContext::getObjCProtocolListType(QualType T,
- ObjCProtocolDecl **Protocols,
- unsigned NumProtocols) {
- llvm::FoldingSetNodeID ID;
- ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols);
+ unsigned UniqueCount = NumProtocols;
+ SortAndUniqueProtocols(&Sorted[0], UniqueCount);
- void *InsertPos = 0;
- if (ObjCProtocolListType *QT =
- ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(QT, 0);
+ Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount);
+
+ ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos);
+ }
+
+ ObjCInterfaceType *QType = new (*this, TypeAlignment)
+ ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
+ Protocols, NumProtocols);
- // No Match;
- ObjCProtocolListType *QType = new (*this, TypeAlignment)
- ObjCProtocolListType(T, Protocols, NumProtocols);
Types.push_back(QType);
- ObjCProtocolListTypes.InsertNode(QType, InsertPos);
+ ObjCInterfaceTypes.InsertNode(QType, InsertPos);
return QualType(QType, 0);
}
@@ -2168,6 +2170,24 @@ QualType ASTContext::getPointerDiffType() const {
// Type Operators
//===----------------------------------------------------------------------===//
+CanQualType ASTContext::getCanonicalParamType(QualType T) {
+ // Push qualifiers into arrays, and then discard any remaining
+ // qualifiers.
+ T = getCanonicalType(T);
+ const Type *Ty = T.getTypePtr();
+
+ QualType Result;
+ if (isa<ArrayType>(Ty)) {
+ Result = getArrayDecayedType(QualType(Ty,0));
+ } else if (isa<FunctionType>(Ty)) {
+ Result = getPointerType(QualType(Ty, 0));
+ } else {
+ Result = QualType(Ty, 0);
+ }
+
+ return CanQualType::CreateUnsafe(Result);
+}
+
/// getCanonicalType - Return the canonical (structural) type corresponding to
/// the specified potentially non-canonical type. The non-canonical version
/// of a type may have many "decorated" versions of types. Decorators can
@@ -2512,7 +2532,7 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) {
/// routine will assert if passed a built-in type that isn't an integer or enum,
/// or if it is not canonicalized.
unsigned ASTContext::getIntegerRank(Type *T) {
- assert(T->isCanonical() && "T should be canonicalized");
+ assert(T->isCanonicalUnqualified() && "T should be canonicalized");
if (EnumType* ET = dyn_cast<EnumType>(T))
T = ET->getDecl()->getIntegerType().getTypePtr();
@@ -2713,6 +2733,226 @@ QualType ASTContext::getObjCFastEnumerationStateType() {
return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
}
+QualType ASTContext::getBlockDescriptorType() {
+ if (BlockDescriptorType)
+ return getTagDeclType(BlockDescriptorType);
+
+ RecordDecl *T;
+ // FIXME: Needs the FlagAppleBlock bit.
+ T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor"));
+
+ QualType FieldTypes[] = {
+ UnsignedLongTy,
+ UnsignedLongTy,
+ };
+
+ const char *FieldNames[] = {
+ "reserved",
+ "Size"
+ };
+
+ for (size_t i = 0; i < 2; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this,
+ T,
+ SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*DInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition(*this);
+
+ BlockDescriptorType = T;
+
+ return getTagDeclType(BlockDescriptorType);
+}
+
+void ASTContext::setBlockDescriptorType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid BlockDescriptorType");
+ BlockDescriptorType = Rec->getDecl();
+}
+
+QualType ASTContext::getBlockDescriptorExtendedType() {
+ if (BlockDescriptorExtendedType)
+ return getTagDeclType(BlockDescriptorExtendedType);
+
+ RecordDecl *T;
+ // FIXME: Needs the FlagAppleBlock bit.
+ T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get("__block_descriptor_withcopydispose"));
+
+ QualType FieldTypes[] = {
+ UnsignedLongTy,
+ UnsignedLongTy,
+ getPointerType(VoidPtrTy),
+ getPointerType(VoidPtrTy)
+ };
+
+ const char *FieldNames[] = {
+ "reserved",
+ "Size",
+ "CopyFuncPtr",
+ "DestroyFuncPtr"
+ };
+
+ for (size_t i = 0; i < 4; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this,
+ T,
+ SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*DInfo=*/0,
+ /*BitWidth=*/0,
+ /*Mutable=*/false);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition(*this);
+
+ BlockDescriptorExtendedType = T;
+
+ return getTagDeclType(BlockDescriptorExtendedType);
+}
+
+void ASTContext::setBlockDescriptorExtendedType(QualType T) {
+ const RecordType *Rec = T->getAs<RecordType>();
+ assert(Rec && "Invalid BlockDescriptorType");
+ BlockDescriptorExtendedType = Rec->getDecl();
+}
+
+bool ASTContext::BlockRequiresCopying(QualType Ty) {
+ if (Ty->isBlockPointerType())
+ return true;
+ if (isObjCNSObjectType(Ty))
+ return true;
+ if (Ty->isObjCObjectPointerType())
+ return true;
+ return false;
+}
+
+QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
+ // type = struct __Block_byref_1_X {
+ // void *__isa;
+ // struct __Block_byref_1_X *__forwarding;
+ // unsigned int __flags;
+ // unsigned int __size;
+ // void *__copy_helper; // as needed
+ // void *__destroy_help // as needed
+ // int X;
+ // } *
+
+ bool HasCopyAndDispose = BlockRequiresCopying(Ty);
+
+ // FIXME: Move up
+ static int UniqueBlockByRefTypeID = 0;
+ char Name[36];
+ sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName);
+ RecordDecl *T;
+ T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get(Name));
+ T->startDefinition();
+ QualType Int32Ty = IntTy;
+ assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
+ QualType FieldTypes[] = {
+ getPointerType(VoidPtrTy),
+ getPointerType(getTagDeclType(T)),
+ Int32Ty,
+ Int32Ty,
+ getPointerType(VoidPtrTy),
+ getPointerType(VoidPtrTy),
+ Ty
+ };
+
+ const char *FieldNames[] = {
+ "__isa",
+ "__forwarding",
+ "__flags",
+ "__size",
+ "__copy_helper",
+ "__destroy_helper",
+ DeclName,
+ };
+
+ for (size_t i = 0; i < 7; ++i) {
+ if (!HasCopyAndDispose && i >=4 && i <= 5)
+ continue;
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*DInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition(*this);
+
+ return getPointerType(getTagDeclType(T));
+}
+
+
+QualType ASTContext::getBlockParmType(
+ bool BlockHasCopyDispose,
+ llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) {
+ // FIXME: Move up
+ static int UniqueBlockParmTypeID = 0;
+ char Name[36];
+ sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID);
+ RecordDecl *T;
+ T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
+ &Idents.get(Name));
+ QualType FieldTypes[] = {
+ getPointerType(VoidPtrTy),
+ IntTy,
+ IntTy,
+ getPointerType(VoidPtrTy),
+ (BlockHasCopyDispose ?
+ getPointerType(getBlockDescriptorExtendedType()) :
+ getPointerType(getBlockDescriptorType()))
+ };
+
+ const char *FieldNames[] = {
+ "__isa",
+ "__flags",
+ "__reserved",
+ "__FuncPtr",
+ "__descriptor"
+ };
+
+ for (size_t i = 0; i < 5; ++i) {
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ &Idents.get(FieldNames[i]),
+ FieldTypes[i], /*DInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ T->addDecl(Field);
+ }
+
+ for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) {
+ const Expr *E = BlockDeclRefDecls[i];
+ const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
+ clang::IdentifierInfo *Name = 0;
+ if (BDRE) {
+ const ValueDecl *D = BDRE->getDecl();
+ Name = &Idents.get(D->getName());
+ }
+ QualType FieldType = E->getType();
+
+ if (BDRE && BDRE->isByRef())
+ FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(),
+ FieldType);
+
+ FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
+ Name, FieldType, /*DInfo=*/0,
+ /*BitWidth=*/0, /*Mutable=*/false);
+ T->addDecl(Field);
+ }
+
+ T->completeDefinition(*this);
+
+ return getPointerType(getTagDeclType(T));
+}
+
void ASTContext::setObjCFastEnumerationStateType(QualType T) {
const RecordType *Rec = T->getAs<RecordType>();
assert(Rec && "Invalid ObjCFAstEnumerationStateType");
@@ -2945,6 +3185,7 @@ static void EncodeBitField(const ASTContext *Context, std::string& S,
S += llvm::utostr(N);
}
+// FIXME: Use SmallString for accumulating string.
void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
bool ExpandPointedToStructures,
bool ExpandStructures,
@@ -3420,7 +3661,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
/// compatible.
static bool areCompatVectorTypes(const VectorType *LHS,
const VectorType *RHS) {
- assert(LHS->isCanonical() && RHS->isCanonical());
+ assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified());
return LHS->getElementType() == RHS->getElementType() &&
LHS->getNumElements() == RHS->getNumElements();
}
@@ -3979,7 +4220,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
unsigned ASTContext::getIntWidth(QualType T) {
if (T == BoolTy)
return 1;
- if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) {
+ if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
return FWIT->getWidth();
}
// For builtin types, just use the standard type sizing method
@@ -3988,10 +4229,18 @@ unsigned ASTContext::getIntWidth(QualType T) {
QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
assert(T->isSignedIntegerType() && "Unexpected type");
- if (const EnumType* ETy = T->getAs<EnumType>())
+
+ // Turn <4 x signed int> -> <4 x unsigned int>
+ if (const VectorType *VTy = T->getAs<VectorType>())
+ return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
+ VTy->getNumElements());
+
+ // For enums, we return the unsigned version of the base type.
+ if (const EnumType *ETy = T->getAs<EnumType>())
T = ETy->getDecl()->getIntegerType();
- const BuiltinType* BTy = T->getAs<BuiltinType>();
- assert (BTy && "Unexpected signed integer type");
+
+ const BuiltinType *BTy = T->getAs<BuiltinType>();
+ assert(BTy && "Unexpected signed integer type");
switch (BTy->getKind()) {
case BuiltinType::Char_S:
case BuiltinType::SChar:
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 4a46eab2e603..b59b45f6467e 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -50,7 +50,7 @@ CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() {
/// different base class subobjects of the same type. BaseType must be
/// an unqualified, canonical class type.
bool CXXBasePaths::isAmbiguous(QualType BaseType) {
- assert(BaseType->isCanonical() && "Base type must be the canonical type");
+ assert(BaseType.isCanonical() && "Base type must be the canonical type");
assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified");
std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index da7959b16f9f..d270a958f0ae 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -231,6 +231,8 @@ std::string NamedDecl::getQualifiedNameAsString() const {
}
std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
+ // FIXME: Collect contexts, then accumulate names to avoid unnecessary
+ // std::string thrashing.
std::vector<std::string> Names;
std::string QualName;
const DeclContext *Ctx = getDeclContext();
@@ -252,7 +254,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size(),
P);
- Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr);
+ Names.push_back(Spec->getIdentifier()->getNameStart() + TemplateArgsStr);
} else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
Names.push_back(ND->getNameAsString());
else
@@ -336,8 +338,15 @@ NamedDecl *NamedDecl::getUnderlyingDecl() {
//===----------------------------------------------------------------------===//
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
- if (DeclInfo)
- return DeclInfo->getTypeLoc().getTypeSpecRange().getBegin();
+ if (DeclInfo) {
+ TypeLoc TL = DeclInfo->getTypeLoc();
+ while (true) {
+ TypeLoc NextTL = TL.getNextTypeLoc();
+ if (!NextTL)
+ return TL.getSourceRange().getBegin();
+ TL = NextTL;
+ }
+ }
return SourceLocation();
}
@@ -408,10 +417,15 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
return getASTContext().getInstantiatedFromStaticDataMember(this);
}
-void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
assert(MSI && "Not an instantiated static data member?");
MSI->setTemplateSpecializationKind(TSK);
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ MSI->getPointOfInstantiation().isInvalid())
+ MSI->setPointOfInstantiation(PointOfInstantiation);
}
bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
@@ -812,18 +826,39 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
}
void
-FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
+FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
if (FunctionTemplateSpecializationInfo *FTSInfo
= TemplateOrSpecialization.dyn_cast<
- FunctionTemplateSpecializationInfo*>())
+ FunctionTemplateSpecializationInfo*>()) {
FTSInfo->setTemplateSpecializationKind(TSK);
- else if (MemberSpecializationInfo *MSInfo
- = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ FTSInfo->getPointOfInstantiation().isInvalid())
+ FTSInfo->setPointOfInstantiation(PointOfInstantiation);
+ } else if (MemberSpecializationInfo *MSInfo
+ = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
MSInfo->setTemplateSpecializationKind(TSK);
- else
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ MSInfo->getPointOfInstantiation().isInvalid())
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ } else
assert(false && "Function cannot have a template specialization kind");
}
+SourceLocation FunctionDecl::getPointOfInstantiation() const {
+ if (FunctionTemplateSpecializationInfo *FTSInfo
+ = TemplateOrSpecialization.dyn_cast<
+ FunctionTemplateSpecializationInfo*>())
+ return FTSInfo->getPointOfInstantiation();
+ else if (MemberSpecializationInfo *MSInfo
+ = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
+ return MSInfo->getPointOfInstantiation();
+
+ return SourceLocation();
+}
+
bool FunctionDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 7836b3f827ce..9a1c65416f71 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -299,7 +299,7 @@ void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
switch (Arg.getKind()) {
default: break;
case TemplateArgument::Type:
- assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
+ assert(Arg.getAsType().isCanonical() && "Type must be canonical!");
break;
}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 101ddd250933..56a597570dd0 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -51,7 +51,7 @@ public:
bool operator<(DeclarationName LHS, DeclarationName RHS) {
if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
- return strcmp(LhsId->getName(), RhsId->getName()) < 0;
+ return LhsId->getName() < RhsId->getName();
return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
}
@@ -60,7 +60,7 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) {
DeclarationName::DeclarationName(Selector Sel) {
if (!Sel.getAsOpaquePtr()) {
- Ptr = StoredObjCZeroArgSelector;
+ Ptr = 0;
return;
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 0e4a29f916fa..a4de3e5b0f7a 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -426,6 +426,18 @@ const char *CastExpr::getCastKindName() const {
return "IntegralToPointer";
case CastExpr::CK_PointerToIntegral:
return "PointerToIntegral";
+ case CastExpr::CK_ToVoid:
+ return "ToVoid";
+ case CastExpr::CK_VectorSplat:
+ return "VectorSplat";
+ case CastExpr::CK_IntegralCast:
+ return "IntegralCast";
+ case CastExpr::CK_IntegralToFloating:
+ return "IntegralToFloating";
+ case CastExpr::CK_FloatingToIntegral:
+ return "FloatingToIntegral";
+ case CastExpr::CK_FloatingCast:
+ return "FloatingCast";
}
assert(0 && "Unhandled cast kind!");
@@ -1740,40 +1752,36 @@ unsigned ExtVectorElementExpr::getNumElements() const {
/// containsDuplicateElements - Return true if any element access is repeated.
bool ExtVectorElementExpr::containsDuplicateElements() const {
- const char *compStr = Accessor->getName();
- unsigned length = Accessor->getLength();
+ // FIXME: Refactor this code to an accessor on the AST node which returns the
+ // "type" of component access, and share with code below and in Sema.
+ llvm::StringRef Comp = Accessor->getName();
// Halving swizzles do not contain duplicate elements.
- if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
- !strcmp(compStr, "even") || !strcmp(compStr, "odd"))
+ if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")
return false;
// Advance past s-char prefix on hex swizzles.
- if (*compStr == 's' || *compStr == 'S') {
- compStr++;
- length--;
- }
+ if (Comp[0] == 's' || Comp[0] == 'S')
+ Comp = Comp.substr(1);
- for (unsigned i = 0; i != length-1; i++) {
- const char *s = compStr+i;
- for (const char c = *s++; *s; s++)
- if (c == *s)
+ for (unsigned i = 0, e = Comp.size(); i != e; ++i)
+ if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos)
return true;
- }
+
return false;
}
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
void ExtVectorElementExpr::getEncodedElementAccess(
llvm::SmallVectorImpl<unsigned> &Elts) const {
- const char *compStr = Accessor->getName();
- if (*compStr == 's' || *compStr == 'S')
- compStr++;
+ llvm::StringRef Comp = Accessor->getName();
+ if (Comp[0] == 's' || Comp[0] == 'S')
+ Comp = Comp.substr(1);
- bool isHi = !strcmp(compStr, "hi");
- bool isLo = !strcmp(compStr, "lo");
- bool isEven = !strcmp(compStr, "even");
- bool isOdd = !strcmp(compStr, "odd");
+ bool isHi = Comp == "hi";
+ bool isLo = Comp == "lo";
+ bool isEven = Comp == "even";
+ bool isOdd = Comp == "odd";
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
uint64_t Index;
@@ -1787,7 +1795,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
else if (isOdd)
Index = 2 * i + 1;
else
- Index = ExtVectorType::getAccessorIdx(compStr[i]);
+ Index = ExtVectorType::getAccessorIdx(Comp[i]);
Elts.push_back(Index);
}
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 3a838fadafa4..6e0da4714912 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -117,7 +117,7 @@ void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
}
const char *LabelStmt::getName() const {
- return getID()->getName();
+ return getID()->getNameStart();
}
// This is defined here to avoid polluting Stmt.h with importing Expr.h
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 0465999a94cc..cf71d6b986a2 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -244,7 +244,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// print a free standing tag decl (e.g. "struct x;").
const char *tagname;
if (const IdentifierInfo *II = TD->getIdentifier())
- tagname = II->getName();
+ tagname = II->getNameStart();
else
tagname = "<anonymous>";
fprintf(F, "\"%s %s;\"", TD->getKindName(), tagname);
@@ -253,7 +253,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// print using-directive decl (e.g. "using namespace x;")
const char *ns;
if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier())
- ns = II->getName();
+ ns = II->getNameStart();
else
ns = "<anonymous>";
fprintf(F, "\"%s %s;\"",UD->getDeclKindName(), ns);
@@ -403,7 +403,7 @@ void StmtDumper::VisitMemberExpr(MemberExpr *Node) {
}
void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
DumpExpr(Node);
- fprintf(F, " %s", Node->getAccessor().getName());
+ fprintf(F, " %s", Node->getAccessor().getNameStart());
}
void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {
DumpExpr(Node);
@@ -495,7 +495,7 @@ void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
DumpExpr(Node);
fprintf(F, " selector=%s", Node->getSelector().getAsString().c_str());
IdentifierInfo* clsName = Node->getClassName();
- if (clsName) fprintf(F, " class=%s", clsName->getName());
+ if (clsName) fprintf(F, " class=%s", clsName->getNameStart());
}
void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 05d0c2683545..2af19765dfaa 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1289,7 +1289,7 @@ void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
return;
}
- if (Policy.Dump) {
+ if (Policy.Dump && &Context) {
dump(Context.getSourceManager());
return;
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 0293862baedb..5fb0178834ff 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -37,18 +37,6 @@ void Type::Destroy(ASTContext& C) {
C.Deallocate(this);
}
-void ConstantArrayWithExprType::Destroy(ASTContext& C) {
- // FIXME: destruction of SizeExpr commented out due to resource contention.
- // SizeExpr->Destroy(C);
- // See FIXME in SemaDecl.cpp:1536: if we were able to either steal
- // or clone the SizeExpr there, then here we could freely delete it.
- // Since we do not know how to steal or clone, we keep a pointer to
- // a shared resource, but we cannot free it.
- // (There probably is a trivial solution ... for people knowing clang!).
- this->~ConstantArrayWithExprType();
- C.Deallocate(this);
-}
-
void VariableArrayType::Destroy(ASTContext& C) {
if (SizeExpr)
SizeExpr->Destroy(C);
@@ -177,8 +165,6 @@ bool Type::isDerivedType() const {
case Pointer:
case VariableArray:
case ConstantArray:
- case ConstantArrayWithExpr:
- case ConstantArrayWithoutExpr:
case IncompleteArray:
case FunctionProto:
case FunctionNoProto:
@@ -642,6 +628,7 @@ bool Type::isSpecifierType() const {
case TypeOfExpr:
case TypeOf:
case TemplateTypeParm:
+ case SubstTemplateTypeParm:
case TemplateSpecialization:
case QualifiedName:
case Typename:
@@ -737,18 +724,6 @@ void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType(), 0, 0);
}
-void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID,
- QualType OIT, ObjCProtocolDecl **protocols,
- unsigned NumProtocols) {
- ID.AddPointer(OIT.getAsOpaquePtr());
- for (unsigned i = 0; i != NumProtocols; i++)
- ID.AddPointer(protocols[i]);
-}
-
-void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getBaseType(), &Protocols[0], getNumProtocols());
-}
-
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
/// potentially looking through *all* consequtive typedefs. This returns the
/// sum of the type qualifiers, so if you have:
@@ -1072,10 +1047,10 @@ void LValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli
// Handle things like 'int (&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(getPointeeType()))
+ if (isa<ArrayType>(getPointeeTypeAsWritten()))
S = '(' + S + ')';
- getPointeeType().getAsStringInternal(S, Policy);
+ getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
}
void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
@@ -1083,10 +1058,10 @@ void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli
// Handle things like 'int (&&A)[4];' correctly.
// FIXME: this should include vectors, but vectors use attributes I guess.
- if (isa<ArrayType>(getPointeeType()))
+ if (isa<ArrayType>(getPointeeTypeAsWritten()))
S = '(' + S + ')';
- getPointeeType().getAsStringInternal(S, Policy);
+ getPointeeTypeAsWritten().getAsStringInternal(S, Policy);
}
void MemberPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
@@ -1111,29 +1086,6 @@ void ConstantArrayType::getAsStringInternal(std::string &S, const PrintingPolicy
getElementType().getAsStringInternal(S, Policy);
}
-void ConstantArrayWithExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- if (Policy.ConstantArraySizeAsWritten) {
- std::string SStr;
- llvm::raw_string_ostream s(SStr);
- getSizeExpr()->printPretty(s, 0, Policy);
- S += '[';
- S += s.str();
- S += ']';
- getElementType().getAsStringInternal(S, Policy);
- }
- else
- ConstantArrayType::getAsStringInternal(S, Policy);
-}
-
-void ConstantArrayWithoutExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
- if (Policy.ConstantArraySizeAsWritten) {
- S += "[]";
- getElementType().getAsStringInternal(S, Policy);
- }
- else
- ConstantArrayType::getAsStringInternal(S, Policy);
-}
-
void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
S += "[]";
@@ -1290,7 +1242,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy
void TypedefType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
- InnerString = getDecl()->getIdentifier()->getName() + InnerString;
+ InnerString = getDecl()->getIdentifier()->getName().str() + InnerString;
}
void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
@@ -1301,7 +1253,11 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const P
InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' +
llvm::utostr_32(Index) + InnerString;
else
- InnerString = Name->getName() + InnerString;
+ InnerString = Name->getName().str() + InnerString;
+}
+
+void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
+ getReplacementType().getAsStringInternal(InnerString, Policy);
}
std::string
@@ -1495,25 +1451,6 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
InnerString = ObjCQIString + InnerString;
}
-void ObjCProtocolListType::getAsStringInternal(std::string &InnerString,
- const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
-
- std::string ObjCQIString = getBaseType().getAsString(Policy);
- ObjCQIString += '<';
- bool isFirst = true;
- for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
- if (isFirst)
- isFirst = false;
- else
- ObjCQIString += ',';
- ObjCQIString += (*I)->getNameAsString();
- }
- ObjCQIString += '>';
- InnerString = ObjCQIString + InnerString;
-}
-
void ElaboratedType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
std::string TypeStr;
@@ -1534,11 +1471,11 @@ void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy
const char *Kind = Policy.SuppressTagKind? 0 : getDecl()->getKindName();
const char *ID;
if (const IdentifierInfo *II = getDecl()->getIdentifier())
- ID = II->getName();
+ ID = II->getNameStart();
else if (TypedefDecl *Typedef = getDecl()->getTypedefForAnonDecl()) {
Kind = 0;
assert(Typedef->getIdentifier() && "Typedef without identifier?");
- ID = Typedef->getIdentifier()->getName();
+ ID = Typedef->getIdentifier()->getNameStart();
} else
ID = "<anonymous>";
@@ -1573,7 +1510,7 @@ void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size(),
Policy);
- MyPart = Spec->getIdentifier()->getName() + TemplateArgsStr;
+ MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr;
} else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
MyPart = Typedef->getIdentifier()->getName();
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 04e708370af3..50a512028e96 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -20,55 +20,32 @@ using namespace clang;
//===----------------------------------------------------------------------===//
namespace {
-
-/// \brief Return the source range for the visited TypeSpecLoc.
-class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
-public:
-#define ABSTRACT_TYPELOC(CLASS)
+ class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- SourceRange Visit##CLASS(CLASS TyLoc) { return TyLoc.getSourceRange(); }
+ SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getSourceRange(); \
+ }
#include "clang/AST/TypeLocNodes.def"
-
- SourceRange VisitTypeLoc(TypeLoc TyLoc) {
- assert(0 && "A typeloc wrapper was not handled!");
- return SourceRange();
- }
-};
-
-}
-
-SourceRange TypeLoc::getSourceRange() const {
- if (isNull())
- return SourceRange();
- return TypeLocRanger().Visit(*this);
+ };
}
-/// \brief Find the TypeSpecLoc that is part of this TypeLoc.
-TypeSpecLoc TypeLoc::getTypeSpecLoc() const {
- if (isNull())
- return TypeSpecLoc();
- UnqualTypeLoc Cur = getUnqualifiedLoc();
- if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(&Cur))
- return DL->getTypeSpecLoc();
- return cast<TypeSpecLoc>(Cur);
+SourceRange TypeLoc::getSourceRangeImpl(TypeLoc TL) {
+ if (TL.isNull()) return SourceRange();
+ return TypeLocRanger().Visit(TL);
}
namespace {
-
-/// \brief Report the full source info data size for the visited TypeLoc.
-class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
-public:
-#define ABSTRACT_TYPELOC(CLASS)
+ class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
- unsigned Visit##CLASS(CLASS TyLoc) { return TyLoc.getFullDataSize(); }
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getFullDataSize(); \
+ }
#include "clang/AST/TypeLocNodes.def"
-
- unsigned VisitTypeLoc(TypeLoc TyLoc) {
- assert(0 && "A type loc wrapper was not handled!");
- return 0;
- }
-};
-
+ };
}
/// \brief Returns the size of the type source info data block.
@@ -78,138 +55,42 @@ unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
}
namespace {
-
-/// \brief Return the "next" TypeLoc for the visited TypeLoc, e.g for "int*" the
-/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
-class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
-public:
-#define TYPELOC(CLASS, PARENT)
-#define DECLARATOR_TYPELOC(CLASS, TYPE) \
- TypeLoc Visit##CLASS(CLASS TyLoc);
+ class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getNextTypeLoc(); \
+ }
#include "clang/AST/TypeLocNodes.def"
-
- TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); }
- TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
- TypeLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
- return TyLoc.getUnqualifiedLoc();
- }
-
- TypeLoc VisitTypeLoc(TypeLoc TyLoc) {
- assert(0 && "A declarator loc wrapper was not handled!");
- return TypeLoc();
- }
-};
-
-}
-
-TypeLoc NextLoc::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
- return TL.getBaseTypeLoc();
-}
-
-TypeLoc NextLoc::VisitPointerLoc(PointerLoc TL) {
- return TL.getPointeeLoc();
-}
-TypeLoc NextLoc::VisitMemberPointerLoc(MemberPointerLoc TL) {
- return TL.getPointeeLoc();
-}
-TypeLoc NextLoc::VisitBlockPointerLoc(BlockPointerLoc TL) {
- return TL.getPointeeLoc();
-}
-TypeLoc NextLoc::VisitReferenceLoc(ReferenceLoc TL) {
- return TL.getPointeeLoc();
-}
-TypeLoc NextLoc::VisitFunctionLoc(FunctionLoc TL) {
- return TL.getResultLoc();
-}
-TypeLoc NextLoc::VisitArrayLoc(ArrayLoc TL) {
- return TL.getElementLoc();
+ };
}
/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
-TypeLoc TypeLoc::getNextTypeLoc() const {
- //llvm::errs() << "getNextTypeLoc: Ty=" << Ty << ", Data=" << Data << "\n";
- TypeLoc Tmp = NextLoc().Visit(*this);
- //llvm::errs() << " result: Ty=" << Tmp.Ty << ", Data=" << Tmp.Data << "\n";
- return Tmp;
+TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
+ return NextLoc().Visit(TL);
}
-//===----------------------------------------------------------------------===//
-// TypeSpecLoc Implementation
-//===----------------------------------------------------------------------===//
-
namespace {
-class TypeSpecChecker : public TypeLocVisitor<TypeSpecChecker, bool> {
-public:
- bool VisitTypeSpecLoc(TypeSpecLoc TyLoc) { return true; }
-};
-
-}
-
-bool TypeSpecLoc::classof(const UnqualTypeLoc *TL) {
- return TypeSpecChecker().Visit(*TL);
-}
-
-//===----------------------------------------------------------------------===//
-// DeclaratorLoc Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-/// \brief Return the TypeSpecLoc for the visited DeclaratorLoc.
-class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> {
-public:
-#define TYPELOC(CLASS, PARENT)
-#define DECLARATOR_TYPELOC(CLASS, TYPE) \
- TypeSpecLoc Visit##CLASS(CLASS TyLoc) { return TyLoc.getTypeSpecLoc(); }
+ struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
+ SourceLocation Loc;
+ TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ TyLoc.initializeLocal(Loc); \
+ }
#include "clang/AST/TypeLocNodes.def"
-
- TypeSpecLoc VisitTypeLoc(TypeLoc TyLoc) {
- assert(0 && "A declarator loc wrapper was not handled!");
- return TypeSpecLoc();
- }
-
- TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) {
- return Visit(TyLoc.getUnqualifiedLoc());
- }
-};
-
-}
-
-/// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc.
-TypeSpecLoc DeclaratorLoc::getTypeSpecLoc() const {
- return TypeSpecGetter().Visit(*this);
-}
-
-namespace {
-
-class DeclaratorLocChecker : public TypeLocVisitor<DeclaratorLocChecker, bool> {
-public:
- bool VisitDeclaratorLoc(DeclaratorLoc TyLoc) { return true; }
-};
-
-}
-
-bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) {
- return DeclaratorLocChecker().Visit(*TL);
-}
-
-//===----------------------------------------------------------------------===//
-// DefaultTypeSpecLoc Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class DefaultTypeSpecLocChecker :
- public TypeLocVisitor<DefaultTypeSpecLocChecker, bool> {
-public:
- bool VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { return true; }
-};
-
+ };
}
-bool DefaultTypeSpecLoc::classofType(const Type *Ty) {
- return
- DefaultTypeSpecLocChecker().Visit(UnqualTypeLoc(const_cast<Type*>(Ty), 0));
+/// \brief Initializes a type location, and all of its children
+/// recursively, as if the entire tree had been written in the
+/// given location.
+void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) {
+ do {
+ TypeLocInitializer(Loc).Visit(TL);
+ } while ((TL = TL.getNextTypeLoc()));
}
-
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index a4cb66be04b3..640912ad6b39 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -33,6 +33,12 @@ AnalysisContextManager::~AnalysisContextManager() {
delete I->second;
}
+void AnalysisContextManager::clear() {
+ for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
+ delete I->second;
+ Contexts.clear();
+}
+
Stmt *AnalysisContext::getBody() {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
return FD->getBody();
@@ -103,6 +109,21 @@ void ScopeContext::Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
ID.AddPointer(s);
}
+LocationContextManager::~LocationContextManager() {
+ clear();
+}
+
+void LocationContextManager::clear() {
+ for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
+ E = Contexts.end(); I != E; ) {
+ LocationContext *LC = &*I;
+ ++I;
+ delete LC;
+ }
+
+ Contexts.clear();
+}
+
StackFrameContext*
LocationContextManager::getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index af300f36fa72..aa2d0ab5a763 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -45,9 +45,9 @@ static const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) {
}
static const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
- const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
- return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName()
- : NULL;
+ if (const ObjCInterfaceType *ReceiverType = GetReceiverType(ME))
+ return ReceiverType->getDecl()->getIdentifier()->getNameStart();
+ return NULL;
}
namespace {
@@ -62,7 +62,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
BugReporter& BR;
ASTContext &Ctx;
- bool isNSString(const ObjCInterfaceType *T, const char* suffix);
+ bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);
bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);
void Warn(ExplodedNode* N, const Expr* E, const std::string& s);
@@ -114,18 +114,8 @@ bool BasicObjCFoundationChecks::Audit(ExplodedNode* N,
if (!ReceiverType)
return false;
- const char* name = ReceiverType->getDecl()->getIdentifier()->getName();
-
- if (!name)
- return false;
-
- if (name[0] != 'N' || name[1] != 'S')
- return false;
-
- name += 2;
-
- // FIXME: Make all of this faster.
- if (isNSString(ReceiverType, name))
+ if (isNSString(ReceiverType,
+ ReceiverType->getDecl()->getIdentifier()->getName()))
return AuditNSString(N, ME);
return false;
@@ -158,8 +148,8 @@ bool BasicObjCFoundationChecks::CheckNilArg(ExplodedNode* N, unsigned Arg) {
//===----------------------------------------------------------------------===//
bool BasicObjCFoundationChecks::isNSString(const ObjCInterfaceType *T,
- const char* suffix) {
- return !strcmp("String", suffix) || !strcmp("MutableString", suffix);
+ llvm::StringRef ClassName) {
+ return ClassName == "NSString" || ClassName == "NSMutableString";
}
bool BasicObjCFoundationChecks::AuditNSString(ExplodedNode* N,
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index a4f451f36490..d81d83c7bfa2 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -49,7 +49,8 @@ public:
QualType T = QualType());
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
- const Expr *E, unsigned Count);
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS);
const GRState *Bind(const GRState *state, Loc L, SVal V) {
return state->makeWithStore(BindInternal(state->getStore(), L, V));
@@ -623,12 +624,21 @@ StoreManager::BindingsHandler::~BindingsHandler() {}
const GRState *BasicStoreManager::InvalidateRegion(const GRState *state,
const MemRegion *R,
const Expr *E,
- unsigned Count) {
+ unsigned Count,
+ InvalidatedSymbols *IS) {
R = R->getBaseRegion();
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
return state;
+ if (IS) {
+ BindingsTy B = GetBindings(state->getStore());
+ if (BindingsTy::data_type *Val = B.lookup(R)) {
+ if (SymbolRef Sym = Val->getAsSymbol())
+ IS->insert(Sym);
+ }
+ }
+
QualType T = cast<TypedRegion>(R)->getValueType(R->getContext());
SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count);
return Bind(state, loc::MemRegionVal(R), V);
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 7b1d50cb3aee..31417597f798 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/Format.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/OwningPtr.h"
using namespace clang;
@@ -51,7 +52,7 @@ static SourceLocation GetEndLoc(Decl* D) {
///
class VISIBILITY_HIDDEN CFGBuilder {
ASTContext *Context;
- CFG* cfg;
+ llvm::OwningPtr<CFG> cfg;
CFGBlock* Block;
CFGBlock* Succ;
@@ -79,8 +80,6 @@ public:
ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {}
- ~CFGBuilder() { delete cfg; }
-
// buildCFG - Used by external clients to construct the CFG.
CFG* buildCFG(Stmt *Statement, ASTContext *C);
@@ -195,7 +194,7 @@ static VariableArrayType* FindVA(Type* t) {
/// NULL.
CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
Context = C;
- assert(cfg);
+ assert(cfg.get());
if (!Statement)
return NULL;
@@ -210,7 +209,8 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
// Visit the statements and create the CFG.
CFGBlock* B = addStmt(Statement);
- if (!B) B = Succ;
+ if (!B)
+ B = Succ;
if (B) {
// Finalize the last constructed block. This usually involves reversing the
@@ -254,17 +254,7 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {
// Create an empty entry block that has no predecessors.
cfg->setEntry(createBlock());
- if (badCFG) {
- delete cfg;
- cfg = NULL;
- return NULL;
- }
-
- // NULL out cfg so that repeated calls to the builder will fail and that the
- // ownership of the constructed CFG is passed to the caller.
- CFG* t = cfg;
- cfg = NULL;
- return t;
+ return badCFG ? NULL : cfg.take();
}
/// createBlock - Used to lazily create blocks that are connected
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index eb1265dda7ea..c629ad1d9612 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -81,7 +81,7 @@ static NamingConvention deriveNamingConvention(Selector S) {
if (!II)
return NoConvention;
- const char *s = II->getName();
+ const char *s = II->getNameStart();
// A method/function name may contain a prefix. We don't know it is there,
// however, until we encounter the first '_'.
@@ -93,12 +93,14 @@ static NamingConvention deriveNamingConvention(Selector S) {
// Skip '_'.
if (*s == '_') {
if (InPossiblePrefix) {
+ // If we already have a convention, return it. Otherwise, skip
+ // the prefix as if it wasn't there.
+ if (C != NoConvention)
+ break;
+
InPossiblePrefix = false;
AtBeginning = true;
- // Discard whatever 'convention' we
- // had already derived since it occurs
- // in the prefix.
- C = NoConvention;
+ assert(C == NoConvention);
}
++s;
continue;
@@ -208,41 +210,16 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
// Type querying functions.
//===----------------------------------------------------------------------===//
-static bool hasPrefix(const char* s, const char* prefix) {
- if (!prefix)
- return true;
-
- char c = *s;
- char cP = *prefix;
-
- while (c != '\0' && cP != '\0') {
- if (c != cP) break;
- c = *(++s);
- cP = *(++prefix);
- }
-
- return cP == '\0';
-}
-
-static bool hasSuffix(const char* s, const char* suffix) {
- const char* loc = strstr(s, suffix);
- return loc && strcmp(suffix, loc) == 0;
-}
-
static bool isRefType(QualType RetTy, const char* prefix,
ASTContext* Ctx = 0, const char* name = 0) {
// Recursively walk the typedef stack, allowing typedefs of reference types.
- while (1) {
- if (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
- const char* TDName = TD->getDecl()->getIdentifier()->getName();
- if (hasPrefix(TDName, prefix) && hasSuffix(TDName, "Ref"))
- return true;
+ while (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
+ llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName();
+ if (TDName.startswith(prefix) && TDName.endswith("Ref"))
+ return true;
- RetTy = TD->getDecl()->getUnderlyingType();
- continue;
- }
- break;
+ RetTy = TD->getDecl()->getUnderlyingType();
}
if (!Ctx || !name)
@@ -254,7 +231,7 @@ static bool isRefType(QualType RetTy, const char* prefix,
return false;
// Does the name start with the prefix?
- return hasPrefix(name, prefix);
+ return llvm::StringRef(name).startswith(prefix);
}
//===----------------------------------------------------------------------===//
@@ -956,7 +933,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
// function's type.
const FunctionType* FT = FD->getType()->getAs<FunctionType>();
- const char* FName = FD->getIdentifier()->getName();
+ const char* FName = FD->getIdentifier()->getNameStart();
// Strip away preceding '_'. Doing this here will effect all the checks
// down below.
@@ -1009,7 +986,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,DoNothing);
}
break;
@@ -1432,16 +1409,19 @@ void RetainSummaryManager::InitializeClassMethodSummaries() {
addNSObjectClsMethSummary(GetUnarySelector("allocWithZone", Ctx), Summ);
// Create the [NSAssertionHandler currentHander] summary.
- addClsMethSummary(&Ctx.Idents.get("NSAssertionHandler"),
- GetNullarySelector("currentHandler", Ctx),
+ addClassMethSummary("NSAssertionHandler", "currentHandler",
getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
// Create the [NSAutoreleasePool addObject:] summary.
ScratchArgs = AF.Add(ScratchArgs, 0, Autorelease);
- addClsMethSummary(&Ctx.Idents.get("NSAutoreleasePool"),
- GetUnarySelector("addObject", Ctx),
- getPersistentSummary(RetEffect::MakeNoRet(),
- DoNothing, Autorelease));
+ addClassMethSummary("NSAutoreleasePool", "addObject",
+ getPersistentSummary(RetEffect::MakeNoRet(),
+ DoNothing, Autorelease));
+
+ // Create a summary for [NSCursor dragCopyCursor].
+ addClassMethSummary("NSCursor", "dragCopyCursor",
+ getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
+ DoNothing));
// Create the summaries for [NSObject performSelector...]. We treat
// these as 'stop tracking' for the arguments because they are often
@@ -2856,14 +2836,13 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
// FIXME: What about layers of ElementRegions?
}
- // Is the invalidated variable something that we were tracking?
- SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol();
-
- // Remove any existing reference-count binding.
- if (Sym)
- state = state->remove<RefBindings>(Sym);
-
- state = StoreMgr.InvalidateRegion(state, R, *I, Count);
+ StoreManager::InvalidatedSymbols IS;
+ state = StoreMgr.InvalidateRegion(state, R, *I, Count, &IS);
+ for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
+ E = IS.end(); I!=E; ++I) {
+ // Remove any existing reference-count binding.
+ state = state->remove<RefBindings>(*I);
+ }
}
else {
// Nuke all other arguments passed by reference.
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 5079acef54b4..ea0255ded8a9 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -207,7 +207,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// Precondition: the first argument of 'main' is an integer guaranteed
// to be > 0.
- if (strcmp(FD->getIdentifier()->getName(), "main") == 0 &&
+ if (FD->getIdentifier()->getName() == "main" &&
FD->getNumParams() > 0) {
const ParmVarDecl *PD = FD->getParamDecl(0);
QualType T = PD->getType();
@@ -1445,10 +1445,9 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
// HACK: Some functions are not marked noreturn, and don't return.
// Here are a few hardwired ones. If this takes too long, we can
// potentially cache these results.
- const char* s = FD->getIdentifier()->getName();
- unsigned n = strlen(s);
+ const char* s = FD->getIdentifier()->getNameStart();
- switch (n) {
+ switch (FD->getIdentifier()->getLength()) {
default:
break;
@@ -2788,66 +2787,55 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
SVal RightV = state->getSVal(RHS);
BinaryOperator::Opcode Op = B->getOpcode();
- switch (Op) {
- case BinaryOperator::Assign: {
-
- // EXPERIMENTAL: "Conjured" symbols.
- // FIXME: Handle structs.
- QualType T = RHS->getType();
-
- if ((RightV.isUnknown() ||
- !getConstraintManager().canReasonAbout(RightV))
- && (Loc::IsLocType(T) ||
- (T->isScalarType() && T->isIntegerType()))) {
- unsigned Count = Builder->getCurrentBlockCount();
- RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
- }
- // Simulate the effects of a "store": bind the value of the RHS
- // to the L-Value represented by the LHS.
- EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV),
- LeftV, RightV);
- continue;
+ if (Op == BinaryOperator::Assign) {
+ // EXPERIMENTAL: "Conjured" symbols.
+ // FIXME: Handle structs.
+ QualType T = RHS->getType();
+
+ if ((RightV.isUnknown()||!getConstraintManager().canReasonAbout(RightV))
+ && (Loc::IsLocType(T) || (T->isScalarType()&&T->isIntegerType()))) {
+ unsigned Count = Builder->getCurrentBlockCount();
+ RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
}
-
- // FALL-THROUGH.
-
- default: {
-
- if (B->isAssignmentOp())
- break;
-
- // Process non-assignments except commas or short-circuited
- // logical expressions (LAnd and LOr).
- SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
-
- if (Result.isUnknown()) {
- if (OldSt != state) {
- // Generate a new node if we have already created a new state.
- MakeNode(Dst, B, *I2, state);
- }
- else
- Dst.Add(*I2);
-
- continue;
+
+ // Simulate the effects of a "store": bind the value of the RHS
+ // to the L-Value represented by the LHS.
+ EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), LeftV, RightV);
+ continue;
+ }
+
+ if (!B->isAssignmentOp()) {
+ // Process non-assignments except commas or short-circuited
+ // logical expressions (LAnd and LOr).
+ SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
+
+ if (Result.isUnknown()) {
+ if (OldSt != state) {
+ // Generate a new node if we have already created a new state.
+ MakeNode(Dst, B, *I2, state);
}
-
- state = state->BindExpr(B, Result);
-
- if (Result.isUndef()) {
- // The operands were *not* undefined, but the result is undefined.
- // This is a special node that should be flagged as an error.
- if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){
- UndefNode->markAsSink();
- UndefResults.insert(UndefNode);
- }
- continue;
+ else
+ Dst.Add(*I2);
+
+ continue;
+ }
+
+ state = state->BindExpr(B, Result);
+
+ if (Result.isUndef()) {
+ // The operands were *not* undefined, but the result is undefined.
+ // This is a special node that should be flagged as an error.
+ if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){
+ UndefNode->markAsSink();
+ UndefResults.insert(UndefNode);
}
-
- // Otherwise, create a new node.
- MakeNode(Dst, B, *I2, state);
continue;
}
+
+ // Otherwise, create a new node.
+ MakeNode(Dst, B, *I2, state);
+ continue;
}
assert (B->isCompoundAssignmentOp());
@@ -2875,7 +2863,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3;
++I3) {
-
state = GetState(*I3);
SVal V = state->getSVal(LHS);
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index cc1ec4b77e48..da24192c9d5a 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -742,11 +742,11 @@ void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
}
}
-class VISIBILITY_HIDDEN CheckBadDiv : public CheckerVisitor<CheckBadDiv> {
+class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
DivZero *BT;
public:
- CheckBadDiv() : BT(0) {}
- ~CheckBadDiv() {}
+ CheckDivZero() : BT(0) {}
+ ~CheckDivZero() {}
const void *getTag() {
static int x;
@@ -756,8 +756,8 @@ public:
void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
};
-void CheckBadDiv::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
+ const BinaryOperator *B) {
BinaryOperator::Opcode Op = B->getOpcode();
if (Op != BinaryOperator::Div &&
Op != BinaryOperator::Rem &&
@@ -792,7 +792,8 @@ void CheckBadDiv::PreVisitBinaryOperator(CheckerContext &C,
return;
}
- // If we get here, then the denom should not be zero.
+ // If we get here, then the denom should not be zero. We abandon the implicit
+ // zero denom case for now.
if (stateNotZero != C.getState())
C.addTransition(C.GenerateNode(B, stateNotZero));
}
@@ -828,5 +829,5 @@ void GRExprEngine::RegisterInternalChecks() {
registerCheck(new CheckAttrNonNull());
registerCheck(new CheckUndefinedArg());
registerCheck(new CheckBadCall());
- registerCheck(new CheckBadDiv());
+ registerCheck(new CheckDivZero());
}
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 4d96c8f8f401..ae78d1f35ff6 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -21,9 +21,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
-
-#include <string.h>
-#include <stdio.h>
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -341,20 +339,19 @@ void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),
E = AD.end_decl(); I!=E; ++I)
if (V.getDeclBit(I->second)) {
- fprintf(stderr, " %s <", I->first->getIdentifier()->getName());
+ llvm::errs() << " " << I->first->getIdentifier()->getName() << " <";
I->first->getLocation().dump(SM);
- fprintf(stderr, ">\n");
+ llvm::errs() << ">\n";
}
}
void LiveVariables::dumpBlockLiveness(SourceManager& M) const {
for (BlockDataMapTy::iterator I = getBlockDataMap().begin(),
E = getBlockDataMap().end(); I!=E; ++I) {
- fprintf(stderr, "\n[ B%d (live variables at block exit) ]\n",
- I->first->getBlockID());
-
+ llvm::errs() << "\n[ B" << I->first->getBlockID()
+ << " (live variables at block exit) ]\n";
dumpLiveness(I->second,M);
}
- fprintf(stderr,"\n");
+ llvm::errs() << "\n";
}
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 9456ab64542c..780772a6f129 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -262,7 +262,8 @@ public:
//===-------------------------------------------------------------------===//
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
- const Expr *E, unsigned Count);
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS);
private:
void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
@@ -455,7 +456,8 @@ void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
const MemRegion *R,
const Expr *Ex,
- unsigned Count) {
+ unsigned Count,
+ InvalidatedSymbols *IS) {
ASTContext& Ctx = StateMgr.getContext();
// Strip away casts.
@@ -490,9 +492,21 @@ const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
if (Optional<SVal> V = getDirectBinding(B, R)) {
if (const MemRegion *RV = V->getAsRegion())
WorkList.push_back(RV);
+
+ // A symbol? Mark it touched by the invalidation.
+ if (IS) {
+ if (SymbolRef Sym = V->getAsSymbol())
+ IS->insert(Sym);
+ }
}
- // Handle region.
+ // Symbolic region? Mark that symbol touched by the invalidation.
+ if (IS) {
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+ IS->insert(SR->getSymbol());
+ }
+
+ // Handle the region itself.
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) ||
isa<ObjCObjectRegion>(R)) {
// Invalidate the region by setting its default value to
@@ -1230,8 +1244,8 @@ SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state,
const MemRegion *superR = R->getSuperRegion();
- // Check if the super region has a binding.
- if (Optional<SVal> V = getDirectBinding(B, superR)) {
+ // Check if the super region has a default binding.
+ if (Optional<SVal> V = getDefaultBinding(B, superR)) {
if (SymbolRef parentSym = V->getAsSymbol())
return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
@@ -1376,7 +1390,7 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
// For now, just invalidate the fields of the struct/union/class.
// FIXME: Precisely handle the fields of the record.
if (superTy->isRecordType())
- return InvalidateRegion(state, superR, NULL, 0);
+ return InvalidateRegion(state, superR, NULL, 0, NULL);
}
}
}
@@ -1588,36 +1602,13 @@ RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
//===----------------------------------------------------------------------===//
// State pruning.
//===----------------------------------------------------------------------===//
-
-namespace {
-class VISIBILITY_HIDDEN RBDNode
- : public std::pair<const GRState*, const MemRegion *> {
-public:
- RBDNode(const GRState *st, const MemRegion *r)
- : std::pair<const GRState*, const MemRegion*>(st, r) {}
-
- const GRState *getState() const { return first; }
- const MemRegion *getRegion() const { return second; }
-};
-
-enum VisitFlag { NotVisited = 0, VisitedFromSubRegion, VisitedFromSuperRegion };
-
-class RBDItem : public RBDNode {
-private:
- const VisitFlag VF;
-
-public:
- RBDItem(const GRState *st, const MemRegion *r, VisitFlag vf)
- : RBDNode(st, r), VF(vf) {}
-
- VisitFlag getVisitFlag() const { return VF; }
-};
-} // end anonymous namespace
void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
+ typedef std::pair<const GRState*, const MemRegion *> RBDNode;
+
Store store = state.getStore();
RegionBindings B = GetRegionBindings(store);
@@ -1638,27 +1629,26 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// Process the "intermediate" roots to find if they are referenced by
// real roots.
- llvm::SmallVector<RBDItem, 10> WorkList;
- llvm::DenseMap<const MemRegion*,unsigned> IntermediateVisited;
+ llvm::SmallVector<RBDNode, 10> WorkList;
+ llvm::DenseSet<const MemRegion*> IntermediateVisited;
while (!IntermediateRoots.empty()) {
const MemRegion* R = IntermediateRoots.back();
IntermediateRoots.pop_back();
- unsigned &visited = IntermediateVisited[R];
- if (visited)
+ if (IntermediateVisited.count(R))
continue;
- visited = 1;
+ IntermediateVisited.insert(R);
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
if (SymReaper.isLive(Loc, VR->getDecl()))
- WorkList.push_back(RBDItem(&state, VR, VisitedFromSuperRegion));
+ WorkList.push_back(std::make_pair(&state, VR));
continue;
}
if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
if (SymReaper.isLive(SR->getSymbol()))
- WorkList.push_back(RBDItem(&state, SR, VisitedFromSuperRegion));
+ WorkList.push_back(std::make_pair(&state, SR));
continue;
}
@@ -1671,54 +1661,40 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// Enqueue the RegionRoots onto WorkList.
for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),
E=RegionRoots.end(); I!=E; ++I) {
- WorkList.push_back(RBDItem(&state, *I, VisitedFromSuperRegion));
+ WorkList.push_back(std::make_pair(&state, *I));
}
RegionRoots.clear();
- // Process the worklist.
- typedef llvm::DenseMap<std::pair<const GRState*, const MemRegion*>, VisitFlag>
- VisitMap;
-
- VisitMap Visited;
+ llvm::DenseSet<RBDNode> Visited;
while (!WorkList.empty()) {
- RBDItem N = WorkList.back();
+ RBDNode N = WorkList.back();
WorkList.pop_back();
// Have we visited this node before?
- VisitFlag &VF = Visited[N];
- if (VF >= N.getVisitFlag())
+ if (Visited.count(N))
continue;
+ Visited.insert(N);
+
+ const MemRegion *R = N.second;
+ const GRState *state_N = N.first;
- const MemRegion *R = N.getRegion();
- const GRState *state_N = N.getState();
-
- // Enqueue subregions?
- if (N.getVisitFlag() == VisitedFromSuperRegion) {
- RegionStoreSubRegionMap *M;
-
- if (&state == state_N)
- M = SubRegions.get();
- else {
- RegionStoreSubRegionMap *& SM = SC[state_N];
- if (!SM)
- SM = getRegionStoreSubRegionMap(state_N->getStore());
- M = SM;
- }
+ // Enqueue subregions.
+ RegionStoreSubRegionMap *M;
- RegionStoreSubRegionMap::iterator I, E;
- for (llvm::tie(I, E) = M->begin_end(R); I != E; ++I)
- WorkList.push_back(RBDItem(state_N, *I, VisitedFromSuperRegion));
- }
-
- // At this point, if we have already visited this region before, we are
- // done.
- if (VF != NotVisited) {
- VF = N.getVisitFlag();
- continue;
+ if (&state == state_N)
+ M = SubRegions.get();
+ else {
+ RegionStoreSubRegionMap *& SM = SC[state_N];
+ if (!SM)
+ SM = getRegionStoreSubRegionMap(state_N->getStore());
+ M = SM;
}
- VF = N.getVisitFlag();
+ RegionStoreSubRegionMap::iterator I, E;
+ for (llvm::tie(I, E) = M->begin_end(R); I != E; ++I)
+ WorkList.push_back(std::make_pair(state_N, *I));
+
// Enqueue the super region.
if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
const MemRegion *superR = SR->getSuperRegion();
@@ -1726,12 +1702,9 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// If 'R' is a field or an element, we want to keep the bindings
// for the other fields and elements around. The reason is that
// pointer arithmetic can get us to the other fields or elements.
- // FIXME: add an assertion that this is always true.
- VisitFlag NewVisit =
- isa<FieldRegion>(R) || isa<ElementRegion>(R) || isa<ObjCIvarRegion>(R)
- ? VisitedFromSuperRegion : VisitedFromSubRegion;
-
- WorkList.push_back(RBDItem(state_N, superR, NewVisit));
+ assert(isa<FieldRegion>(R) || isa<ElementRegion>(R)
+ || isa<ObjCIvarRegion>(R));
+ WorkList.push_back(std::make_pair(state_N, superR));
}
}
@@ -1752,8 +1725,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) {
const LazyCompoundValData *D = LCV->getCVData();
- WorkList.push_back(RBDItem(D->getState(), D->getRegion(),
- VisitedFromSuperRegion));
+ WorkList.push_back(std::make_pair(D->getState(), D->getRegion()));
}
else {
// Update the set of live symbols.
@@ -1763,7 +1735,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
// If V is a region, then add it to the worklist.
if (const MemRegion *RX = V->getAsRegion())
- WorkList.push_back(RBDItem(state_N, RX, VisitedFromSuperRegion));
+ WorkList.push_back(std::make_pair(state_N, RX));
}
}
}
@@ -1774,7 +1746,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
const MemRegion* R = I.getKey();
// If this region live? Is so, none of its symbols are dead.
- if (Visited.find(std::make_pair(&state, R)) != Visited.end())
+ if (Visited.count(std::make_pair(&state, R)))
continue;
// Remove this dead region from the store.
@@ -1820,7 +1792,7 @@ GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
void RegionStoreManager::print(Store store, llvm::raw_ostream& OS,
const char* nl, const char *sep) {
RegionBindings B = GetRegionBindings(store);
- OS << "Store (direct bindings):" << nl;
+ OS << "Store (direct and default bindings):" << nl;
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
OS << ' ' << I.getKey() << " : " << I.getData() << nl;
diff --git a/lib/Analysis/SimpleSValuator.cpp b/lib/Analysis/SimpleSValuator.cpp
index 636ce15c3326..4487aa9d3028 100644
--- a/lib/Analysis/SimpleSValuator.cpp
+++ b/lib/Analysis/SimpleSValuator.cpp
@@ -346,16 +346,29 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
SymbolRef Sym = slhs->getSymbol();
- // Does the symbol simplify to a constant?
+ // Does the symbol simplify to a constant? If so, "fold" the constant
+ // by setting 'lhs' to a ConcreteInt and try again.
if (Sym->getType(ValMgr.getContext())->isIntegerType())
if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
- // What should we convert it to?
- if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
- BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
- lhs = nonloc::ConcreteInt(BVF.Convert(rhs_I->getValue(),
- *Constant));
+ // The symbol evaluates to a constant. If necessary, promote the
+ // folded constant (LHS) to the result type.
+ BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
+ const llvm::APSInt &lhs_I = BVF.Convert(resultTy, *Constant);
+ lhs = nonloc::ConcreteInt(lhs_I);
+
+ // Also promote the RHS (if necessary).
+
+ // For shifts, it necessary promote the RHS to the result type.
+ if (BinaryOperator::isShiftOp(op))
continue;
+
+ // Other operators: do an implicit conversion. This shouldn't be
+ // necessary once we support truncation/extension of symbolic values.
+ if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
+ rhs = nonloc::ConcreteInt(BVF.Convert(resultTy, rhs_I->getValue()));
}
+
+ continue;
}
if (isa<nonloc::ConcreteInt>(rhs)) {
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 4a29997a2ccc..fbc731311653 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -25,6 +25,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include <vector>
#include <map>
#include <cstring>
@@ -82,9 +83,14 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
#ifndef NDEBUG
static bool IsFirst = true;
if (IsFirst) {
- for (unsigned i = 1; i != NumDiagEntries; ++i)
+ for (unsigned i = 1; i != NumDiagEntries; ++i) {
+ assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
+ "Diag ID conflict, the enums at the start of clang::diag (in "
+ "Diagnostic.h) probably need to be increased");
+
assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
"Improperly sorted diag info");
+ }
IsFirst = false;
}
#endif
@@ -184,6 +190,8 @@ namespace clang {
static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
const char *Modifier, unsigned ML,
const char *Argument, unsigned ArgLen,
+ const Diagnostic::ArgumentValue *PrevArgs,
+ unsigned NumPrevArgs,
llvm::SmallVectorImpl<char> &Output,
void *Cookie) {
const char *Str = "<can't format argument>";
@@ -222,6 +230,8 @@ Diagnostic::~Diagnostic() {
void Diagnostic::pushMappings() {
+ // Avoids undefined behavior when the stack has to resize.
+ DiagMappingsStack.reserve(DiagMappingsStack.size() + 1);
DiagMappingsStack.push_back(DiagMappingsStack.back());
}
@@ -679,6 +689,12 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
const char *DiagStr = getDiags()->getDescription(getID());
const char *DiagEnd = DiagStr+strlen(DiagStr);
+ /// FormattedArgs - Keep track of all of the arguments formatted by
+ /// ConvertArgToString and pass them into subsequent calls to
+ /// ConvertArgToString, allowing the implementation to avoid redundancies in
+ /// obvious cases.
+ llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs;
+
while (DiagStr != DiagEnd) {
if (DiagStr[0] != '%') {
// Append non-%0 substrings to Str if we have one.
@@ -726,7 +742,9 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
unsigned ArgNo = *DiagStr++ - '0';
- switch (getArgKind(ArgNo)) {
+ Diagnostic::ArgumentKind Kind = getArgKind(ArgNo);
+
+ switch (Kind) {
// ---- STRINGS ----
case Diagnostic::ak_std_string: {
const std::string &S = getArgStdStr(ArgNo);
@@ -757,9 +775,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
- // FIXME: Optimize
- std::string S = llvm::itostr(Val);
- OutStr.append(S.begin(), S.end());
+ llvm::raw_svector_ostream(OutStr) << Val;
}
break;
}
@@ -774,10 +790,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
-
- // FIXME: Optimize
- std::string S = llvm::utostr_32(Val);
- OutStr.append(S.begin(), S.end());
+ llvm::raw_svector_ostream(OutStr) << Val;
}
break;
}
@@ -793,9 +806,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
continue;
}
- OutStr.push_back('\'');
- OutStr.append(II->getName(), II->getName() + II->getLength());
- OutStr.push_back('\'');
+ llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
break;
}
case Diagnostic::ak_qualtype:
@@ -803,11 +814,23 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
case Diagnostic::ak_nameddecl:
case Diagnostic::ak_nestednamespec:
case Diagnostic::ak_declcontext:
- getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
+ getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
Modifier, ModifierLen,
- Argument, ArgumentLen, OutStr);
+ Argument, ArgumentLen,
+ FormattedArgs.data(), FormattedArgs.size(),
+ OutStr);
break;
}
+
+ // Remember this argument info for subsequent formatting operations. Turn
+ // std::strings into a null terminated string to make it be the same case as
+ // all the other ones.
+ if (Kind != Diagnostic::ak_std_string)
+ FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
+ else
+ FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string,
+ (intptr_t)getArgStdStr(ArgNo).c_str()));
+
}
}
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index df86f9d04702..ee4309de937b 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -149,6 +149,41 @@ FileManager::~FileManager() {
delete &UniqueFiles;
}
+void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) {
+ assert(statCache && "No stat cache provided?");
+ if (AtBeginning || StatCache.get() == 0) {
+ statCache->setNextStatCache(StatCache.take());
+ StatCache.reset(statCache);
+ return;
+ }
+
+ StatSysCallCache *LastCache = StatCache.get();
+ while (LastCache->getNextStatCache())
+ LastCache = LastCache->getNextStatCache();
+
+ LastCache->setNextStatCache(statCache);
+}
+
+void FileManager::removeStatCache(StatSysCallCache *statCache) {
+ if (!statCache)
+ return;
+
+ if (StatCache.get() == statCache) {
+ // This is the first stat cache.
+ StatCache.reset(StatCache->takeNextStatCache());
+ return;
+ }
+
+ // Find the stat cache in the list.
+ StatSysCallCache *PrevCache = StatCache.get();
+ while (PrevCache && PrevCache->getNextStatCache() != statCache)
+ PrevCache = PrevCache->getNextStatCache();
+ if (PrevCache)
+ PrevCache->setNextStatCache(statCache->getNextStatCache());
+ else
+ assert(false && "Stat cache not found for removal");
+}
+
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
///
@@ -290,8 +325,8 @@ void FileManager::PrintStats() const {
}
int MemorizeStatCalls::stat(const char *path, struct stat *buf) {
- int result = ::stat(path, buf);
-
+ int result = StatSysCallCache::stat(path, buf);
+
if (result != 0) {
// Cache failed 'stat' results.
struct stat empty;
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 93c260fdbe17..16aa0c54846a 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -16,6 +16,7 @@
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/raw_ostream.h"
#include <cstdio>
using namespace clang;
@@ -153,7 +154,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
unsigned Len = getLength();
if (Len < 2) return tok::pp_not_keyword;
- const char *Name = getName();
+ const char *Name = getNameStart();
switch (HASH(Len, Name[0], Name[2])) {
default: return tok::pp_not_keyword;
CASE( 2, 'i', '\0', if);
@@ -301,24 +302,15 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
}
std::string MultiKeywordSelector::getName() const {
- std::string Result;
- unsigned Length = 0;
+ llvm::SmallString<256> Str;
+ llvm::raw_svector_ostream OS(Str);
for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
if (*I)
- Length += (*I)->getLength();
- ++Length; // :
+ OS << (*I)->getName();
+ OS << ':';
}
- Result.reserve(Length);
-
- for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
- if (*I)
- Result.insert(Result.end(), (*I)->getName(),
- (*I)->getName()+(*I)->getLength());
- Result.push_back(':');
- }
-
- return Result;
+ return OS.str();
}
std::string Selector::getAsString() const {
@@ -332,9 +324,10 @@ std::string Selector::getAsString() const {
if (getNumArgs() == 0)
return II->getName();
- std::string Res = II ? II->getName() : "";
- Res += ":";
- return Res;
+ if (!II)
+ return ":";
+
+ return II->getName().str() + ":";
}
// We have a multiple keyword selector (no embedded flags).
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 9cd12493e7a4..8f3c777c2004 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -43,6 +43,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
UIntMaxType = UnsignedLongLong;
IntPtrType = SignedLong;
WCharType = SignedInt;
+ WIntType = SignedInt;
Char16Type = UnsignedShort;
Char32Type = UnsignedInt;
Int64Type = SignedLongLong;
@@ -73,6 +74,57 @@ const char *TargetInfo::getTypeName(IntType T) {
}
}
+/// getTypeConstantSuffix - Return the constant suffix for the specified
+/// integer type enum. For example, SignedLong -> "L".
+const char *TargetInfo::getTypeConstantSuffix(IntType T) {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case SignedInt: return "";
+ case SignedLong: return "L";
+ case SignedLongLong: return "LL";
+ case UnsignedShort:
+ case UnsignedInt: return "U";
+ case UnsignedLong: return "UL";
+ case UnsignedLongLong: return "ULL";
+ }
+}
+
+/// getTypeWidth - Return the width (in bits) of the specified integer type
+/// enum. For example, SignedInt -> getIntWidth().
+unsigned TargetInfo::getTypeWidth(IntType T) const {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort: return getShortWidth();
+ case UnsignedShort: return getShortWidth();
+ case SignedInt: return getIntWidth();
+ case UnsignedInt: return getIntWidth();
+ case SignedLong: return getLongWidth();
+ case UnsignedLong: return getLongWidth();
+ case SignedLongLong: return getLongLongWidth();
+ case UnsignedLongLong: return getLongLongWidth();
+ };
+}
+
+/// getTypeSigned - Return whether an integer types is signed. Returns true if
+/// the type is signed; false otherwise.
+bool TargetInfo::getTypeSigned(IntType T) const {
+ switch (T) {
+ default: assert(0 && "not an integer!");
+ case SignedShort:
+ case SignedInt:
+ case SignedLong:
+ case SignedLongLong:
+ return true;
+ case UnsignedShort:
+ case UnsignedInt:
+ case UnsignedLong:
+ case UnsignedLongLong:
+ return false;
+ };
+}
+
+
//===----------------------------------------------------------------------===//
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 1d4d1235c963..66d6824b6f29 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -320,6 +320,27 @@ public:
: OSTargetInfo<Target>(triple) {}
};
+// AuroraUX target
+template<typename Target>
+class AuroraUXTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ std::vector<char> &Defs) const {
+ DefineStd(Defs, "sun", Opts);
+ DefineStd(Defs, "unix", Opts);
+ Define(Defs, "__ELF__");
+ Define(Defs, "__svr4__");
+ Define(Defs, "__SVR4");
+ }
+public:
+ AuroraUXTargetInfo(const std::string& triple)
+ : OSTargetInfo<Target>(triple) {
+ this->UserLabelPrefix = "";
+ this->WCharType = this->SignedLong;
+ // FIXME: WIntType should be SignedLong
+ }
+};
+
// Solaris target
template<typename Target>
class SolarisTargetInfo : public OSTargetInfo<Target> {
@@ -1456,6 +1477,14 @@ void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
} // end anonymous namespace.
namespace {
+class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> {
+public:
+ AuroraUXSparcV8TargetInfo(const std::string& triple) :
+ AuroraUXTargetInfo<SparcV8TargetInfo>(triple) {
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ }
+};
class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {
public:
SolarisSparcV8TargetInfo(const std::string& triple) :
@@ -1573,8 +1602,8 @@ namespace {
}
virtual bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const {
- // FIXME: implement
- return true;
+ // No target constraints for now.
+ return false;
}
virtual const char *getClobbers() const {
// FIXME: Is this really right?
@@ -1846,6 +1875,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
return new PPC64TargetInfo(T);
case llvm::Triple::sparc:
+ if (os == llvm::Triple::AuroraUX)
+ return new AuroraUXSparcV8TargetInfo(T);
if (os == llvm::Triple::Solaris)
return new SolarisSparcV8TargetInfo(T);
return new SparcV8TargetInfo(T);
@@ -1858,6 +1889,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
case llvm::Triple::x86:
switch (os) {
+ case llvm::Triple::AuroraUX:
+ return new AuroraUXTargetInfo<X86_32TargetInfo>(T);
case llvm::Triple::Darwin:
return new DarwinI386TargetInfo(T);
case llvm::Triple::Linux:
@@ -1884,6 +1917,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {
case llvm::Triple::x86_64:
switch (os) {
+ case llvm::Triple::AuroraUX:
+ return new AuroraUXTargetInfo<X86_64TargetInfo>(T);
case llvm::Triple::Darwin:
return new DarwinX86_64TargetInfo(T);
case llvm::Triple::Linux:
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 736425e01276..682cf5da1e72 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -73,29 +73,60 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
return NSConcreteStackBlock;
}
-static void CollectBlockDeclRefInfo(const Stmt *S,
- CodeGenFunction::BlockInfo &Info) {
+static void CollectBlockDeclRefInfo(
+ const Stmt *S, CodeGenFunction::BlockInfo &Info,
+ llvm::SmallSet<const DeclContext *, 16> &InnerContexts) {
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
I != E; ++I)
if (*I)
- CollectBlockDeclRefInfo(*I, Info);
+ CollectBlockDeclRefInfo(*I, Info, InnerContexts);
- if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
+ // We want to ensure we walk down into block literals so we can find
+ // all nested BlockDeclRefExprs.
+ if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+ InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl()));
+ CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
+ }
+
+ if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
// FIXME: Handle enums.
- if (isa<FunctionDecl>(DE->getDecl()))
+ if (isa<FunctionDecl>(BDRE->getDecl()))
return;
- if (DE->isByRef())
- Info.ByRefDeclRefs.push_back(DE);
- else
- Info.ByCopyDeclRefs.push_back(DE);
+ // Only Decls that escape are added.
+ if (!InnerContexts.count(BDRE->getDecl()->getDeclContext()))
+ Info.DeclRefs.push_back(BDRE);
}
}
/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be
/// declared as a global variable instead of on the stack.
static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) {
- return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
+ return Info.DeclRefs.empty();
+}
+
+/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
+/// ensure we can generate the debug information for the parameter for the block
+/// invoke function.
+static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info,
+ CodeGenFunction *CGF) {
+ // Always allocate self, as it is often handy in the debugger, even if there
+ // is no codegen in the block that uses it. This is also useful to always do
+ // this as if we didn't, we'd have to figure out all code that uses a self
+ // pointer, including implicit uses.
+ if (const ObjCMethodDecl *OMD
+ = dyn_cast_or_null<ObjCMethodDecl>(CGF->CurFuncDecl)) {
+ ImplicitParamDecl *SelfDecl = OMD->getSelfDecl();
+ BlockDeclRefExpr *BDRE = new (CGF->getContext())
+ BlockDeclRefExpr(SelfDecl,
+ SelfDecl->getType(), SourceLocation(), false);
+ CGF->AllocateBlockDecl(BDRE);
+ }
+
+ // FIXME: Also always forward the this pointer in C++ as well.
+
+ for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
+ CGF->AllocateBlockDecl(Info.DeclRefs[i]);
}
// FIXME: Push most into CGM, passing down a few bits, like current function
@@ -104,7 +135,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
std::string Name = CurFn->getName();
CodeGenFunction::BlockInfo Info(0, Name.c_str());
- CollectBlockDeclRefInfo(BE->getBody(), Info);
+ llvm::SmallSet<const DeclContext *, 16> InnerContexts;
+ InnerContexts.insert(BE->getBlockDecl());
+ CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
// Check if the block can be global.
// FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
@@ -159,7 +192,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (subBlockDeclRefDecls.size() == 0) {
// __descriptor
- Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, 0, 0);
+ Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize,
+ 0, 0);
// Optimize to being a global block.
Elts[0] = CGM.getNSConcreteGlobalBlock();
@@ -269,7 +303,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
llvm::Value *BlockLiteral = LoadBlockStruct();
Loc = Builder.CreateGEP(BlockLiteral,
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
offset),
"block.literal");
Ty = llvm::PointerType::get(Ty, 0);
@@ -391,10 +425,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
return GenericExtendedBlockLiteralType;
}
-bool BlockFunction::BlockRequiresCopying(QualType Ty) {
- return CGM.BlockRequiresCopying(Ty);
-}
-
RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>();
@@ -447,24 +477,34 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
return EmitCall(FnInfo, Func, Args);
}
-llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
const ValueDecl *VD = E->getDecl();
-
uint64_t &offset = BlockDecls[VD];
-
// See if we have already allocated an offset for this variable.
- if (offset == 0) {
- // Don't run the expensive check, unless we have to.
- if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
+ if (offset)
+ return offset;
+
+ // Don't run the expensive check, unless we have to.
+ if (!BlockHasCopyDispose)
+ if (E->isByRef()
+ || BlockRequiresCopying(E->getType()))
BlockHasCopyDispose = true;
- // if not, allocate one now.
- offset = getBlockOffset(E);
- }
+
+ // if not, allocate one now.
+ offset = getBlockOffset(E);
+
+ return offset;
+}
+
+llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
+ const ValueDecl *VD = E->getDecl();
+ uint64_t offset = AllocateBlockDecl(E);
+
llvm::Value *BlockLiteral = LoadBlockStruct();
llvm::Value *V = Builder.CreateGEP(BlockLiteral,
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
offset),
"block.literal");
if (E->isByRef()) {
@@ -576,7 +616,10 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
}
llvm::Value *CodeGenFunction::LoadBlockStruct() {
- return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
+ llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()],
+ "self");
+ // For now, we codegen based upon byte offsets.
+ return Builder.CreateBitCast(V, PtrToInt8Ty);
}
llvm::Function *
@@ -605,14 +648,8 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
LocalDeclMap[VD] = i->second;
}
- // FIXME: We need to rearrange the code for copy/dispose so we have this
- // sooner, so we can calculate offsets correctly.
- if (!BlockHasCopyDispose)
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
- else
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8;
+ BlockOffset = CGM.getTargetData()
+ .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
const FunctionType *BlockFunctionType = BExpr->getFunctionType();
@@ -630,13 +667,22 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
FunctionArgList Args;
+ CurFuncDecl = OuterFuncDecl;
+
const BlockDecl *BD = BExpr->getBlockDecl();
+ IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
+
+ // Allocate all BlockDeclRefDecls, so we can calculate the right ParmTy below.
+ AllocateAllBlockDeclRefs(Info, this);
+
+ QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
+ BlockDeclRefDecls);
// FIXME: This leaks
ImplicitParamDecl *SelfDecl =
ImplicitParamDecl::Create(getContext(), 0,
- SourceLocation(), 0,
- getContext().getPointerType(getContext().VoidTy));
+ SourceLocation(), II,
+ ParmTy);
Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
BlockStructDecl = SelfDecl;
@@ -758,11 +804,13 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Dst =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Dst, Dst->getType()));
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
@@ -843,7 +891,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
@@ -922,13 +971,15 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Dst =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Dst, Dst->getType()));
// FIXME: This leaks
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
@@ -991,7 +1042,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
FunctionArgList Args;
// FIXME: This leaks
ImplicitParamDecl *Src =
- ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ ImplicitParamDecl::Create(getContext(), 0,
+ SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
Args.push_back(std::make_pair(Src, Src->getType()));
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 3a860c0d3c36..3ab4efb71bee 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -115,15 +115,8 @@ public:
PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());
}
- bool BlockRequiresCopying(QualType Ty) {
- if (Ty->isBlockPointerType())
- return true;
- if (getContext().isObjCNSObjectType(Ty))
- return true;
- if (Ty->isObjCObjectPointerType())
- return true;
- return false;
- }
+ bool BlockRequiresCopying(QualType Ty)
+ { return getContext().BlockRequiresCopying(Ty); }
};
class BlockFunction : public BlockBase {
@@ -165,11 +158,7 @@ public:
/// ByCopyDeclRefs - Variables from parent scopes that have been imported
/// into this block.
- llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;
-
- // ByRefDeclRefs - __block variables from parent scopes that have been
- // imported into this block.
- llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;
+ llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
BlockInfo(const llvm::Type *blt, const char *n)
: BlockLiteralTy(blt), Name(n) {
@@ -228,7 +217,8 @@ public:
llvm::Value *getBlockObjectDispose();
void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
- bool BlockRequiresCopying(QualType Ty);
+ bool BlockRequiresCopying(QualType Ty)
+ { return getContext().BlockRequiresCopying(Ty); }
};
} // end namespace CodeGen
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 3960cf51868f..cfa669dc4b6e 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -590,12 +590,15 @@ void
CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
const CXXConstructExpr *E) {
assert(Dest && "Must have a destination!");
-
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
- if (RD->hasTrivialConstructor())
+ const CXXConstructorDecl *CD = E->getConstructor();
+ // For a copy constructor, even if it is trivial, must fall thru so
+ // its argument is code-gen'ed.
+ if (!CD->isCopyConstructor(getContext())) {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+ if (RD->hasTrivialConstructor())
return;
-
+ }
// Code gen optimization to eliminate copy constructor and return
// its first argument instead.
if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
@@ -604,7 +607,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
return;
}
// Call the constructor.
- EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest,
+ EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
E->arg_begin(), E->arg_end());
}
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index bad166f01ef5..78655168e857 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -639,9 +639,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// If this structure was expanded into multiple arguments then
// we need to create a temporary and reconstruct it from the
// arguments.
- std::string Name = Arg->getNameAsString();
llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty),
- (Name + ".addr").c_str());
+ Arg->getName() + ".addr");
// FIXME: What are the right qualifiers here?
llvm::Function::arg_iterator End =
ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
@@ -650,7 +649,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Name the arguments used in expansion and increment AI.
unsigned Index = 0;
for (; AI != End; ++AI, ++Index)
- AI->setName(Name + "." + llvm::Twine(Index));
+ AI->setName(Arg->getName() + "." + llvm::Twine(Index));
continue;
}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 4c624205b4ca..1b01e1537b42 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -173,10 +173,14 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
uint64_t Align = M->getContext().getTypeAlign(BT);
uint64_t Offset = 0;
- return DebugFactory.CreateBasicType(Unit,
- BT->getName(M->getContext().getLangOptions()),
- Unit, 0, Size, Align,
- Offset, /*flags*/ 0, Encoding);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateBasicType(Unit,
+ BT->getName(M->getContext().getLangOptions()),
+ Unit, 0, Size, Align,
+ Offset, /*flags*/ 0, Encoding);
+
+ TypeCache[QualType(BT, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
@@ -190,9 +194,12 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,
uint64_t Align = M->getContext().getTypeAlign(Ty);
uint64_t Offset = 0;
- return DebugFactory.CreateBasicType(Unit, "complex",
- Unit, 0, Size, Align,
- Offset, /*flags*/ 0, Encoding);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateBasicType(Unit, "complex",
+ Unit, 0, Size, Align,
+ Offset, /*flags*/ 0, Encoding);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
/// CreateCVRType - Get the qualified type from the cache or create
@@ -226,8 +233,11 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit U
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
- return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
- 0, 0, 0, 0, 0, FromTy);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
+ 0, 0, 0, 0, 0, FromTy);
+ TypeCache[Ty.getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
@@ -238,9 +248,12 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
uint64_t Size = M->getContext().getTypeSize(Ty);
uint64_t Align = M->getContext().getTypeAlign(Ty);
- return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
- "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0, EltTy);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
+ "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0, EltTy);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
@@ -251,9 +264,10 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
uint64_t Size = M->getContext().getTypeSize(Ty);
uint64_t Align = M->getContext().getTypeAlign(Ty);
- return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
- "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0, EltTy);
+ return
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
+ "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0, EltTy);
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
@@ -401,8 +415,11 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);
unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine();
- return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
- TyName, DefUnit, Line, 0, 0, 0, 0, Src);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
+ TyName, DefUnit, Line, 0, 0, 0, 0, Src);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
@@ -424,10 +441,13 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
llvm::DIArray EltTypeArray =
DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
- return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
- Unit, "", llvm::DICompileUnit(),
- 0, 0, 0, 0, 0,
- llvm::DIType(), EltTypeArray);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, 0, 0, 0, 0,
+ llvm::DIType(), EltTypeArray);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
/// CreateType - get structure or union type.
@@ -713,10 +733,14 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
Align = M->getContext().getTypeAlign(Ty);
}
- return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
- Unit, EnumName, DefUnit, Line,
- Size, Align, 0, 0,
- llvm::DIType(), EltArray);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
+ Unit, EnumName, DefUnit, Line,
+ Size, Align, 0, 0,
+ llvm::DIType(), EltArray);
+
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
@@ -767,11 +791,15 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
llvm::DIArray SubscriptArray =
DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size());
- return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
- Unit, "", llvm::DICompileUnit(),
- 0, Size, Align, 0, 0,
- getOrCreateType(EltTy, Unit),
- SubscriptArray);
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0,
+ getOrCreateType(EltTy, Unit),
+ SubscriptArray);
+
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode();
+ return DbgTy;
}
@@ -793,7 +821,6 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
// Otherwise create the type.
llvm::DIType Res = CreateTypeNode(Ty, Unit);
- TypeCache.insert(std::make_pair(Ty.getAsOpaquePtr(), Res.getNode()));
return Res;
}
@@ -846,8 +873,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
Unit);
case Type::ConstantArray:
- case Type::ConstantArrayWithExpr:
- case Type::ConstantArrayWithoutExpr:
case Type::VariableArray:
case Type::IncompleteArray:
return CreateType(cast<ArrayType>(Ty), Unit);
@@ -863,7 +888,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
/// EmitFunctionStart - Constructs the debug code for entering a function -
/// "llvm.dbg.func.start.".
-void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
+void CGDebugInfo::EmitFunctionStart(const char *Name, QualType FnType,
llvm::Function *Fn,
CGBuilderTy &Builder) {
const char *LinkageName = Name;
@@ -881,7 +906,7 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
llvm::DISubprogram SP =
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
- getOrCreateType(ReturnType, Unit),
+ getOrCreateType(FnType, Unit),
Fn->hasInternalLinkage(), true/*definition*/);
#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN
@@ -1366,7 +1391,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
}
DebugFactory.CreateGlobalVariable(getContext(Decl, Unit),
- Name, Name, "", Unit, LineNo,
+ Name, Name, Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(),
true/*definition*/, Var);
@@ -1396,7 +1421,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ArrayType::Normal, 0);
}
- DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
+ DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(),
true/*definition*/, Var);
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 0a617b999240..2e44e09d2590 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -88,7 +88,7 @@ public:
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
- void EmitFunctionStart(const char *Name, QualType ReturnType,
+ void EmitFunctionStart(const char *Name, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder);
/// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 7feff83dee6b..1728c67292b7 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -37,6 +37,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Enum: // enum X;
case Decl::EnumConstant: // enum ? { X = ? }
case Decl::CXXRecord: // struct/union/class X; [C++]
+ case Decl::UsingDirective: // using X; [C++]
// None of these decls require codegen support.
return;
@@ -275,8 +276,8 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {
unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
if (NumPaddingBytes > 0) {
const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext);
- // FIXME: We need a sema error for alignment larger than the minimum of the
- // maximal stack alignmint and the alignment of malloc on the system.
+ // FIXME: We need a sema error for alignment larger than the minimum of
+ // the maximal stack alignmint and the alignment of malloc on the system.
if (NumPaddingBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 01a057f67455..bb487f6e3fdf 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -28,9 +28,9 @@ using namespace CodeGen;
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty,
- const char *Name) {
+ const llvm::Twine &Name) {
if (!Builder.isNamePreserving())
- Name = "";
+ return new llvm::AllocaInst(Ty, 0, "", AllocaInsertPt);
return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);
}
@@ -78,24 +78,18 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E,
RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
QualType DestType,
bool IsInitializer) {
+ bool ShouldDestroyTemporaries = false;
+ unsigned OldNumLiveTemporaries = 0;
+
if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) {
- // If we shouldn't destroy the temporaries, just emit the
- // child expression.
- if (!TE->shouldDestroyTemporaries())
- return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
- IsInitializer);
-
- // Keep track of the current cleanup stack depth.
- unsigned OldNumLiveTemporaries = LiveTemporaries.size();
-
- RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType,
- IsInitializer);
-
- // Pop temporaries.
- while (LiveTemporaries.size() > OldNumLiveTemporaries)
- PopCXXTemporary();
+ ShouldDestroyTemporaries = TE->shouldDestroyTemporaries();
+
+ if (ShouldDestroyTemporaries) {
+ // Keep track of the current cleanup stack depth.
+ OldNumLiveTemporaries = LiveTemporaries.size();
+ }
- return RV;
+ E = TE->getSubExpr();
}
RValue Val;
@@ -105,6 +99,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
if (LV.isSimple())
return RValue::get(LV.getAddress());
Val = EmitLoadOfLValue(LV, E->getType());
+
+ if (ShouldDestroyTemporaries) {
+ // Pop temporaries.
+ while (LiveTemporaries.size() > OldNumLiveTemporaries)
+ PopCXXTemporary();
+ }
} else {
const CXXRecordDecl *BaseClassDecl = 0;
const CXXRecordDecl *DerivedClassDecl = 0;
@@ -124,6 +124,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,
IsInitializer);
+ if (ShouldDestroyTemporaries) {
+ // Pop temporaries.
+ while (LiveTemporaries.size() > OldNumLiveTemporaries)
+ PopCXXTemporary();
+ }
+
if (IsInitializer) {
// We might have to destroy the temporary variable.
if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
@@ -297,6 +303,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass:
return EmitCastLValue(cast<CastExpr>(E));
+ case Expr::CXXZeroInitValueExprClass:
+ return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E));
}
}
@@ -858,6 +866,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
llvm::Value *V = LocalDeclMap[IPD];
assert(V && "BlockVarDecl not entered in LocalDeclMap?");
return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ } else if (const QualifiedDeclRefExpr *QDRExpr =
+ dyn_cast<QualifiedDeclRefExpr>(E)) {
+ return EmitPointerToDataMemberLValue(QDRExpr);
}
assert(0 && "Unimp declref");
//an invalid LValue, but the assert will
@@ -1307,6 +1318,18 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
}
}
+LValue CodeGenFunction::EmitNullInitializationLValue(
+ const CXXZeroInitValueExpr *E) {
+ QualType Ty = E->getType();
+ const llvm::Type *LTy = ConvertTypeForMem(Ty);
+ llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
+ unsigned Align = getContext().getTypeAlign(Ty)/8;
+ Alloc->setAlignment(Align);
+ LValue lvalue = LValue::MakeAddr(Alloc, Qualifiers());
+ EmitMemSetToZero(lvalue.getAddress(), Ty);
+ return lvalue;
+}
+
//===--------------------------------------------------------------------===//
// Expression Emission
//===--------------------------------------------------------------------===//
@@ -1356,11 +1379,24 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
return EmitLValue(E->getRHS());
}
+ if (E->getOpcode() == BinaryOperator::PtrMemD)
+ return EmitPointerToDataMemberBinaryExpr(E);
+
// Can only get l-value for binary operator expressions which are a
// simple assignment of aggregate type.
if (E->getOpcode() != BinaryOperator::Assign)
return EmitUnsupportedLValue(E, "binary l-value expression");
+ if (!hasAggregateLLVMType(E->getType())) {
+ // Emit the LHS as an l-value.
+ LValue LV = EmitLValue(E->getLHS());
+
+ llvm::Value *RHS = EmitScalarExpr(E->getRHS());
+ EmitStoreOfScalar(RHS, LV.getAddress(), LV.isVolatileQualified(),
+ E->getType());
+ return LV;
+ }
+
llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));
EmitAggExpr(E, Temp, false);
// FIXME: Are these qualifiers correct?
@@ -1483,6 +1519,25 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
}
+LValue CodeGenFunction::EmitPointerToDataMemberLValue(
+ const QualifiedDeclRefExpr *E) {
+ const FieldDecl *Field = cast<FieldDecl>(E->getDecl());
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext());
+ QualType NNSpecTy =
+ getContext().getCanonicalType(
+ getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(ClassDecl)));
+ NNSpecTy = getContext().getPointerType(NNSpecTy);
+ llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy));
+ LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),
+ /*isUnion*/false, /*Qualifiers*/0);
+ const llvm::Type* ResultType = ConvertType(
+ getContext().getPointerDiffType());
+ V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType,
+ "datamember");
+ LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ return LV;
+}
+
RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd,
@@ -1492,11 +1547,13 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!");
- QualType FnType = CalleeType->getAs<PointerType>()->getPointeeType();
- QualType ResultType = FnType->getAs<FunctionType>()->getResultType();
+ CalleeType = getContext().getCanonicalType(CalleeType);
+
+ QualType FnType = cast<PointerType>(CalleeType)->getPointeeType();
+ QualType ResultType = cast<FunctionType>(FnType)->getResultType();
CallArgList Args;
- EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), ArgBeg, ArgEnd);
+ EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
// FIXME: We should not need to do this, it should be part of the function
// type.
@@ -1508,3 +1565,25 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,
CallingConvention),
Callee, Args, TargetDecl);
}
+
+LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr(
+ const BinaryOperator *E) {
+ llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress();
+ const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
+ BaseV = Builder.CreateBitCast(BaseV, i8Ty);
+ LValue RHSLV = EmitLValue(E->getRHS());
+ llvm::Value *OffsetV =
+ EmitLoadOfLValue(RHSLV, E->getRHS()->getType()).getScalarVal();
+ const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType());
+ OffsetV = Builder.CreateBitCast(OffsetV, ResultType);
+ llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
+ QualType Ty = E->getRHS()->getType();
+ const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>();
+ Ty = MemPtrType->getPointeeType();
+ const llvm::Type* PType =
+ ConvertType(getContext().getPointerType(Ty));
+ AddV = Builder.CreateBitCast(AddV, PType);
+ LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty));
+ return LV;
+}
+
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 0866ff893c4e..f47b6ab3c8cc 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -92,6 +92,7 @@ public:
void VisitCallExpr(const CallExpr *E);
void VisitStmtExpr(const StmtExpr *E);
void VisitBinaryOperator(const BinaryOperator *BO);
+ void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
void VisitBinAssign(const BinaryOperator *E);
void VisitBinComma(const BinaryOperator *E);
void VisitUnaryAddrOf(const UnaryOperator *E);
@@ -112,6 +113,7 @@ public:
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
void VisitCXXConstructExpr(const CXXConstructExpr *E);
void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E);
+ void VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
void VisitVAArgExpr(VAArgExpr *E);
@@ -214,6 +216,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break;
}
+ case CastExpr::CK_BitCast: {
+ // This must be a member function pointer cast.
+ Visit(E->getSubExpr());
+ break;
+ }
+
case CastExpr::CK_BaseToDerivedMemberPointer: {
QualType SrcType = E->getSubExpr()->getType();
@@ -285,6 +293,7 @@ void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
// We have a member function pointer.
const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ (void) MPT;
assert(MPT->getPointeeType()->isFunctionProtoType() &&
"Unexpected member pointer type!");
@@ -320,7 +329,16 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
}
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
- CGF.ErrorUnsupported(E, "aggregate binary expression");
+ if (E->getOpcode() == BinaryOperator::PtrMemD)
+ VisitPointerToDataMemberBinaryOperator(E);
+ else
+ CGF.ErrorUnsupported(E, "aggregate binary expression");
+}
+
+void AggExprEmitter::VisitPointerToDataMemberBinaryOperator(
+ const BinaryOperator *E) {
+ LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E);
+ EmitFinalDestCopy(E, LV);
}
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
@@ -438,6 +456,11 @@ void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer);
}
+void AggExprEmitter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) {
+ LValue lvalue = LValue::MakeAddr(DestPtr, Qualifiers());
+ EmitNullInitializationToLValue(lvalue, E->getType());
+}
+
void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {
// FIXME: Ignore result?
// FIXME: Are initializers affected by volatile?
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 7f540c3c0688..fc3748c8e3c8 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -542,7 +542,11 @@ public:
return CS;
}
}
-
+
+ case CastExpr::CK_BitCast:
+ // This must be a member function pointer cast.
+ return Visit(E->getSubExpr());
+
default: {
// FIXME: This should be handled by the CK_NoOp cast kind.
// Explicit and implicit no-op casts
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index cc81256032af..69604f9aaaee 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -106,6 +106,7 @@ public:
return 0;
}
Value *VisitExpr(Expr *S);
+
Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); }
// Leaves.
@@ -181,48 +182,7 @@ public:
Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); }
- Value *VisitInitListExpr(InitListExpr *E) {
- bool Ignore = TestAndClearIgnoreResultAssign();
- (void)Ignore;
- assert (Ignore == false && "init list ignored");
- unsigned NumInitElements = E->getNumInits();
-
- if (E->hadArrayRangeDesignator()) {
- CGF.ErrorUnsupported(E, "GNU array range designator extension");
- }
-
- const llvm::VectorType *VType =
- dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
-
- // We have a scalar in braces. Just use the first element.
- if (!VType)
- return Visit(E->getInit(0));
-
- unsigned NumVectorElements = VType->getNumElements();
- const llvm::Type *ElementType = VType->getElementType();
-
- // Emit individual vector element stores.
- llvm::Value *V = llvm::UndefValue::get(VType);
-
- // Emit initializers
- unsigned i;
- for (i = 0; i < NumInitElements; ++i) {
- Value *NewV = Visit(E->getInit(i));
- Value *Idx =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i);
- V = Builder.CreateInsertElement(V, NewV, Idx);
- }
-
- // Emit remaining default initializers
- for (/* Do not initialize i*/; i < NumVectorElements; ++i) {
- Value *Idx =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i);
- llvm::Value *NewV = llvm::Constant::getNullValue(ElementType);
- V = Builder.CreateInsertElement(V, NewV, Idx);
- }
-
- return V;
- }
+ Value *VisitInitListExpr(InitListExpr *E);
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return llvm::Constant::getNullValue(ConvertType(E->getType()));
@@ -404,7 +364,7 @@ public:
/// EmitConversionToBool - Convert the specified expression value to a
/// boolean (i1) truth value. This is equivalent to "Val != 0".
Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
- assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs");
+ assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
if (SrcType->isRealFloatingType()) {
// Compare against 0.0 for fp scalars.
@@ -577,6 +537,13 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
//===----------------------------------------------------------------------===//
Value *ScalarExprEmitter::VisitExpr(Expr *E) {
+ if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E))
+ if (BExpr->getOpcode() == BinaryOperator::PtrMemD) {
+ LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr);
+ Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal();
+ return InVal;
+ }
+
CGF.ErrorUnsupported(E, "scalar expression");
if (E->getType()->isVoidType())
return 0;
@@ -616,6 +583,174 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
return Builder.CreateExtractElement(Base, Idx, "vecext");
}
+static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
+ unsigned Off, const llvm::Type *I32Ty) {
+ int MV = SVI->getMaskValue(Idx);
+ if (MV == -1)
+ return llvm::UndefValue::get(I32Ty);
+ return llvm::ConstantInt::get(I32Ty, Off+MV);
+}
+
+Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
+ bool Ignore = TestAndClearIgnoreResultAssign();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
+ unsigned NumInitElements = E->getNumInits();
+
+ if (E->hadArrayRangeDesignator())
+ CGF.ErrorUnsupported(E, "GNU array range designator extension");
+
+ const llvm::VectorType *VType =
+ dyn_cast<llvm::VectorType>(ConvertType(E->getType()));
+
+ // We have a scalar in braces. Just use the first element.
+ if (!VType)
+ return Visit(E->getInit(0));
+
+ unsigned ResElts = VType->getNumElements();
+ const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CGF.getLLVMContext());
+
+ // Loop over initializers collecting the Value for each, and remembering
+ // whether the source was swizzle (ExtVectorElementExpr). This will allow
+ // us to fold the shuffle for the swizzle into the shuffle for the vector
+ // initializer, since LLVM optimizers generally do not want to touch
+ // shuffles.
+ unsigned CurIdx = 0;
+ bool VIsUndefShuffle = false;
+ llvm::Value *V = llvm::UndefValue::get(VType);
+ for (unsigned i = 0; i != NumInitElements; ++i) {
+ Expr *IE = E->getInit(i);
+ Value *Init = Visit(IE);
+ llvm::SmallVector<llvm::Constant*, 16> Args;
+
+ const llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType());
+
+ // Handle scalar elements. If the scalar initializer is actually one
+ // element of a different vector of the same width, use shuffle instead of
+ // extract+insert.
+ if (!VVT) {
+ if (isa<ExtVectorElementExpr>(IE)) {
+ llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init);
+
+ if (EI->getVectorOperandType()->getNumElements() == ResElts) {
+ llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand());
+ Value *LHS = 0, *RHS = 0;
+ if (CurIdx == 0) {
+ // insert into undef -> shuffle (src, undef)
+ Args.push_back(C);
+ for (unsigned j = 1; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+
+ LHS = EI->getVectorOperand();
+ RHS = V;
+ VIsUndefShuffle = true;
+ } else if (VIsUndefShuffle) {
+ // insert into undefshuffle && size match -> shuffle (v, src)
+ llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V);
+ for (unsigned j = 0; j != CurIdx; ++j)
+ Args.push_back(getMaskElt(SVV, j, 0, I32Ty));
+ Args.push_back(llvm::ConstantInt::get(I32Ty,
+ ResElts + C->getZExtValue()));
+ for (unsigned j = CurIdx + 1; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+
+ LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
+ RHS = EI->getVectorOperand();
+ VIsUndefShuffle = false;
+ }
+ if (!Args.empty()) {
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
+ V = Builder.CreateShuffleVector(LHS, RHS, Mask);
+ ++CurIdx;
+ continue;
+ }
+ }
+ }
+ Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx);
+ V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
+ VIsUndefShuffle = false;
+ ++CurIdx;
+ continue;
+ }
+
+ unsigned InitElts = VVT->getNumElements();
+
+ // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's
+ // input is the same width as the vector being constructed, generate an
+ // optimized shuffle of the swizzle input into the result.
+ if (isa<ExtVectorElementExpr>(IE)) {
+ llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init);
+ Value *SVOp = SVI->getOperand(0);
+ const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType());
+
+ if (OpTy->getNumElements() == ResElts) {
+ unsigned Offset = (CurIdx == 0) ? 0 : ResElts;
+
+ for (unsigned j = 0; j != CurIdx; ++j) {
+ // If the current vector initializer is a shuffle with undef, merge
+ // this shuffle directly into it.
+ if (VIsUndefShuffle) {
+ Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0,
+ I32Ty));
+ } else {
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j));
+ }
+ }
+ for (unsigned j = 0, je = InitElts; j != je; ++j)
+ Args.push_back(getMaskElt(SVI, j, Offset, I32Ty));
+ for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+
+ if (VIsUndefShuffle)
+ V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0);
+
+ Init = SVOp;
+ }
+ }
+
+ // Extend init to result vector length, and then shuffle its contribution
+ // to the vector initializer into V.
+ if (Args.empty()) {
+ for (unsigned j = 0; j != InitElts; ++j)
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j));
+ for (unsigned j = InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
+ Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT),
+ Mask, "vecext");
+
+ Args.clear();
+ for (unsigned j = 0; j != CurIdx; ++j)
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j));
+ for (unsigned j = 0; j != InitElts; ++j)
+ Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts));
+ for (unsigned j = CurIdx + InitElts; j != ResElts; ++j)
+ Args.push_back(llvm::UndefValue::get(I32Ty));
+ }
+
+ // If V is undef, make sure it ends up on the RHS of the shuffle to aid
+ // merging subsequent shuffles into this one.
+ if (CurIdx == 0)
+ std::swap(V, Init);
+ llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts);
+ V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit");
+ VIsUndefShuffle = isa<llvm::UndefValue>(Init);
+ CurIdx += InitElts;
+ }
+
+ // FIXME: evaluate codegen vs. shuffling against constant null vector.
+ // Emit remaining default initializers.
+ const llvm::Type *EltTy = VType->getElementType();
+
+ // Emit remaining default initializers
+ for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) {
+ Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx);
+ llvm::Value *Init = llvm::Constant::getNullValue(EltTy);
+ V = Builder.CreateInsertElement(V, Init, Idx, "vecinit");
+ }
+ return V;
+}
+
// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts
// have to handle a more broad range of conversions than explicit casts, as they
// handle things like function to ptr-to-function decay etc.
@@ -700,7 +835,16 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {
case CastExpr::CK_IntegralToPointer: {
Value *Src = Visit(const_cast<Expr*>(E));
- return Builder.CreateIntToPtr(Src, ConvertType(DestTy));
+
+ // First, convert to the correct width so that we control the kind of
+ // extension.
+ const llvm::Type *MiddleTy =
+ llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth);
+ bool InputSigned = E->getType()->isSignedIntegerType();
+ llvm::Value* IntResult =
+ Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
+
+ return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
}
case CastExpr::CK_PointerToIntegral: {
@@ -1379,18 +1523,20 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}
Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
+ const llvm::Type *ResTy = ConvertType(E->getType());
+
// If we have 0 && RHS, see if we can elide RHS, if so, just return 0.
// If we have 1 && X, just emit X without inserting the control flow.
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
if (Cond == 1) { // If we have 1 && X, just emit X.
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
- // ZExt result to int.
- return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext");
+ // ZExt result to int or bool.
+ return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");
}
- // 0 && RHS: If it is safe, just elide the RHS, and return 0.
+ // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
if (!CGF.ContainsLabel(E->getRHS()))
- return llvm::Constant::getNullValue(CGF.LLVMIntTy);
+ return llvm::Constant::getNullValue(ResTy);
}
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end");
@@ -1423,22 +1569,24 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
PN->addIncoming(RHSCond, RHSBlock);
// ZExt result to int.
- return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext");
+ return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");
}
Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
+ const llvm::Type *ResTy = ConvertType(E->getType());
+
// If we have 1 || RHS, see if we can elide RHS, if so, just return 1.
// If we have 0 || X, just emit X without inserting the control flow.
if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {
if (Cond == -1) { // If we have 0 || X, just emit X.
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
- // ZExt result to int.
- return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext");
+ // ZExt result to int or bool.
+ return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");
}
- // 1 || RHS: If it is safe, just elide the RHS, and return 1.
+ // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
if (!CGF.ContainsLabel(E->getRHS()))
- return llvm::ConstantInt::get(CGF.LLVMIntTy, 1);
+ return llvm::ConstantInt::get(ResTy, 1);
}
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end");
@@ -1474,7 +1622,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
PN->addIncoming(RHSCond, RHSBlock);
// ZExt result to int.
- return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext");
+ return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");
}
Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 4485ed5aee75..9b2f4a1faee7 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -850,7 +850,7 @@ protected:
/// \param[out] NameOut - The return value.
void GetNameForMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD,
- std::string &NameOut);
+ llvm::SmallVectorImpl<char> &NameOut);
/// GetMethodVarName - Return a unique constant for the given
/// selector's name. The return value has type char *.
@@ -900,7 +900,7 @@ protected:
/// EmitPropertyList - Emit the given property list. The return
/// value has type PropertyListPtrTy.
- llvm::Constant *EmitPropertyList(const std::string &Name,
+ llvm::Constant *EmitPropertyList(llvm::Twine Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes);
@@ -924,7 +924,7 @@ protected:
/// \param Align - The alignment for the variable, or 0.
/// \param AddToUsed - Whether the variable should be added to
/// "llvm.used".
- llvm::GlobalVariable *CreateMetadataVar(const std::string &Name,
+ llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
llvm::Constant *Init,
const char *Section,
unsigned Align,
@@ -1025,7 +1025,7 @@ private:
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListPtrTy.
- llvm::Constant *EmitMethodList(const std::string &Name,
+ llvm::Constant *EmitMethodList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods);
@@ -1040,7 +1040,7 @@ private:
/// - begin, end: The method list to output.
///
/// The return value has type MethodDescriptionListPtrTy.
- llvm::Constant *EmitMethodDescList(const std::string &Name,
+ llvm::Constant *EmitMethodDescList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods);
@@ -1066,7 +1066,7 @@ private:
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
- llvm::Constant *EmitProtocolList(const std::string &Name,
+ llvm::Constant *EmitProtocolList(llvm::Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end);
@@ -1197,7 +1197,7 @@ private:
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListnfABITy.
- llvm::Constant *EmitMethodList(const std::string &Name,
+ llvm::Constant *EmitMethodList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods);
/// EmitIvarList - Emit the ivar list for the given
@@ -1224,7 +1224,7 @@ private:
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
- llvm::Constant *EmitProtocolList(const std::string &Name,
+ llvm::Constant *EmitProtocolList(llvm::Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end);
@@ -1616,8 +1616,6 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
// resolved. Investigate. Its also wasteful to look this up over and over.
LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
- const char *ProtocolName = PD->getNameAsCString();
-
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
@@ -1647,17 +1645,15 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Values[1] = GetClassName(PD->getIdentifier());
Values[2] =
- EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
+ EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
PD->protocol_begin(),
PD->protocol_end());
Values[3] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
- + PD->getNameAsString(),
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
InstanceMethods);
Values[4] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
- + PD->getNameAsString(),
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
ClassMethods);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
@@ -1672,7 +1668,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
llvm::GlobalValue::InternalLinkage,
Init,
- std::string("\01L_OBJC_PROTOCOL_")+ProtocolName);
+ "\01L_OBJC_PROTOCOL_" + PD->getName());
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Entry->setAlignment(4);
// FIXME: Is this necessary? Why only for protocol?
@@ -1694,7 +1690,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
llvm::GlobalValue::ExternalLinkage,
0,
- "\01L_OBJC_PROTOCOL_" + PD->getNameAsString());
+ "\01L_OBJC_PROTOCOL_" + PD->getName());
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Entry->setAlignment(4);
// FIXME: Is this necessary? Why only for protocol?
@@ -1722,16 +1718,14 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Values[1] =
EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
OptInstanceMethods);
Values[2] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_"
- + PD->getNameAsString(),
+ EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
OptClassMethods);
- Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" +
- PD->getNameAsString(),
+ Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
0, PD, ObjCTypes);
// Return null if no extension bits are used.
@@ -1743,7 +1737,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
// No special section, but goes in llvm.used
- return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(),
+ return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Init,
0, 0, true);
}
@@ -1756,7 +1750,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
};
*/
llvm::Constant *
-CGObjCMac::EmitProtocolList(const std::string &Name,
+CGObjCMac::EmitProtocolList(llvm::Twine Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end) {
std::vector<llvm::Constant*> ProtocolRefs;
@@ -1800,7 +1794,7 @@ CGObjCMac::EmitProtocolList(const std::string &Name,
struct _objc_property[prop_count];
};
*/
-llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name,
+llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes) {
@@ -1854,7 +1848,7 @@ CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Desc);
}
-llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
+llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods) {
// Return null for empty list.
@@ -1894,8 +1888,10 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
const ObjCCategoryDecl *Category =
Interface->FindCategoryDeclaration(OCD->getIdentifier());
- std::string ExtName(Interface->getNameAsString() + "_" +
- OCD->getNameAsString());
+
+ llvm::SmallString<256> ExtName;
+ llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
+ << OCD->getName();
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
for (ObjCCategoryImplDecl::instmeth_iterator
@@ -1914,17 +1910,16 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Values[1] = GetClassName(Interface->getIdentifier());
LazySymbols.insert(Interface->getIdentifier());
Values[2] =
- EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
- ExtName,
+ EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
InstanceMethods);
Values[3] =
- EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
+ EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
ClassMethods);
if (Category) {
Values[4] =
- EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
+ EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Category->protocol_begin(),
Category->protocol_end());
} else {
@@ -1934,7 +1929,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
// If there is no category @interface then there can be no properties.
if (Category) {
- Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_")+ExtName,
+ Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
OCD, Category, ObjCTypes);
} else {
Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
@@ -1944,7 +1939,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Values);
llvm::GlobalVariable *GV =
- CreateMetadataVar(std::string("\01L_OBJC_CATEGORY_")+ExtName, Init,
+ CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
"__OBJC,__category,regular,no_dead_strip",
4, true);
DefinedCategories.push_back(GV);
@@ -1988,7 +1983,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
ObjCInterfaceDecl *Interface =
const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
llvm::Constant *Protocols =
- EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(),
+ EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Interface->protocol_begin(),
Interface->protocol_end());
unsigned Flags = eClassFlags_Factory;
@@ -2046,7 +2041,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Values[ 6] = EmitIvarList(ID, false);
Values[ 7] =
- EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(),
+ EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
"__OBJC,__inst_meth,regular,no_dead_strip",
InstanceMethods);
// cache is always NULL.
@@ -2058,7 +2053,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Values);
llvm::GlobalVariable *GV =
- CreateMetadataVar(std::string("\01L_OBJC_CLASS_")+ClassName, Init,
+ CreateMetadataVar("\01L_OBJC_CLASS_" + ClassName, Init,
"__OBJC,__class,regular,no_dead_strip",
4, true);
DefinedClasses.push_back(GV);
@@ -2174,7 +2169,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
std::vector<llvm::Constant*> Values(3);
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Values[1] = BuildIvarLayout(ID, false);
- Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
+ Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
ID, ID->getClassInterface(), ObjCTypes);
// Return null if no extension bits are used.
@@ -2183,7 +2178,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
llvm::Constant *Init =
llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
- return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getNameAsString(),
+ return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Init, "__OBJC,__class_ext,regular,no_dead_strip",
4, true);
}
@@ -2243,12 +2238,11 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
llvm::GlobalVariable *GV;
if (ForClass)
- GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getNameAsString(),
+ GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Init, "__OBJC,__class_vars,regular,no_dead_strip",
4, true);
else
- GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_"
- + ID->getNameAsString(),
+ GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Init, "__OBJC,__instance_vars,regular,no_dead_strip",
4, true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
@@ -2286,7 +2280,7 @@ llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
}
-llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
+llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
const char *Section,
const ConstantVector &Methods) {
// Return null for empty list.
@@ -2308,7 +2302,7 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) {
- std::string Name;
+ llvm::SmallString<256> Name;
GetNameForMethod(OMD, CD, Name);
CodeGenTypes &Types = CGM.getTypes();
@@ -2317,7 +2311,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
llvm::Function *Method =
llvm::Function::Create(MethodTy,
llvm::GlobalValue::InternalLinkage,
- Name,
+ Name.str(),
&CGM.getModule());
MethodDefinitions.insert(std::make_pair(OMD, Method));
@@ -2325,7 +2319,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
}
llvm::GlobalVariable *
-CGObjCCommonMac::CreateMetadataVar(const std::string &Name,
+CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
llvm::Constant *Init,
const char *Section,
unsigned Align,
@@ -2985,7 +2979,8 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
if (!Entry)
Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
- llvm::ConstantArray::get(VMContext, Ident->getName()),
+ llvm::ConstantArray::get(VMContext,
+ Ident->getNameStart()),
"__TEXT,__cstring,cstring_literals",
1, true);
@@ -3434,7 +3429,8 @@ llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
if (!Entry)
Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
- llvm::ConstantArray::get(VMContext, Ident->getName()),
+ llvm::ConstantArray::get(VMContext,
+ Ident->getNameStart()),
"__TEXT,__cstring,cstring_literals",
1, true);
@@ -3453,21 +3449,15 @@ CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
const ObjCContainerDecl *CD,
- std::string &NameOut) {
- NameOut = '\01';
- NameOut += (D->isInstanceMethod() ? '-' : '+');
- NameOut += '[';
+ llvm::SmallVectorImpl<char> &Name) {
+ llvm::raw_svector_ostream OS(Name);
assert (CD && "Missing container decl in GetNameForMethod");
- NameOut += CD->getNameAsString();
+ OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
+ << '[' << CD->getName();
if (const ObjCCategoryImplDecl *CID =
- dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) {
- NameOut += '(';
- NameOut += CID->getNameAsString();
- NameOut+= ')';
- }
- NameOut += ' ';
- NameOut += D->getSelector().getAsString();
- NameOut += ']';
+ dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
+ OS << '(' << CID->getNameAsString() << ')';
+ OS << ' ' << D->getSelector().getAsString() << ']';
}
void CGObjCMac::FinishModule() {
@@ -4256,7 +4246,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
const ObjCInterfaceDecl *OID = ID->getClassInterface();
assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
- + OID->getNameAsString(),
+ + OID->getName(),
OID->protocol_begin(),
OID->protocol_end());
@@ -4269,9 +4259,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
if (flags & CLS_META)
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
else
- Values[ 9] =
- EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
- ID, ID->getClassInterface(), ObjCTypes);
+ Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
+ ID, ID->getClassInterface(), ObjCTypes);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Values);
llvm::GlobalVariable *CLASS_RO_GV =
@@ -4532,16 +4521,16 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
const ObjCCategoryDecl *Category =
Interface->FindCategoryDeclaration(OCD->getIdentifier());
if (Category) {
- std::string ExtName(Interface->getNameAsString() + "_$_" +
- OCD->getNameAsString());
+ llvm::SmallString<256> ExtName;
+ llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
+ << OCD->getName();
Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
- + Interface->getNameAsString() + "_$_"
- + Category->getNameAsString(),
+ + Interface->getName() + "_$_"
+ + Category->getName(),
Category->protocol_begin(),
Category->protocol_end());
- Values[5] =
- EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName,
- OCD, Category, ObjCTypes);
+ Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes);
} else {
Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
@@ -4593,10 +4582,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
/// struct _objc_method method_list[method_count];
/// }
///
-llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(
- const std::string &Name,
- const char *Section,
- const ConstantVector &Methods) {
+llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
+ const char *Section,
+ const ConstantVector &Methods) {
// Return null for empty list.
if (Methods.empty())
return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
@@ -4742,7 +4730,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
llvm::GlobalValue::InternalLinkage,
Init,
- Prefix + OID->getNameAsString());
+ Prefix + OID->getName());
GV->setAlignment(
CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
GV->setSection("__DATA, __objc_const");
@@ -4763,7 +4751,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
llvm::GlobalValue::ExternalLinkage,
0,
- "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString());
+ "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Entry->setSection("__DATA,__datacoal_nt,coalesced");
}
@@ -4795,8 +4783,6 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
if (Entry && Entry->hasInitializer())
return Entry;
- const char *ProtocolName = PD->getNameAsCString();
-
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
@@ -4826,28 +4812,27 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
// isa is NULL
Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Values[1] = GetClassName(PD->getIdentifier());
- Values[2] = EmitProtocolList(
- "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(),
- PD->protocol_begin(),
- PD->protocol_end());
+ Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
+ PD->protocol_begin(),
+ PD->protocol_end());
Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
InstanceMethods);
Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
ClassMethods);
Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
OptInstanceMethods);
Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
- + PD->getNameAsString(),
+ + PD->getName(),
"__DATA, __objc_const",
OptClassMethods);
- Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(),
+ Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
0, PD, ObjCTypes);
uint32_t Size =
CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
@@ -4862,10 +4847,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Entry->setInitializer(Init);
} else {
Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName);
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
+ false, llvm::GlobalValue::WeakAnyLinkage, Init,
+ "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Entry->setAlignment(
CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
Entry->setSection("__DATA,__datacoal_nt,coalesced");
@@ -4875,13 +4859,10 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
// Use this protocol meta-data to build protocol list table in section
// __DATA, __objc_protolist
- llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
- CGM.getModule(),
- ObjCTypes.ProtocolnfABIPtrTy, false,
- llvm::GlobalValue::WeakAnyLinkage,
- Entry,
- std::string("\01l_OBJC_LABEL_PROTOCOL_$_")
- +ProtocolName);
+ llvm::GlobalVariable *PTGV =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
+ false, llvm::GlobalValue::WeakAnyLinkage, Entry,
+ "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
PTGV->setAlignment(
CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
@@ -4899,9 +4880,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
/// @endcode
///
llvm::Constant *
-CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
- ObjCProtocolDecl::protocol_iterator begin,
- ObjCProtocolDecl::protocol_iterator end) {
+CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
+ ObjCProtocolDecl::protocol_iterator begin,
+ ObjCProtocolDecl::protocol_iterator end) {
std::vector<llvm::Constant*> ProtocolRefs;
// Just return null for empty protocol lists
@@ -4909,10 +4890,12 @@ CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
// FIXME: We shouldn't need to do this lookup here, should we?
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
+ llvm::SmallString<256> TmpName;
+ Name.toVector(TmpName);
+ llvm::GlobalVariable *GV =
+ CGM.getModule().getGlobalVariable(TmpName.str(), true);
if (GV)
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.ProtocolListnfABIPtrTy);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
for (; begin != end; ++begin)
ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
@@ -5683,7 +5666,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::ExternalLinkage,
0,
- (std::string("OBJC_EHTYPE_$_") +
+ ("OBJC_EHTYPE_$_" +
ID->getIdentifier()->getName()));
}
@@ -5715,7 +5698,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::WeakAnyLinkage,
Init,
- (std::string("OBJC_EHTYPE_$_") +
+ ("OBJC_EHTYPE_$_" +
ID->getIdentifier()->getName()));
}
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 6e73db359af1..9df0e1abd547 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -119,6 +119,43 @@ public:
Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B);
+ Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B,
+ Index_t Offset = 0) {
+
+ if (B == D)
+ return Offset;
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D);
+ for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(),
+ e = D->bases_end(); i != e; ++i) {
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+ int64_t BaseOffset = 0;
+ if (!i->isVirtual())
+ BaseOffset = Offset + Layout.getBaseClassOffset(Base);
+ int64_t o = getNVOffset_1(Base, B, BaseOffset);
+ if (o >= 0)
+ return o;
+ }
+
+ return -1;
+ }
+
+ /// getNVOffset - Returns the non-virtual offset for the given (B) base of the
+ /// derived class D.
+ Index_t getNVOffset(QualType qB, QualType qD) {
+ qD = qD->getAs<PointerType>()->getPointeeType();
+ qB = qB->getAs<PointerType>()->getPointeeType();
+ CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
+ CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
+ int64_t o = getNVOffset_1(D, B);
+ if (o >= 0)
+ return o;
+
+ assert(false && "FIXME: non-virtual base not found");
+ return 0;
+ }
+
/// getVbaseOffset - Returns the index into the vtable for the virtual base
/// offset for the given (B) virtual base of the derived class D.
Index_t getVbaseOffset(QualType qB, QualType qD) {
@@ -138,8 +175,10 @@ public:
}
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
- bool MorallyVirtual, Index_t Offset) {
+ bool MorallyVirtual, Index_t OverrideOffset,
+ Index_t Offset) {
typedef CXXMethodDecl::method_iterator meth_iter;
+ // FIXME: Should OverrideOffset's be Offset?
// FIXME: Don't like the nested loops. For very large inheritance
// heirarchies we could have a table on the side with the final overridder
@@ -166,11 +205,12 @@ public:
CallOffset ReturnOffset = std::make_pair(0, 0);
if (oret != ret) {
// FIXME: calculate offsets for covariance
- Index_t nv = 0;
if (CovariantThunks.count(OMD)) {
oret = CovariantThunks[OMD].second;
CovariantThunks.erase(OMD);
}
+ // FIXME: Double check oret
+ Index_t nv = getNVOffset(oret, ret)/8;
ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
}
Index[MD] = i;
@@ -180,17 +220,16 @@ public:
if (MorallyVirtual) {
Index_t &idx = VCall[OMD];
if (idx == 0) {
- VCallOffset[MD] = Offset/8;
+ VCallOffset[MD] = OverrideOffset/8;
idx = VCalls.size()+1;
VCalls.push_back(0);
} else {
VCallOffset[MD] = VCallOffset[OMD];
- VCalls[idx-1] = -VCallOffset[OMD] + Offset/8;
+ VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;
}
VCall[MD] = idx;
CallOffset ThisOffset;
- // FIXME: calculate non-virtual offset
- ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */,
+ ThisOffset = std::make_pair(CurrentVBaseOffset/8 - Offset/8,
-((idx+extra+2)*LLVMPointerWidth/8));
// FIXME: Do we always have to build a covariant thunk to save oret,
// which is the containing virtual base class?
@@ -204,8 +243,8 @@ public:
}
// FIXME: finish off
- int64_t O = VCallOffset[OMD] - Offset/8;
- // int64_t O = CurrentVBaseOffset/8 - Offset/8;
+ int64_t O = VCallOffset[OMD] - OverrideOffset/8;
+ // int64_t O = CurrentVBaseOffset/8 - OverrideOffset/8;
if (O || ReturnOffset.first || ReturnOffset.second) {
CallOffset ThisOffset = std::make_pair(O, 0);
@@ -248,11 +287,11 @@ public:
CovariantThunks.clear();
}
- void OverrideMethods(Path_t *Path, bool MorallyVirtual) {
+ void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {
for (Path_t::reverse_iterator i = Path->rbegin(),
e = Path->rend(); i != e; ++i) {
const CXXRecordDecl *RD = i->first;
- int64_t Offset = i->second;
+ int64_t OverrideOffset = i->second;
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi) {
if (!mi->isVirtual())
@@ -272,7 +311,7 @@ public:
m = wrap(CGM.GetAddrOfFunction(MD, Ty));
}
- OverrideMethod(MD, m, MorallyVirtual, Offset);
+ OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);
}
}
}
@@ -291,7 +330,7 @@ public:
}
// If we can find a previously allocated slot for this, reuse it.
- if (OverrideMethod(MD, m, MorallyVirtual, Offset))
+ if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))
return;
// else allocate a new slot.
@@ -344,7 +383,7 @@ public:
llvm::Constant *e = 0;
D(VCalls.insert(VCalls.begin(), 673));
D(VCalls.push_back(672));
- methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e);
+ methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);
// The vcalls come first...
for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),
e = VCalls.rend();
@@ -380,7 +419,9 @@ public:
int VCallInsertionPoint = methods.size();
if (!DeferVCalls) {
insertVCalls(VCallInsertionPoint);
- }
+ } else
+ // FIXME: just for extra, or for all uses of VCalls.size post this?
+ extra = -VCalls.size();
if (ForVirtualBase) {
D(methods.push_back(wrap(668)));
@@ -463,7 +504,7 @@ public:
AddMethods(RD, MorallyVirtual, Offset);
if (Path)
- OverrideMethods(Path, MorallyVirtual);
+ OverrideMethods(Path, MorallyVirtual, Offset);
return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,
MorallyVirtual, Offset, ForVirtualBase, Path);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 5206f447f8d0..ba93e5d0ebc8 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -167,18 +167,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Builder.SetInsertPoint(EntryBB);
+ QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0);
+
// Emit subprogram debug descriptor.
// FIXME: The cast here is a huge hack.
if (CGDebugInfo *DI = getDebugInfo()) {
DI->setLocation(StartLoc);
if (isa<FunctionDecl>(D)) {
- DI->EmitFunctionStart(CGM.getMangledName(GD), RetTy, CurFn, Builder);
+ DI->EmitFunctionStart(CGM.getMangledName(GD), FnType, CurFn, Builder);
} else {
// Just use LLVM function name.
// FIXME: Remove unnecessary conversion to std::string when API settles.
DI->EmitFunctionStart(std::string(Fn->getName()).c_str(),
- RetTy, CurFn, Builder);
+ FnType, CurFn, Builder);
}
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 722d002c19f5..639e683f0369 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -34,6 +34,7 @@ namespace llvm {
class LLVMContext;
class Module;
class SwitchInst;
+ class Twine;
class Value;
}
@@ -355,6 +356,7 @@ public:
void BlockForwardSelf();
llvm::Value *LoadBlockStruct();
+ uint64_t AllocateBlockDecl(const BlockDeclRefExpr *E);
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
const llvm::Type *BuildByRefType(const ValueDecl *D);
@@ -508,7 +510,7 @@ public:
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty,
- const char *Name = "tmp");
+ const llvm::Twine &Name = "tmp");
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
/// expression and compare the result against zero, returning an Int1Ty value.
@@ -816,7 +818,9 @@ public:
LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);
LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);
LValue EmitCastLValue(const CastExpr *E);
-
+ LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E);
+ LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E);
+
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field,
@@ -841,7 +845,8 @@ public:
LValue EmitObjCKVCRefLValue(const ObjCImplicitSetterGetterRefExpr *E);
LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E);
LValue EmitStmtExprLValue(const StmtExpr *E);
-
+ LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
+
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 4763b7fc1ee2..ea84829b78a5 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -825,7 +825,7 @@ llvm::Constant *
CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
const char *Name) {
// Convert Name to be a uniqued string from the IdentifierInfo table.
- Name = getContext().Idents.get(Name).getName();
+ Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());
}
@@ -911,7 +911,7 @@ llvm::Constant *
CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,
const char *Name) {
// Convert Name to be a uniqued string from the IdentifierInfo table.
- Name = getContext().Idents.get(Name).getName();
+ Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0);
}
@@ -1254,7 +1254,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
// Unique the name through the identifier table.
const char *AliaseeName = AA->getAliasee().c_str();
- AliaseeName = getContext().Idents.get(AliaseeName).getName();
+ AliaseeName = getContext().Idents.get(AliaseeName).getNameStart();
// Create a reference to the named value. This ensures that it is emitted
// if a deferred decl.
@@ -1341,7 +1341,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
cast<llvm::FunctionType>(getTypes().ConvertType(Type));
// Unique the name through the identifier table.
- Name = getContext().Idents.get(Name).getName();
+ Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD));
}
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index fd772748dbda..2e6034bbcd97 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -248,7 +248,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
FD = PrimaryTemplate->getTemplatedDecl();
}
- mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), MangleReturnType);
+ // Do the canonicalization out here because parameter types can
+ // undergo additional canonicalization (e.g. array decay).
+ FunctionType *FT = cast<FunctionType>(Context.getASTContext()
+ .getCanonicalType(FD->getType()));
+
+ mangleBareFunctionType(FT, MangleReturnType);
}
static bool isStdNamespace(const DeclContext *DC) {
@@ -705,7 +710,7 @@ void CXXNameMangler::mangleType(QualType T) {
// Only operate on the canonical type!
T = Context.getASTContext().getCanonicalType(T);
- bool IsSubstitutable = !isa<BuiltinType>(T);
+ bool IsSubstitutable = T.hasQualifiers() || !isa<BuiltinType>(T);
if (IsSubstitutable && mangleSubstitution(T))
return;
@@ -1236,10 +1241,7 @@ static bool isCharSpecialization(QualType T, const char *Name) {
if (!isCharType(TemplateArgs[0].getAsType()))
return false;
- if (strcmp(SD->getIdentifier()->getName(), Name) != 0)
- return false;
-
- return true;
+ return SD->getIdentifier()->getName() == Name;
}
bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp
index 59f579f7b17e..852bba4ef033 100644
--- a/lib/CodeGen/TargetABIInfo.cpp
+++ b/lib/CodeGen/TargetABIInfo.cpp
@@ -353,11 +353,17 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
return ABIArgInfo::getDirect();
} else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- // Structures with flexible arrays are always indirect.
- if (const RecordType *RT = RetTy->getAsStructureType())
+ if (const RecordType *RT = RetTy->getAsStructureType()) {
+ // Structures with either a non-trivial destructor or a non-trivial
+ // copy constructor are always indirect.
+ if (hasNonTrivialDestructorOrCopyConstructor(RT))
+ return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+ // Structures with flexible arrays are always indirect.
if (RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0);
-
+ }
+
// If specified, structs and unions are always indirect.
if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
return ABIArgInfo::getIndirect(0);
@@ -1744,14 +1750,14 @@ const ABIInfo &CodeGenTypes::getABIInfo() const {
return *(TheABIInfo = new SystemZABIInfo());
case llvm::Triple::x86:
- if (Triple.getOS() == llvm::Triple::Darwin)
- return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
-
switch (Triple.getOS()) {
+ case llvm::Triple::Darwin:
+ return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
case llvm::Triple::Cygwin:
- case llvm::Triple::DragonFly:
case llvm::Triple::MinGW32:
case llvm::Triple::MinGW64:
+ case llvm::Triple::AuroraUX:
+ case llvm::Triple::DragonFly:
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
return *(TheABIInfo = new X86_32ABIInfo(Context, false, true));
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index a5a48adcf028..ae8119d33d64 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -38,7 +38,8 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
DarwinVersion[2] = _DarwinVersion[2];
llvm::raw_string_ostream(MacosxVersionMin)
- << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1];
+ << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.'
+ << DarwinVersion[1];
// FIXME: Lift default up.
IPhoneOSVersionMin = "3.0";
@@ -54,7 +55,6 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
GCCVersion[2] = _GCCVersion[2];
// Set up the tool chain paths to match gcc.
-
ToolChainDir = "i686-apple-darwin";
ToolChainDir += llvm::utostr(DarwinVersion[0]);
ToolChainDir += "/";
@@ -64,6 +64,26 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
ToolChainDir += '.';
ToolChainDir += llvm::utostr(GCCVersion[2]);
+ // Try the next major version if that tool chain dir is invalid.
+ std::string Tmp = "/usr/lib/gcc/" + ToolChainDir;
+ if (!llvm::sys::Path(Tmp).exists()) {
+ std::string Next = "i686-apple-darwin";
+ Next += llvm::utostr(DarwinVersion[0] + 1);
+ Next += "/";
+ Next += llvm::utostr(GCCVersion[0]);
+ Next += '.';
+ Next += llvm::utostr(GCCVersion[1]);
+ Next += '.';
+ Next += llvm::utostr(GCCVersion[2]);
+
+ // Use that if it exists, otherwise hope the user isn't linking.
+ //
+ // FIXME: Drop dependency on gcc's tool chain.
+ Tmp = "/usr/lib/gcc/" + Next;
+ if (llvm::sys::Path(Tmp).exists())
+ ToolChainDir = Next;
+ }
+
std::string Path;
if (getArchName() == "x86_64") {
Path = getHost().getDriver().Dir;
@@ -676,6 +696,7 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
getFilePaths().push_back("/usr/lib");
getFilePaths().push_back("/usr/sfw/lib");
getFilePaths().push_back("/opt/gcc4/lib");
+ getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");
}
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index fc91e4c43799..c9d0b266d1cc 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -142,10 +142,15 @@ void Clang::AddPreprocessingOptions(const Driver &D,
continue;
if (A->getOption().matches(options::OPT_include)) {
+ // Use PCH if the user requested it, except for C++ (for now).
+ bool UsePCH = D.CCCUsePCH;
+ if (types::isCXX(Inputs[0].getType()))
+ UsePCH = false;
+
bool FoundPTH = false;
bool FoundPCH = false;
llvm::sys::Path P(A->getValue(Args));
- if (D.CCCUsePCH) {
+ if (UsePCH) {
P.appendSuffix("pch");
if (P.exists())
FoundPCH = true;
@@ -164,8 +169,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
if (!FoundPCH && !FoundPTH) {
P.appendSuffix("gch");
if (P.exists()) {
- FoundPCH = D.CCCUsePCH;
- FoundPTH = !D.CCCUsePCH;
+ FoundPCH = UsePCH;
+ FoundPTH = !UsePCH;
}
else
P.eraseSuffix();
@@ -173,7 +178,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
if (FoundPCH || FoundPTH) {
A->claim();
- if (D.CCCUsePCH)
+ if (UsePCH)
CmdArgs.push_back("-include-pch");
else
CmdArgs.push_back("-include-pth");
@@ -528,7 +533,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-E");
} else if (isa<PrecompileJobAction>(JA)) {
- if (D.CCCUsePCH)
+ // Use PCH if the user requested it, except for C++ (for now).
+ bool UsePCH = D.CCCUsePCH;
+ if (types::isCXX(Inputs[0].getType()))
+ UsePCH = false;
+
+ if (UsePCH)
CmdArgs.push_back("-emit-pch");
else
CmdArgs.push_back("-emit-pth");
@@ -759,7 +769,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// option.
if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
if (Std->getOption().matches(options::OPT_ansi))
- CmdArgs.push_back("-std=c89");
+ if (types::isCXX(InputType))
+ CmdArgs.push_back("-std=c++98");
+ else
+ CmdArgs.push_back("-std=c89");
else
Std->render(Args, CmdArgs);
@@ -2149,7 +2162,7 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "gas"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -2164,18 +2177,19 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
if ((!Args.hasArg(options::OPT_nostdlib)) &&
(!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
- CmdArgs.push_back("__start");
+ CmdArgs.push_back("_start");
}
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
+ CmdArgs.push_back("-dn");
} else {
- CmdArgs.push_back("--eh-frame-hdr");
+// CmdArgs.push_back("--eh-frame-hdr");
CmdArgs.push_back("-Bdynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
} else {
- CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("--dynamic-linker");
CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
}
}
@@ -2193,11 +2207,14 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+// CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
}
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
}
CmdArgs.push_back(MakeFormattedString(Args,
@@ -2242,8 +2259,8 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
- else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+// else
+// CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
}
const char *Exec =
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index d3475b5236d9..c0415bf550f8 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -21,11 +21,20 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/System/Path.h"
using namespace clang;
-ASTUnit::ASTUnit(Diagnostic &_Diags) : Diags(_Diags) { }
-ASTUnit::~ASTUnit() { }
+ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) {
+ Diags.setClient(diagClient ? diagClient : new TextDiagnosticBuffer());
+}
+ASTUnit::~ASTUnit() {
+ if (tempFile)
+ llvm::sys::Path(getPCHFileName()).eraseFromDisk();
+
+ // The ASTUnit object owns the DiagnosticClient.
+ delete Diags.getClient();
+}
namespace {
@@ -80,17 +89,18 @@ const std::string &ASTUnit::getOriginalSourceFileName() {
return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile();
}
-FileManager &ASTUnit::getFileManager() {
- return HeaderInfo->getFileMgr();
+const std::string &ASTUnit::getPCHFileName() {
+ return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName();
}
ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
- Diagnostic &Diags,
- FileManager &FileMgr,
- std::string *ErrMsg) {
- llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags));
-
- AST->HeaderInfo.reset(new HeaderSearch(FileMgr));
+ std::string *ErrMsg,
+ DiagnosticClient *diagClient,
+ bool OnlyLocalDecls,
+ bool UseBumpAllocator) {
+ llvm::OwningPtr<ASTUnit> AST(new ASTUnit(diagClient));
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
// Gather Info for preprocessor construction later on.
@@ -103,7 +113,8 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
llvm::OwningPtr<PCHReader> Reader;
llvm::OwningPtr<ExternalASTSource> Source;
- Reader.reset(new PCHReader(AST->getSourceManager(), FileMgr, AST->Diags));
+ Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
+ AST->Diags));
Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
Predefines, Counter));
@@ -138,7 +149,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
PP.getIdentifierTable(),
PP.getSelectorTable(),
PP.getBuiltinInfo(),
- /* FreeMemory = */ true,
+ /* FreeMemory = */ !UseBumpAllocator,
/* size_reserve = */0));
ASTContext &Context = *AST->Ctx.get();
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 276599470b78..55f274005909 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -196,7 +196,7 @@ void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
case Decl::Function: {
FunctionDecl* FD = cast<FunctionDecl>(D);
- if (Opts.AnalyzeSpecificFunction.size() > 0 &&
+ if (!Opts.AnalyzeSpecificFunction.empty() &&
Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
break;
@@ -273,6 +273,9 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
!Ctx->getSourceManager().isFromMainFile(D->getLocation()))
return;
+ // Clear the AnalysisManager of old AnalysisContexts.
+ Mgr->ClearContexts();
+
// Dispatch on the actions.
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
(*I)(*Mgr, D);
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index e7fc5660ad20..339a1c466bc9 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -20,11 +20,12 @@
#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
-#include "llvm/ADT/StringMap.h"
// FIXME: put this somewhere else?
#ifndef S_ISDIR
@@ -69,7 +70,7 @@ public:
bool isFile() const { return Kind == IsFE; }
- const char* getCString() const {
+ llvm::StringRef getString() const {
return Kind == IsFE ? FE->getName() : Path;
}
@@ -113,14 +114,14 @@ public:
typedef const PTHEntry& data_type_ref;
static unsigned ComputeHash(PTHEntryKeyVariant V) {
- return BernsteinHash(V.getCString());
+ return llvm::HashString(V.getString());
}
static std::pair<unsigned,unsigned>
EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
const PTHEntry& E) {
- unsigned n = strlen(V.getCString()) + 1 + 1;
+ unsigned n = V.getString().size() + 1 + 1;
::Emit16(Out, n);
unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0);
@@ -133,7 +134,7 @@ public:
// Emit the entry kind.
::Emit8(Out, (unsigned) V.getKind());
// Emit the string.
- Out.write(V.getCString(), n - 1);
+ Out.write(V.getString().data(), n - 1);
}
static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V,
@@ -516,7 +517,7 @@ public:
~StatListener() {}
int stat(const char *path, struct stat *buf) {
- int result = ::stat(path, buf);
+ int result = StatSysCallCache::stat(path, buf);
if (result != 0) // Failed 'stat'.
PM.insert(path, PTHEntry());
@@ -553,7 +554,8 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
PTHWriter PW(*OS, PP);
// Install the 'stat' system call listener in the FileManager.
- PP.getFileManager().setStatCache(new StatListener(PW.getPM()));
+ StatListener *StatCache = new StatListener(PW.getPM());
+ PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true);
// Lex through the entire file. This will populate SourceManager with
// all of the header information.
@@ -562,7 +564,7 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
// Generate the PTH file.
- PP.getFileManager().setStatCache(0);
+ PP.getFileManager().removeStatCache(StatCache);
PW.GeneratePTH(&MainFileName);
}
@@ -584,12 +586,12 @@ public:
typedef data_type data_type_ref;
static unsigned ComputeHash(PTHIdKey* key) {
- return BernsteinHash(key->II->getName());
+ return llvm::HashString(key->II->getName());
}
static std::pair<unsigned,unsigned>
EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) {
- unsigned n = strlen(key->II->getName()) + 1;
+ unsigned n = key->II->getLength() + 1;
::Emit16(Out, n);
return std::make_pair(n, sizeof(uint32_t));
}
@@ -598,7 +600,7 @@ public:
// Record the location of the key data. This is used when generating
// the mapping from persistent IDs to strings.
key->FileOffset = Out.tell();
- Out.write(key->II->getName(), n);
+ Out.write(key->II->getNameStart(), n);
}
static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID,
diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp
index bc45cc422585..0e4f83ff09f5 100644
--- a/lib/Frontend/GeneratePCH.cpp
+++ b/lib/Frontend/GeneratePCH.cpp
@@ -53,7 +53,7 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP,
// Install a stat() listener to keep track of all of the stat()
// calls.
StatCalls = new MemorizeStatCalls;
- PP.getFileManager().setStatCache(StatCalls);
+ PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true);
}
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 822a5baf5972..25316bed9fb4 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -369,6 +369,12 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-gnu",
triple);
+ // Gentoo x86 2009.1 stable
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+ "i686-pc-linux-gnu",
+ "i686-pc-linux-gnu",
+ triple);
// Gentoo x86 2009.0 stable
AddGnuCPlusPlusIncludePaths(
"/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
@@ -386,6 +392,11 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
"i486-pc-linux-gnu",
"i486-pc-linux-gnu",
triple);
+ // Ubuntu 9.04
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
+ "i486-linux-gnu",
+ "i486-linux-gnu",
+ triple);
// Gentoo amd64 stable
AddGnuCPlusPlusIncludePaths(
"/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
@@ -400,6 +411,8 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
AddPath("/usr/include/c++/4.2", System, true, false, false);
break;
case llvm::Triple::Solaris:
+ // Solaris - Fall though..
+ case llvm::Triple::AuroraUX:
// AuroraUX
AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
"i386-pc-solaris2.11",
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 0f3b4b8236be..b1a0a5ee8d51 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -317,13 +317,22 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineBuiltinMacro(Buf, "_GNU_SOURCE=1");
}
- // Filter out some microsoft extensions when trying to parse in ms-compat
- // mode.
if (LangOpts.Microsoft) {
+ // Filter out some microsoft extensions when trying to parse in ms-compat
+ // mode.
DefineBuiltinMacro(Buf, "__int8=__INT8_TYPE__");
DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__");
DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__");
DefineBuiltinMacro(Buf, "__int64=__INT64_TYPE__");
+ // Work around some issues with Visual C++ headerws.
+ if (LangOpts.CPlusPlus) {
+ // Since we define wchar_t in C++ mode.
+ DefineBuiltinMacro(Buf, "_WCHAR_T_DEFINED=1");
+ DefineBuiltinMacro(Buf, "_NATIVE_WCHAR_T_DEFINED=1");
+ // FIXME: This should be temporary until we have a __pragma
+ // solution, to avoid some errors flagged in VC++ headers.
+ DefineBuiltinMacro(Buf, "_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES=0");
+ }
}
if (LangOpts.Optimize)
@@ -365,8 +374,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Buf);
DefineType("__SIZE_TYPE__", TI.getSizeType(), Buf);
DefineType("__WCHAR_TYPE__", TI.getWCharType(), Buf);
- // FIXME: TargetInfo hookize __WINT_TYPE__.
- DefineBuiltinMacro(Buf, "__WINT_TYPE__=int");
+ DefineType("__WINT_TYPE__", TI.getWIntType(), Buf);
DefineFloatMacros(Buf, "FLT", &TI.getFloatFormat());
DefineFloatMacros(Buf, "DBL", &TI.getDoubleFormat());
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index e61668dd3177..9c6059b1c7c0 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
@@ -27,6 +28,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -335,8 +337,6 @@ void PCHValidator::ReadCounter(unsigned Value) {
PP.setCounterValue(Value);
}
-
-
//===----------------------------------------------------------------------===//
// PCH reader implementation
//===----------------------------------------------------------------------===//
@@ -345,7 +345,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
const char *isysroot)
: Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
- SemaObj(0), PP(&PP), Context(Context), Consumer(0),
+ SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),
IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@@ -362,7 +362,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
Diagnostic &Diags, const char *isysroot)
: SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
- SemaObj(0), PP(0), Context(0), Consumer(0),
+ SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@@ -383,7 +383,7 @@ Expr *PCHReader::ReadDeclExpr() {
}
Expr *PCHReader::ReadTypeExpr() {
- return dyn_cast_or_null<Expr>(ReadStmt(Stream));
+ return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
}
@@ -411,7 +411,7 @@ public:
unsigned R = 5381;
for (unsigned I = 0; I != N; ++I)
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
- R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
+ R = llvm::HashString(II->getName(), R);
return R;
}
@@ -521,7 +521,7 @@ public:
}
static unsigned ComputeHash(const internal_key_type& a) {
- return BernsteinHash(a.first, a.second);
+ return llvm::HashString(llvm::StringRef(a.first, a.second));
}
// This hopefully will just get inlined and removed by the optimizer.
@@ -731,7 +731,7 @@ class VISIBILITY_HIDDEN PCHStatLookupTrait {
typedef PCHStatData data_type;
static unsigned ComputeHash(const char *path) {
- return BernsteinHash(path);
+ return llvm::HashString(path);
}
static internal_key_type GetInternalKey(const char *path) { return path; }
@@ -794,7 +794,7 @@ public:
// If we don't get a hit in the PCH file just forward to 'stat'.
if (I == Cache->end()) {
++NumStatMisses;
- return ::stat(path, buf);
+ return StatSysCallCache::stat(path, buf);
}
++NumStatHits;
@@ -1158,15 +1158,7 @@ PCHReader::ReadPCHBlock() {
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
switch (Stream.ReadSubBlockID()) {
- case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
- default: // Skip unknown content.
- if (Stream.SkipBlock()) {
- Error("malformed block record in PCH file");
- return Failure;
- }
- break;
-
- case pch::DECLS_BLOCK_ID:
+ case pch::DECLTYPES_BLOCK_ID:
// We lazily load the decls block, but we want to set up the
// DeclsCursor cursor to point into it. Clone our current bitcode
// cursor to it, enter the block and read the abbrevs in that block.
@@ -1174,7 +1166,7 @@ PCHReader::ReadPCHBlock() {
DeclsCursor = Stream;
if (Stream.SkipBlock() || // Skip with the main cursor.
// Read the abbrevs.
- ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
+ ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
Error("malformed block record in PCH file");
return Failure;
}
@@ -1352,13 +1344,16 @@ PCHReader::ReadPCHBlock() {
}
break;
- case pch::STAT_CACHE:
- FileMgr.setStatCache(
- new PCHStatCache((const unsigned char *)BlobStart + Record[0],
- (const unsigned char *)BlobStart,
- NumStatHits, NumStatMisses));
+ case pch::STAT_CACHE: {
+ PCHStatCache *MyStatCache =
+ new PCHStatCache((const unsigned char *)BlobStart + Record[0],
+ (const unsigned char *)BlobStart,
+ NumStatHits, NumStatMisses);
+ FileMgr.addStatCache(MyStatCache);
+ StatCache = MyStatCache;
break;
-
+ }
+
case pch::EXT_VECTOR_DECLS:
if (!ExtVectorDecls.empty()) {
Error("duplicate EXT_VECTOR_DECLS record in PCH file");
@@ -1466,7 +1461,8 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache.
- FileMgr.setStatCache(0);
+ if (StatCache)
+ FileMgr.removeStatCache((PCHStatCache*)StatCache);
return IgnorePCH;
}
@@ -1509,7 +1505,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
IdentifierInfo *II = Identifiers[I];
// Look in the on-disk hash table for an entry for
PCHIdentifierLookupTrait Info(*this, II);
- std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
+ std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
if (Pos == IdTable->end())
continue;
@@ -1593,6 +1589,11 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
if (unsigned ObjCClassRedef
= SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
+ if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
+ Context->setBlockDescriptorType(GetType(String));
+ if (unsigned String
+ = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
+ Context->setBlockDescriptorExtendedType(GetType(String));
}
/// \brief Retrieve the name of the original source file name
@@ -1770,15 +1771,15 @@ void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
// Keep track of where we are in the stream, then jump back there
// after reading this type.
- SavedStreamPosition SavedPosition(Stream);
+ SavedStreamPosition SavedPosition(DeclsCursor);
// Note that we are loading a type record.
LoadingTypeOrDecl Loading(*this);
- Stream.JumpToBit(Offset);
+ DeclsCursor.JumpToBit(Offset);
RecordData Record;
- unsigned Code = Stream.ReadCode();
- switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
+ unsigned Code = DeclsCursor.ReadCode();
+ switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
case pch::TYPE_EXT_QUAL: {
assert(Record.size() == 2 &&
"Incorrect encoding of extended qualifier type");
@@ -1839,30 +1840,6 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
ASM, IndexTypeQuals);
}
- case pch::TYPE_CONSTANT_ARRAY_WITH_EXPR: {
- QualType ElementType = GetType(Record[0]);
- ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
- unsigned IndexTypeQuals = Record[2];
- SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
- SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
- unsigned Idx = 5;
- llvm::APInt Size = ReadAPInt(Record, Idx);
- return Context->getConstantArrayWithExprType(ElementType,
- Size, ReadTypeExpr(),
- ASM, IndexTypeQuals,
- SourceRange(LBLoc, RBLoc));
- }
-
- case pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR: {
- QualType ElementType = GetType(Record[0]);
- ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
- unsigned IndexTypeQuals = Record[2];
- unsigned Idx = 3;
- llvm::APInt Size = ReadAPInt(Record, Idx);
- return Context->getConstantArrayWithoutExprType(ElementType, Size,
- ASM, IndexTypeQuals);
- }
-
case pch::TYPE_INCOMPLETE_ARRAY: {
QualType ElementType = GetType(Record[0]);
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
@@ -1987,20 +1964,184 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
}
- case pch::TYPE_OBJC_PROTOCOL_LIST: {
+ case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
unsigned Idx = 0;
- QualType OIT = GetType(Record[Idx++]);
- unsigned NumProtos = Record[Idx++];
- llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
- for (unsigned I = 0; I != NumProtos; ++I)
- Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
- return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos);
+ QualType Parm = GetType(Record[Idx++]);
+ QualType Replacement = GetType(Record[Idx++]);
+ return
+ Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
+ Replacement);
}
}
// Suppress a GCC warning
return QualType();
}
+namespace {
+
+class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
+ PCHReader &Reader;
+ const PCHReader::RecordData &Record;
+ unsigned &Idx;
+
+public:
+ TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
+ unsigned &Idx)
+ : Reader(Reader), Record(Record), Idx(Idx) { }
+
+ // We want compile-time assurance that we've enumerated all of
+ // these, so unfortunately we have to declare them first, then
+ // define them out-of-line.
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+ void VisitFunctionTypeLoc(FunctionTypeLoc);
+ void VisitArrayTypeLoc(ArrayTypeLoc);
+};
+
+}
+
+void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ // nothing to do
+}
+void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ if (Record[Idx++])
+ TL.setSizeExpr(Reader.ReadDeclExpr());
+ else
+ TL.setSizeExpr(0);
+}
+void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedArrayTypeLoc(
+ DependentSizedArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
+ DependentSizedExtVectorTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+ TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
+ }
+}
+void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ TL.setHasBaseTypeAsWritten(Record[Idx++]);
+ TL.setHasProtocolsAsWritten(Record[Idx++]);
+ if (TL.hasProtocolsAsWritten())
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
+DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
+ unsigned &Idx) {
+ QualType InfoTy = GetType(Record[Idx++]);
+ if (InfoTy.isNull())
+ return 0;
+
+ DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy);
+ TypeLocReader TLR(*this, Record, Idx);
+ for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ TLR.Visit(TL);
+ return DInfo;
+}
QualType PCHReader::GetType(pch::TypeID ID) {
unsigned FastQuals = ID & Qualifiers::FastMask;
@@ -2374,7 +2515,10 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
// All of the strings in the PCH file are preceded by a 16-bit
// length. Extract that 16-bit length to avoid having to execute
// strlen().
- const char *StrLenPtr = Str - 2;
+ // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
+ // unsigned integers. This is important to avoid integer overflow when
+ // we cast them to 'unsigned'.
+ const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
unsigned StrLen = (((unsigned) StrLenPtr[0])
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
IdentifiersLoaded[ID - 1]
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index b6732561dff0..d1cb461640b7 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/TypeLocVisitor.h"
using namespace clang;
@@ -86,6 +85,7 @@ void PCHDeclReader::VisitDecl(Decl *D) {
D->setImplicit(Record[Idx++]);
D->setUsed(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]);
+ D->setPCHLevel(Record[Idx++] + 1);
}
void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
@@ -149,84 +149,11 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
}
-namespace {
-
-class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
- PCHReader &Reader;
- const PCHReader::RecordData &Record;
- unsigned &Idx;
-
-public:
- TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
- unsigned &Idx)
- : Reader(Reader), Record(Record), Idx(Idx) { }
-
-#define ABSTRACT_TYPELOC(CLASS)
-#define TYPELOC(CLASS, PARENT) \
- void Visit##CLASS(CLASS TyLoc);
-#include "clang/AST/TypeLocNodes.def"
-
- void VisitTypeLoc(TypeLoc TyLoc) {
- assert(0 && "A type loc wrapper was not handled!");
- }
-};
-
-}
-
-void TypeLocReader::VisitQualifiedLoc(QualifiedLoc TyLoc) {
- // nothing to do
-}
-void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
- TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitTypedefLoc(TypedefLoc TyLoc) {
- TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) {
- TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) {
- TyLoc.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- TyLoc.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i)
- TyLoc.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitPointerLoc(PointerLoc TyLoc) {
- TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitBlockPointerLoc(BlockPointerLoc TyLoc) {
- TyLoc.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitMemberPointerLoc(MemberPointerLoc TyLoc) {
- TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitReferenceLoc(ReferenceLoc TyLoc) {
- TyLoc.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-}
-void TypeLocReader::VisitFunctionLoc(FunctionLoc TyLoc) {
- TyLoc.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- TyLoc.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i)
- TyLoc.setArg(i, cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
-}
-void TypeLocReader::VisitArrayLoc(ArrayLoc TyLoc) {
- TyLoc.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- TyLoc.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- if (Record[Idx++])
- TyLoc.setSizeExpr(Reader.ReadDeclExpr());
-}
-
void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
VisitValueDecl(DD);
- QualType InfoTy = Reader.GetType(Record[Idx++]);
- if (InfoTy.isNull())
- return;
-
- DeclaratorInfo *DInfo = Reader.getContext()->CreateDeclaratorInfo(InfoTy);
- TypeLocReader TLR(Reader, Record, Idx);
- for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
- TLR.Visit(TL);
- DD->setDeclaratorInfo(DInfo);
+ DeclaratorInfo *DInfo = Reader.GetDeclaratorInfo(Record, Idx);
+ if (DInfo)
+ DD->setDeclaratorInfo(DInfo);
}
void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 64a678ea450b..fb48df332121 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/HeaderSearch.h"
@@ -30,6 +31,7 @@
#include "clang/Basic/Version.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -117,23 +119,6 @@ void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
Code = pch::TYPE_CONSTANT_ARRAY;
}
-void PCHTypeWriter
-::VisitConstantArrayWithExprType(const ConstantArrayWithExprType *T) {
- VisitArrayType(T);
- Writer.AddSourceLocation(T->getLBracketLoc(), Record);
- Writer.AddSourceLocation(T->getRBracketLoc(), Record);
- Writer.AddAPInt(T->getSize(), Record);
- Writer.AddStmt(T->getSizeExpr());
- Code = pch::TYPE_CONSTANT_ARRAY_WITH_EXPR;
-}
-
-void PCHTypeWriter
-::VisitConstantArrayWithoutExprType(const ConstantArrayWithoutExprType *T) {
- VisitArrayType(T);
- Writer.AddAPInt(T->getSize(), Record);
- Code = pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR;
-}
-
void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
VisitArrayType(T);
Code = pch::TYPE_INCOMPLETE_ARRAY;
@@ -225,6 +210,14 @@ void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
}
void
+PCHTypeWriter::VisitSubstTemplateTypeParmType(
+ const SubstTemplateTypeParmType *T) {
+ Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
+ Writer.AddTypeRef(T->getReplacementType(), Record);
+ Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
+}
+
+void
PCHTypeWriter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
// FIXME: Serialize this type (C++ only)
@@ -255,13 +248,150 @@ PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
Code = pch::TYPE_OBJC_OBJECT_POINTER;
}
-void PCHTypeWriter::VisitObjCProtocolListType(const ObjCProtocolListType *T) {
- Writer.AddTypeRef(T->getBaseType(), Record);
- Record.push_back(T->getNumProtocols());
- for (ObjCProtocolListType::qual_iterator I = T->qual_begin(),
- E = T->qual_end(); I != E; ++I)
- Writer.AddDeclRef(*I, Record);
- Code = pch::TYPE_OBJC_PROTOCOL_LIST;
+namespace {
+
+class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
+ PCHWriter &Writer;
+ PCHWriter::RecordData &Record;
+
+public:
+ TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+ : Writer(Writer), Record(Record) { }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
+#include "clang/AST/TypeLocNodes.def"
+
+ void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
+ void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
+};
+
+}
+
+void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ // nothing to do
+}
+void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getCaretLoc(), Record);
+}
+void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getAmpLoc(), Record);
+}
+void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record);
+}
+void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getStarLoc(), Record);
+}
+void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getLBracketLoc(), Record);
+ Writer.AddSourceLocation(TL.getRBracketLoc(), Record);
+ Record.push_back(TL.getSizeExpr() ? 1 : 0);
+ if (TL.getSizeExpr())
+ Writer.AddStmt(TL.getSizeExpr());
+}
+void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
+ DependentSizedArrayTypeLoc TL) {
+ VisitArrayTypeLoc(TL);
+}
+void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
+ DependentSizedExtVectorTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getLParenLoc(), Record);
+ Writer.AddSourceLocation(TL.getRParenLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+ Writer.AddDeclRef(TL.getArg(i), Record);
+}
+void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
+ VisitFunctionTypeLoc(TL);
+}
+void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
+ SubstTemplateTypeParmTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
+void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
+}
+void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getStarLoc(), Record);
+ Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ Record.push_back(TL.hasBaseTypeAsWritten());
+ Record.push_back(TL.hasProtocolsAsWritten());
+ if (TL.hasProtocolsAsWritten())
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
}
//===----------------------------------------------------------------------===//
@@ -411,8 +541,8 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(PP_MACRO_FUNCTION_LIKE);
RECORD(PP_TOKEN);
- // Types block.
- BLOCK(TYPES_BLOCK);
+ // Decls and Types block.
+ BLOCK(DECLTYPES_BLOCK);
RECORD(TYPE_EXT_QUAL);
RECORD(TYPE_FIXED_WIDTH_INT);
RECORD(TYPE_COMPLEX);
@@ -435,12 +565,6 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(TYPE_ENUM);
RECORD(TYPE_OBJC_INTERFACE);
RECORD(TYPE_OBJC_OBJECT_POINTER);
- RECORD(TYPE_OBJC_PROTOCOL_LIST);
- // Statements and Exprs can occur in the Types block.
- AddStmtsExprs(Stream, Record);
-
- // Decls block.
- BLOCK(DECLS_BLOCK);
RECORD(DECL_ATTR);
RECORD(DECL_TRANSLATION_UNIT);
RECORD(DECL_TYPEDEF);
@@ -470,7 +594,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(DECL_BLOCK);
RECORD(DECL_CONTEXT_LEXICAL);
RECORD(DECL_CONTEXT_VISIBLE);
- // Statements and Exprs can occur in the Decls block.
+ // Statements and Exprs can occur in the Decls and Types block.
AddStmtsExprs(Stream, Record);
#undef RECORD
#undef BLOCK
@@ -662,7 +786,7 @@ public:
typedef const data_type& data_type_ref;
static unsigned ComputeHash(const char *path) {
- return BernsteinHash(path);
+ return llvm::HashString(path);
}
std::pair<unsigned,unsigned>
@@ -878,10 +1002,10 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
std::vector<uint32_t> SLocEntryOffsets;
RecordData PreloadSLocs;
SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1);
- for (SourceManager::sloc_entry_iterator
- SLoc = SourceMgr.sloc_entry_begin() + 1,
- SLocEnd = SourceMgr.sloc_entry_end();
- SLoc != SLocEnd; ++SLoc) {
+ for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) {
+ // Get this source location entry.
+ const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
+
// Record the offset of this source-location entry.
SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
@@ -956,9 +1080,8 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// Compute the token length for this macro expansion.
unsigned NextOffset = SourceMgr.getNextOffset();
- SourceManager::sloc_entry_iterator NextSLoc = SLoc;
- if (++NextSLoc != SLocEnd)
- NextOffset = NextSLoc->getOffset();
+ if (I + 1 != N)
+ NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
Record.push_back(NextOffset - SLoc->getOffset() - 1);
Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);
}
@@ -1019,6 +1142,7 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
// Loop over all the macro definitions that are live at the end of the file,
// emitting each to the PP section.
+ // FIXME: Make sure that this sees macros defined in included PCH files.
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
I != E; ++I) {
// FIXME: This emits macros in hash table order, we should do it in a stable
@@ -1152,22 +1276,6 @@ void PCHWriter::WriteType(QualType T) {
FlushStmts();
}
-/// \brief Write a block containing all of the types.
-void PCHWriter::WriteTypesBlock(ASTContext &Context) {
- // Enter the types block.
- Stream.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
-
- // Emit all of the types that need to be emitted (so far).
- while (!TypesToEmit.empty()) {
- QualType T = TypesToEmit.front();
- TypesToEmit.pop();
- WriteType(T);
- }
-
- // Exit the types block
- Stream.ExitBlock();
-}
-
//===----------------------------------------------------------------------===//
// Declaration Serialization
//===----------------------------------------------------------------------===//
@@ -1266,7 +1374,7 @@ public:
unsigned R = 5381;
for (unsigned I = 0; I != N; ++I)
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
- R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
+ R = llvm::HashString(II->getName(), R);
return R;
}
@@ -1475,13 +1583,13 @@ public:
: Writer(Writer), PP(PP) { }
static unsigned ComputeHash(const IdentifierInfo* II) {
- return clang::BernsteinHash(II->getName());
+ return llvm::HashString(II->getName());
}
std::pair<unsigned,unsigned>
EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
pch::IdentID ID) {
- unsigned KeyLen = strlen(II->getName()) + 1;
+ unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
if (isInterestingIdentifier(II)) {
DataLen += 2; // 2 bytes for builtin ID, flags
@@ -1506,7 +1614,7 @@ public:
// Record the location of the key data. This is used when generating
// the mapping from persistent IDs to strings.
Writer.SetIdentifierOffset(II, Out.tell());
- Out.write(II->getName(), KeyLen);
+ Out.write(II->getNameStart(), KeyLen);
}
void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
@@ -1810,7 +1918,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
// The translation unit is the first declaration we'll emit.
DeclIDs[Context.getTranslationUnitDecl()] = 1;
- DeclsToEmit.push(Context.getTranslationUnitDecl());
+ DeclTypesToEmit.push(Context.getTranslationUnitDecl());
// Make sure that we emit IdentifierInfos (and any attached
// declarations) for builtins.
@@ -1858,7 +1966,6 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
if (StatCalls && !isysroot)
WriteStatCache(*StatCalls, isysroot);
WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
- WritePreprocessor(PP);
WriteComments(Context);
// Write the record of special types.
Record.clear();
@@ -1875,17 +1982,25 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
AddTypeRef(Context.getsigjmp_bufType(), Record);
AddTypeRef(Context.ObjCIdRedefinitionType, Record);
AddTypeRef(Context.ObjCClassRedefinitionType, Record);
+ AddTypeRef(Context.getRawBlockdescriptorType(), Record);
+ AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);
Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
// Keep writing types and declarations until all types and
// declarations have been written.
- do {
- if (!DeclsToEmit.empty())
- WriteDeclsBlock(Context);
- if (!TypesToEmit.empty())
- WriteTypesBlock(Context);
- } while (!(DeclsToEmit.empty() && TypesToEmit.empty()));
-
+ Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
+ WriteDeclsBlockAbbrevs();
+ while (!DeclTypesToEmit.empty()) {
+ DeclOrType DOT = DeclTypesToEmit.front();
+ DeclTypesToEmit.pop();
+ if (DOT.isType())
+ WriteType(DOT.getType());
+ else
+ WriteDecl(Context, DOT.getDecl());
+ }
+ Stream.ExitBlock();
+
+ WritePreprocessor(PP);
WriteMethodPool(SemaRef);
WriteIdentifierTable(PP);
@@ -1991,6 +2106,18 @@ void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
Record.push_back(SID);
}
+void PCHWriter::AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record) {
+ if (DInfo == 0) {
+ AddTypeRef(QualType(), Record);
+ return;
+ }
+
+ AddTypeRef(DInfo->getType(), Record);
+ TypeLocWriter TLW(*this, Record);
+ for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ TLW.Visit(TL);
+}
+
void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
if (T.isNull()) {
Record.push_back(pch::PREDEF_TYPE_NULL_ID);
@@ -2007,7 +2134,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
// Assign it a new ID. This is the only time we enqueue a
// qualified type, and it has no CV qualifiers.
ID = NextTypeID++;
- TypesToEmit.push(T);
+ DeclTypesToEmit.push(T);
}
// Encode the type qualifiers in the type reference.
@@ -2061,7 +2188,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
// We haven't seen this type before. Assign it a new ID and put it
// into the queue of types to emit.
ID = NextTypeID++;
- TypesToEmit.push(T);
+ DeclTypesToEmit.push(T);
}
// Encode the type qualifiers in the type reference.
@@ -2079,7 +2206,7 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
// We haven't seen this declaration before. Give it a new ID and
// enqueue it in the list of declarations to emit.
ID = DeclIDs.size();
- DeclsToEmit.push(const_cast<Decl *>(D));
+ DeclTypesToEmit.push(const_cast<Decl *>(D));
}
Record.push_back(ID);
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index ef7c5ec4b1a6..fbd9929e49d7 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -14,7 +14,6 @@
#include "clang/Frontend/PCHWriter.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/TypeLocVisitor.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include <cstdio>
@@ -88,6 +87,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->isImplicit());
Record.push_back(D->isUsed());
Record.push_back(D->getAccess());
+ Record.push_back(D->getPCHLevel());
}
void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
@@ -149,84 +149,10 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
Writer.AddAPSInt(D->getInitVal(), Record);
Code = pch::DECL_ENUM_CONSTANT;
}
-namespace {
-
-class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
- PCHWriter &Writer;
- PCHWriter::RecordData &Record;
-
-public:
- TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
- : Writer(Writer), Record(Record) { }
-
-#define ABSTRACT_TYPELOC(CLASS)
-#define TYPELOC(CLASS, PARENT) \
- void Visit##CLASS(CLASS TyLoc);
-#include "clang/AST/TypeLocNodes.def"
-
- void VisitTypeLoc(TypeLoc TyLoc) {
- assert(0 && "A type loc wrapper was not handled!");
- }
-};
-
-}
-
-void TypeLocWriter::VisitQualifiedLoc(QualifiedLoc TyLoc) {
- // nothing to do here
-}
-void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getStartLoc(), Record);
-}
-void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getNameLoc(), Record);
-}
-void TypeLocWriter::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getLAngleLoc(), Record);
- Writer.AddSourceLocation(TyLoc.getRAngleLoc(), Record);
- for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i)
- Writer.AddSourceLocation(TyLoc.getProtocolLoc(i), Record);
-}
-void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
-}
-void TypeLocWriter::VisitBlockPointerLoc(BlockPointerLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getCaretLoc(), Record);
-}
-void TypeLocWriter::VisitMemberPointerLoc(MemberPointerLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getStarLoc(), Record);
-}
-void TypeLocWriter::VisitReferenceLoc(ReferenceLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getAmpLoc(), Record);
-}
-void TypeLocWriter::VisitFunctionLoc(FunctionLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getLParenLoc(), Record);
- Writer.AddSourceLocation(TyLoc.getRParenLoc(), Record);
- for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i)
- Writer.AddDeclRef(TyLoc.getArg(i), Record);
-}
-void TypeLocWriter::VisitArrayLoc(ArrayLoc TyLoc) {
- Writer.AddSourceLocation(TyLoc.getLBracketLoc(), Record);
- Writer.AddSourceLocation(TyLoc.getRBracketLoc(), Record);
- Record.push_back(TyLoc.getSizeExpr() ? 1 : 0);
- if (TyLoc.getSizeExpr())
- Writer.AddStmt(TyLoc.getSizeExpr());
-}
void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
VisitValueDecl(D);
- DeclaratorInfo *DInfo = D->getDeclaratorInfo();
- if (DInfo == 0) {
- Writer.AddTypeRef(QualType(), Record);
- return;
- }
-
- Writer.AddTypeRef(DInfo->getTypeLoc().getSourceType(), Record);
- TypeLocWriter TLW(Writer, Record);
- for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
- TLW.Visit(TL);
+ Writer.AddDeclaratorInfo(D->getDeclaratorInfo(), Record);
}
void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
@@ -448,6 +374,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
!D->isImplicit() &&
!D->isUsed() &&
D->getAccess() == AS_none &&
+ D->getPCHLevel() == 0 &&
D->getStorageClass() == 0 &&
!D->hasCXXDirectInitializer() && // Can params have this ever?
D->getObjCDeclQualifier() == 0)
@@ -523,6 +450,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
Abv->Add(BitCodeAbbrevOp(0)); // isUsed
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
+ Abv->Add(BitCodeAbbrevOp(0)); // PCH level
// NamedDecl
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
@@ -607,80 +535,64 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
}
}
-/// \brief Write a block containing all of the declarations.
-void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
- // Enter the declarations block.
- Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 3);
-
- // Output the abbreviations that we will use in this block.
- WriteDeclsBlockAbbrevs();
-
- // Emit all of the declarations.
+void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
RecordData Record;
PCHDeclWriter W(*this, Context, Record);
- while (!DeclsToEmit.empty()) {
- // Pull the next declaration off the queue
- Decl *D = DeclsToEmit.front();
- DeclsToEmit.pop();
-
- // If this declaration is also a DeclContext, write blocks for the
- // declarations that lexically stored inside its context and those
- // declarations that are visible from its context. These blocks
- // are written before the declaration itself so that we can put
- // their offsets into the record for the declaration.
- uint64_t LexicalOffset = 0;
- uint64_t VisibleOffset = 0;
- DeclContext *DC = dyn_cast<DeclContext>(D);
- if (DC) {
- LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
- VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
- }
- // Determine the ID for this declaration
- pch::DeclID &ID = DeclIDs[D];
- if (ID == 0)
- ID = DeclIDs.size();
+ // If this declaration is also a DeclContext, write blocks for the
+ // declarations that lexically stored inside its context and those
+ // declarations that are visible from its context. These blocks
+ // are written before the declaration itself so that we can put
+ // their offsets into the record for the declaration.
+ uint64_t LexicalOffset = 0;
+ uint64_t VisibleOffset = 0;
+ DeclContext *DC = dyn_cast<DeclContext>(D);
+ if (DC) {
+ LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
+ VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
+ }
- unsigned Index = ID - 1;
+ // Determine the ID for this declaration
+ pch::DeclID &ID = DeclIDs[D];
+ if (ID == 0)
+ ID = DeclIDs.size();
- // Record the offset for this declaration
- if (DeclOffsets.size() == Index)
- DeclOffsets.push_back(Stream.GetCurrentBitNo());
- else if (DeclOffsets.size() < Index) {
- DeclOffsets.resize(Index+1);
- DeclOffsets[Index] = Stream.GetCurrentBitNo();
- }
+ unsigned Index = ID - 1;
- // Build and emit a record for this declaration
- Record.clear();
- W.Code = (pch::DeclCode)0;
- W.AbbrevToUse = 0;
- W.Visit(D);
- if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
-
- if (!W.Code) {
- fprintf(stderr, "Cannot serialize declaration of kind %s\n",
- D->getDeclKindName());
- assert(false && "Unhandled declaration kind while generating PCH");
- exit(-1);
- }
- Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
+ // Record the offset for this declaration
+ if (DeclOffsets.size() == Index)
+ DeclOffsets.push_back(Stream.GetCurrentBitNo());
+ else if (DeclOffsets.size() < Index) {
+ DeclOffsets.resize(Index+1);
+ DeclOffsets[Index] = Stream.GetCurrentBitNo();
+ }
- // If the declaration had any attributes, write them now.
- if (D->hasAttrs())
- WriteAttributeRecord(D->getAttrs());
+ // Build and emit a record for this declaration
+ Record.clear();
+ W.Code = (pch::DeclCode)0;
+ W.AbbrevToUse = 0;
+ W.Visit(D);
+ if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+
+ if (!W.Code) {
+ fprintf(stderr, "Cannot serialize declaration of kind %s\n",
+ D->getDeclKindName());
+ assert(false && "Unhandled declaration kind while generating PCH");
+ exit(-1);
+ }
+ Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
- // Flush any expressions that were written as part of this declaration.
- FlushStmts();
+ // If the declaration had any attributes, write them now.
+ if (D->hasAttrs())
+ WriteAttributeRecord(D->getAttrs());
- // Note "external" declarations so that we can add them to a record in the
- // PCH file later.
- //
- // FIXME: This should be renamed, the predicate is much more complicated.
- if (isRequiredDecl(D, Context))
- ExternalDefinitions.push_back(ID);
- }
+ // Flush any expressions that were written as part of this declaration.
+ FlushStmts();
- // Exit the declarations block
- Stream.ExitBlock();
+ // Note "external" declarations so that we can add them to a record in the
+ // PCH file later.
+ //
+ // FIXME: This should be renamed, the predicate is much more complicated.
+ if (isRequiredDecl(D, Context))
+ ExternalDefinitions.push_back(Index + 1);
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 492b31a0ec39..f3cb20619ed5 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -399,7 +399,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
}
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
- OS.write(II->getName(), II->getLength());
+ OS << II->getName();
} else if (Tok.isLiteral() && !Tok.needsCleaning() &&
Tok.getLiteralData()) {
OS.write(Tok.getLiteralData(), Tok.getLength());
@@ -434,7 +434,7 @@ namespace {
struct SortMacrosByID {
typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
bool operator()(const id_macro_pair &LHS, const id_macro_pair &RHS) const {
- return strcmp(LHS.first->getName(), RHS.first->getName()) < 0;
+ return LHS.first->getName() < RHS.first->getName();
}
};
}
diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp
index d92f5c78e690..b5d59c0aa401 100644
--- a/lib/Frontend/RewriteMacros.cpp
+++ b/lib/Frontend/RewriteMacros.cpp
@@ -128,13 +128,13 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) {
// comment the line out.
if (RawTokens[CurRawTok].is(tok::identifier)) {
const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo();
- if (!strcmp(II->getName(), "warning")) {
+ if (II->getName() == "warning") {
// Comment out #warning.
RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
- } else if (!strcmp(II->getName(), "pragma") &&
+ } else if (II->getName() == "pragma" &&
RawTokens[CurRawTok+1].is(tok::identifier) &&
- !strcmp(RawTokens[CurRawTok+1].getIdentifierInfo()->getName(),
- "mark")){
+ (RawTokens[CurRawTok+1].getIdentifierInfo()->getName() ==
+ "mark")) {
// Comment out #pragma mark.
RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");
}
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 55ab78e638bb..0ea0a58d5239 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -675,7 +675,7 @@ static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
S = "((struct ";
S += ClassDecl->getIdentifier()->getName();
S += "_IMPL *)self)->";
- S += OID->getNameAsCString();
+ S += OID->getName();
return S;
}
@@ -2265,7 +2265,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
if (clsName) { // class message.
// FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle
// the 'super' idiom within a class method.
- if (!strcmp(clsName->getName(), "super")) {
+ if (clsName->getName() == "super") {
MsgSendFlavor = MsgSendSuperFunctionDecl;
if (MsgSendStretFlavor)
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
@@ -2289,9 +2289,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
- SuperDecl->getIdentifier()->getName(),
- SuperDecl->getIdentifier()->getLength(),
- false, argType, SourceLocation()));
+ SuperDecl->getIdentifier()->getNameStart(),
+ SuperDecl->getIdentifier()->getLength(),
+ false, argType, SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
&ClsExprs[0],
ClsExprs.size());
@@ -2343,7 +2343,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
- clsName->getName(),
+ clsName->getNameStart(),
clsName->getLength(),
false, argType,
SourceLocation()));
@@ -2375,9 +2375,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
- SuperDecl->getIdentifier()->getName(),
- SuperDecl->getIdentifier()->getLength(),
- false, argType, SourceLocation()));
+ SuperDecl->getIdentifier()->getNameStart(),
+ SuperDecl->getIdentifier()->getLength(),
+ false, argType, SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
&ClsExprs[0],
ClsExprs.size());
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 63d9a50b368b..14769c187393 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -214,6 +214,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine,
// Move the end of the interesting region right until we've
// pulled in something else interesting.
if (CaretEnd != SourceLength) {
+ assert(CaretEnd < SourceLength && "Unexpected caret position!");
unsigned NewEnd = CaretEnd;
// Skip over any whitespace we see here; we're looking for
@@ -320,6 +321,11 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
++LineEnd;
+ // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
+ // the source line length as currently being computed. See
+ // test/Misc/message-length.c.
+ CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
+
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(LineStart, LineEnd);
diff --git a/lib/Index/ASTLocation.cpp b/lib/Index/ASTLocation.cpp
index 6294d699a88c..c24f3bf5b3c1 100644
--- a/lib/Index/ASTLocation.cpp
+++ b/lib/Index/ASTLocation.cpp
@@ -101,7 +101,7 @@ void ASTLocation::print(llvm::raw_ostream &OS) const {
break;
case N_Type: {
- QualType T = AsTypeLoc().getSourceType();
+ QualType T = AsTypeLoc().getType();
OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();
}
}
diff --git a/lib/Index/ASTVisitor.h b/lib/Index/ASTVisitor.h
index e18aa57b4d1a..0ae78fb74ff4 100644
--- a/lib/Index/ASTVisitor.h
+++ b/lib/Index/ASTVisitor.h
@@ -123,14 +123,14 @@ public:
BaseTypeLocVisitor::Visit(TL);
}
- void VisitArrayLoc(ArrayLoc TL) {
- BaseTypeLocVisitor::VisitArrayLoc(TL);
+ void VisitArrayLoc(ArrayTypeLoc TL) {
+ BaseTypeLocVisitor::VisitArrayTypeLoc(TL);
if (TL.getSizeExpr())
Visit(TL.getSizeExpr());
}
- void VisitFunctionLoc(FunctionLoc TL) {
- BaseTypeLocVisitor::VisitFunctionLoc(TL);
+ void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);
for (unsigned i = 0; i != TL.getNumArgs(); ++i)
Visit(TL.getArg(i));
}
diff --git a/lib/Index/DeclReferenceMap.cpp b/lib/Index/DeclReferenceMap.cpp
index 0e48a369d5d9..366cf1b10830 100644
--- a/lib/Index/DeclReferenceMap.cpp
+++ b/lib/Index/DeclReferenceMap.cpp
@@ -31,8 +31,8 @@ public:
void VisitMemberExpr(MemberExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
- void VisitTypedefLoc(TypedefLoc TL);
- void VisitObjCInterfaceLoc(ObjCInterfaceLoc TL);
+ void VisitTypedefTypeLoc(TypedefTypeLoc TL);
+ void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
};
} // anonymous namespace
@@ -55,12 +55,12 @@ void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node)));
}
-void RefMapper::VisitTypedefLoc(TypedefLoc TL) {
+void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
NamedDecl *ND = TL.getTypedefDecl();
Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
}
-void RefMapper::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) {
+void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
NamedDecl *ND = TL.getIFaceDecl();
Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
}
diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp
index 77d7a84da4db..03fe9f73af40 100644
--- a/lib/Index/Entity.cpp
+++ b/lib/Index/Entity.cpp
@@ -72,7 +72,8 @@ Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
IdentifierInfo *GlobII =
- &ProgImpl.getIdents().get(II->getName(), II->getName() + II->getLength());
+ &ProgImpl.getIdents().get(II->getNameStart(),
+ II->getNameStart() + II->getLength());
GlobName = DeclarationName(GlobII);
} else {
Selector LocalSel = LocalName.getObjCSelector();
@@ -139,8 +140,9 @@ Decl *EntityImpl::getDecl(ASTContext &AST) {
DeclarationName LocalName;
if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
- IdentifierInfo &II = AST.Idents.get(GlobII->getName(),
- GlobII->getName() + GlobII->getLength());
+ IdentifierInfo &II =
+ AST.Idents.get(GlobII->getNameStart(),
+ GlobII->getNameStart() + GlobII->getLength());
LocalName = DeclarationName(&II);
} else {
Selector GlobSel = Name.getObjCSelector();
diff --git a/lib/Index/GlobalSelector.cpp b/lib/Index/GlobalSelector.cpp
index f3ec41d44ffe..2b2ca6d3b1cc 100644
--- a/lib/Index/GlobalSelector.cpp
+++ b/lib/Index/GlobalSelector.cpp
@@ -29,8 +29,9 @@ Selector GlobalSelector::getSelector(ASTContext &AST) const {
for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();
i != e; ++i) {
IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i);
- IdentifierInfo *II = &AST.Idents.get(GlobII->getName(),
- GlobII->getName() + GlobII->getLength());
+ IdentifierInfo *II =
+ &AST.Idents.get(GlobII->getNameStart(),
+ GlobII->getNameStart() + GlobII->getLength());
Ids.push_back(II);
}
@@ -57,8 +58,9 @@ GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {
for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();
i != e; ++i) {
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i);
- IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName(),
- II->getName() + II->getLength());
+ IdentifierInfo *GlobII =
+ &ProgImpl.getIdents().get(II->getNameStart(),
+ II->getNameStart() + II->getLength());
Ids.push_back(GlobII);
}
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
index 229669dc330b..8edd634f8af4 100644
--- a/lib/Index/ResolveLocation.cpp
+++ b/lib/Index/ResolveLocation.cpp
@@ -120,11 +120,12 @@ public:
TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
: LocResolverBase(ctx, loc), ParentDecl(pd) { }
- ASTLocation VisitTypedefLoc(TypedefLoc TL);
- ASTLocation VisitFunctionLoc(FunctionLoc TL);
- ASTLocation VisitArrayLoc(ArrayLoc TL);
- ASTLocation VisitObjCInterfaceLoc(ObjCInterfaceLoc TL);
- ASTLocation VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
+ ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
+ ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
+ ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
+ ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
+ ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
+ ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
ASTLocation VisitTypeLoc(TypeLoc TL);
};
@@ -349,7 +350,25 @@ ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
return ASTLocation(D);
}
-ASTLocation TypeLocResolver::VisitTypedefLoc(TypedefLoc TL) {
+ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ // Continue the 'id' magic by making the builtin type (which cannot
+ // actually be spelled) map to the typedef.
+ BuiltinType *T = TL.getTypePtr();
+ if (T->getKind() == BuiltinType::ObjCId) {
+ TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
+ return ASTLocation(ParentDecl, D, TL.getNameLoc());
+ }
+
+ // Same thing with 'Class'.
+ if (T->getKind() == BuiltinType::ObjCClass) {
+ TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
+ return ASTLocation(ParentDecl, D, TL.getNameLoc());
+ }
+
+ return ASTLocation(ParentDecl, TL);
+}
+
+ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
assert(ContainsLocation(TL) &&
"Should visit only after verifying that loc is in range");
if (ContainsLocation(TL.getNameLoc()))
@@ -357,7 +376,7 @@ ASTLocation TypeLocResolver::VisitTypedefLoc(TypedefLoc TL) {
return ASTLocation(ParentDecl, TL);
}
-ASTLocation TypeLocResolver::VisitFunctionLoc(FunctionLoc TL) {
+ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
assert(ContainsLocation(TL) &&
"Should visit only after verifying that loc is in range");
@@ -373,7 +392,7 @@ ASTLocation TypeLocResolver::VisitFunctionLoc(FunctionLoc TL) {
return ASTLocation(ParentDecl, TL);
}
-ASTLocation TypeLocResolver::VisitArrayLoc(ArrayLoc TL) {
+ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
assert(ContainsLocation(TL) &&
"Should visit only after verifying that loc is in range");
@@ -384,17 +403,11 @@ ASTLocation TypeLocResolver::VisitArrayLoc(ArrayLoc TL) {
return ASTLocation(ParentDecl, TL);
}
-ASTLocation TypeLocResolver::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) {
+ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
assert(ContainsLocation(TL) &&
"Should visit only after verifying that loc is in range");
if (ContainsLocation(TL.getNameLoc()))
return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
SourceLocation L = TL.getProtocolLoc(i);
@@ -408,6 +421,24 @@ ASTLocation TypeLocResolver::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
return ASTLocation(ParentDecl, TL);
}
+ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ assert(ContainsLocation(TL) &&
+ "Should visit only after verifying that loc is in range");
+
+ if (TL.hasProtocolsAsWritten()) {
+ for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
+ SourceLocation L = TL.getProtocolLoc(i);
+ RangePos RP = CheckRange(L);
+ if (RP == AfterLoc)
+ break;
+ if (RP == ContainsLoc)
+ return ASTLocation(ParentDecl, TL.getProtocol(i), L);
+ }
+ }
+
+ return ASTLocation(ParentDecl, TL);
+}
+
ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
assert(ContainsLocation(TL) &&
"Should visit only after verifying that loc is in range");
@@ -497,9 +528,12 @@ void LocResolverBase::print(Stmt *Node) {
/// \brief Returns the AST node that a source location points to.
///
-ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc) {
+ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
+ Decl *RelativeToDecl) {
if (Loc.isInvalid())
return ASTLocation();
+ if (RelativeToDecl)
+ return DeclLocResolver(Ctx, Loc).Visit(RelativeToDecl);
return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
}
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 196a77f6426a..e264efab9d7b 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -1071,7 +1071,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,
// we allow macros that expand to nothing after the filename, because this
// falls into the category of "#include pp-tokens new-line" specified in
// C99 6.10.2p4.
- CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getName(), true);
+ CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getNameStart(), true);
// Check that we don't have infinite #include recursion.
if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index 36ace8be7e06..f17a5d93a91a 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -20,8 +20,9 @@
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Token.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/MemoryBuffer.h"
#include <sys/stat.h>
using namespace clang;
@@ -95,14 +96,6 @@ LexNextToken:
//===--------------------------------------==//
// Process the token.
//===--------------------------------------==//
-#if 0
- SourceManager& SM = PP->getSourceManager();
- llvm::errs() << SM.getFileEntryForID(FileID)->getName()
- << ':' << SM.getLogicalLineNumber(Tok.getLocation())
- << ':' << SM.getLogicalColumnNumber(Tok.getLocation())
- << '\n';
-#endif
-
if (TKind == tok::eof) {
// Save the end-of-file token.
EofToken = Tok;
@@ -308,7 +301,7 @@ public:
typedef std::pair<unsigned char, const char*> internal_key_type;
static unsigned ComputeHash(internal_key_type x) {
- return BernsteinHash(x.second);
+ return llvm::HashString(x.second);
}
static std::pair<unsigned, unsigned>
@@ -363,7 +356,7 @@ public:
}
static unsigned ComputeHash(const internal_key_type& a) {
- return BernsteinHash(a.first, a.second);
+ return llvm::HashString(llvm::StringRef(a.first, a.second));
}
// This hopefully will just get inlined and removed by the optimizer.
@@ -562,7 +555,7 @@ IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {
// Store the new IdentifierInfo in the cache.
PerIDCache[PersistentID] = II;
- assert(II->getName() && II->getName()[0] != '\0');
+ assert(II->getNameStart() && II->getNameStart()[0] != '\0');
return II;
}
@@ -679,7 +672,8 @@ public:
CacheTy::iterator I = Cache.find(path);
// If we don't get a hit in the PTH file just forward to 'stat'.
- if (I == Cache.end()) return ::stat(path, buf);
+ if (I == Cache.end())
+ return StatSysCallCache::stat(path, buf);
const PTHStatData& Data = *I;
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index bfa090a09e87..7f3afc60764c 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -122,7 +122,7 @@ Preprocessor::~Preprocessor() {
void Preprocessor::setPTHManager(PTHManager* pm) {
PTH.reset(pm);
- FileMgr.setStatCache(PTH->createStatCache());
+ FileMgr.addStatCache(PTH->createStatCache());
}
void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
@@ -234,7 +234,7 @@ unsigned Preprocessor::getSpelling(const Token &Tok,
// If this token is an identifier, just return the string from the identifier
// table, which is very quick.
if (const IdentifierInfo *II = Tok.getIdentifierInfo()) {
- Buffer = II->getName();
+ Buffer = II->getNameStart();
return II->getLength();
}
diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp
index ade7f8516ea7..07951646ffe1 100644
--- a/lib/Lex/TokenConcatenation.cpp
+++ b/lib/Lex/TokenConcatenation.cpp
@@ -95,7 +95,7 @@ TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
static char GetFirstChar(Preprocessor &PP, const Token &Tok) {
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
// Avoid spelling identifiers, the most common form of token.
- return II->getName()[0];
+ return II->getNameStart()[0];
} else if (!Tok.needsCleaning()) {
if (Tok.isLiteral() && Tok.getLiteralData()) {
return *Tok.getLiteralData();
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 2ee41bc3eb8d..224a31cd5a5e 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -45,18 +45,15 @@ AttributeList::~AttributeList() {
}
AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
- const char *Str = Name->getName();
- unsigned Len = Name->getLength();
+ llvm::StringRef AttrName = Name->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 (AttrName.startswith("__") && AttrName.endswith("__"))
+ AttrName = AttrName.substr(2, AttrName.size() - 4);
// FIXME: Hand generating this is neither smart nor efficient.
- switch (Len) {
+ const char *Str = AttrName.data();
+ switch (AttrName.size()) {
case 4:
if (!memcmp(Str, "weak", 4)) return AT_weak;
if (!memcmp(Str, "pure", 4)) return AT_pure;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 72e30e3b6079..8be89a891680 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -972,13 +972,41 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
return ExprError();
}
- if (!LHS.isInvalid())
- LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
- OpLoc, OpKind,
- Tok.getLocation(),
- Tok.getIdentifierInfo(),
- SS,
- NextToken().is(tok::l_paren));
+ if (NextToken().is(tok::less)) {
+ // class-name:
+ // ~ simple-template-id
+ TemplateTy Template
+ = Actions.ActOnDependentTemplateName(SourceLocation(),
+ *Tok.getIdentifierInfo(),
+ Tok.getLocation(),
+ SS,
+ ObjectType);
+ if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS,
+ SourceLocation(), true))
+ return ExprError();
+
+ assert(Tok.is(tok::annot_typename) &&
+ "AnnotateTemplateIdToken didn't work?");
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+ OpLoc, OpKind,
+ Tok.getAnnotationRange(),
+ Tok.getAnnotationValue(),
+ SS,
+ NextToken().is(tok::l_paren));
+ } else {
+ // class-name:
+ // ~ identifier
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+ OpLoc, OpKind,
+ Tok.getLocation(),
+ Tok.getIdentifierInfo(),
+ SS,
+ NextToken().is(tok::l_paren));
+ }
+
+ // Consume the identifier or template-id token.
ConsumeToken();
} else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
// We have a reference to a member operator, e.g., t.operator int or
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 325f085a49d8..fa651569f8e1 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -356,7 +356,8 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
TemplateId->NumArgs);
OwningExprResult Result
- = Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template),
+ = Actions.ActOnTemplateIdExpr(SS,
+ TemplateTy::make(TemplateId->Template),
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 6ab23fd42ddc..c4e79cae3f54 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -65,9 +66,9 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
if (Tok.is(tok::identifier)) {
const IdentifierInfo *FieldName = Tok.getIdentifierInfo();
- std::string NewSyntax(".");
- NewSyntax += FieldName->getName();
- NewSyntax += " = ";
+ llvm::SmallString<256> NewSyntax;
+ llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()
+ << " = ";
SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
@@ -77,7 +78,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
Diag(Tok, diag::ext_gnu_old_style_field_designator)
<< CodeModificationHint::CreateReplacement(SourceRange(NameLoc,
ColonLoc),
- NewSyntax);
+ NewSyntax.str());
Designation D;
D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 1d29f319c584..2e0cd6d0d932 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -428,7 +428,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
return;
}
- if (II->getName()[0] == 's') {
+ if (II->getNameStart()[0] == 's') {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
DS.setSetterName(Tok.getIdentifierInfo());
ConsumeToken(); // consume method name
@@ -1371,8 +1371,11 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
"parsing Objective-C method");
// parse optional ';'
- if (Tok.is(tok::semi))
+ if (Tok.is(tok::semi)) {
+ if (ObjCImpDecl)
+ Diag(Tok, diag::warn_semicolon_before_method_nody);
ConsumeToken();
+ }
// We should have an opening brace now.
if (Tok.isNot(tok::l_brace)) {
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 907ca802b4ae..272be2f66017 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -1256,6 +1256,8 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
/// asm-string-literal '(' expression ')'
/// '[' identifier ']' asm-string-literal '(' expression ')'
///
+//
+// FIXME: Avoid unnecessary std::string trashing.
bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
llvm::SmallVectorImpl<ExprTy*> &Constraints,
llvm::SmallVectorImpl<ExprTy*> &Exprs) {
@@ -1281,7 +1283,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
IdentifierInfo *II = Tok.getIdentifierInfo();
ConsumeToken();
- Names.push_back(std::string(II->getName(), II->getLength()));
+ Names.push_back(II->getName());
MatchRHSPunctuation(tok::r_square, Loc);
} else
Names.push_back(std::string());
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 2f500a484da3..bc737e9f0c80 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -77,7 +77,10 @@ void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {
const Preprocessor &PP = P.getPreprocessor();
Tok.getLocation().print(OS, PP.getSourceManager());
- OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n";
+ if (Tok.isAnnotation())
+ OS << ": at annotation token \n";
+ else
+ OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n";
}
diff --git a/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp
index 30bbcfafb532..fdb6fc385ba1 100644
--- a/lib/Rewrite/RewriteRope.cpp
+++ b/lib/Rewrite/RewriteRope.cpp
@@ -154,6 +154,7 @@ namespace {
~RopePieceBTreeLeaf() {
if (PrevLeaf || NextLeaf)
removeFromLeafInOrder();
+ clear();
}
bool isFull() const { return NumPieces == 2*WidthFactor; }
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index ba05a07f2654..fc9c14f456bd 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 80f366302171..6dd081bdc25e 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 69d1f92a0832..bf396041b473 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 92bf83f0830d..589b0c6bd0ec 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 3981b8d22fa3..381151325a03 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 606b33f5f74b..b83181becb93 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 50ebb49e7d5b..341d49ead418 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 419c8a13c2d4..6d1f4ea4a865 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 a946500660e8..ae45429952c7 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 5f111c8a60e7..d4d031f91ed5 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 d7e4e4a67fe9..b78c10b0dd80 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 27f089680763..4746a2597e55 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 99e7b0811c91..ebcf3ad8e2bc 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 e8cd6b081de1..145342438503 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 ab0bbe081dbf..0f223208a938 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 b981389d1d15..2a44f83598e8 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 24b83704eba9..53d158088c8e 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 060cc559833f..be4adbc93d15 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 9603ca8a51c4..49f7119c8b06 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 ec5c6676f5d2..7e0972fe03c4 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>());
}