summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-06-22 08:08:35 +0000
committered <ed@FreeBSD.org>2009-06-22 08:08:35 +0000
commit8927c19a5ed03bef55dac4b623688387bcc794dc (patch)
treeb6403365e77095a79062d3379c9e6aea0df5f088 /lib
parentb8e7410b22fa573fb0078712439f343bc69208dd (diff)
downloadFreeBSD-src-8927c19a5ed03bef55dac4b623688387bcc794dc.zip
FreeBSD-src-8927c19a5ed03bef55dac4b623688387bcc794dc.tar.gz
Update Clang sources to r73879.
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp101
-rw-r--r--lib/AST/Decl.cpp35
-rw-r--r--lib/AST/DeclBase.cpp48
-rw-r--r--lib/AST/DeclCXX.cpp73
-rw-r--r--lib/AST/DeclTemplate.cpp41
-rw-r--r--lib/AST/Expr.cpp37
-rw-r--r--lib/AST/ExprCXX.cpp9
-rw-r--r--lib/AST/StmtPrinter.cpp8
-rw-r--r--lib/AST/Type.cpp107
-rw-r--r--lib/Analysis/BasicConstraintManager.cpp191
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp41
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.h2
-rw-r--r--lib/Analysis/BasicStore.cpp61
-rw-r--r--lib/Analysis/BugReporter.cpp2
-rw-r--r--lib/Analysis/CFRefCount.cpp277
-rw-r--r--lib/Analysis/CheckDeadStores.cpp4
-rw-r--r--lib/Analysis/CheckNSError.cpp15
-rw-r--r--lib/Analysis/CheckObjCDealloc.cpp2
-rw-r--r--lib/Analysis/CheckObjCUnusedIVars.cpp2
-rw-r--r--lib/Analysis/Environment.cpp20
-rw-r--r--lib/Analysis/GRExprEngine.cpp434
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp30
-rw-r--r--lib/Analysis/GRSimpleVals.cpp22
-rw-r--r--lib/Analysis/GRState.cpp53
-rw-r--r--lib/Analysis/GRTransferFuncs.cpp3
-rw-r--r--lib/Analysis/MemRegion.cpp8
-rw-r--r--lib/Analysis/RangeConstraintManager.cpp49
-rw-r--r--lib/Analysis/RegionStore.cpp822
-rw-r--r--lib/Analysis/SVals.cpp13
-rw-r--r--lib/Analysis/SimpleConstraintManager.cpp185
-rw-r--r--lib/Analysis/SimpleConstraintManager.h86
-rw-r--r--lib/Analysis/Store.cpp3
-rw-r--r--lib/Analysis/SymbolManager.cpp9
-rw-r--r--lib/Basic/Builtins.cpp11
-rw-r--r--lib/Basic/Diagnostic.cpp2
-rw-r--r--lib/Basic/SourceManager.cpp42
-rw-r--r--lib/CodeGen/CGBuiltin.cpp4
-rw-r--r--lib/CodeGen/CGCXXTemp.cpp5
-rw-r--r--lib/CodeGen/CGCall.cpp11
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp62
-rw-r--r--lib/CodeGen/CGDebugInfo.h4
-rw-r--r--lib/CodeGen/CGDecl.cpp12
-rw-r--r--lib/CodeGen/CGExpr.cpp5
-rw-r--r--lib/CodeGen/CGExprComplex.cpp117
-rw-r--r--lib/CodeGen/CGExprConstant.cpp7
-rw-r--r--lib/CodeGen/CGExprScalar.cpp24
-rw-r--r--lib/CodeGen/CGObjC.cpp2
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp33
-rw-r--r--lib/CodeGen/CGObjCMac.cpp11
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp70
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--lib/CodeGen/Mangle.cpp4
-rw-r--r--lib/Driver/CMakeLists.txt2
-rw-r--r--lib/Driver/Driver.cpp48
-rw-r--r--lib/Driver/HostInfo.cpp34
-rw-r--r--lib/Frontend/ASTConsumers.cpp8
-rw-r--r--lib/Frontend/ASTUnit.cpp159
-rw-r--r--lib/Frontend/CMakeLists.txt4
-rw-r--r--lib/Frontend/DeclXML.cpp161
-rw-r--r--lib/Frontend/DocumentXML.cpp348
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp6
-rw-r--r--lib/Frontend/InitPreprocessor.cpp6
-rw-r--r--lib/Frontend/PCHReader.cpp814
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp4
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp1
-rw-r--r--lib/Frontend/PCHWriter.cpp10
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp6
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp1
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp35
-rw-r--r--lib/Frontend/RewriteBlocks.cpp2
-rw-r--r--lib/Frontend/RewriteObjC.cpp2
-rw-r--r--lib/Frontend/StmtXML.cpp100
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp13
-rw-r--r--lib/Frontend/TypeXML.cpp127
-rw-r--r--lib/Headers/CMakeLists.txt7
-rw-r--r--lib/Lex/HeaderSearch.cpp4
-rw-r--r--lib/Lex/Pragma.cpp20
-rw-r--r--lib/Lex/Preprocessor.cpp2
-rw-r--r--lib/Lex/TokenConcatenation.cpp8
-rw-r--r--lib/Parse/MinimalAction.cpp16
-rw-r--r--lib/Parse/ParseDecl.cpp15
-rw-r--r--lib/Parse/ParseDeclCXX.cpp91
-rw-r--r--lib/Parse/ParseExpr.cpp22
-rw-r--r--lib/Parse/ParseExprCXX.cpp11
-rw-r--r--lib/Sema/JumpDiagnostics.cpp6
-rw-r--r--lib/Sema/Sema.cpp5
-rw-r--r--lib/Sema/Sema.h92
-rw-r--r--lib/Sema/SemaAttr.cpp2
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp15
-rw-r--r--lib/Sema/SemaChecking.cpp7
-rw-r--r--lib/Sema/SemaDecl.cpp139
-rw-r--r--lib/Sema/SemaDeclAttr.cpp175
-rw-r--r--lib/Sema/SemaDeclCXX.cpp176
-rw-r--r--lib/Sema/SemaDeclObjC.cpp12
-rw-r--r--lib/Sema/SemaExpr.cpp119
-rw-r--r--lib/Sema/SemaExprCXX.cpp11
-rw-r--r--lib/Sema/SemaExprObjC.cpp35
-rw-r--r--lib/Sema/SemaLookup.cpp12
-rw-r--r--lib/Sema/SemaOverload.cpp48
-rw-r--r--lib/Sema/SemaStmt.cpp21
-rw-r--r--lib/Sema/SemaTemplate.cpp24
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp108
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp45
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp5
-rw-r--r--lib/Sema/SemaType.cpp42
106 files changed, 3927 insertions, 2482 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7ed9e45..b80142f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -222,7 +222,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
unsigned Align = Target.getCharWidth();
- if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
+ if (const AlignedAttr* AA = D->getAttr<AlignedAttr>(*this))
Align = std::max(Align, AA->getAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
@@ -369,7 +369,7 @@ ASTContext::getTypeInfo(const Type *T) {
// FIXME: Pointers into different addr spaces could have different sizes and
// alignment requirements: getPointerInfo should take an AddrSpace.
return getTypeInfo(QualType(cast<ExtQualType>(T)->getBaseType(), 0));
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
case Type::ObjCQualifiedInterface:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
@@ -445,7 +445,7 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
- if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
+ if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>(*this)) {
Align = Aligned->getAlignment();
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
@@ -505,7 +505,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// FIXME: Should this override struct packing? Probably we want to
// take the minimum?
- if (const PackedAttr *PA = FD->getAttr<PackedAttr>())
+ if (const PackedAttr *PA = FD->getAttr<PackedAttr>(Context))
FieldPacking = PA->getAlignment();
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
@@ -525,7 +525,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
FieldAlign = FieldInfo.second;
if (FieldPacking)
FieldAlign = std::min(FieldAlign, FieldPacking);
- if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Check if we need to add padding to give the field the correct
@@ -565,7 +565,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// is smaller than the specified packing?
if (FieldPacking)
FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
- if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Round up the current record size to the field's alignment boundary.
@@ -731,10 +731,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
}
unsigned StructPacking = 0;
- if (const PackedAttr *PA = D->getAttr<PackedAttr>())
+ if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
StructPacking = PA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
@@ -783,10 +783,10 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
bool IsUnion = D->isUnion();
unsigned StructPacking = 0;
- if (const PackedAttr *PA = D->getAttr<PackedAttr>())
+ if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
StructPacking = PA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
@@ -1269,6 +1269,18 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
return QualType(New, 0);
}
+QualType ASTContext::getDependentSizedExtVectorType(QualType vecType,
+ Expr *SizeExpr,
+ SourceLocation AttrLoc) {
+ DependentSizedExtVectorType *New =
+ new (*this,8) DependentSizedExtVectorType(vecType, QualType(),
+ SizeExpr, AttrLoc);
+
+ DependentSizedExtVectorTypes.push_back(New);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
@@ -1414,11 +1426,13 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) {
}
/// \brief Retrieve the template type parameter type for a template
-/// parameter with the given depth, index, and (optionally) name.
+/// parameter or parameter pack with the given depth, index, and (optionally)
+/// name.
QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ bool ParameterPack,
IdentifierInfo *Name) {
llvm::FoldingSetNodeID ID;
- TemplateTypeParmType::Profile(ID, Depth, Index, Name);
+ TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name);
void *InsertPos = 0;
TemplateTypeParmType *TypeParm
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -1426,11 +1440,12 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
if (TypeParm)
return QualType(TypeParm, 0);
- if (Name)
- TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, Name,
- getTemplateTypeParmType(Depth, Index));
- else
- TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index);
+ if (Name) {
+ QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack);
+ TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, ParameterPack,
+ Name, Canon);
+ } else
+ TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, ParameterPack);
Types.push_back(TypeParm);
TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos);
@@ -1563,6 +1578,31 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
NumProtocols = ProtocolsEnd-Protocols;
}
+/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
+/// the given interface decl and the conforming protocol list.
+QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **Protocols,
+ unsigned NumProtocols) {
+ // Sort the protocol list alphabetically to canonicalize it.
+ if (NumProtocols)
+ SortAndUniqueProtocols(Protocols, NumProtocols);
+
+ llvm::FoldingSetNodeID ID;
+ ObjCObjectPointerType::Profile(ID, Decl, Protocols, NumProtocols);
+
+ void *InsertPos = 0;
+ if (ObjCObjectPointerType *QT =
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
+
+ // No Match;
+ ObjCObjectPointerType *QType =
+ new (*this,8) ObjCObjectPointerType(Decl, Protocols, NumProtocols);
+
+ Types.push_back(QType);
+ ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
+ return QualType(QType, 0);
+}
/// getObjCQualifiedInterfaceType - Return a ObjCQualifiedInterfaceType type for
/// the given interface decl and the conforming protocol list.
@@ -1592,23 +1632,7 @@ QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
/// and the conforming protocol list.
QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
- // Sort the protocol list alphabetically to canonicalize it.
- SortAndUniqueProtocols(Protocols, NumProtocols);
-
- llvm::FoldingSetNodeID ID;
- ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
-
- void *InsertPos = 0;
- if (ObjCQualifiedIdType *QT =
- ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(QT, 0);
-
- // No Match;
- ObjCQualifiedIdType *QType =
- new (*this,8) ObjCQualifiedIdType(Protocols, NumProtocols);
- Types.push_back(QType);
- ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
- return QualType(QType, 0);
+ return getObjCObjectPointerType(0, Protocols, NumProtocols);
}
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
@@ -2398,9 +2422,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (FD || EncodingProperty) {
// Note that we do extended encoding of protocol qualifer list
// Only when doing ivar or property encoding.
- const ObjCQualifiedIdType *QIDT = T->getAsObjCQualifiedIdType();
+ const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType();
S += '"';
- for (ObjCQualifiedIdType::qual_iterator I = QIDT->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(),
E = QIDT->qual_end(); I != E; ++I) {
S += '<';
S += (*I)->getNameAsString();
@@ -2758,7 +2782,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
bool ASTContext::isObjCNSObjectType(QualType Ty) const {
if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
if (TypedefDecl *TD = TDT->getDecl())
- if (TD->getAttr<ObjCNSObjectAttr>())
+ if (TD->getAttr<ObjCNSObjectAttr>(*const_cast<ASTContext*>(this)))
return true;
}
return false;
@@ -3283,7 +3307,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return QualType();
}
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
+ // FIXME: finish
// Distinct qualified id's are not compatible.
return QualType();
case Type::FixedWidthInt:
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a3e406b..bf63932 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -315,6 +315,12 @@ void VarDecl::Destroy(ASTContext& C) {
VarDecl::~VarDecl() {
}
+SourceRange VarDecl::getSourceRange() const {
+ if (getInit())
+ return SourceRange(getLocation(), getInit()->getLocEnd());
+ return SourceRange(getLocation(), getLocation());
+}
+
bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus)
return false;
@@ -371,6 +377,12 @@ Stmt *FunctionDecl::getBodyIfAvailable() const {
return 0;
}
+void FunctionDecl::setBody(Stmt *B) {
+ Body = B;
+ if (B && EndRangeLoc < B->getLocEnd())
+ EndRangeLoc = B->getLocEnd();
+}
+
bool FunctionDecl::isMain() const {
return getDeclContext()->getLookupContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
@@ -380,13 +392,14 @@ bool FunctionDecl::isExternC(ASTContext &Context) const {
// In C, any non-static, non-overloadable function has external
// linkage.
if (!Context.getLangOptions().CPlusPlus)
- return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+ return getStorageClass() != Static && !getAttr<OverloadableAttr>(Context);
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+ return getStorageClass() != Static &&
+ !getAttr<OverloadableAttr>(Context);
break;
}
@@ -451,7 +464,7 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
if (isa<LinkageSpecDecl>(getDeclContext()) &&
cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
== LinkageSpecDecl::lang_c &&
- !getAttr<OverloadableAttr>())
+ !getAttr<OverloadableAttr>(Context))
return BuiltinID;
// Not a builtin
@@ -480,6 +493,10 @@ void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
+
+ // Update source range.
+ if (EndRangeLoc < NewParamInfo[NumParams-1]->getLocEnd())
+ EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
}
}
@@ -496,25 +513,25 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
return NumRequiredArgs;
}
-bool FunctionDecl::hasActiveGNUInlineAttribute() const {
- if (!isInline() || !hasAttr<GNUInlineAttr>())
+bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
+ if (!isInline() || !hasAttr<GNUInlineAttr>(Context))
return false;
for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
FD = FD->getPreviousDeclaration()) {
- if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
+ if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>(Context))
return false;
}
return true;
}
-bool FunctionDecl::isExternGNUInline() const {
- if (!hasActiveGNUInlineAttribute())
+bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
+ if (!hasActiveGNUInlineAttribute(Context))
return false;
for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
- if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
+ if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>(Context))
return true;
return false;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index a39a506..02e71d7 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -38,12 +38,6 @@ using namespace clang;
static bool StatSwitch = false;
-// This keeps track of all decl attributes. Since so few decls have attrs, we
-// keep them in a hash map instead of wasting space in the Decl class.
-typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
-
-static DeclAttrMapTy *DeclAttrs = 0;
-
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: assert(0 && "Declaration not in DeclNodes.def!");
@@ -170,6 +164,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ParmVar:
case OriginalParmVar:
case NonTypeTemplateParm:
+ case Using:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
@@ -224,11 +219,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
}
}
-void Decl::addAttr(Attr *NewAttr) {
- if (!DeclAttrs)
- DeclAttrs = new DeclAttrMapTy();
-
- Attr *&ExistingAttr = (*DeclAttrs)[this];
+void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
+ Attr *&ExistingAttr = Context.getDeclAttrs(this);
NewAttr->setNext(ExistingAttr);
ExistingAttr = NewAttr;
@@ -236,25 +228,19 @@ void Decl::addAttr(Attr *NewAttr) {
HasAttrs = true;
}
-void Decl::invalidateAttrs() {
+void Decl::invalidateAttrs(ASTContext &Context) {
if (!HasAttrs) return;
-
+
HasAttrs = false;
- (*DeclAttrs)[this] = 0;
- DeclAttrs->erase(this);
-
- if (DeclAttrs->empty()) {
- delete DeclAttrs;
- DeclAttrs = 0;
- }
+ Context.eraseDeclAttrs(this);
}
-const Attr *Decl::getAttrsImpl() const {
+const Attr *Decl::getAttrsImpl(ASTContext &Context) const {
assert(HasAttrs && "getAttrs() should verify this!");
- return (*DeclAttrs)[this];
+ return Context.getDeclAttrs(this);
}
-void Decl::swapAttrs(Decl *RHS) {
+void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
bool HasLHSAttr = this->HasAttrs;
bool HasRHSAttr = RHS->HasAttrs;
@@ -263,17 +249,17 @@ void Decl::swapAttrs(Decl *RHS) {
// If 'this' has no attrs, swap the other way.
if (!HasLHSAttr)
- return RHS->swapAttrs(this);
+ return RHS->swapAttrs(Context, this);
// Handle the case when both decls have attrs.
if (HasRHSAttr) {
- std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
+ std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
return;
}
// Otherwise, LHS has an attr and RHS doesn't.
- (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
- (*DeclAttrs).erase(this);
+ Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
+ Context.eraseDeclAttrs(this);
this->HasAttrs = false;
RHS->HasAttrs = true;
}
@@ -282,12 +268,8 @@ void Decl::swapAttrs(Decl *RHS) {
void Decl::Destroy(ASTContext &C) {
// Free attributes for this decl.
if (HasAttrs) {
- DeclAttrMapTy::iterator it = DeclAttrs->find(this);
- assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
-
- // release attributes.
- it->second->Destroy(C);
- invalidateAttrs();
+ C.getDeclAttrs(this)->Destroy(C);
+ invalidateAttrs(C);
HasAttrs = false;
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 8430da2..7a930d7 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -128,36 +128,33 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
void
CXXRecordDecl::addedConstructor(ASTContext &Context,
CXXConstructorDecl *ConDecl) {
- if (!ConDecl->isImplicit()) {
- // Note that we have a user-declared constructor.
- UserDeclaredConstructor = true;
-
- // C++ [dcl.init.aggr]p1:
- // An aggregate is an array or a class (clause 9) with no
- // user-declared constructors (12.1) [...].
- Aggregate = false;
-
- // C++ [class]p4:
- // A POD-struct is an aggregate class [...]
- PlainOldData = false;
-
- // C++ [class.ctor]p5:
- // A constructor is trivial if it is an implicitly-declared default
- // constructor.
- HasTrivialConstructor = false;
+ assert(!ConDecl->isImplicit() && "addedConstructor - not for implicit decl");
+ // Note that we have a user-declared constructor.
+ UserDeclaredConstructor = true;
+
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with no
+ // user-declared constructors (12.1) [...].
+ Aggregate = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class [...]
+ PlainOldData = false;
+
+ // C++ [class.ctor]p5:
+ // A constructor is trivial if it is an implicitly-declared default
+ // constructor.
+ HasTrivialConstructor = false;
- // Note when we have a user-declared copy constructor, which will
- // suppress the implicit declaration of a copy constructor.
- if (ConDecl->isCopyConstructor(Context))
- UserDeclaredCopyConstructor = true;
- }
+ // Note when we have a user-declared copy constructor, which will
+ // suppress the implicit declaration of a copy constructor.
+ if (ConDecl->isCopyConstructor(Context))
+ UserDeclaredCopyConstructor = true;
}
void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
CXXMethodDecl *OpDecl) {
// We're interested specifically in copy assignment operators.
- // Unlike addedConstructor, this method is not called for implicit
- // declarations.
const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType();
assert(FnType && "Overloaded operator has no proto function type.");
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
@@ -187,10 +184,28 @@ void CXXRecordDecl::addConversionFunction(ASTContext &Context,
Conversions.addOverload(ConvDecl);
}
+
+CXXConstructorDecl *
+CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
+ QualType ClassType = Context.getTypeDeclType(this);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isDefaultConstructor())
+ return Constructor;
+ }
+ return 0;
+}
+
const CXXDestructorDecl *
CXXRecordDecl::getDestructor(ASTContext &Context) {
QualType ClassType = Context.getTypeDeclType(this);
-
+
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
@@ -428,6 +443,14 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
Qualifier, IdentLoc, Namespace);
}
+UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
+ SourceLocation UL, NamedDecl* Target,
+ NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) {
+ return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target,
+ TargetNNS, IsTypeNameArg);
+}
+
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, Expr *AssertExpr,
StringLiteral *Message) {
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 5b1bf9b..23c2637 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -190,7 +190,7 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack) {
- QualType Type = C.getTemplateTypeParmType(D, P, Id);
+ QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id);
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
}
@@ -238,6 +238,22 @@ TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
StartLoc = E->getSourceRange().getBegin();
}
+/// \brief Construct a template argument pack.
+TemplateArgument::TemplateArgument(SourceLocation Loc, TemplateArgument *args,
+ unsigned NumArgs, bool CopyArgs)
+ : Kind(Pack) {
+ Args.NumArgs = NumArgs;
+ Args.CopyArgs = CopyArgs;
+ if (!Args.CopyArgs) {
+ Args.Args = args;
+ return;
+ }
+
+ Args.Args = new TemplateArgument[NumArgs];
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args.Args[I] = args[I];
+}
+
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
@@ -249,25 +265,28 @@ void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
break;
}
- if (!isAddingFromParameterPack()) {
- // Add begin and end indicies.
- Indices.push_back(Args.size());
- Indices.push_back(Args.size());
- }
-
- Args.push_back(Arg);
+ FlatArgs.push_back(Arg);
+
+ if (!isAddingFromParameterPack())
+ StructuredArgs.push_back(Arg);
}
void TemplateArgumentListBuilder::BeginParameterPack() {
assert(!isAddingFromParameterPack() && "Already adding to parameter pack!");
-
- Indices.push_back(Args.size());
+
+ PackBeginIndex = FlatArgs.size();
}
void TemplateArgumentListBuilder::EndParameterPack() {
assert(isAddingFromParameterPack() && "Not adding to parameter pack!");
+
+ unsigned NumArgs = FlatArgs.size() - PackBeginIndex;
+ TemplateArgument *Args = NumArgs ? &FlatArgs[PackBeginIndex] : 0;
+
+ StructuredArgs.push_back(TemplateArgument(SourceLocation(), Args, NumArgs,
+ /*CopyArgs=*/false));
- Indices.push_back(Args.size());
+ PackBeginIndex = std::numeric_limits<unsigned>::max();
}
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 309be41..4a3ad26 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -456,7 +456,7 @@ Stmt *BlockExpr::getBody() {
/// with location to warn on and the source range[s] to report with the
/// warning.
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
- SourceRange &R2) const {
+ SourceRange &R2, ASTContext &Context) const {
// Don't warn if the expr is type dependent. The type could end up
// instantiating to void.
if (isTypeDependent())
@@ -469,7 +469,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return true;
case ParenExprClass:
return cast<ParenExpr>(this)->getSubExpr()->
- isUnusedResultAWarning(Loc, R1, R2);
+ isUnusedResultAWarning(Loc, R1, R2, Context);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
@@ -492,7 +492,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
break;
case UnaryOperator::Extension:
- return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
Loc = UO->getOperatorLoc();
R1 = UO->getSubExpr()->getSourceRange();
@@ -502,8 +502,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const BinaryOperator *BO = cast<BinaryOperator>(this);
// Consider comma to have side effects if the LHS or RHS does.
if (BO->getOpcode() == BinaryOperator::Comma)
- return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
- BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context) ||
+ BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
if (BO->isAssignmentOp())
return false;
@@ -519,9 +519,10 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// The condition must be evaluated, but if either the LHS or RHS is a
// warning, warn about them.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
- if (Exp->getLHS() && Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
+ if (Exp->getLHS() &&
+ Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context))
return true;
- return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
case MemberExprClass:
@@ -554,8 +555,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
- if (FD->getAttr<WarnUnusedResultAttr>() ||
- FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
+ if (FD->getAttr<WarnUnusedResultAttr>(Context) ||
+ FD->getAttr<PureAttr>(Context) || FD->getAttr<ConstAttr>(Context)) {
Loc = CE->getCallee()->getLocStart();
R1 = CE->getCallee()->getSourceRange();
@@ -578,7 +579,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
if (!CS->body_empty())
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
- return E->isUnusedResultAWarning(Loc, R1, R2);
+ return E->isUnusedResultAWarning(Loc, R1, R2, Context);
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
@@ -588,8 +589,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
if (getType()->isVoidType())
- return cast<CastExpr>(this)->getSubExpr()->isUnusedResultAWarning(Loc,
- R1, R2);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Context);
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@@ -597,8 +598,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If this is a cast to void, check the operand. Otherwise, the result of
// the cast is unused.
if (getType()->isVoidType())
- return cast<CastExpr>(this)->getSubExpr()->isUnusedResultAWarning(Loc,
- R1, R2);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(Loc, R1, R2, Context);
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@@ -606,11 +607,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
return cast<ImplicitCastExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)
- ->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
@@ -619,7 +620,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
case CXXExprWithTemporariesClass:
return cast<CXXExprWithTemporaries>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
}
@@ -1570,7 +1571,7 @@ ObjCSelectorExpr *ObjCSelectorExpr::Clone(ASTContext &C) const {
}
ObjCProtocolExpr *ObjCProtocolExpr::Clone(ASTContext &C) const {
- return new (C) ObjCProtocolExpr(getType(), Protocol, AtLoc, RParenLoc);
+ return new (C) ObjCProtocolExpr(getType(), TheProtocol, AtLoc, RParenLoc);
}
// constructor for class messages.
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 8fd66a2..18c0f77 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -306,10 +306,11 @@ void CXXConstructExpr::Destroy(ASTContext &C) {
CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr,
CXXTemporary **temps,
unsigned numtemps,
- bool destroytemps)
+ bool shoulddestroytemps)
: Expr(CXXExprWithTemporariesClass, subexpr->getType(),
subexpr->isTypeDependent(), subexpr->isValueDependent()),
- SubExpr(subexpr), Temps(0), NumTemps(numtemps), DestroyTemps(destroytemps) {
+ SubExpr(subexpr), Temps(0), NumTemps(numtemps),
+ ShouldDestroyTemps(shoulddestroytemps) {
if (NumTemps > 0) {
Temps = new CXXTemporary*[NumTemps];
for (unsigned i = 0; i < NumTemps; ++i)
@@ -321,9 +322,9 @@ CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps,
- bool DestroyTemps) {
+ bool ShouldDestroyTemps){
return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps,
- DestroyTemps);
+ ShouldDestroyTemps);
}
void CXXExprWithTemporaries::Destroy(ASTContext &C) {
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 710da63..b300940 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -643,7 +643,8 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
if (!Node->isPostfix()) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
- // Print a space if this is an "identifier operator" like __real.
+ // Print a space if this is an "identifier operator" like __real, or if
+ // it might be concatenated incorrectly like '+'.
switch (Node->getOpcode()) {
default: break;
case UnaryOperator::Real:
@@ -651,6 +652,11 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
case UnaryOperator::Extension:
OS << ' ';
break;
+ case UnaryOperator::Plus:
+ case UnaryOperator::Minus:
+ if (isa<UnaryOperator>(Node->getSubExpr()))
+ OS << ' ';
+ break;
}
}
PrintExpr(Node->getSubExpr());
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index e304f54..7b45b21 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -50,6 +50,13 @@ void DependentSizedArrayType::Destroy(ASTContext& C) {
C.Deallocate(this);
}
+void DependentSizedExtVectorType::Destroy(ASTContext& C) {
+ if (SizeExpr)
+ SizeExpr->Destroy(C);
+ this->~DependentSizedExtVectorType();
+ C.Deallocate(this);
+}
+
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -555,6 +562,12 @@ const ObjCInterfaceType *Type::getAsObjCInterfaceType() const {
return dyn_cast<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
}
+const ObjCObjectPointerType *Type::getAsObjCObjectPointerType() const {
+ // There is no sugar for ObjCObjectPointerType's, just return the
+ // canonical type pointer if it is the right class.
+ return dyn_cast<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
+}
+
const ObjCQualifiedInterfaceType *
Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCQualifiedInterfaceType's, just return the
@@ -562,10 +575,14 @@ Type::getAsObjCQualifiedInterfaceType() const {
return dyn_cast<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
-const ObjCQualifiedIdType *Type::getAsObjCQualifiedIdType() const {
+const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
- return dyn_cast<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ if (OPT->isObjCQualifiedIdType())
+ return OPT;
+ }
+ return 0;
}
const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
@@ -770,7 +787,7 @@ bool Type::isScalarType() const {
isa<BlockPointerType>(CanonicalType) ||
isa<MemberPointerType>(CanonicalType) ||
isa<ComplexType>(CanonicalType) ||
- isa<ObjCQualifiedIdType>(CanonicalType);
+ isa<ObjCObjectPointerType>(CanonicalType);
}
/// \brief Determines whether the type is a C++ aggregate type or C
@@ -857,7 +874,7 @@ bool Type::isPODType() const {
case MemberPointer:
case Vector:
case ExtVector:
- case ObjCQualifiedId:
+ case ObjCObjectPointer:
return true;
case Enum:
@@ -912,7 +929,7 @@ bool Type::isSpecifierType() const {
case Typename:
case ObjCInterface:
case ObjCQualifiedInterface:
- case ObjCQualifiedId:
+ case ObjCObjectPointer:
return true;
default:
return false;
@@ -973,28 +990,30 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
getNumExceptions(), exception_begin());
}
-void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
- const ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **protocols,
- unsigned NumProtocols) {
+void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **protocols,
+ unsigned NumProtocols) {
ID.AddPointer(Decl);
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
-void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
+void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
}
-void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
- ObjCProtocolDecl **protocols,
- unsigned NumProtocols) {
+void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **protocols,
+ unsigned NumProtocols) {
+ ID.AddPointer(Decl);
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
-void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, &Protocols[0], getNumProtocols());
+void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
}
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
@@ -1068,6 +1087,10 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
Args[Idx].getAsExpr()->isValueDependent())
return true;
break;
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
@@ -1352,6 +1375,19 @@ void DependentSizedArrayType::getAsStringInternal(std::string &S, const Printing
getElementType().getAsStringInternal(S, Policy);
}
+void DependentSizedExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
+ getElementType().getAsStringInternal(S, Policy);
+
+ S += " __attribute__((ext_vector_type(";
+ if (getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ")))";
+}
+
void VectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
// FIXME: We prefer to print the size directly here, but have no way
// to get the size of the type.
@@ -1476,6 +1512,9 @@ TemplateSpecializationType::PrintTemplateArgumentList(
Args[Arg].getAsExpr()->printPretty(s, 0, Policy);
break;
}
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
// If this is the first argument and its string representation
@@ -1566,6 +1605,30 @@ void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const Prin
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
}
+void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const {
+ if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ InnerString = ' ' + InnerString;
+
+ std::string ObjCQIString;
+
+ if (getDecl())
+ ObjCQIString = getDecl()->getNameAsString();
+ else
+ ObjCQIString = "id";
+
+ if (!qual_empty()) {
+ ObjCQIString += '<';
+ for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
+ ObjCQIString += (*I)->getNameAsString();
+ if (I+1 != E)
+ ObjCQIString += ',';
+ }
+ ObjCQIString += '>';
+ }
+ InnerString = ObjCQIString + InnerString;
+}
+
void
ObjCQualifiedInterfaceType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
@@ -1585,20 +1648,6 @@ ObjCQualifiedInterfaceType::getAsStringInternal(std::string &InnerString,
InnerString = ObjCQIString + InnerString;
}
-void ObjCQualifiedIdType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
- std::string ObjCQIString = "id";
- ObjCQIString += '<';
- for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
- ObjCQIString += (*I)->getNameAsString();
- if (I+1 != E)
- ObjCQIString += ',';
- }
- ObjCQIString += '>';
- InnerString = ObjCQIString + InnerString;
-}
-
void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (Policy.SuppressTag)
return;
diff --git a/lib/Analysis/BasicConstraintManager.cpp b/lib/Analysis/BasicConstraintManager.cpp
index b272214..ffa8a86 100644
--- a/lib/Analysis/BasicConstraintManager.cpp
+++ b/lib/Analysis/BasicConstraintManager.cpp
@@ -51,39 +51,39 @@ class VISIBILITY_HIDDEN BasicConstraintManager
GRState::IntSetTy::Factory ISetFactory;
public:
BasicConstraintManager(GRStateManager& statemgr)
- : SimpleConstraintManager(statemgr), ISetFactory(statemgr.getAllocator()) {}
+ : ISetFactory(statemgr.getAllocator()) {}
- const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymNE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymEQ(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymLT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymGT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymGE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+ const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
- const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+ const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
- const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
- bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V)
+ const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const;
+ bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
const;
- bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V)
+ bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
const;
- const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
+ const GRState* RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper);
- void print(const GRState* St, std::ostream& Out,
+ void print(const GRState* state, std::ostream& Out,
const char* nl, const char *sep);
};
@@ -95,87 +95,77 @@ ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
}
const GRState*
-BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+BasicConstraintManager::AssumeSymNE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) {
// First, determine if sym == X, where X != V.
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = (*X != V);
- return St;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = (*X != V);
+ return isFeasible ? state : NULL;
}
// Second, determine if sym != V.
- if (isNotEqual(St, sym, V)) {
- isFeasible = true;
- return St;
- }
+ if (isNotEqual(state, sym, V))
+ return state;
// If we reach here, sym is not a constant and we don't know if it is != V.
// Make that assumption.
- isFeasible = true;
- return AddNE(St, sym, V);
+ return AddNE(state, sym, V);
}
-const GRState*
-BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+const GRState *BasicConstraintManager::AssumeSymEQ(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt &V) {
// First, determine if sym == X, where X != V.
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = *X == V;
- return St;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = *X == V;
+ return isFeasible ? state : NULL;
}
// Second, determine if sym != V.
- if (isNotEqual(St, sym, V)) {
- isFeasible = false;
- return St;
- }
+ if (isNotEqual(state, sym, V))
+ return NULL;
// If we reach here, sym is not a constant and we don't know if it is == V.
// Make that assumption.
-
- isFeasible = true;
- return AddEQ(St, sym, V);
+ return AddEQ(state, sym, V);
}
// These logic will be handled in another ConstraintManager.
-const GRState*
-BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
-
+const GRState *BasicConstraintManager::AssumeSymLT(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt& V) {
// Is 'V' the smallest possible value?
if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
// sym cannot be any value less than 'V'. This path is infeasible.
- isFeasible = false;
- return St;
+ return NULL;
}
// FIXME: For now have assuming x < y be the same as assuming sym != V;
- return AssumeSymNE(St, sym, V, isFeasible);
+ return AssumeSymNE(state, sym, V);
}
-const GRState*
-BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+const GRState *BasicConstraintManager::AssumeSymGT(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt& V) {
// Is 'V' the largest possible value?
if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
// sym cannot be any value greater than 'V'. This path is infeasible.
- isFeasible = false;
- return St;
+ return NULL;
}
// FIXME: For now have assuming x > y be the same as assuming sym != V;
- return AssumeSymNE(St, sym, V, isFeasible);
+ return AssumeSymNE(state, sym, V);
}
-const GRState*
-BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+const GRState *BasicConstraintManager::AssumeSymGE(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt &V) {
// Reject a path if the value of sym is a constant X and !(X >= V).
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = *X >= V;
- return St;
+ if (const llvm::APSInt *X = getSymVal(state, sym)) {
+ bool isFeasible = *X >= V;
+ return isFeasible ? state : NULL;
}
// Sym is not a constant, but it is worth looking to see if V is the
@@ -183,28 +173,25 @@ BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
// If we know that sym != V, then this condition is infeasible since
// there is no other value greater than V.
- isFeasible = !isNotEqual(St, sym, V);
+ bool isFeasible = !isNotEqual(state, sym, V);
// If the path is still feasible then as a consequence we know that
// 'sym == V' because we cannot have 'sym > V' (no larger values).
// Add this constraint.
- if (isFeasible)
- return AddEQ(St, sym, V);
+ return isFeasible ? AddEQ(state, sym, V) : NULL;
}
- else
- isFeasible = true;
- return St;
+ return state;
}
const GRState*
-BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+BasicConstraintManager::AssumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V) {
// Reject a path if the value of sym is a constant X and !(X <= V).
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = *X <= V;
- return St;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = *X <= V;
+ return isFeasible ? state : NULL;
}
// Sym is not a constant, but it is worth looking to see if V is the
@@ -212,64 +199,57 @@ BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
// If we know that sym != V, then this condition is infeasible since
// there is no other value less than V.
- isFeasible = !isNotEqual(St, sym, V);
+ bool isFeasible = !isNotEqual(state, sym, V);
// If the path is still feasible then as a consequence we know that
// 'sym == V' because we cannot have 'sym < V' (no smaller values).
// Add this constraint.
- if (isFeasible)
- return AddEQ(St, sym, V);
+ return isFeasible ? AddEQ(state, sym, V) : NULL;
}
- else
- isFeasible = true;
- return St;
+ return state;
}
-const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
+const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
// Create a new state with the old binding replaced.
- GRStateRef state(St, StateMgr);
- return state.set<ConstEq>(sym, &V);
+ return state->set<ConstEq>(sym, &V);
}
-const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym,
+const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
// First, retrieve the NE-set associated with the given symbol.
- ConstNotEqTy::data_type* T = state.get<ConstNotEq>(sym);
+ ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
-
// Now add V to the NE set.
S = ISetFactory.Add(S, &V);
// Create a new state with the old binding replaced.
- return state.set<ConstNotEq>(sym, S);
+ return state->set<ConstNotEq>(sym, S);
}
-const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
+const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state,
SymbolRef sym) const {
- const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
+ const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
return T ? *T : NULL;
}
-bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym,
+bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) const {
// Retrieve the NE-set associated with the given symbol.
- const ConstNotEqTy::data_type* T = St->get<ConstNotEq>(sym);
+ const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
// See if V is present in the NE-set.
return T ? T->contains(&V) : false;
}
-bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
+bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) const {
// Retrieve the EQ-set associated with the given symbol.
- const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
+ const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
// See if V is present in the EQ-set.
return T ? **T == V : false;
}
@@ -277,35 +257,34 @@ bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
const GRState*
-BasicConstraintManager::RemoveDeadBindings(const GRState* St,
+BasicConstraintManager::RemoveDeadBindings(const GRState* state,
SymbolReaper& SymReaper) {
- GRStateRef state(St, StateMgr);
- ConstEqTy CE = state.get<ConstEq>();
- ConstEqTy::Factory& CEFactory = state.get_context<ConstEq>();
+ ConstEqTy CE = state->get<ConstEq>();
+ ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym);
}
- state = state.set<ConstEq>(CE);
+ state = state->set<ConstEq>(CE);
- ConstNotEqTy CNE = state.get<ConstNotEq>();
- ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEq>();
+ ConstNotEqTy CNE = state->get<ConstNotEq>();
+ ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym);
}
- return state.set<ConstNotEq>(CNE);
+ return state->set<ConstNotEq>(CNE);
}
-void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
+void BasicConstraintManager::print(const GRState* state, std::ostream& Out,
const char* nl, const char *sep) {
// Print equality constraints.
- ConstEqTy CE = St->get<ConstEq>();
+ ConstEqTy CE = state->get<ConstEq>();
if (!CE.isEmpty()) {
Out << nl << sep << "'==' constraints:";
@@ -319,7 +298,7 @@ void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
// Print != constraints.
- ConstNotEqTy CNE = St->get<ConstNotEq>();
+ ConstNotEqTy CNE = state->get<ConstNotEq>();
if (!CNE.isEmpty()) {
Out << nl << sep << "'!=' constraints:";
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index 98e9551..aa85769 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -66,9 +66,6 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
APIMisuse *BT;
BugReporter& BR;
ASTContext &Ctx;
- GRStateManager* VMgr;
-
- SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); }
bool isNSString(ObjCInterfaceType* T, const char* suffix);
bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
@@ -79,9 +76,8 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
bool CheckNilArg(NodeTy* N, unsigned Arg);
public:
- BasicObjCFoundationChecks(ASTContext& ctx, GRStateManager* vmgr,
- BugReporter& br)
- : BT(0), BR(br), Ctx(ctx), VMgr(vmgr) {}
+ BasicObjCFoundationChecks(ASTContext& ctx, BugReporter& br)
+ : BT(0), BR(br), Ctx(ctx) {}
bool Audit(ExplodedNode<GRState>* N, GRStateManager&);
@@ -106,10 +102,8 @@ private:
GRSimpleAPICheck*
-clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx,
- GRStateManager* VMgr, BugReporter& BR) {
-
- return new BasicObjCFoundationChecks(Ctx, VMgr, BR);
+clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, BugReporter& BR) {
+ return new BasicObjCFoundationChecks(Ctx, BR);
}
@@ -157,7 +151,7 @@ bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
Expr * E = ME->getArg(Arg);
- if (isNil(GetSVal(N->getState(), E))) {
+ if (isNil(N->getState()->getSVal(E))) {
WarnNilArg(N, ME, Arg);
return true;
}
@@ -259,14 +253,11 @@ class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck {
// approach makes this class more stateless.
ASTContext& Ctx;
IdentifierInfo* II;
- GRStateManager* VMgr;
BugReporter& BR;
-
- SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); }
-
+
public:
- AuditCFNumberCreate(ASTContext& ctx, GRStateManager* vmgr, BugReporter& br)
- : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), VMgr(vmgr), BR(br){}
+ AuditCFNumberCreate(ASTContext& ctx, BugReporter& br)
+ : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), BR(br){}
~AuditCFNumberCreate() {}
@@ -374,14 +365,14 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Expr* Callee = CE->getCallee();
- SVal CallV = GetSVal(N->getState(), Callee);
+ SVal CallV = N->getState()->getSVal(Callee);
const FunctionDecl* FD = CallV.getAsFunctionDecl();
if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
return false;
// Get the value of the "theType" argument.
- SVal TheTypeVal = GetSVal(N->getState(), CE->getArg(1));
+ SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1));
// FIXME: We really should allow ranges of valid theType values, and
// bifurcate the state appropriately.
@@ -400,7 +391,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
// Look at the value of the integer being passed by reference. Essentially
// we want to catch cases where the value passed in is not equal to the
// size of the type being created.
- SVal TheValueExpr = GetSVal(N->getState(), CE->getArg(2));
+ SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2));
// FIXME: Eventually we should handle arbitrary locations. We can do this
// by having an enhanced memory model that does low-level typing.
@@ -469,9 +460,8 @@ void AuditCFNumberCreate::AddError(const TypedRegion* R, Expr* Ex,
}
GRSimpleAPICheck*
-clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
- GRStateManager* VMgr, BugReporter& BR) {
- return new AuditCFNumberCreate(Ctx, VMgr, BR);
+clang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) {
+ return new AuditCFNumberCreate(Ctx, BR);
}
//===----------------------------------------------------------------------===//
@@ -479,13 +469,12 @@ clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
void clang::RegisterAppleChecks(GRExprEngine& Eng) {
ASTContext& Ctx = Eng.getContext();
- GRStateManager* VMgr = &Eng.getStateManager();
BugReporter &BR = Eng.getBugReporter();
- Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, VMgr, BR),
+ Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, BR),
Stmt::ObjCMessageExprClass);
- Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, VMgr, BR),
+ Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, BR),
Stmt::CallExprClass);
RegisterNSErrorChecks(BR, Eng);
diff --git a/lib/Analysis/BasicObjCFoundationChecks.h b/lib/Analysis/BasicObjCFoundationChecks.h
index 6c594ea..5c9701e 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.h
+++ b/lib/Analysis/BasicObjCFoundationChecks.h
@@ -33,11 +33,9 @@ class BugReporter;
class GRExprEngine;
GRSimpleAPICheck* CreateBasicObjCFoundationChecks(ASTContext& Ctx,
- GRStateManager* VMgr,
BugReporter& BR);
GRSimpleAPICheck* CreateAuditCFNumberCreate(ASTContext& Ctx,
- GRStateManager* VMgr,
BugReporter& BR);
void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng);
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 2dd46c3..fcb405d 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -45,15 +45,14 @@ public:
~BasicStoreManager() {}
- SubRegionMap* getSubRegionMap(const GRState *state) {
+ SubRegionMap *getSubRegionMap(const GRState *state) {
return new BasicStoreSubRegionMap();
}
SVal Retrieve(const GRState *state, Loc loc, QualType T = QualType());
- const GRState* Bind(const GRState* St, Loc L, SVal V) {
- Store store = BindInternal(St->getStore(), L, V);
- return StateMgr.MakeStateWithStore(St, store);
+ const GRState *Bind(const GRState *state, Loc L, SVal V) {
+ return state->makeWithStore(BindInternal(state->getStore(), L, V));
}
Store scanForIvars(Stmt *B, const Decl* SelfDecl, Store St);
@@ -67,19 +66,19 @@ public:
return Loc::MakeVal(MRMgr.getVarRegion(VD));
}
- const GRState* BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL,
- SVal V) {
- return St;
+ const GRState *BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* cl,
+ SVal val) {
+ return state;
}
- SVal getLValueVar(const GRState* St, const VarDecl* VD);
- SVal getLValueString(const GRState* St, const StringLiteral* S);
- SVal getLValueCompoundLiteral(const GRState* St,
+ SVal getLValueVar(const GRState *state, const VarDecl* VD);
+ SVal getLValueString(const GRState *state, const StringLiteral* S);
+ SVal getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL);
- SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
- SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);
- SVal getLValueElement(const GRState* St, QualType elementType,
+ SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base);
+ SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D);
+ SVal getLValueElement(const GRState *state, QualType elementType,
SVal Base, SVal Offset);
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
@@ -92,23 +91,19 @@ public:
const MemRegion* getSelfRegion(Store) { return SelfRegion; }
/// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
- /// It returns a new Store with these values removed, and populates LSymbols
- /// and DSymbols with the known set of live and dead symbols respectively.
- Store
- RemoveDeadBindings(const GRState* state, Stmt* Loc,
+ /// It returns a new Store with these values removed.
+ Store RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
void iterBindings(Store store, BindingsHandler& f);
- const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) {
- Store store = BindDeclInternal(St->getStore(), VD, &InitVal);
- return StateMgr.MakeStateWithStore(St, store);
+ const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(),VD, &InitVal));
}
- const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
- Store store = BindDeclInternal(St->getStore(), VD, 0);
- return StateMgr.MakeStateWithStore(St, store);
+ const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(), VD, 0));
}
Store BindDeclInternal(Store store, const VarDecl* VD, SVal* InitVal);
@@ -130,21 +125,21 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
return new BasicStoreManager(StMgr);
}
-SVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
+SVal BasicStoreManager::getLValueVar(const GRState *state, const VarDecl* VD) {
return Loc::MakeVal(MRMgr.getVarRegion(VD));
}
-SVal BasicStoreManager::getLValueString(const GRState* St,
+SVal BasicStoreManager::getLValueString(const GRState *state,
const StringLiteral* S) {
return Loc::MakeVal(MRMgr.getStringRegion(S));
}
-SVal BasicStoreManager::getLValueCompoundLiteral(const GRState* St,
+SVal BasicStoreManager::getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL){
return Loc::MakeVal(MRMgr.getCompoundLiteralRegion(CL));
}
-SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl* D,
SVal Base) {
if (Base.isUnknownOrUndef())
@@ -162,7 +157,7 @@ SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
return UnknownVal();
}
-SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
+SVal BasicStoreManager::getLValueField(const GRState *state, SVal Base,
const FieldDecl* D) {
if (Base.isUnknownOrUndef())
@@ -194,7 +189,7 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
return Loc::MakeVal(MRMgr.getFieldRegion(D, BaseR));
}
-SVal BasicStoreManager::getLValueElement(const GRState* St,
+SVal BasicStoreManager::getLValueElement(const GRState *state,
QualType elementType,
SVal Base, SVal Offset) {
@@ -248,7 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St,
if (BaseR)
return Loc::MakeVal(MRMgr.getElementRegion(elementType, UnknownVal(),
- BaseR));
+ BaseR, getContext()));
else
return UnknownVal();
}
@@ -274,7 +269,7 @@ static bool isHigherOrderRawPtr(QualType T, ASTContext &C) {
}
}
-SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) {
+SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) {
if (isa<UnknownVal>(loc))
return UnknownVal();
@@ -390,7 +385,7 @@ Store BasicStoreManager::Remove(Store store, Loc loc) {
}
Store
-BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
+BasicStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 32998e1..5dbbfc3 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -336,7 +336,7 @@ GetMostRecentVarDeclBinding(const ExplodedNode<GRState>* N,
if (!DR)
continue;
- SVal Y = VMgr.GetSVal(N->getState(), DR);
+ SVal Y = N->getState()->getSVal(DR);
if (X != Y)
continue;
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index f5ca322..c58ceb4 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -971,8 +971,12 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXME: This should all be refactored into a chain of "summary lookup"
// filters.
+ assert (ScratchArgs.isEmpty());
+
switch (strlen(FName)) {
default: break;
+
+
case 17:
// Handle: id NSMakeCollectable(CFTypeRef)
if (!memcmp(FName, "NSMakeCollectable", 17)) {
@@ -980,13 +984,55 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
? getUnarySummary(FT, cfmakecollectable)
: getPersistentStopSummary();
}
+ else if (!memcmp(FName, "IOBSDNameMatching", 17) ||
+ !memcmp(FName, "IOServiceMatching", 17)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
break;
-
+
+ case 21:
+ if (!memcmp(FName, "IOServiceNameMatching", 21)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
+ break;
+
+ case 24:
+ if (!memcmp(FName, "IOServiceAddNotification", 24)) {
+ // 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);
+ }
+ break;
+
+ case 25:
+ if (!memcmp(FName, "IORegistryEntryIDMatching", 25)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
+ break;
+
+ case 26:
+ if (!memcmp(FName, "IOOpenFirmwarePathMatching", 26)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
+ break;
+
case 27:
if (!memcmp(FName, "IOServiceGetMatchingService", 27)) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
- assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
@@ -997,11 +1043,19 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXES: <rdar://problem/6326900>
// This should be addressed using a API table. This strcmp is also
// a little gross, but there is no need to super optimize here.
- assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
+
+ case 32:
+ if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
+ // Part of <rdar://problem/6961230>.
+ // This should be addressed using a API table.
+ ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ }
+ break;
}
// Did we get a summary?
@@ -1195,15 +1249,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(RetTy)) {
- if (FD->getAttr<NSReturnsRetainedAttr>()) {
+ if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(ObjCAllocRetE);
}
- else if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
else if (RetTy->getAsPointerType()) {
- if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@@ -1217,10 +1271,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(MD->getResultType())) {
- if (MD->getAttr<NSReturnsRetainedAttr>()) {
+ if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(ObjCAllocRetE);
}
- else if (MD->getAttr<CFReturnsRetainedAttr>()) {
+ else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@@ -1485,11 +1539,14 @@ void RetainSummaryManager::InitializeMethodSummaries() {
addInstMethSummary("QCView", AllocSumm,
"createSnapshotImageOfType", NULL);
- // Create summaries for CIContext, 'createCGImage'.
+ // Create summaries for CIContext, 'createCGImage' and
+ // 'createCGLayerWithSize'.
addInstMethSummary("CIContext", AllocSumm,
"createCGImage", "fromRect", NULL);
addInstMethSummary("CIContext", AllocSumm,
- "createCGImage", "fromRect", "format", "colorSpace", NULL);
+ "createCGImage", "fromRect", "format", "colorSpace", NULL);
+ addInstMethSummary("CIContext", AllocSumm, "createCGLayerWithSize",
+ "info", NULL);
}
//===----------------------------------------------------------------------===//
@@ -1747,11 +1804,11 @@ static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
return stack.isEmpty() ? SymbolRef() : stack.getHead();
}
-static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
- SymbolRef sym) {
+static const GRState * SendAutorelease(const GRState *state,
+ ARCounts::Factory &F, SymbolRef sym) {
SymbolRef pool = GetCurrentAutoreleasePool(state);
- const ARCounts *cnts = state.get<AutoreleasePoolContents>(pool);
+ const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
ARCounts newCnts(0);
if (cnts) {
@@ -1761,7 +1818,7 @@ static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
else
newCnts = F.Add(F.GetEmptyMap(), sym, 1);
- return state.set<AutoreleasePoolContents>(pool, newCnts);
+ return state->set<AutoreleasePoolContents>(pool, newCnts);
}
//===----------------------------------------------------------------------===//
@@ -1794,7 +1851,7 @@ private:
BugType *returnNotOwnedForOwned;
BugReporter *BR;
- GRStateRef Update(GRStateRef state, SymbolRef sym, RefVal V, ArgEffect E,
+ const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
RefVal::Kind& hasErr);
void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
@@ -1804,10 +1861,10 @@ private:
const GRState* St,
RefVal::Kind hasErr, SymbolRef Sym);
- GRStateRef HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V,
+ const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
llvm::SmallVectorImpl<SymbolRef> &Leaked);
- ExplodedNode<GRState>* ProcessLeaks(GRStateRef state,
+ ExplodedNode<GRState>* ProcessLeaks(const GRState * state,
llvm::SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilder &Builder,
GRExprEngine &Eng,
@@ -1882,8 +1939,8 @@ public:
Stmt* S, const GRState* state,
SymbolReaper& SymReaper);
- std::pair<ExplodedNode<GRState>*, GRStateRef>
- HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
+ std::pair<ExplodedNode<GRState>*, const GRState *>
+ HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
ExplodedNode<GRState>* Pred, GRExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop);
// Return statements.
@@ -1896,9 +1953,8 @@ public:
// Assumptions.
- virtual const GRState* EvalAssume(GRStateManager& VMgr,
- const GRState* St, SVal Cond,
- bool Assumption, bool& isFeasible);
+ virtual const GRState *EvalAssume(const GRState* state, SVal condition,
+ bool assumption);
};
} // end anonymous namespace
@@ -2226,15 +2282,14 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
return NULL;
// Check if the type state has changed.
- GRStateManager &StMgr = BRC.getStateManager();
- GRStateRef PrevSt(PrevN->getState(), StMgr);
- GRStateRef CurrSt(N->getState(), StMgr);
+ const GRState *PrevSt = PrevN->getState();
+ const GRState *CurrSt = N->getState();
- const RefVal* CurrT = CurrSt.get<RefBindings>(Sym);
+ const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
if (!CurrT) return NULL;
- const RefVal& CurrV = *CurrT;
- const RefVal* PrevT = PrevSt.get<RefBindings>(Sym);
+ const RefVal &CurrV = *CurrT;
+ const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
// Create a string buffer to constain all the useful things we want
// to tell the user.
@@ -2248,7 +2303,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available).
- SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee());
+ SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
if (const FunctionDecl* FD = X.getAsFunctionDecl())
os << "Call to function '" << FD->getNameAsString() <<'\'';
else
@@ -2305,7 +2360,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
// Retrieve the value of the argument. Is it the symbol
// we are interested in?
- if (CurrSt.GetSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
+ if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
continue;
// We have an argument. Get the effect!
@@ -2314,7 +2369,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
}
else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
if (Expr *receiver = ME->getReceiver())
- if (CurrSt.GetSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
+ if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
// The symbol we are tracking is the receiver.
AEffects.push_back(Summ->getReceiverEffect());
}
@@ -2342,7 +2397,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (contains(AEffects, MakeCollectable)) {
// Get the name of the function.
Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
- SVal X = CurrSt.GetSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
+ SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
const FunctionDecl* FD = X.getAsFunctionDecl();
const std::string& FName = FD->getNameAsString();
@@ -2453,7 +2508,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
// to Sym.
for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
if (Expr* Exp = dyn_cast_or_null<Expr>(*I))
- if (CurrSt.GetSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
+ if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
P->addRange(Exp->getSourceRange());
break;
}
@@ -2705,7 +2760,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// Get the state.
GRStateManager& StateMgr = Eng.getStateManager();
- GRStateRef state(Builder.GetState(Pred), StateMgr);
+ const GRState *state = Builder.GetState(Pred);
ASTContext& Ctx = StateMgr.getContext();
ValueManager &ValMgr = Eng.getValueManager();
@@ -2716,11 +2771,11 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
SymbolRef ErrorSym = 0;
for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
- SVal V = state.GetSValAsScalarOrLoc(*I);
+ SVal V = state->getSValAsScalarOrLoc(*I);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym)
- if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) {
+ if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
if (hasErr) {
ErrorExpr = *I;
@@ -2775,10 +2830,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
}
// Is the invalidated variable something that we were tracking?
- SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol();
+ SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol();
// Remove any existing reference-count binding.
- if (Sym) state = state.remove<RefBindings>(Sym);
+ if (Sym) state = state->remove<RefBindings>(Sym);
if (R->isBoundable(Ctx)) {
// Set the value of the variable to be a conjured symbol.
@@ -2788,7 +2843,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){
ValueManager &ValMgr = Eng.getValueManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, T, Count);
- state = state.BindLoc(Loc::MakeVal(R), V);
+ state = state->bindLoc(Loc::MakeVal(R), V);
}
else if (const RecordType *RT = T->getAsStructureType()) {
// Handle structs in a not so awesome way. Here we just
@@ -2802,7 +2857,8 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (!RD)
continue;
- MemRegionManager &MRMgr = state.getManager().getRegionManager();
+ MemRegionManager &MRMgr =
+ state->getStateManager().getRegionManager();
// Iterate through the fields and construct new symbols.
for (RecordDecl::field_iterator FI=RD->field_begin(Ctx),
@@ -2817,7 +2873,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
- state = state.BindLoc(Loc::MakeVal(FR), V);
+ state = state->bindLoc(Loc::MakeVal(FR), V);
}
}
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
@@ -2825,31 +2881,30 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, AT->getElementType(),
Count);
- state = GRStateRef(StoreMgr.setDefaultValue(state, R, V),
- StateMgr);
+ state = StoreMgr.setDefaultValue(state, R, V);
} else {
// Just blast away other values.
- state = state.BindLoc(*MR, UnknownVal());
+ state = state->bindLoc(*MR, UnknownVal());
}
}
}
else
- state = state.BindLoc(*MR, UnknownVal());
+ state = state->bindLoc(*MR, UnknownVal());
}
else {
// Nuke all other arguments passed by reference.
- state = state.Unbind(cast<Loc>(V));
+ state = state->unbindLoc(cast<Loc>(V));
}
}
else if (isa<nonloc::LocAsInteger>(V))
- state = state.Unbind(cast<nonloc::LocAsInteger>(V).getLoc());
+ state = state->unbindLoc(cast<nonloc::LocAsInteger>(V).getLoc());
}
// Evaluate the effect on the message receiver.
if (!ErrorExpr && Receiver) {
- SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol();
+ SymbolRef Sym = state->getSValAsScalarOrLoc(Receiver).getAsLocSymbol();
if (Sym) {
- if (const RefVal* T = state.get<RefBindings>(Sym)) {
+ if (const RefVal* T = state->get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
if (hasErr) {
ErrorExpr = Receiver;
@@ -2871,10 +2926,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
assert(Receiver);
- SVal V = state.GetSValAsScalarOrLoc(Receiver);
+ SVal V = state->getSValAsScalarOrLoc(Receiver);
bool found = false;
if (SymbolRef Sym = V.getAsLocSymbol())
- if (state.get<RefBindings>(Sym)) {
+ if (state->get<RefBindings>(Sym)) {
found = true;
RE = Summaries.getObjAllocRetEffect();
}
@@ -2902,7 +2957,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
unsigned Count = Builder.getCurrentBlockCount();
ValueManager &ValMgr = Eng.getValueManager();
SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count);
- state = state.BindExpr(Ex, X, false);
+ state = state->bindExpr(Ex, X, false);
}
break;
@@ -2912,15 +2967,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
unsigned idx = RE.getIndex();
assert (arg_end >= arg_beg);
assert (idx < (unsigned) (arg_end - arg_beg));
- SVal V = state.GetSValAsScalarOrLoc(*(arg_beg+idx));
- state = state.BindExpr(Ex, V, false);
+ SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx));
+ state = state->bindExpr(Ex, V, false);
break;
}
case RetEffect::ReceiverAlias: {
assert (Receiver);
- SVal V = state.GetSValAsScalarOrLoc(Receiver);
- state = state.BindExpr(Ex, V, false);
+ SVal V = state->getSValAsScalarOrLoc(Receiver);
+ state = state->bindExpr(Ex, V, false);
break;
}
@@ -2930,9 +2985,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ValueManager &ValMgr = Eng.getValueManager();
SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
- state = state.set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
+ state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
RetT));
- state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
+ state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
// FIXME: Add a flag to the checker where allocations are assumed to
// *not fail.
@@ -2953,9 +3008,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ValueManager &ValMgr = Eng.getValueManager();
SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
- state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
+ state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
RetT));
- state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
+ state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
break;
}
}
@@ -3001,7 +3056,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// FIXME: Is this really working as expected? There are cases where
// we just use the 'ID' from the message expression.
const GRState* St = Builder.GetState(Pred);
- SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
+ SVal V = St->getSValAsScalarOrLoc(Receiver);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym) {
@@ -3034,7 +3089,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// This is a hack. When we have full-IP this should be removed.
if (isa<ObjCMethodDecl>(&Eng.getGraph().getCodeDecl())) {
if (Expr* Receiver = ME->getReceiver()) {
- SVal X = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
+ SVal X = St->getSValAsScalarOrLoc(Receiver);
if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X))
if (L->getRegion() == Eng.getStateManager().getSelfRegion(St)) {
// Update the summary to make the default argument effect
@@ -3057,17 +3112,15 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
namespace {
class VISIBILITY_HIDDEN StopTrackingCallback : public SymbolVisitor {
- GRStateRef state;
+ const GRState *state;
public:
- StopTrackingCallback(GRStateRef st) : state(st) {}
- GRStateRef getState() { return state; }
+ StopTrackingCallback(const GRState *st) : state(st) {}
+ const GRState *getState() const { return state; }
bool VisitSymbol(SymbolRef sym) {
- state = state.remove<RefBindings>(sym);
+ state = state->remove<RefBindings>(sym);
return true;
}
-
- const GRState* getState() const { return state.getState(); }
};
} // end anonymous namespace
@@ -3082,7 +3135,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// (2) we are binding to a memregion that does not have stack storage
// (3) we are binding to a memregion with stack storage that the store
// does not understand.
- GRStateRef state = B.getState();
+ const GRState *state = B.getState();
if (!isa<loc::MemRegionVal>(location))
escapes = true;
@@ -3094,7 +3147,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// To test (3), generate a new state with the binding removed. If it is
// the same state, then it escapes (since the store cannot represent
// the binding).
- escapes = (state == (state.BindLoc(cast<Loc>(location), UnknownVal())));
+ escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal())));
}
}
@@ -3106,10 +3159,9 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// Otherwise, find all symbols referenced by 'val' that we are tracking
// and stop tracking them.
- B.MakeNode(state.scanReachableSymbols<StopTrackingCallback>(val).getState());
+ B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState());
}
-
// Return statements.
void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
@@ -3122,14 +3174,14 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
if (!RetE)
return;
- GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
- SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol();
+ const GRState *state = Builder.GetState(Pred);
+ SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
if (!Sym)
return;
// Get the reference count binding (if any).
- const RefVal* T = state.get<RefBindings>(Sym);
+ const RefVal* T = state->get<RefBindings>(Sym);
if (!T)
return;
@@ -3163,7 +3215,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
}
// Update the binding.
- state = state.set<RefBindings>(Sym, X);
+ state = state->set<RefBindings>(Sym, X);
Pred = Builder.MakeNode(Dst, S, Pred, state);
// Did we cache out?
@@ -3182,7 +3234,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
return;
// Get the updated binding.
- T = state.get<RefBindings>(Sym);
+ T = state->get<RefBindings>(Sym);
assert(T);
X = *T;
@@ -3217,7 +3269,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
if (hasError) {
// Generate an error node.
static int ReturnOwnLeakTag = 0;
- state = state.set<RefBindings>(Sym, X);
+ state = state->set<RefBindings>(Sym, X);
ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnOwnLeakTag), state, Pred);
if (N) {
@@ -3238,7 +3290,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
// owned object.
static int ReturnNotOwnedForOwnedTag = 0;
- state = state.set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
+ state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
if (ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnNotOwnedForOwnedTag),
state, Pred)) {
@@ -3254,10 +3306,8 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
// Assumptions.
-const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
- const GRState* St,
- SVal Cond, bool Assumption,
- bool& isFeasible) {
+const GRState* CFRefCount::EvalAssume(const GRState *state,
+ SVal Cond, bool Assumption) {
// FIXME: We may add to the interface of EvalAssume the list of symbols
// whose assumptions have changed. For now we just iterate through the
@@ -3265,32 +3315,30 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
// too bad since the number of symbols we will track in practice are
// probably small and EvalAssume is only called at branches and a few
// other places.
- RefBindings B = St->get<RefBindings>();
+ RefBindings B = state->get<RefBindings>();
if (B.isEmpty())
- return St;
+ return state;
- bool changed = false;
-
- GRStateRef state(St, VMgr);
- RefBindings::Factory& RefBFactory = state.get_context<RefBindings>();
+ bool changed = false;
+ RefBindings::Factory& RefBFactory = state->get_context<RefBindings>();
for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
// Check if the symbol is null (or equal to any constant).
// If this is the case, stop tracking the symbol.
- if (VMgr.getSymVal(St, I.getKey())) {
+ if (state->getSymVal(I.getKey())) {
changed = true;
B = RefBFactory.Remove(B, I.getKey());
}
}
if (changed)
- state = state.set<RefBindings>(B);
+ state = state->set<RefBindings>(B);
return state;
}
-GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
+const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
RefVal V, ArgEffect E,
RefVal::Kind& hasErr) {
@@ -3308,7 +3356,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
if (!isGCEnabled() && V.getKind() == RefVal::Released) {
V = V ^ RefVal::ErrorUseAfterRelease;
hasErr = V.getKind();
- return state.set<RefBindings>(sym, V);
+ return state->set<RefBindings>(sym, V);
}
switch (E) {
@@ -3330,7 +3378,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
// The object immediately transitions to the released state.
V = V ^ RefVal::Released;
V.clearCounts();
- return state.set<RefBindings>(sym, V);
+ return state->set<RefBindings>(sym, V);
case RefVal::NotOwned:
V = V ^ RefVal::ErrorDeallocNotOwned;
hasErr = V.getKind();
@@ -3340,7 +3388,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
case NewAutoreleasePool:
assert(!isGCEnabled());
- return state.add<AutoreleaseStack>(sym);
+ return state->add<AutoreleaseStack>(sym);
case MayEscape:
if (V.getKind() == RefVal::Owned) {
@@ -3364,7 +3412,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
break;
case StopTracking:
- return state.remove<RefBindings>(sym);
+ return state->remove<RefBindings>(sym);
case IncRef:
switch (V.getKind()) {
@@ -3416,15 +3464,15 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
}
break;
}
- return state.set<RefBindings>(sym, V);
+ return state->set<RefBindings>(sym, V);
}
//===----------------------------------------------------------------------===//
// Handle dead symbols and end-of-path.
//===----------------------------------------------------------------------===//
-std::pair<ExplodedNode<GRState>*, GRStateRef>
-CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
+std::pair<ExplodedNode<GRState>*, const GRState *>
+CFRefCount::HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
ExplodedNode<GRState>* Pred,
GRExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop) {
@@ -3456,7 +3504,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
V.setCount(Cnt - ACnt);
V.setAutoreleaseCount(0);
}
- state = state.set<RefBindings>(Sym, V);
+ state = state->set<RefBindings>(Sym, V);
ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred);
stop = (N == 0);
return std::make_pair(N, state);
@@ -3466,7 +3514,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
// Emit hard error.
stop = true;
V = V ^ RefVal::ErrorOverAutorelease;
- state = state.set<RefBindings>(Sym, V);
+ state = state->set<RefBindings>(Sym, V);
if (ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred)) {
N->markAsSink();
@@ -3492,22 +3540,22 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
return std::make_pair((ExplodedNode<GRState>*)0, state);
}
-GRStateRef
-CFRefCount::HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V,
+const GRState *
+CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
llvm::SmallVectorImpl<SymbolRef> &Leaked) {
bool hasLeak = V.isOwned() ||
((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
if (!hasLeak)
- return state.remove<RefBindings>(sid);
+ return state->remove<RefBindings>(sid);
Leaked.push_back(sid);
- return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
+ return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
}
ExplodedNode<GRState>*
-CFRefCount::ProcessLeaks(GRStateRef state,
+CFRefCount::ProcessLeaks(const GRState * state,
llvm::SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilder &Builder,
GRExprEngine& Eng,
@@ -3537,9 +3585,9 @@ CFRefCount::ProcessLeaks(GRStateRef state,
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
GREndPathNodeBuilder<GRState>& Builder) {
- GRStateRef state(Builder.getState(), Eng.getStateManager());
+ const GRState *state = Builder.getState();
GenericNodeBuilder Bd(Builder);
- RefBindings B = state.get<RefBindings>();
+ RefBindings B = state->get<RefBindings>();
ExplodedNode<GRState> *Pred = 0;
for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
@@ -3552,7 +3600,7 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
return;
}
- B = state.get<RefBindings>();
+ B = state->get<RefBindings>();
llvm::SmallVector<SymbolRef, 10> Leaked;
for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
@@ -3566,11 +3614,10 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
GRStmtNodeBuilder<GRState>& Builder,
ExplodedNode<GRState>* Pred,
Stmt* S,
- const GRState* St,
+ const GRState* state,
SymbolReaper& SymReaper) {
- GRStateRef state(St, Eng.getStateManager());
- RefBindings B = state.get<RefBindings>();
+ RefBindings B = state->get<RefBindings>();
// Update counts from autorelease pools
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
@@ -3588,7 +3635,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
}
}
- B = state.get<RefBindings>();
+ B = state->get<RefBindings>();
llvm::SmallVector<SymbolRef, 10> Leaked;
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
@@ -3608,12 +3655,12 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
return;
// Now generate a new node that nukes the old bindings.
- RefBindings::Factory& F = state.get_context<RefBindings>();
+ RefBindings::Factory& F = state->get_context<RefBindings>();
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
E = SymReaper.dead_end(); I!=E; ++I) B = F.Remove(B, *I);
- state = state.set<RefBindings>(B);
+ state = state->set<RefBindings>(B);
Builder.MakeNode(Dst, S, Pred, state);
}
diff --git a/lib/Analysis/CheckDeadStores.cpp b/lib/Analysis/CheckDeadStores.cpp
index 69433d6..0f61a5e 100644
--- a/lib/Analysis/CheckDeadStores.cpp
+++ b/lib/Analysis/CheckDeadStores.cpp
@@ -85,7 +85,7 @@ public:
const LiveVariables::AnalysisDataTy& AD,
const LiveVariables::ValTy& Live) {
- if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>())
+ if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx))
Report(VD, dsk, Ex->getSourceRange().getBegin(),
Val->getSourceRange());
}
@@ -190,7 +190,7 @@ public:
// A dead initialization is a variable that is dead after it
// is initialized. We don't flag warnings for those variables
// marked 'unused'.
- if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
+ if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) {
// Special case: check for initializations with constants.
//
// e.g. : int x = 0;
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/CheckNSError.cpp
index ff9da0f..c91442b 100644
--- a/lib/Analysis/CheckNSError.cpp
+++ b/lib/Analysis/CheckNSError.cpp
@@ -41,7 +41,7 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
bool CheckNSErrorArgument(QualType ArgTy);
bool CheckCFErrorArgument(QualType ArgTy);
- void CheckParamDeref(VarDecl* V, GRStateRef state, BugReporter& BR);
+ void CheckParamDeref(VarDecl* V, const GRState *state, BugReporter& BR);
void EmitRetTyWarning(BugReporter& BR, Decl& CodeDecl);
@@ -94,8 +94,7 @@ void NSErrorCheck::FlushReports(BugReporter& BR) {
// Scan the parameters for an implicit null dereference.
for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(),
E=ErrorParams.end(); I!=E; ++I)
- CheckParamDeref(*I, GRStateRef((*RI)->getState(),Eng.getStateManager()),
- BR);
+ CheckParamDeref(*I, (*RI)->getState(), BR);
}
}
@@ -186,13 +185,13 @@ bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
return TT->getDecl()->getIdentifier() == II;
}
-void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
+void NSErrorCheck::CheckParamDeref(VarDecl* Param, const GRState *rootState,
BugReporter& BR) {
- SVal ParamL = rootState.GetLValue(Param);
+ SVal ParamL = rootState->getLValue(Param);
const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
assert (ParamR && "Parameters always have VarRegions.");
- SVal ParamSVal = rootState.GetSVal(ParamR);
+ SVal ParamSVal = rootState->getSVal(ParamR);
// FIXME: For now assume that ParamSVal is symbolic. We need to generalize
// this later.
@@ -204,8 +203,8 @@ void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(),
E=Eng.implicit_null_derefs_end(); I!=E; ++I) {
- GRStateRef state = GRStateRef((*I)->getState(), Eng.getStateManager());
- const SVal* X = state.get<GRState::NullDerefTag>();
+ const GRState *state = (*I)->getState();
+ const SVal* X = state->get<GRState::NullDerefTag>();
if (!X || X->getAsSymbol() != ParamSym)
continue;
diff --git a/lib/Analysis/CheckObjCDealloc.cpp b/lib/Analysis/CheckObjCDealloc.cpp
index f50d7a1..2ba7d86 100644
--- a/lib/Analysis/CheckObjCDealloc.cpp
+++ b/lib/Analysis/CheckObjCDealloc.cpp
@@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
QualType T = ID->getType();
if (!Ctx.isObjCObjectPointerType(T) ||
- ID->getAttr<IBOutletAttr>()) // Skip IBOutlets.
+ ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets.
continue;
containsPointerIvar = true;
diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp
index 7979f9c..92c50e2 100644
--- a/lib/Analysis/CheckObjCUnusedIVars.cpp
+++ b/lib/Analysis/CheckObjCUnusedIVars.cpp
@@ -74,7 +74,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) {
continue;
// Skip IB Outlets.
- if (ID->getAttr<IBOutletAttr>())
+ if (ID->getAttr<IBOutletAttr>(Ctx))
continue;
M[ID] = Unused;
diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp
index 2bc071a..7ada6d8 100644
--- a/lib/Analysis/Environment.cpp
+++ b/lib/Analysis/Environment.cpp
@@ -18,7 +18,7 @@
using namespace clang;
-SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
+SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
for (;;) {
@@ -34,7 +34,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
continue;
case Stmt::CharacterLiteralClass: {
- CharacterLiteral* C = cast<CharacterLiteral>(E);
+ const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
}
@@ -48,7 +48,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
case Stmt::ImplicitCastExprClass:
case Stmt::CStyleCastExprClass: {
- CastExpr* C = cast<CastExpr>(E);
+ const CastExpr* C = cast<CastExpr>(E);
QualType CT = C->getType();
if (CT->isVoidType())
@@ -69,7 +69,8 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
return LookupExpr(E);
}
-SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
+SVal Environment::GetBlkExprSVal(const Stmt *E,
+ BasicValueFactory& BasicVals) const {
while (1) {
switch (E->getStmtClass()) {
@@ -78,7 +79,7 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
continue;
case Stmt::CharacterLiteralClass: {
- CharacterLiteral* C = cast<CharacterLiteral>(E);
+ const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
}
@@ -92,8 +93,9 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
}
}
-Environment EnvironmentManager::BindExpr(const Environment& Env, Stmt* E,SVal V,
- bool isBlkExpr, bool Invalidate) {
+Environment EnvironmentManager::BindExpr(const Environment& Env, const Stmt* E,
+ SVal V, bool isBlkExpr,
+ bool Invalidate) {
assert (E);
if (V.isUnknown()) {
@@ -136,7 +138,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
// Iterate over the block-expr bindings.
for (Environment::beb_iterator I = Env.beb_begin(), E = Env.beb_end();
I != E; ++I) {
- Stmt* BlkExpr = I.getKey();
+ const Stmt *BlkExpr = I.getKey();
if (SymReaper.isLive(Loc, BlkExpr)) {
SVal X = I.getData();
@@ -147,7 +149,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
// Mark all symbols in the block expr's value live.
MarkLiveCallback cb(SymReaper);
- StateMgr.scanReachableSymbols(X, state, cb);
+ state->scanReachableSymbols(X, cb);
} else {
// The block expr is dead.
SVal X = I.getData();
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 7a8fef5..87432d4 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -177,14 +177,13 @@ const GRState* GRExprEngine::getInitialState() {
QualType T = PD->getType();
if (T->isIntegerType())
if (const MemRegion *R = StateMgr.getRegion(PD)) {
- SVal V = GetSVal(state, loc::MemRegionVal(R));
+ SVal V = state->getSVal(loc::MemRegionVal(R));
SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V,
ValMgr.makeZeroVal(T),
getContext().IntTy);
- bool isFeasible = false;
- const GRState *newState = Assume(state, Constraint, true,
- isFeasible);
- if (newState) state = newState;
+
+ if (const GRState *newState = state->assume(Constraint, true))
+ state = newState;
}
}
@@ -310,7 +309,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
}
else if (B->getOpcode() == BinaryOperator::Comma) {
const GRState* state = GetState(Pred);
- MakeNode(Dst, B, Pred, BindExpr(state, B, GetSVal(state, B->getRHS())));
+ MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS())));
break;
}
@@ -426,7 +425,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
const GRState* state = GetState(Pred);
- MakeNode(Dst, SE, Pred, BindExpr(state, SE, GetSVal(state, LastExpr)));
+ MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr)));
}
else
Dst.Add(Pred);
@@ -506,8 +505,8 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
case Stmt::StringLiteralClass: {
const GRState* state = GetState(Pred);
- SVal V = StateMgr.GetLValue(state, cast<StringLiteral>(Ex));
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V));
+ SVal V = state->getLValue(cast<StringLiteral>(Ex));
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
return;
}
@@ -579,7 +578,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
(Op == BinaryOperator::LOr && !branchTaken)
? B->getRHS() : B->getLHS();
- return BindBlkExpr(state, B, UndefinedVal(Ex));
+ return state->bindBlkExpr(B, UndefinedVal(Ex));
}
case Stmt::ConditionalOperatorClass: { // ?:
@@ -596,7 +595,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
else
Ex = C->getRHS();
- return BindBlkExpr(state, C, UndefinedVal(Ex));
+ return state->bindBlkExpr(C, UndefinedVal(Ex));
}
case Stmt::ChooseExprClass: { // ?:
@@ -604,7 +603,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
ChooseExpr* C = cast<ChooseExpr>(Terminator);
Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
- return BindBlkExpr(state, C, UndefinedVal(Ex));
+ return state->bindBlkExpr(C, UndefinedVal(Ex));
}
}
}
@@ -645,7 +644,7 @@ static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
return UnknownVal();
- return StateMgr.GetSVal(state, Ex);
+ return state->getSVal(Ex);
}
void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
@@ -665,7 +664,7 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
Condition->getLocStart(),
"Error evaluating branch");
- SVal V = GetSVal(PrevState, Condition);
+ SVal V = PrevState->getSVal(Condition);
switch (V.getBaseKind()) {
default:
@@ -708,21 +707,13 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
}
// Process the true branch.
-
- bool isFeasible = false;
- const GRState* state = Assume(PrevState, V, true, isFeasible);
-
- if (isFeasible)
+ if (const GRState *state = PrevState->assume(V, true))
builder.generateNode(MarkBranch(state, Term, true), true);
else
builder.markInfeasible(true);
// Process the false branch.
-
- isFeasible = false;
- state = Assume(PrevState, V, false, isFeasible);
-
- if (isFeasible)
+ if (const GRState *state = PrevState->assume(V, false))
builder.generateNode(MarkBranch(state, Term, false), false);
else
builder.markInfeasible(false);
@@ -732,8 +723,8 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
/// nodes by processing the 'effects' of a computed goto jump.
void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
- const GRState* state = builder.getState();
- SVal V = GetSVal(state, builder.getTarget());
+ const GRState *state = builder.getState();
+ SVal V = state->getSVal(builder.getTarget());
// Three possibilities:
//
@@ -779,18 +770,16 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex));
const GRState* state = GetState(Pred);
- SVal X = GetBlkExprSVal(state, Ex);
+ SVal X = state->getBlkExprSVal(Ex);
assert (X.isUndef());
- Expr* SE = (Expr*) cast<UndefinedVal>(X).getData();
-
- assert (SE);
-
- X = GetBlkExprSVal(state, SE);
+ Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
+ assert(SE);
+ X = state->getBlkExprSVal(SE);
// Make sure that we invalidate the previous binding.
- MakeNode(Dst, Ex, Pred, StateMgr.BindExpr(state, Ex, X, true, true));
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, X, true, true));
}
/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
@@ -799,7 +788,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
typedef SwitchNodeBuilder::iterator iterator;
const GRState* state = builder.getState();
Expr* CondE = builder.getCondition();
- SVal CondV = GetSVal(state, CondE);
+ SVal CondV = state->getSVal(CondE);
if (CondV.isUndef()) {
NodeTy* N = builder.generateDefaultCaseNode(state, true);
@@ -808,7 +797,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
}
const GRState* DefaultSt = state;
- bool DefaultFeasible = false;
+ bool defaultIsFeasible = false;
for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
CaseStmt* Case = cast<CaseStmt>(I.getCase());
@@ -846,11 +835,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
getContext().IntTy);
// Now "assume" that the case matches.
- bool isFeasible = false;
- const GRState* StNew = Assume(state, Res, true, isFeasible);
-
- if (isFeasible) {
- builder.generateCaseStmtNode(I, StNew);
+ if (const GRState* stateNew = state->assume(Res, true)) {
+ builder.generateCaseStmtNode(I, stateNew);
// If CondV evaluates to a constant, then we know that this
// is the *only* case that we can take, so stop evaluating the
@@ -861,13 +847,9 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
// Now "assume" that the case doesn't match. Add this state
// to the default state (if it is feasible).
-
- isFeasible = false;
- StNew = Assume(DefaultSt, Res, false, isFeasible);
-
- if (isFeasible) {
- DefaultFeasible = true;
- DefaultSt = StNew;
+ if (const GRState *stateNew = DefaultSt->assume(Res, false)) {
+ defaultIsFeasible = true;
+ DefaultSt = stateNew;
}
// Concretize the next value in the range.
@@ -882,7 +864,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
// If we reach here, than we know that the default branch is
// possible.
- if (DefaultFeasible) builder.generateDefaultCaseNode(DefaultSt);
+ if (defaultIsFeasible) builder.generateDefaultCaseNode(DefaultSt);
}
//===----------------------------------------------------------------------===//
@@ -892,28 +874,27 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
NodeSet& Dst) {
- assert (B->getOpcode() == BinaryOperator::LAnd ||
- B->getOpcode() == BinaryOperator::LOr);
+ assert(B->getOpcode() == BinaryOperator::LAnd ||
+ B->getOpcode() == BinaryOperator::LOr);
- assert (B == CurrentStmt && getCFG().isBlkExpr(B));
+ assert(B == CurrentStmt && getCFG().isBlkExpr(B));
const GRState* state = GetState(Pred);
- SVal X = GetBlkExprSVal(state, B);
-
- assert (X.isUndef());
+ SVal X = state->getBlkExprSVal(B);
+ assert(X.isUndef());
Expr* Ex = (Expr*) cast<UndefinedVal>(X).getData();
- assert (Ex);
+ assert(Ex);
if (Ex == B->getRHS()) {
- X = GetBlkExprSVal(state, Ex);
+ X = state->getBlkExprSVal(Ex);
// Handle undefined values.
if (X.isUndef()) {
- MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X));
+ MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
return;
}
@@ -922,29 +903,19 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
// or 1. Alternatively, we could take a lazy approach, and calculate this
// value later when necessary. We don't have the machinery in place for
// this right now, and since most logical expressions are used for branches,
- // the payoff is not likely to be large. Instead, we do eager evaluation.
-
- bool isFeasible = false;
- const GRState* NewState = Assume(state, X, true, isFeasible);
-
- if (isFeasible)
- MakeNode(Dst, B, Pred,
- BindBlkExpr(NewState, B, MakeConstantVal(1U, B)));
+ // the payoff is not likely to be large. Instead, we do eager evaluation.
+ if (const GRState *newState = state->assume(X, true))
+ MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(1U, B)));
- isFeasible = false;
- NewState = Assume(state, X, false, isFeasible);
-
- if (isFeasible)
- MakeNode(Dst, B, Pred,
- BindBlkExpr(NewState, B, MakeConstantVal(0U, B)));
+ if (const GRState *newState = state->assume(X, false))
+ MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(0U, B)));
}
else {
// We took the LHS expression. Depending on whether we are '&&' or
// '||' we know what the value of the expression is via properties of
// the short-circuiting.
-
X = MakeConstantVal( B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U, B);
- MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X));
+ MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
}
}
@@ -961,10 +932,10 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
- SVal V = StateMgr.GetLValue(state, VD);
+ SVal V = state->getLValue(VD);
if (asLValue)
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V),
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, Ex, Pred, state, V);
@@ -975,13 +946,13 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
SVal V = nonloc::ConcreteInt(BasicVals.getValue(ED->getInitVal()));
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V));
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
return;
} else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
assert(asLValue);
SVal V = ValMgr.getFunctionPointer(FD);
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V),
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V),
ProgramPoint::PostLValueKind);
return;
}
@@ -1014,12 +985,11 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred,
for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) {
const GRState* state = GetState(*I2);
- SVal V = StateMgr.GetLValue(state, A->getType(),
- GetSVal(state, Base),
- GetSVal(state, Idx));
+ SVal V = state->getLValue(A->getType(), state->getSVal(Base),
+ state->getSVal(Idx));
if (asLValue)
- MakeNode(Dst, A, *I2, BindExpr(state, A, V),
+ MakeNode(Dst, A, *I2, state->bindExpr(A, V),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, A, *I2, state, V);
@@ -1048,10 +1018,10 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
// FIXME: Should we insert some assumption logic in here to determine
// if "Base" is a valid piece of memory? Before we put this assumption
// later when using FieldOffset lvals (which we no longer have).
- SVal L = StateMgr.GetLValue(state, GetSVal(state, Base), Field);
+ SVal L = state->getLValue(state->getSVal(Base), Field);
if (asLValue)
- MakeNode(Dst, M, *I, BindExpr(state, M, L),
+ MakeNode(Dst, M, *I, state->bindExpr(M, L),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, M, *I, state, L);
@@ -1135,11 +1105,11 @@ void GRExprEngine::EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
if (location.isUnknown()) {
// This is important. We must nuke the old binding.
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, UnknownVal()), K, tag);
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal()), K, tag);
}
else {
- SVal V = GetSVal(state, cast<Loc>(location), Ex->getType());
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), K, tag);
+ SVal V = state->getSVal(cast<Loc>(location), Ex->getType());
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), K, tag);
}
}
@@ -1189,19 +1159,15 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
Loc LV = cast<Loc>(location);
// "Assume" that the pointer is not NULL.
- bool isFeasibleNotNull = false;
- const GRState* StNotNull = Assume(state, LV, true, isFeasibleNotNull);
+ const GRState *StNotNull = state->assume(LV, true);
// "Assume" that the pointer is NULL.
- bool isFeasibleNull = false;
- GRStateRef StNull = GRStateRef(Assume(state, LV, false, isFeasibleNull),
- getStateManager());
+ const GRState *StNull = state->assume(LV, false);
- if (isFeasibleNull) {
-
+ if (StNull) {
// Use the Generic Data Map to mark in the state what lval was null.
const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV);
- StNull = StNull.set<GRState::NullDerefTag>(PersistentLV);
+ StNull = StNull->set<GRState::NullDerefTag>(PersistentLV);
// We don't use "MakeNode" here because the node will be a sink
// and we have no intention of processing it later.
@@ -1209,17 +1175,15 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
Builder->generateNode(Ex, StNull, Pred,
ProgramPoint::PostNullCheckFailedKind);
- if (NullNode) {
-
- NullNode->markAsSink();
-
- if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
+ if (NullNode) {
+ NullNode->markAsSink();
+ if (StNotNull) ImplicitNullDeref.insert(NullNode);
else ExplicitNullDeref.insert(NullNode);
}
}
- if (!isFeasibleNotNull)
- return 0;
+ if (!StNotNull)
+ return NULL;
// Check for out-of-bound array access.
if (isa<loc::MemRegionVal>(LV)) {
@@ -1231,15 +1195,12 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
SVal NumElements = getStoreManager().getSizeInElements(StNotNull,
ER->getSuperRegion());
- bool isFeasibleInBound = false;
- const GRState* StInBound = AssumeInBound(StNotNull, Idx, NumElements,
- true, isFeasibleInBound);
-
- bool isFeasibleOutBound = false;
- const GRState* StOutBound = AssumeInBound(StNotNull, Idx, NumElements,
- false, isFeasibleOutBound);
+ const GRState * StInBound = StNotNull->assumeInBound(Idx, NumElements,
+ true);
+ const GRState* StOutBound = StNotNull->assumeInBound(Idx, NumElements,
+ false);
- if (isFeasibleOutBound) {
+ if (StOutBound) {
// Report warning. Make sink node manually.
NodeTy* OOBNode =
Builder->generateNode(Ex, StOutBound, Pred,
@@ -1248,16 +1209,16 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
if (OOBNode) {
OOBNode->markAsSink();
- if (isFeasibleInBound)
+ if (StInBound)
ImplicitOOBMemAccesses.insert(OOBNode);
else
ExplicitOOBMemAccesses.insert(OOBNode);
}
}
- if (!isFeasibleInBound)
- return 0;
-
+ if (!StInBound)
+ return NULL;
+
StNotNull = StInBound;
}
}
@@ -1319,10 +1280,9 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
const void *OSAtomicStoreTag = &magic_store;
// Load 'theValue'.
- GRStateManager &StateMgr = Engine.getStateManager();
const GRState *state = Pred->getState();
ExplodedNodeSet<GRState> Tmp;
- SVal location = StateMgr.GetSVal(state, theValueExpr);
+ SVal location = state->getSVal(theValueExpr);
Engine.EvalLoad(Tmp, theValueExpr, Pred, state, location, OSAtomicLoadTag);
for (ExplodedNodeSet<GRState>::iterator I = Tmp.begin(), E = Tmp.end();
@@ -1330,24 +1290,22 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
ExplodedNode<GRState> *N = *I;
const GRState *stateLoad = N->getState();
- SVal theValueVal = StateMgr.GetSVal(stateLoad, theValueExpr);
- SVal oldValueVal = StateMgr.GetSVal(stateLoad, oldValueExpr);
+ SVal theValueVal = stateLoad->getSVal(theValueExpr);
+ SVal oldValueVal = stateLoad->getSVal(oldValueExpr);
// Perform the comparison.
SVal Cmp = Engine.EvalBinOp(stateLoad,
BinaryOperator::EQ, theValueVal, oldValueVal,
Engine.getContext().IntTy);
- bool isFeasible = false;
- const GRState *stateEqual = StateMgr.Assume(stateLoad, Cmp, true,
- isFeasible);
+
+ const GRState *stateEqual = stateLoad->assume(Cmp, true);
// Were they equal?
- if (isFeasible) {
+ if (stateEqual) {
// Perform the store.
ExplodedNodeSet<GRState> TmpStore;
Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location,
- StateMgr.GetSVal(stateEqual, newValueExpr),
- OSAtomicStoreTag);
+ stateEqual->getSVal(newValueExpr), OSAtomicStoreTag);
// Now bind the result of the comparison.
for (ExplodedNodeSet<GRState>::iterator I2 = TmpStore.begin(),
@@ -1355,18 +1313,14 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
ExplodedNode<GRState> *predNew = *I2;
const GRState *stateNew = predNew->getState();
SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType());
- Engine.MakeNode(Dst, CE, predNew, Engine.BindExpr(stateNew, CE, Res));
+ Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res));
}
}
// Were they not equal?
- isFeasible = false;
- const GRState *stateNotEqual = StateMgr.Assume(stateLoad, Cmp, false,
- isFeasible);
-
- if (isFeasible) {
+ if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) {
SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType());
- Engine.MakeNode(Dst, CE, N, Engine.BindExpr(stateNotEqual, CE, Res));
+ Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res));
}
}
@@ -1460,7 +1414,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) {
const GRState* state = GetState(*DI);
- SVal L = GetSVal(state, Callee);
+ SVal L = state->getSVal(Callee);
// FIXME: Add support for symbolic function calls (calls involving
// function pointer values that are symbolic).
@@ -1483,7 +1437,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
const FunctionDecl* FD = L.getAsFunctionDecl();
if (FD) {
- if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>())
+ if (FD->getAttr<NoReturnAttr>(getContext()) ||
+ FD->getAttr<AnalyzerNoReturnAttr>(getContext()))
Builder->BuildSinks = true;
else {
// HACK: Some functions are not marked noreturn, and don't return.
@@ -1504,7 +1459,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
else if (!memcmp(s, "error", 5)) {
if (CE->getNumArgs() > 0) {
- SVal X = GetSVal(state, *CE->arg_begin());
+ SVal X = state->getSVal(*CE->arg_begin());
// FIXME: use Assume to inspect the possible symbolic value of
// X. Also check the specific signature of error().
nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
@@ -1571,8 +1526,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
case Builtin::BI__builtin_expect: {
// For __builtin_expect, just return the value of the subexpression.
assert (CE->arg_begin() != CE->arg_end());
- SVal X = GetSVal(state, *(CE->arg_begin()));
- MakeNode(Dst, CE, *DI, BindExpr(state, CE, X));
+ SVal X = state->getSVal(*(CE->arg_begin()));
+ MakeNode(Dst, CE, *DI, state->bindExpr(CE, X));
continue;
}
@@ -1585,10 +1540,10 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
// Set the extent of the region in bytes. This enables us to use the
// SVal of the argument directly. If we save the extent in bits, we
// cannot represent values like symbol*8.
- SVal Extent = GetSVal(state, *(CE->arg_begin()));
+ SVal Extent = state->getSVal(*(CE->arg_begin()));
state = getStoreManager().setExtent(state, R, Extent);
- MakeNode(Dst, CE, *DI, BindExpr(state, CE, loc::MemRegionVal(R)));
+ MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R)));
continue;
}
@@ -1604,7 +1559,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
- if (GetSVal(GetState(*DI), *I).isUndef()) {
+ if (GetState(*DI)->getSVal(*I).isUndef()) {
NodeTy* N = Builder->generateNode(CE, GetState(*DI), *DI);
if (N) {
@@ -1656,22 +1611,18 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) {
}
const GRState* state = Pred->getState();
- SVal V = GetSVal(state, Ex);
+ SVal V = state->getSVal(Ex);
if (isa<nonloc::SymExprVal>(V)) {
// First assume that the condition is true.
- bool isFeasible = false;
- const GRState *stateTrue = Assume(state, V, true, isFeasible);
- if (isFeasible) {
- stateTrue = BindExpr(stateTrue, Ex, MakeConstantVal(1U, Ex));
+ if (const GRState *stateTrue = state->assume(V, true)) {
+ stateTrue = stateTrue->bindExpr(Ex, MakeConstantVal(1U, Ex));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateTrue, Pred));
}
// Next, assume that the condition is false.
- isFeasible = false;
- const GRState *stateFalse = Assume(state, V, false, isFeasible);
- if (isFeasible) {
- stateFalse = BindExpr(stateFalse, Ex, MakeConstantVal(0U, Ex));
+ if (const GRState *stateFalse = state->assume(V, false)) {
+ stateFalse = stateFalse->bindExpr(Ex, MakeConstantVal(0U, Ex));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateFalse, Pred));
}
@@ -1695,11 +1646,11 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal BaseVal = GetSVal(state, Base);
- SVal location = StateMgr.GetLValue(state, Ex->getDecl(), BaseVal);
+ SVal BaseVal = state->getSVal(Base);
+ SVal location = state->getLValue(Ex->getDecl(), BaseVal);
if (asLValue)
- MakeNode(Dst, Ex, *I, BindExpr(state, Ex, location));
+ MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location));
else
EvalLoad(Dst, Ex, *I, state, location);
}
@@ -1743,7 +1694,7 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
assert (ElemD->getInit() == 0);
- ElementV = getStateManager().GetLValue(GetState(Pred), ElemD);
+ ElementV = GetState(Pred)->getLValue(ElemD);
VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
return;
}
@@ -1753,7 +1704,7 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- VisitObjCForCollectionStmtAux(S, *I, Dst, GetSVal(state, elem));
+ VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem));
}
}
@@ -1771,16 +1722,16 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
if (!Pred)
return;
- GRStateRef state = GRStateRef(GetState(Pred), getStateManager());
+ const GRState *state = GetState(Pred);
// Handle the case where the container still has elements.
QualType IntTy = getContext().IntTy;
SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy);
- GRStateRef hasElems = state.BindExpr(S, TrueV);
+ const GRState *hasElems = state->bindExpr(S, TrueV);
// Handle the case where the container has no elements.
SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy);
- GRStateRef noElems = state.BindExpr(S, FalseV);
+ const GRState *noElems = state->bindExpr(S, FalseV);
if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
@@ -1792,11 +1743,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
unsigned Count = Builder->getCurrentBlockCount();
SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
SVal V = Loc::MakeVal(getStoreManager().getRegionManager().getSymbolicRegion(Sym));
- hasElems = hasElems.BindLoc(ElementV, V);
+ hasElems = hasElems->bindLoc(ElementV, V);
// Bind the location to 'nil' on the false branch.
SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T));
- noElems = noElems.BindLoc(ElementV, nilV);
+ noElems = noElems->bindLoc(ElementV, nilV);
}
// Create the new nodes.
@@ -1858,7 +1809,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
if (Expr* Receiver = ME->getReceiver()) {
- SVal L = GetSVal(state, Receiver);
+ SVal L = state->getSVal(Receiver);
// Check for undefined control-flow.
if (L.isUndef()) {
@@ -1873,14 +1824,12 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
}
// "Assume" that the receiver is not NULL.
- bool isFeasibleNotNull = false;
- const GRState *StNotNull = Assume(state, L, true, isFeasibleNotNull);
+ const GRState *StNotNull = state->assume(L, true);
// "Assume" that the receiver is NULL.
- bool isFeasibleNull = false;
- const GRState *StNull = Assume(state, L, false, isFeasibleNull);
+ const GRState *StNull = state->assume(L, false);
- if (isFeasibleNull) {
+ if (StNull) {
QualType RetTy = ME->getType();
// Check if the receiver was nil and the return value a struct.
@@ -1894,7 +1843,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// garbage.
if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) {
N->markAsSink();
- if (isFeasibleNotNull)
+ if (StNotNull)
NilReceiverStructRetImplicit.insert(N);
else
NilReceiverStructRetExplicit.insert(N);
@@ -1913,13 +1862,13 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
if(voidPtrSize < returnTypeSize) {
if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) {
N->markAsSink();
- if(isFeasibleNotNull)
+ if(StNotNull)
NilReceiverLargerThanVoidPtrRetImplicit.insert(N);
else
NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
}
}
- else if (!isFeasibleNotNull) {
+ else if (!StNotNull) {
// Handle the safe cases where the return value is 0 if the
// receiver is nil.
//
@@ -1934,7 +1883,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// of this case unless we have *a lot* more knowledge.
//
SVal V = ValMgr.makeZeroVal(ME->getType());
- MakeNode(Dst, ME, Pred, BindExpr(StNull, ME, V));
+ MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V));
return;
}
}
@@ -2004,7 +1953,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
- if (GetSVal(state, *I).isUndef()) {
+ if (state->getSVal(*I).isUndef()) {
// Generate an error node for passing an uninitialized/undefined value
// as an argument to a message expression. This node is a sink.
@@ -2053,11 +2002,11 @@ void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state,
// FIXME: Determine if the number of bits of the target type is
// equal or exceeds the number of bits to store the pointer value.
// If not, flag an error.
- MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, EvalCast(cast<Loc>(V),
+ MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, EvalCast(cast<Loc>(V),
CastE->getType())));
}
else
- MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V));
+ MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, V));
}
@@ -2089,7 +2038,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
NodeTy* N = *I1;
const GRState* state = GetState(N);
- SVal V = GetSVal(state, Ex);
+ SVal V = state->getSVal(Ex);
ASTContext& C = getContext();
// Unknown?
@@ -2118,7 +2067,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&V)) {
// Just unpackage the lval and return it.
V = LV->getLoc();
- MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
+ MakeNode(Dst, CastE, N, state->bindExpr(CastE, V));
continue;
}
@@ -2190,18 +2139,18 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); }
// Generate the new node in the ExplodedGraph.
- MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V));
+ MakeNode(Dst, CastE, N, Res.getState()->bindExpr(CastE, V));
continue;
}
// All other cases.
DispatchCast: {
- MakeNode(Dst, CastE, N, BindExpr(state, CastE,
- EvalCast(V, CastE->getType())));
+ MakeNode(Dst, CastE, N, state->bindExpr(CastE,
+ EvalCast(V, CastE->getType())));
continue;
}
PassThrough: {
- MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
+ MakeNode(Dst, CastE, N, state->bindExpr(CastE, V));
}
}
}
@@ -2215,13 +2164,13 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {
const GRState* state = GetState(*I);
- SVal ILV = GetSVal(state, ILE);
- state = StateMgr.BindCompoundLiteral(state, CL, ILV);
+ SVal ILV = state->getSVal(ILE);
+ state = state->bindCompoundLiteral(CL, ILV);
if (asLValue)
- MakeNode(Dst, CL, *I, BindExpr(state, CL, StateMgr.GetLValue(state, CL)));
+ MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL)));
else
- MakeNode(Dst, CL, *I, BindExpr(state, CL, ILV));
+ MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV));
}
}
@@ -2256,7 +2205,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
// FIXME: Handle multi-dimensional VLAs.
Expr* SE = VLA->getSizeExpr();
- SVal Size = GetSVal(state, SE);
+ SVal Size = state->getSVal(SE);
if (Size.isUndef()) {
if (NodeTy* N = Builder->generateNode(DS, state, Pred)) {
@@ -2266,27 +2215,26 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
continue;
}
- bool isFeasibleZero = false;
- const GRState* ZeroSt = Assume(state, Size, false, isFeasibleZero);
+ const GRState* zeroState = state->assume(Size, false);
+ state = state->assume(Size, true);
- bool isFeasibleNotZero = false;
- state = Assume(state, Size, true, isFeasibleNotZero);
-
- if (isFeasibleZero) {
- if (NodeTy* N = Builder->generateNode(DS, ZeroSt, Pred)) {
+ if (zeroState) {
+ if (NodeTy* N = Builder->generateNode(DS, zeroState, Pred)) {
N->markAsSink();
- if (isFeasibleNotZero) ImplicitBadSizedVLA.insert(N);
- else ExplicitBadSizedVLA.insert(N);
+ if (state)
+ ImplicitBadSizedVLA.insert(N);
+ else
+ ExplicitBadSizedVLA.insert(N);
}
}
- if (!isFeasibleNotZero)
+ if (!state)
continue;
}
// Decls without InitExpr are not initialized explicitly.
if (InitEx) {
- SVal InitVal = GetSVal(state, InitEx);
+ SVal InitVal = state->getSVal(InitEx);
QualType T = VD->getType();
// Recover some path-sensitivity if a scalar value evaluated to
@@ -2343,7 +2291,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
// e.g: static int* myArray[] = {};
if (NumInitElements == 0) {
SVal V = NonLoc::MakeCompoundVal(T, StartVals, getBasicVals());
- MakeNode(Dst, E, Pred, BindExpr(state, E, V));
+ MakeNode(Dst, E, Pred, state->bindExpr(E, V));
return;
}
@@ -2366,7 +2314,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
for (NodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
// Get the last initializer value.
state = GetState(*NI);
- SVal InitV = GetSVal(state, cast<Expr>(*X.Itr));
+ SVal InitV = state->getSVal(cast<Expr>(*X.Itr));
// Construct the new list of values by prepending the new value to
// the already constructed list.
@@ -2378,7 +2326,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals());
// Make final state and node.
- MakeNode(Dst, E, *NI, BindExpr(state, E, V));
+ MakeNode(Dst, E, *NI, state->bindExpr(E, V));
}
else {
// Still some initializer values to go. Push them onto the worklist.
@@ -2404,7 +2352,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
Visit(Init, Pred, Tmp);
for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) {
state = GetState(*I);
- MakeNode(Dst, E, *I, BindExpr(state, E, GetSVal(state, Init)));
+ MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init)));
}
return;
}
@@ -2445,8 +2393,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
amt = getContext().getTypeAlign(T) / 8;
MakeNode(Dst, Ex, Pred,
- BindExpr(GetState(Pred), Ex,
- NonLoc::MakeVal(getBasicVals(), amt, Ex->getType())));
+ GetState(Pred)->bindExpr(Ex, NonLoc::MakeVal(getBasicVals(), amt,
+ Ex->getType())));
}
@@ -2467,10 +2415,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal location = GetSVal(state, Ex);
+ SVal location = state->getSVal(Ex);
if (asLValue)
- MakeNode(Dst, U, *I, BindExpr(state, U, location),
+ MakeNode(Dst, U, *I, state->bindExpr(U, location),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, U, *I, state, location);
@@ -2497,7 +2445,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
// For all other types, UnaryOperator::Real is an identity operation.
assert (U->getType() == Ex->getType());
const GRState* state = GetState(*I);
- MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex)));
+ MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex)));
}
return;
@@ -2521,7 +2469,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
assert (Ex->getType()->isIntegerType());
const GRState* state = GetState(*I);
SVal X = NonLoc::MakeVal(getBasicVals(), 0, Ex->getType());
- MakeNode(Dst, U, *I, BindExpr(state, U, X));
+ MakeNode(Dst, U, *I, state->bindExpr(U, X));
}
return;
@@ -2546,7 +2494,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex)));
+ MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex)));
}
return;
@@ -2561,8 +2509,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal V = GetSVal(state, Ex);
- state = BindExpr(state, U, V);
+ SVal V = state->getSVal(Ex);
+ state = state->bindExpr(U, V);
MakeNode(Dst, U, *I, state);
}
@@ -2582,10 +2530,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
const GRState* state = GetState(*I);
// Get the value of the subexpression.
- SVal V = GetSVal(state, Ex);
+ SVal V = state->getSVal(Ex);
if (V.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I, BindExpr(state, U, V));
+ MakeNode(Dst, U, *I, state->bindExpr(U, V));
continue;
}
@@ -2607,12 +2555,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
case UnaryOperator::Not:
// FIXME: Do we need to handle promotions?
- state = BindExpr(state, U, EvalComplement(cast<NonLoc>(V)));
+ state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V)));
break;
case UnaryOperator::Minus:
// FIXME: Do we need to handle promotions?
- state = BindExpr(state, U, EvalMinus(U, cast<NonLoc>(V)));
+ state = state->bindExpr(U, EvalMinus(U, cast<NonLoc>(V)));
break;
case UnaryOperator::LNot:
@@ -2626,7 +2574,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
Loc X = Loc::MakeNull(getBasicVals());
SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X,
U->getType());
- state = BindExpr(state, U, Result);
+ state = state->bindExpr(U, Result);
}
else {
nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
@@ -2660,7 +2608,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal V1 = GetSVal(state, Ex);
+ SVal V1 = state->getSVal(Ex);
// Perform a load.
NodeSet Tmp2;
@@ -2669,11 +2617,11 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I2 = Tmp2.begin(), E2 = Tmp2.end(); I2!=E2; ++I2) {
state = GetState(*I2);
- SVal V2 = GetSVal(state, Ex);
+ SVal V2 = state->getSVal(Ex);
// Propagate unknown and undefined values.
if (V2.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I2, BindExpr(state, U, V2));
+ MakeNode(Dst, U, *I2, state->bindExpr(U, V2));
continue;
}
@@ -2697,23 +2645,20 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
ValMgr.makeZeroVal(U->getType()),
getContext().IntTy);
- bool isFeasible = false;
- Assume(state, Constraint, true, isFeasible);
- if (!isFeasible) {
+ if (!state->assume(Constraint, true)) {
// It isn't feasible for the original value to be null.
// Propagate this constraint.
Constraint = EvalBinOp(state, BinaryOperator::EQ, Result,
ValMgr.makeZeroVal(U->getType()),
getContext().IntTy);
- bool isFeasible = false;
- state = Assume(state, Constraint, false, isFeasible);
- assert(isFeasible && state);
+ state = state->assume(Constraint, false);
+ assert(state);
}
}
}
- state = BindExpr(state, U, U->isPostfix() ? V2 : Result);
+ state = state->bindExpr(U, U->isPostfix() ? V2 : Result);
// Perform the store.
EvalStore(Dst, U, *I2, state, V1, Result);
@@ -2761,11 +2706,11 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
for (AsmStmt::outputs_iterator OI = A->begin_outputs(),
OE = A->end_outputs(); OI != OE; ++OI) {
- SVal X = GetSVal(state, *OI);
+ SVal X = state->getSVal(*OI);
assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
if (isa<Loc>(X))
- state = BindLoc(state, cast<Loc>(X), UnknownVal());
+ state = state->bindLoc(cast<Loc>(X), UnknownVal());
}
MakeNode(Dst, A, Pred, state);
@@ -2810,7 +2755,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) {
Visit(R, Pred, Tmp);
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
- SVal X = GetSVal((*I)->getState(), R);
+ SVal X = (*I)->getState()->getSVal(R);
// Check if we return the address of a stack variable.
if (isa<loc::MemRegionVal>(X)) {
@@ -2861,29 +2806,24 @@ const GRState* GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* state,
// Check for divide/remainder-by-zero.
// First, "assume" that the denominator is 0 or undefined.
-
- bool isFeasibleZero = false;
- const GRState* ZeroSt = Assume(state, Denom, false, isFeasibleZero);
+ const GRState* zeroState = state->assume(Denom, false);
// Second, "assume" that the denominator cannot be 0.
+ state = state->assume(Denom, true);
- bool isFeasibleNotZero = false;
- state = Assume(state, Denom, true, isFeasibleNotZero);
-
- // Create the node for the divide-by-zero (if it occurred).
-
- if (isFeasibleZero)
- if (NodeTy* DivZeroNode = Builder->generateNode(Ex, ZeroSt, Pred)) {
+ // Create the node for the divide-by-zero (if it occurred).
+ if (zeroState)
+ if (NodeTy* DivZeroNode = Builder->generateNode(Ex, zeroState, Pred)) {
DivZeroNode->markAsSink();
- if (isFeasibleNotZero)
+ if (state)
ImplicitBadDivides.insert(DivZeroNode);
else
ExplicitBadDivides.insert(DivZeroNode);
}
- return isFeasibleNotZero ? state : 0;
+ return state;
}
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
@@ -2907,7 +2847,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
for (NodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1 != E1; ++I1) {
- SVal LeftV = GetSVal((*I1)->getState(), LHS);
+ SVal LeftV = (*I1)->getState()->getSVal(LHS);
// Process the RHS.
@@ -2921,7 +2861,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
const GRState* state = GetState(*I2);
const GRState* OldSt = state;
- SVal RightV = GetSVal(state, RHS);
+ SVal RightV = state->getSVal(RHS);
BinaryOperator::Opcode Op = B->getOpcode();
switch (Op) {
@@ -2942,7 +2882,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// 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, BindExpr(state, B, RightV), LeftV,
+ EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV), LeftV,
RightV);
continue;
}
@@ -2996,7 +2936,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Otherwise, create a new node.
- MakeNode(Dst, B, *I2, BindExpr(state, B, Result));
+ MakeNode(Dst, B, *I2, state->bindExpr(B, Result));
continue;
}
}
@@ -3021,13 +2961,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
NodeSet Tmp3;
- SVal location = GetSVal(state, LHS);
+ SVal location = state->getSVal(LHS);
EvalLoad(Tmp3, LHS, *I2, state, location);
for (NodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3; ++I3) {
state = GetState(*I3);
- SVal V = GetSVal(state, LHS);
+ SVal V = state->getSVal(LHS);
// Check for divide-by-zero.
if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
@@ -3044,13 +2984,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Propagate undefined values (left-side).
if (V.isUndef()) {
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, V), location, V);
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V), location, V);
continue;
}
// Propagate unknown values (left and right-side).
if (RightV.isUnknown() || V.isUnknown()) {
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, UnknownVal()),
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal()),
location, UnknownVal());
continue;
}
@@ -3076,7 +3016,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Evaluate operands and promote to result type.
if (RightV.isUndef()) {
// Propagate undefined values (right-side).
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, RightV), location,
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV), location,
RightV);
continue;
}
@@ -3120,7 +3060,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
LHSVal = (LTy == CTy) ? Result : EvalCast(Result,LTy);
}
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, Result), location,
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, Result), location,
LHSVal);
}
}
@@ -3353,8 +3293,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
Out << "\\|StateID: " << (void*) N->getState() << "\\|";
- GRStateRef state(N->getState(), GraphPrintCheckerState->getStateManager());
- state.printDOT(Out);
+ const GRState *state = N->getState();
+ state->printDOT(Out);
Out << "\\l";
return Out.str();
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 9aea124..7f7270d 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -347,9 +347,7 @@ public:
assert (E && "Return expression cannot be NULL");
// Get the value associated with E.
- loc::MemRegionVal V =
- cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
- E));
+ loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
// Generate a report for this bug.
std::string buf;
@@ -427,7 +425,7 @@ class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
return Ex;
}
- bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
+ bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
};
public:
@@ -519,8 +517,7 @@ public:
"variable-length array (VLA) '"
<< VD->getNameAsString() << "' evaluates to ";
- bool isUndefined = Eng.getStateManager().GetSVal(N->getState(),
- SizeExpr).isUndef();
+ bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
if (isUndefined)
os << "an undefined or garbage value.";
@@ -563,13 +560,13 @@ public:
CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
const GRState* state = N->getState();
- SVal X = VMgr.GetSVal(state, CE->getCallee());
+ SVal X = state->getSVal(CE->getCallee());
const FunctionDecl* FD = X.getAsFunctionDecl();
if (!FD)
return false;
- const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+ const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext());
if (!Att)
return false;
@@ -819,24 +816,15 @@ public:
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
-
- GRStateManager &StateMgr = BRC.getStateManager();
- bool isFeasible = false;
- if (StateMgr.Assume(PrevN->getState(), Constraint, !Assumption,
- isFeasible)) {
- assert(isFeasible); // Eventually we don't need 'isFeasible'.
+ if (PrevN->getState()->assume(Constraint, !Assumption)) {
isSatisfied = true;
// As a sanity check, make sure that the negation of the constraint
// was infeasible in the current state. If it is feasible, we somehow
// missed the transition point.
- isFeasible = false;
- if (StateMgr.Assume(N->getState(), Constraint, !Assumption,
- isFeasible)) {
- assert(isFeasible);
+ if (N->getState()->assume(Constraint, !Assumption))
return NULL;
- }
// We found the transition point for the constraint. We now need to
// pretty-print the constraint. (work-in-progress)
@@ -897,7 +885,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
StateMgr.getRegionManager().getVarRegion(VD);
// What did we load?
- SVal V = StateMgr.GetSVal(state, S);
+ SVal V = state->getSVal(S);
if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
|| V.isUndef()) {
@@ -906,7 +894,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
}
}
- SVal V = StateMgr.GetSValAsScalarOrLoc(state, S);
+ SVal V = state->getSValAsScalarOrLoc(S);
// Uncomment this to find cases where we aren't properly getting the
// base value that was dereferenced.
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index e1c4848..7e54f1a 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -363,11 +363,13 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
- SVal V = StateMgr.GetSVal(St, *I);
+ SVal V = St->getSVal(*I);
- if (isa<loc::MemRegionVal>(V))
- St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
- else if (isa<nonloc::LocAsInteger>(V))
+ if (isa<loc::MemRegionVal>(V)) {
+ const MemRegion *R = cast<loc::MemRegionVal>(V).getRegion();
+ if (R->isBoundable(Eng.getContext()))
+ St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
+ } else if (isa<nonloc::LocAsInteger>(V))
St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
UnknownVal());
@@ -380,7 +382,7 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
unsigned Count = Builder.getCurrentBlockCount();
SVal X = Eng.getValueManager().getConjuredSymbolVal(CE, Count);
- St = StateMgr.BindExpr(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
+ St = St->bindExpr(CE, X, Eng.getCFG().isBlkExpr(CE), false);
}
Builder.MakeNode(Dst, CE, Pred, St);
@@ -398,18 +400,16 @@ void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// The basic transfer function logic for message expressions does nothing.
- // We just invalidate all arguments passed in by references.
-
- GRStateManager& StateMgr = Eng.getStateManager();
- const GRState* St = Builder.GetState(Pred);
+ // We just invalidate all arguments passed in by references.
+ const GRState *St = Builder.GetState(Pred);
for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
- SVal V = StateMgr.GetSVal(St, *I);
+ SVal V = St->getSVal(*I);
if (isa<Loc>(V))
- St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
+ St = St->bindLoc(cast<Loc>(V), UnknownVal());
}
Builder.MakeNode(Dst, ME, Pred, St);
diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp
index e0e478c..aeb1c04 100644
--- a/lib/Analysis/GRState.cpp
+++ b/lib/Analysis/GRState.cpp
@@ -69,8 +69,7 @@ const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) {
}
const GRState* GRStateManager::getInitialState() {
-
- GRState StateImpl(EnvMgr.getInitialEnvironment(),
+ GRState StateImpl(this, EnvMgr.getInitialEnvironment(),
StoreMgr->getInitialStore(),
GDMFactory.GetEmptyMap());
@@ -92,25 +91,19 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
return I;
}
-const GRState* GRStateManager::MakeStateWithStore(const GRState* St,
- Store store) {
- GRState NewSt = *St;
+const GRState* GRState::makeWithStore(Store store) const {
+ GRState NewSt = *this;
NewSt.St = store;
- return getPersistentState(NewSt);
+ return Mgr->getPersistentState(NewSt);
}
-
//===----------------------------------------------------------------------===//
// State pretty-printing.
//===----------------------------------------------------------------------===//
-void GRState::print(std::ostream& Out, StoreManager& StoreMgr,
- ConstraintManager& ConstraintMgr,
- Printer** Beg, Printer** End,
- const char* nl, const char* sep) const {
-
+void GRState::print(std::ostream& Out, const char* nl, const char* sep) const {
// Print the store.
- StoreMgr.print(getStore(), Out, nl, sep);
+ Mgr->getStoreManager().print(getStore(), Out, nl, sep);
// Print Subexpression bindings.
bool isFirst = true;
@@ -150,24 +143,21 @@ void GRState::print(std::ostream& Out, StoreManager& StoreMgr,
I.getData().print(Out);
}
- ConstraintMgr.print(this, Out, nl, sep);
+ Mgr->getConstraintManager().print(this, Out, nl, sep);
- // Print checker-specific data.
- for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
+ // Print checker-specific data.
+ for (std::vector<Printer*>::iterator I = Mgr->Printers.begin(),
+ E = Mgr->Printers.end(); I != E; ++I) {
+ (*I)->Print(Out, this, nl, sep);
+ }
}
-void GRStateRef::printDOT(std::ostream& Out) const {
+void GRState::printDOT(std::ostream& Out) const {
print(Out, "\\l", "\\|");
}
-void GRStateRef::printStdErr() const {
+void GRState::printStdErr() const {
print(*llvm::cerr);
-}
-
-void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{
- GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0];
- GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size();
- St->print(Out, *Mgr->StoreMgr, *Mgr->ConstraintMgr, beg, end, nl, sep);
}
//===----------------------------------------------------------------------===//
@@ -213,13 +203,13 @@ class VISIBILITY_HIDDEN ScanReachableSymbols : public SubRegionMap::Visitor {
typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy;
VisitedRegionsTy visited;
- GRStateRef state;
+ const GRState *state;
SymbolVisitor &visitor;
llvm::OwningPtr<SubRegionMap> SRM;
public:
- ScanReachableSymbols(GRStateManager* sm, const GRState *st, SymbolVisitor& v)
- : state(st, *sm), visitor(v) {}
+ ScanReachableSymbols(const GRState *st, SymbolVisitor& v)
+ : state(st), visitor(v) {}
bool scan(nonloc::CompoundVal val);
bool scan(SVal val);
@@ -270,19 +260,18 @@ bool ScanReachableSymbols::scan(const MemRegion *R) {
return false;
// Now look at the binding to this region (if any).
- if (!scan(state.GetSValAsScalarOrLoc(R)))
+ if (!scan(state->getSValAsScalarOrLoc(R)))
return false;
// Now look at the subregions.
if (!SRM.get())
- SRM.reset(state.getManager().getStoreManager().getSubRegionMap(state));
+ SRM.reset(state->getStateManager().getStoreManager().getSubRegionMap(state));
return SRM->iterSubRegions(R, *this);
}
-bool GRStateManager::scanReachableSymbols(SVal val, const GRState* state,
- SymbolVisitor& visitor) {
- ScanReachableSymbols S(this, state, visitor);
+bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
+ ScanReachableSymbols S(this, visitor);
return S.scan(val);
}
diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp
index 69c09d9..3c14ee9 100644
--- a/lib/Analysis/GRTransferFuncs.cpp
+++ b/lib/Analysis/GRTransferFuncs.cpp
@@ -23,6 +23,5 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R, QualType T) {
- OStates.Add(Eng.getStateManager().BindExpr(St, Ex,
- DetermEvalBinOpNN(Eng, Op, L, R, T)));
+ OStates.Add(St->bindExpr(Ex, DetermEvalBinOpNN(Eng, Op, L, R, T)));
}
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 9f066f4..9e11a26 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -296,10 +296,12 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
- const MemRegion* superRegion){
+ const MemRegion* superRegion, ASTContext& Ctx){
+
+ QualType T = Ctx.getCanonicalType(elementType);
llvm::FoldingSetNodeID ID;
- ElementRegion::ProfileRegion(ID, elementType, Idx, superRegion);
+ ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
@@ -307,7 +309,7 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
if (!R) {
R = (ElementRegion*) A.Allocate<ElementRegion>();
- new (R) ElementRegion(elementType, Idx, superRegion);
+ new (R) ElementRegion(T, Idx, superRegion);
Regions.InsertNode(R, InsertPos);
}
diff --git a/lib/Analysis/RangeConstraintManager.cpp b/lib/Analysis/RangeConstraintManager.cpp
index f6ac2b9..73c68bc 100644
--- a/lib/Analysis/RangeConstraintManager.cpp
+++ b/lib/Analysis/RangeConstraintManager.cpp
@@ -233,28 +233,27 @@ struct GRStateTrait<ConstraintRange>
namespace {
class VISIBILITY_HIDDEN RangeConstraintManager : public SimpleConstraintManager{
- RangeSet GetRange(GRStateRef state, SymbolRef sym);
+ RangeSet GetRange(const GRState *state, SymbolRef sym);
public:
- RangeConstraintManager(GRStateManager& statemgr)
- : SimpleConstraintManager(statemgr) {}
+ RangeConstraintManager() {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
@@ -275,9 +274,8 @@ private:
} // end anonymous namespace
-ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager& StateMgr)
-{
- return new RangeConstraintManager(StateMgr);
+ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) {
+ return new RangeConstraintManager();
}
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
@@ -289,12 +287,11 @@ const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
const GRState*
-RangeConstraintManager::RemoveDeadBindings(const GRState* St,
+RangeConstraintManager::RemoveDeadBindings(const GRState* state,
SymbolReaper& SymReaper) {
- GRStateRef state(St, StateMgr);
- ConstraintRangeTy CR = state.get<ConstraintRange>();
- ConstraintRangeTy::Factory& CRFactory = state.get_context<ConstraintRange>();
+ ConstraintRangeTy CR = state->get<ConstraintRange>();
+ ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
@@ -302,7 +299,7 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St,
CR = CRFactory.Remove(CR, sym);
}
- return state.set<ConstraintRange>(CR);
+ return state->set<ConstraintRange>(CR);
}
//===------------------------------------------------------------------------===
@@ -310,14 +307,14 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St,
//===------------------------------------------------------------------------===/
RangeSet
-RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
- if (ConstraintRangeTy::data_type* V = state.get<ConstraintRange>(sym))
+RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) {
+ if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
return *V;
// Lazily generate a new RangeSet representing all possible values for the
// given symbol type.
- QualType T = state.getSymbolManager().getType(sym);
- BasicValueFactory& BV = state.getBasicVals();
+ QualType T = state->getSymbolManager().getType(sym);
+ BasicValueFactory& BV = state->getBasicVals();
return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
}
@@ -327,12 +324,10 @@ RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
#define AssumeX(OP)\
const GRState*\
-RangeConstraintManager::AssumeSym ## OP(const GRState* St, SymbolRef sym,\
- const llvm::APSInt& V, bool& isFeasible){\
- GRStateRef state(St, StateMgr);\
- const RangeSet& R = GetRange(state, sym).Add##OP(state.getBasicVals(), F, V);\
- isFeasible = !R.isEmpty();\
- return isFeasible ? state.set<ConstraintRange>(sym, R).getState() : 0;\
+RangeConstraintManager::AssumeSym ## OP(const GRState* state, SymbolRef sym,\
+ const llvm::APSInt& V){\
+ const RangeSet& R = GetRange(state, sym).Add##OP(state->getBasicVals(), F, V);\
+ return !R.isEmpty() ? state->set<ConstraintRange>(sym, R) : NULL;\
}
AssumeX(EQ)
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index eae3aef..5f2b8f8 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -31,6 +31,32 @@ using namespace clang;
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
//===----------------------------------------------------------------------===//
+// Fine-grained control of RegionStoreManager.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct VISIBILITY_HIDDEN minimal_features_tag {};
+struct VISIBILITY_HIDDEN maximal_features_tag {};
+
+class VISIBILITY_HIDDEN RegionStoreFeatures {
+ bool SupportsFields;
+ bool SupportsRemaining;
+
+public:
+ RegionStoreFeatures(minimal_features_tag) :
+ SupportsFields(false), SupportsRemaining(false) {}
+
+ RegionStoreFeatures(maximal_features_tag) :
+ SupportsFields(true), SupportsRemaining(false) {}
+
+ void enableFields(bool t) { SupportsFields = t; }
+
+ bool supportsFields() const { return SupportsFields; }
+ bool supportsRemaining() const { return SupportsRemaining; }
+};
+}
+
+//===----------------------------------------------------------------------===//
// Region "Views"
//===----------------------------------------------------------------------===//
//
@@ -151,6 +177,7 @@ public:
};
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
+ const RegionStoreFeatures Features;
RegionBindingsTy::Factory RBFactory;
RegionViews::Factory RVFactory;
@@ -158,8 +185,9 @@ class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
const ImplicitParamDecl *SelfDecl;
public:
- RegionStoreManager(GRStateManager& mgr)
+ RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f)
: StoreManager(mgr),
+ Features(f),
RBFactory(mgr.getAllocator()),
RVFactory(mgr.getAllocator()),
SelfRegion(0), SelfDecl(0) {
@@ -172,36 +200,32 @@ public:
SubRegionMap* getSubRegionMap(const GRState *state);
- const GRState* BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL, SVal V);
-
/// getLValueString - Returns an SVal representing the lvalue of a
/// StringLiteral. Within RegionStore a StringLiteral has an
/// associated StringRegion, and the lvalue of a StringLiteral is
/// the lvalue of that region.
- SVal getLValueString(const GRState* St, const StringLiteral* S);
+ SVal getLValueString(const GRState *state, const StringLiteral* S);
/// getLValueCompoundLiteral - Returns an SVal representing the
/// lvalue of a compound literal. Within RegionStore a compound
/// literal has an associated region, and the lvalue of the
/// compound literal is the lvalue of that region.
- SVal getLValueCompoundLiteral(const GRState* St, const CompoundLiteralExpr*);
+ SVal getLValueCompoundLiteral(const GRState *state, const CompoundLiteralExpr*);
/// getLValueVar - Returns an SVal that represents the lvalue of a
/// variable. Within RegionStore a variable has an associated
/// VarRegion, and the lvalue of the variable is the lvalue of that region.
- SVal getLValueVar(const GRState* St, const VarDecl* VD);
+ SVal getLValueVar(const GRState *state, const VarDecl* VD);
- SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
+ SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base);
- SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);
+ SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D);
- SVal getLValueFieldOrIvar(const GRState* St, SVal Base, const Decl* D);
+ SVal getLValueFieldOrIvar(const GRState *state, SVal Base, const Decl* D);
- SVal getLValueElement(const GRState* St, QualType elementType,
+ SVal getLValueElement(const GRState *state, QualType elementType,
SVal Base, SVal Offset);
- SVal getSizeInElements(const GRState* St, const MemRegion* R);
/// ArrayToPointer - Emulates the "decay" of an array to a pointer
/// type. 'Array' represents the lvalue of the array being decayed
@@ -211,27 +235,13 @@ public:
/// casts from arrays to pointers.
SVal ArrayToPointer(Loc Array);
- CastResult CastRegion(const GRState* state, const MemRegion* R,
+ CastResult CastRegion(const GRState *state, const MemRegion* R,
QualType CastToTy);
- SVal EvalBinOp(const GRState *state,BinaryOperator::Opcode Op,Loc L,NonLoc R);
+ SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,Loc L,NonLoc R);
- /// The high level logic for this method is this:
- /// Retrieve (L)
- /// if L has binding
- /// return L's binding
- /// else if L is in killset
- /// return unknown
- /// else
- /// if L is on stack or heap
- /// return undefined
- /// else
- /// return symbolic
- SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
- const GRState* Bind(const GRState* St, Loc LV, SVal V);
- Store Remove(Store store, Loc LV);
Store getInitialStore() { return RBFactory.GetEmptyMap().getRoot(); }
@@ -251,65 +261,130 @@ public:
return SelfRegion;
}
- /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
- /// It returns a new Store with these values removed, and populates LSymbols
- // and DSymbols with the known set of live and dead symbols respectively.
- Store RemoveDeadBindings(const GRState* state, Stmt* Loc,
- SymbolReaper& SymReaper,
- llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
- const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal);
+
+ //===-------------------------------------------------------------------===//
+ // Binding values to regions.
+ //===-------------------------------------------------------------------===//
- const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
- return St;
- }
+ const GRState *Bind(const GRState *state, Loc LV, SVal V);
- const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent);
- const GRState* setCastType(const GRState* St, const MemRegion* R, QualType T);
+ const GRState *BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* CL, SVal V);
+
+ const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal);
- static inline RegionBindingsTy GetRegionBindings(Store store) {
- return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
+ const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) {
+ return state;
}
- void print(Store store, std::ostream& Out, const char* nl, const char *sep);
+ /// BindStruct - Bind a compound value to a structure.
+ const GRState *BindStruct(const GRState *, const TypedRegion* R, SVal V);
+
+ const GRState *BindArray(const GRState *state, const TypedRegion* R, SVal V);
+
+ /// KillStruct - Set the entire struct to unknown.
+ const GRState *KillStruct(const GRState *state, const TypedRegion* R);
- void iterBindings(Store store, BindingsHandler& f) {
- // FIXME: Implement.
- }
- const GRState* setDefaultValue(const GRState* St, const MemRegion* R, SVal V);
-private:
- const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V);
+ const GRState *setDefaultValue(const GRState *state, const MemRegion* R, SVal V);
+ Store Remove(Store store, Loc LV);
+
+ //===------------------------------------------------------------------===//
+ // Loading values from regions.
+ //===------------------------------------------------------------------===//
+
+ /// The high level logic for this method is this:
+ /// Retrieve (L)
+ /// if L has binding
+ /// return L's binding
+ /// else if L is in killset
+ /// return unknown
+ /// else
+ /// if L is on stack or heap
+ /// return undefined
+ /// else
+ /// return symbolic
+ SVal Retrieve(const GRState *state, Loc L, QualType T = QualType());
+
/// Retrieve the values in a struct and return a CompoundVal, used when doing
/// struct copy:
/// struct s x, y;
/// x = y;
/// y's value is retrieved by this method.
- SVal RetrieveStruct(const GRState* St, const TypedRegion* R);
+ SVal RetrieveStruct(const GRState *St, const TypedRegion* R);
+
+ SVal RetrieveArray(const GRState *St, const TypedRegion* R);
- SVal RetrieveArray(const GRState* St, const TypedRegion* R);
+ //===------------------------------------------------------------------===//
+ // State pruning.
+ //===------------------------------------------------------------------===//
+
+ /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
+ /// It returns a new Store with these values removed.
+ Store RemoveDeadBindings(const GRState *state, Stmt* Loc, SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
- const GRState* BindStruct(const GRState* St, const TypedRegion* R, SVal V);
+ //===------------------------------------------------------------------===//
+ // Region "extents".
+ //===------------------------------------------------------------------===//
+
+ const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent);
+ SVal getSizeInElements(const GRState *state, const MemRegion* R);
- /// KillStruct - Set the entire struct to unknown.
- const GRState* KillStruct(const GRState* St, const TypedRegion* R);
+ //===------------------------------------------------------------------===//
+ // Region "views".
+ //===------------------------------------------------------------------===//
+
+ const GRState *AddRegionView(const GRState *state, const MemRegion* View,
+ const MemRegion* Base);
+
+ const GRState *RemoveRegionView(const GRState *state, const MemRegion* View,
+ const MemRegion* Base);
+ //===------------------------------------------------------------------===//
// Utility methods.
- BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
- ASTContext& getContext() { return StateMgr.getContext(); }
+ //===------------------------------------------------------------------===//
+
+ const GRState *setCastType(const GRState *state, const MemRegion* R, QualType T);
- SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
+ static inline RegionBindingsTy GetRegionBindings(Store store) {
+ return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
+ }
- const GRState* AddRegionView(const GRState* St,
- const MemRegion* View, const MemRegion* Base);
- const GRState* RemoveRegionView(const GRState* St,
- const MemRegion* View, const MemRegion* Base);
+ void print(Store store, std::ostream& Out, const char* nl, const char *sep);
+
+ void iterBindings(Store store, BindingsHandler& f) {
+ // FIXME: Implement.
+ }
+
+ // FIXME: Remove.
+ BasicValueFactory& getBasicVals() {
+ return StateMgr.getBasicVals();
+ }
+
+ // FIXME: Remove.
+ ASTContext& getContext() { return StateMgr.getContext(); }
+
+ // FIXME: Use ValueManager?
+ SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
};
} // end anonymous namespace
-StoreManager* clang::CreateRegionStoreManager(GRStateManager& StMgr) {
- return new RegionStoreManager(StMgr);
+//===----------------------------------------------------------------------===//
+// RegionStore creation.
+//===----------------------------------------------------------------------===//
+
+StoreManager *clang::CreateRegionStoreManager(GRStateManager& StMgr) {
+ RegionStoreFeatures F = maximal_features_tag();
+ return new RegionStoreManager(StMgr, F);
+}
+
+StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
+ RegionStoreFeatures F = minimal_features_tag();
+ F.enableFields(true);
+ return new RegionStoreManager(StMgr, F);
}
SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
@@ -324,11 +399,15 @@ SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
return M;
}
+//===----------------------------------------------------------------------===//
+// getLValueXXX methods.
+//===----------------------------------------------------------------------===//
+
/// getLValueString - Returns an SVal representing the lvalue of a
/// StringLiteral. Within RegionStore a StringLiteral has an
/// associated StringRegion, and the lvalue of a StringLiteral is the
/// lvalue of that region.
-SVal RegionStoreManager::getLValueString(const GRState* St,
+SVal RegionStoreManager::getLValueString(const GRState *St,
const StringLiteral* S) {
return loc::MemRegionVal(MRMgr.getStringRegion(S));
}
@@ -336,7 +415,7 @@ SVal RegionStoreManager::getLValueString(const GRState* St,
/// getLValueVar - Returns an SVal that represents the lvalue of a
/// variable. Within RegionStore a variable has an associated
/// VarRegion, and the lvalue of the variable is the lvalue of that region.
-SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
+SVal RegionStoreManager::getLValueVar(const GRState *St, const VarDecl* VD) {
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
}
@@ -345,22 +424,22 @@ SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
/// has an associated region, and the lvalue of the compound literal
/// is the lvalue of that region.
SVal
-RegionStoreManager::getLValueCompoundLiteral(const GRState* St,
+RegionStoreManager::getLValueCompoundLiteral(const GRState *St,
const CompoundLiteralExpr* CL) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
}
-SVal RegionStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+SVal RegionStoreManager::getLValueIvar(const GRState *St, const ObjCIvarDecl* D,
SVal Base) {
return getLValueFieldOrIvar(St, Base, D);
}
-SVal RegionStoreManager::getLValueField(const GRState* St, SVal Base,
+SVal RegionStoreManager::getLValueField(const GRState *St, SVal Base,
const FieldDecl* D) {
return getLValueFieldOrIvar(St, Base, D);
}
-SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base,
+SVal RegionStoreManager::getLValueFieldOrIvar(const GRState *St, SVal Base,
const Decl* D) {
if (Base.isUnknownOrUndef())
return Base;
@@ -397,7 +476,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base,
return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
}
-SVal RegionStoreManager::getLValueElement(const GRState* St,
+SVal RegionStoreManager::getLValueElement(const GRState *St,
QualType elementType,
SVal Base, SVal Offset) {
@@ -438,7 +517,7 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
}
}
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
- BaseRegion));
+ BaseRegion, getContext()));
}
SVal BaseIdx = ElemR->getIndex();
@@ -473,10 +552,15 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
else
NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI));
- return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR));
+ return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR,
+ getContext()));
}
-SVal RegionStoreManager::getSizeInElements(const GRState* St,
+//===----------------------------------------------------------------------===//
+// Extents for regions.
+//===----------------------------------------------------------------------===//
+
+SVal RegionStoreManager::getSizeInElements(const GRState *state,
const MemRegion* R) {
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
// Get the type of the variable.
@@ -491,8 +575,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
return NonLoc::MakeVal(getBasicVals(), CAT->getSize(), false);
}
- GRStateRef state(St, StateMgr);
- const QualType* CastTy = state.get<RegionCasts>(VR);
+ const QualType* CastTy = state->get<RegionCasts>(VR);
// If the VarRegion is cast to other type, compute the size with respect to
// that type.
@@ -501,6 +584,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
QualType VarTy = VR->getValueType(getContext());
uint64_t EleSize = getContext().getTypeSize(EleTy);
uint64_t VarSize = getContext().getTypeSize(VarTy);
+ assert(VarSize != 0);
return NonLoc::MakeIntVal(getBasicVals(), VarSize / EleSize, false);
}
@@ -538,6 +622,16 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
return UnknownVal();
}
+const GRState *RegionStoreManager::setExtent(const GRState *state,
+ const MemRegion *region,
+ SVal extent) {
+ return state->set<RegionExtents>(region, extent);
+}
+
+//===----------------------------------------------------------------------===//
+// Location and region casting.
+//===----------------------------------------------------------------------===//
+
/// ArrayToPointer - Emulates the "decay" of an array to a pointer
/// type. 'Array' represents the lvalue of the array being decayed
/// to a pointer, and the returned SVal represents the decayed
@@ -560,13 +654,13 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
T = AT->getElementType();
nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
- ElementRegion* ER = MRMgr.getElementRegion(T, Idx, ArrayR);
+ ElementRegion* ER = MRMgr.getElementRegion(T, Idx, ArrayR, getContext());
return loc::MemRegionVal(ER);
}
RegionStoreManager::CastResult
-RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+RegionStoreManager::CastRegion(const GRState *state, const MemRegion* R,
QualType CastToTy) {
ASTContext& Ctx = StateMgr.getContext();
@@ -575,7 +669,7 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
QualType ToTy = Ctx.getCanonicalType(CastToTy);
// Check cast to ObjCQualifiedID type.
- if (isa<ObjCQualifiedIdType>(ToTy)) {
+ if (ToTy->isObjCQualifiedIdType()) {
// FIXME: Record the type information aside.
return CastResult(state, R);
}
@@ -617,15 +711,18 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
uint64_t ObjTySize = getContext().getTypeSize(ObjTy);
if ((PointeeTySize > 0 && PointeeTySize < ObjTySize) ||
- (ObjTy->isAggregateType() && PointeeTy->isScalarType())) {
+ (ObjTy->isAggregateType() && PointeeTy->isScalarType()) ||
+ ObjTySize == 0 /* R has 'void*' type. */) {
// Record the cast type of the region.
state = setCastType(state, R, ToTy);
SVal Idx = ValMgr.makeZeroArrayIndex();
- ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx, R);
+ ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx,R,getContext());
return CastResult(state, ER);
- } else
+ } else {
+ state = setCastType(state, R, ToTy);
return CastResult(state, R);
+ }
}
if (isa<ObjCObjectRegion>(R)) {
@@ -636,6 +733,10 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
return 0;
}
+//===----------------------------------------------------------------------===//
+// Pointer arithmetic.
+//===----------------------------------------------------------------------===//
+
SVal RegionStoreManager::EvalBinOp(const GRState *state,
BinaryOperator::Opcode Op, Loc L, NonLoc R) {
// Assume the base location is MemRegionVal.
@@ -648,26 +749,37 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
// If the operand is a symbolic or alloca region, create the first element
// region on it.
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) {
- // Get symbol's type. It should be a pointer type.
- SymbolRef Sym = SR->getSymbol();
- QualType T = Sym->getType(getContext());
+ QualType T;
+ // If the SymbolicRegion was cast to another type, use that type.
+ if (const QualType *t = state->get<RegionCasts>(SR)) {
+ T = *t;
+ } else {
+ // Otherwise use the symbol's type.
+ SymbolRef Sym = SR->getSymbol();
+ T = Sym->getType(getContext());
+ }
QualType EleTy = T->getAsPointerType()->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR);
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext());
}
else if (const AllocaRegion *AR = dyn_cast<AllocaRegion>(MR)) {
// Get the alloca region's current cast type.
- GRStateRef StRef(state, StateMgr);
- GRStateTrait<RegionCasts>::lookup_type T = StRef.get<RegionCasts>(AR);
+
+ GRStateTrait<RegionCasts>::lookup_type T = state->get<RegionCasts>(AR);
assert(T && "alloca region has no type.");
QualType EleTy = cast<PointerType>(T->getTypePtr())->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR);
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext());
}
- else
+ else if (isa<FieldRegion>(MR)) {
+ // Not track pointer arithmetic on struct fields.
+ return UnknownVal();
+ }
+ else {
ER = cast<ElementRegion>(MR);
+ }
SVal Idx = ER->getIndex();
@@ -686,7 +798,8 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
Offset->getValue()));
SVal NewIdx = Base->EvalBinOp(getBasicVals(), Op, OffConverted);
const MemRegion* NewER =
- MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion());
+ MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion(),
+ getContext());
return Loc::MakeVal(NewER);
}
@@ -694,7 +807,12 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
return UnknownVal();
}
-SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
+//===----------------------------------------------------------------------===//
+// Loading values from regions.
+//===----------------------------------------------------------------------===//
+
+SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
+
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -703,7 +821,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
if (isa<loc::ConcreteInt>(L))
return UndefinedVal();
- const MemRegion* MR = cast<loc::MemRegionVal>(L).getRegion();
+ const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
// FIXME: return symbolic value for these cases.
// Example:
@@ -716,7 +834,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
// FIXME: Perhaps this method should just take a 'const MemRegion*' argument
// instead of 'Loc', and have the other Loc cases handled at a higher level.
- const TypedRegion* R = cast<TypedRegion>(MR);
+ const TypedRegion *R = cast<TypedRegion>(MR);
assert(R && "bad region");
// FIXME: We should eventually handle funny addressing. e.g.:
@@ -731,26 +849,24 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
QualType RTy = R->getValueType(getContext());
if (RTy->isStructureType())
- return RetrieveStruct(St, R);
+ return RetrieveStruct(state, R);
if (RTy->isArrayType())
- return RetrieveArray(St, R);
+ return RetrieveArray(state, R);
// FIXME: handle Vector types.
if (RTy->isVectorType())
return UnknownVal();
- RegionBindingsTy B = GetRegionBindings(St->getStore());
+ RegionBindingsTy B = GetRegionBindings(state->getStore());
RegionBindingsTy::data_type* V = B.lookup(R);
// Check if the region has a binding.
if (V)
return *V;
- GRStateRef state(St, StateMgr);
-
// Check if the region is in killset.
- if (state.contains<RegionKills>(R))
+ if (state->contains<RegionKills>(R))
return UnknownVal();
// Check if the region is an element region of a string literal.
@@ -775,7 +891,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
if (isa<ElementRegion>(R) || isa<FieldRegion>(R)) {
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
GRStateTrait<RegionDefaultValue>::lookup_type D =
- state.get<RegionDefaultValue>(SuperR);
+ state->get<RegionDefaultValue>(SuperR);
if (D) {
// If the default value is symbolic, we need to create a new symbol.
if (D->hasConjuredSymbol())
@@ -829,14 +945,22 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
return UndefinedVal();
}
+ // If the region is already cast to another type, use that type to create the
+ // symbol value.
+ if (const QualType *p = state->get<RegionCasts>(R)) {
+ QualType T = *p;
+ RTy = T->getAsPointerType()->getPointeeType();
+ }
+
// All other integer values are symbolic.
if (Loc::IsLocType(RTy) || RTy->isIntegerType())
- return ValMgr.getRegionValueSymbolVal(R);
+ return ValMgr.getRegionValueSymbolVal(R, RTy);
else
return UnknownVal();
}
-SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
+SVal RegionStoreManager::RetrieveStruct(const GRState *state,
+ const TypedRegion* R){
QualType T = R->getValueType(getContext());
assert(T->isStructureType());
@@ -846,6 +970,8 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
+ // FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a
+ // reverse iterator, we should implement one.
std::vector<FieldDecl *> Fields(RD->field_begin(getContext()),
RD->field_end(getContext()));
@@ -854,14 +980,16 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
Field != FieldEnd; ++Field) {
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
QualType FTy = (*Field)->getType();
- SVal FieldValue = Retrieve(St, loc::MemRegionVal(FR), FTy);
+ SVal FieldValue = Retrieve(state, loc::MemRegionVal(FR), FTy);
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
}
-SVal RegionStoreManager::RetrieveArray(const GRState* St, const TypedRegion* R){
+SVal RegionStoreManager::RetrieveArray(const GRState *state,
+ const TypedRegion * R) {
+
QualType T = R->getValueType(getContext());
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
@@ -871,41 +999,19 @@ SVal RegionStoreManager::RetrieveArray(const GRState* St, const TypedRegion* R){
for (; i < Size; ++i) {
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R);
+ ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
+ getContext());
QualType ETy = ER->getElementType();
- SVal ElementVal = Retrieve(St, loc::MemRegionVal(ER), ETy);
+ SVal ElementVal = Retrieve(state, loc::MemRegionVal(ER), ETy);
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
}
return NonLoc::MakeCompoundVal(T, ArrayVal, getBasicVals());
}
-const GRState* RegionStoreManager::Bind(const GRState* St, Loc L, SVal V) {
- // If we get here, the location should be a region.
- const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
- assert(R);
-
- // Check if the region is a struct region.
- if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getValueType(getContext())->isStructureType())
- return BindStruct(St, TR, V);
-
- Store store = St->getStore();
- RegionBindingsTy B = GetRegionBindings(store);
-
- if (V.isUnknown()) {
- // Remove the binding.
- store = RBFactory.Remove(B, R).getRoot();
-
- // Add the region to the killset.
- GRStateRef state(St, StateMgr);
- St = state.add<RegionKills>(R);
- }
- else
- store = RBFactory.Add(B, R, V).getRoot();
-
- return StateMgr.MakeStateWithStore(St, store);
-}
+//===----------------------------------------------------------------------===//
+// Binding values to regions.
+//===----------------------------------------------------------------------===//
Store RegionStoreManager::Remove(Store store, Loc L) {
const MemRegion* R = 0;
@@ -921,34 +1027,235 @@ Store RegionStoreManager::Remove(Store store, Loc L) {
return store;
}
-const GRState* RegionStoreManager::BindDecl(const GRState* St,
+const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
+ // If we get here, the location should be a region.
+ const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
+
+ // Check if the region is a struct region.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
+ if (TR->getValueType(getContext())->isStructureType())
+ return BindStruct(state, TR, V);
+
+ RegionBindingsTy B = GetRegionBindings(state->getStore());
+
+ if (V.isUnknown()) {
+ B = RBFactory.Remove(B, R); // Remove the binding.
+ state = state->add<RegionKills>(R); // Add the region to the killset.
+ }
+ else
+ B = RBFactory.Add(B, R, V);
+
+ return state->makeWithStore(B.getRoot());
+}
+
+const GRState *RegionStoreManager::BindDecl(const GRState *state,
const VarDecl* VD, SVal InitVal) {
QualType T = VD->getType();
VarRegion* VR = MRMgr.getVarRegion(VD);
if (T->isArrayType())
- return BindArray(St, VR, InitVal);
+ return BindArray(state, VR, InitVal);
if (T->isStructureType())
- return BindStruct(St, VR, InitVal);
+ return BindStruct(state, VR, InitVal);
- return Bind(St, Loc::MakeVal(VR), InitVal);
+ return Bind(state, Loc::MakeVal(VR), InitVal);
}
// FIXME: this method should be merged into Bind().
-const GRState*
-RegionStoreManager::BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL, SVal V) {
+const GRState *
+RegionStoreManager::BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* CL,
+ SVal V) {
+
CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL);
- return Bind(St, loc::MemRegionVal(R), V);
+ return Bind(state, loc::MemRegionVal(R), V);
}
-const GRState* RegionStoreManager::setExtent(const GRState* St,
- const MemRegion* R, SVal Extent) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionExtents>(R, Extent);
+const GRState *RegionStoreManager::BindArray(const GRState *state,
+ const TypedRegion* R,
+ SVal Init) {
+
+ QualType T = R->getValueType(getContext());
+ assert(T->isArrayType());
+
+ // When we are binding the whole array, it always has default value 0.
+ state = state->set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(),
+ 0, false));
+
+ ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
+
+ llvm::APSInt Size(CAT->getSize(), false);
+ llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
+ Size.isUnsigned());
+
+ // Check if the init expr is a StringLiteral.
+ if (isa<loc::MemRegionVal>(Init)) {
+ const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
+ const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
+ const char* str = S->getStrData();
+ unsigned len = S->getByteLength();
+ unsigned j = 0;
+
+ // Copy bytes from the string literal into the target array. Trailing bytes
+ // in the array that are not covered by the string literal are initialized
+ // to zero.
+ for (; i < Size; ++i, ++j) {
+ if (j >= len)
+ break;
+
+ SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
+ ElementRegion* ER =
+ MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
+ Idx, R, getContext());
+
+ SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
+ state = Bind(state, loc::MemRegionVal(ER), V);
+ }
+
+ return state;
+ }
+
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+
+ for (; i < Size; ++i, ++VI) {
+ // The init list might be shorter than the array decl.
+ if (VI == VE)
+ break;
+
+ SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
+ ElementRegion* ER =
+ MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
+ Idx, R, getContext());
+
+ if (CAT->getElementType()->isStructureType())
+ state = BindStruct(state, ER, *VI);
+ else
+ state = Bind(state, Loc::MakeVal(ER), *VI);
+ }
+
+ return state;
}
+const GRState *
+RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
+ SVal V) {
+
+ if (!Features.supportsFields())
+ return state;
+
+ QualType T = R->getValueType(getContext());
+ assert(T->isStructureType());
+
+ const RecordType* RT = T->getAsRecordType();
+ RecordDecl* RD = RT->getDecl();
+
+ if (!RD->isDefinition())
+ return state;
+
+ // We may get non-CompoundVal accidentally due to imprecise cast logic.
+ // Ignore them and kill the field values.
+ if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
+ return KillStruct(state, R);
+
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+
+ for (RecordDecl::field_iterator FI = RD->field_begin(getContext()),
+ FE = RD->field_end(getContext());
+ FI != FE; ++FI, ++VI) {
+
+ // There may be fewer values than fields only when we are initializing a
+ // struct decl. In this case, mark the region as having default value.
+ if (VI == VE) {
+ const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false);
+ state = state->set<RegionDefaultValue>(R, Idx);
+ break;
+ }
+
+ QualType FTy = (*FI)->getType();
+ FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
+
+ if (Loc::IsLocType(FTy) || FTy->isIntegerType())
+ state = Bind(state, Loc::MakeVal(FR), *VI);
+ else if (FTy->isArrayType())
+ state = BindArray(state, FR, *VI);
+ else if (FTy->isStructureType())
+ state = BindStruct(state, FR, *VI);
+ }
+
+ return state;
+}
+
+const GRState *RegionStoreManager::KillStruct(const GRState *state,
+ const TypedRegion* R){
+
+ // (1) Kill the struct region because it is assigned "unknown".
+ // (2) Set the default value of the struct region to "unknown".
+ state = state->add<RegionKills>(R)->set<RegionDefaultValue>(R, UnknownVal());
+ Store store = state->getStore();
+ RegionBindingsTy B = GetRegionBindings(store);
+
+ // Remove all bindings for the subregions of the struct.
+ for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ const MemRegion* R = I.getKey();
+ if (const SubRegion* subRegion = dyn_cast<SubRegion>(R))
+ if (subRegion->isSubRegionOf(R))
+ store = Remove(store, Loc::MakeVal(subRegion));
+ // FIXME: Maybe we should also remove the bindings for the "views" of the
+ // subregions.
+ }
+
+ return state->makeWithStore(store);
+}
+
+//===----------------------------------------------------------------------===//
+// Region views.
+//===----------------------------------------------------------------------===//
+
+const GRState *RegionStoreManager::AddRegionView(const GRState *state,
+ const MemRegion* View,
+ const MemRegion* Base) {
+
+ // First, retrieve the region view of the base region.
+ const RegionViews* d = state->get<RegionViewMap>(Base);
+ RegionViews L = d ? *d : RVFactory.GetEmptySet();
+
+ // Now add View to the region view.
+ L = RVFactory.Add(L, View);
+
+ // Create a new state with the new region view.
+ return state->set<RegionViewMap>(Base, L);
+}
+
+const GRState *RegionStoreManager::RemoveRegionView(const GRState *state,
+ const MemRegion* View,
+ const MemRegion* Base) {
+ // Retrieve the region view of the base region.
+ const RegionViews* d = state->get<RegionViewMap>(Base);
+
+ // If the base region has no view, return.
+ if (!d)
+ return state;
+
+ // Remove the view.
+ return state->set<RegionViewMap>(Base, RVFactory.Remove(*d, View));
+}
+
+const GRState *RegionStoreManager::setCastType(const GRState *state,
+ const MemRegion* R, QualType T) {
+ return state->set<RegionCasts>(R, T);
+}
+
+const GRState *RegionStoreManager::setDefaultValue(const GRState *state,
+ const MemRegion* R, SVal V) {
+ return state->set<RegionDefaultValue>(R, V);
+}
+
+//===----------------------------------------------------------------------===//
+// State pruning.
+//===----------------------------------------------------------------------===//
static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) {
if (loc::MemRegionVal *XR = dyn_cast<loc::MemRegionVal>(&X)) {
@@ -975,11 +1282,10 @@ static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) {
SymReaper.markLive(*SI);
}
-Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
+Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
-{
-
+{
Store store = state->getStore();
RegionBindingsTy B = GetRegionBindings(store);
@@ -1002,18 +1308,17 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// Do a pass over the regions in the store. For VarRegions we check if
// the variable is still live and if so add it to the list of live roots.
- // For other regions we populate our region backmap.
-
+ // For other regions we populate our region backmap.
llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
-
+
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
IntermediateRoots.push_back(I.getKey());
}
-
+
while (!IntermediateRoots.empty()) {
const MemRegion* R = IntermediateRoots.back();
IntermediateRoots.pop_back();
-
+
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
if (SymReaper.isLive(Loc, VR->getDecl()))
RegionRoots.push_back(VR); // This is a live "root".
@@ -1025,14 +1330,14 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
else {
// Get the super region for R.
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
-
+
// Get the current set of subregions for SuperR.
const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);
SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet();
-
+
// Add R to the subregions of SuperR.
SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R));
-
+
// Super region may be VarRegion or subregion of another VarRegion. Add it
// to the work list.
if (isa<SubRegion>(SuperR))
@@ -1048,10 +1353,10 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// Dequeue the next region on the worklist.
const MemRegion* R = RegionRoots.back();
RegionRoots.pop_back();
-
+
// Check if we have already processed this region.
if (Marked.count(R)) continue;
-
+
// Mark this region as processed. This is needed for termination in case
// a region is referenced more than once.
Marked.insert(R);
@@ -1060,13 +1365,13 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// should continue to track that symbol.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
SymReaper.markLive(SymR->getSymbol());
-
+
// Get the data binding for R (if any).
RegionBindingsTy::data_type* Xptr = B.lookup(R);
if (Xptr) {
SVal X = *Xptr;
UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols.
-
+
// If X is a region, then add it the RegionRoots.
if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X))
RegionRoots.push_back(RegionX->getRegion());
@@ -1094,11 +1399,11 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// Remove this dead region from the store.
store = Remove(store, Loc::MakeVal(R));
-
+
// Mark all non-live symbols that this region references as dead.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
SymReaper.maybeDead(SymR->getSymbol());
-
+
SVal X = I.getData();
SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
for (; SI != SE; ++SI) SymReaper.maybeDead(*SI);
@@ -1107,203 +1412,18 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
return store;
}
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
void RegionStoreManager::print(Store store, std::ostream& Out,
const char* nl, const char *sep) {
llvm::raw_os_ostream OS(Out);
RegionBindingsTy B = GetRegionBindings(store);
OS << "Store:" << nl;
-
+
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
OS << ' '; I.getKey()->print(OS); OS << " : ";
I.getData().print(OS); OS << nl;
}
}
-
-const GRState* RegionStoreManager::BindArray(const GRState* St,
- const TypedRegion* R, SVal Init) {
- QualType T = R->getValueType(getContext());
- assert(T->isArrayType());
-
- // When we are binding the whole array, it always has default value 0.
- GRStateRef state(St, StateMgr);
- St = state.set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(), 0,
- false));
-
- ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
-
- llvm::APSInt Size(CAT->getSize(), false);
- llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
- Size.isUnsigned());
-
- // Check if the init expr is a StringLiteral.
- if (isa<loc::MemRegionVal>(Init)) {
- const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
- const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
- const char* str = S->getStrData();
- unsigned len = S->getByteLength();
- unsigned j = 0;
-
- // Copy bytes from the string literal into the target array. Trailing bytes
- // in the array that are not covered by the string literal are initialized
- // to zero.
- for (; i < Size; ++i, ++j) {
- if (j >= len)
- break;
-
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER =
- MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
- Idx, R);
-
- SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
- St = Bind(St, loc::MemRegionVal(ER), V);
- }
-
- return St;
- }
-
- nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
- nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
-
- for (; i < Size; ++i, ++VI) {
- // The init list might be shorter than the array decl.
- if (VI == VE)
- break;
-
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER =
- MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
- Idx, R);
-
- if (CAT->getElementType()->isStructureType())
- St = BindStruct(St, ER, *VI);
- else
- St = Bind(St, Loc::MakeVal(ER), *VI);
- }
-
- return St;
-}
-
-const GRState*
-RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){
- QualType T = R->getValueType(getContext());
- assert(T->isStructureType());
-
- const RecordType* RT = T->getAsRecordType();
- RecordDecl* RD = RT->getDecl();
-
- if (!RD->isDefinition())
- return St;
-
- if (V.isUnknown())
- return KillStruct(St, R);
-
- // We may get non-CompoundVal accidentally due to imprecise cast logic. Ignore
- // them and make struct unknown.
- if (!isa<nonloc::CompoundVal>(V))
- return KillStruct(St, R);
-
- nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
- nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
- RecordDecl::field_iterator FI = RD->field_begin(getContext()),
- FE = RD->field_end(getContext());
-
- for (; FI != FE; ++FI, ++VI) {
-
- // There may be fewer values than fields only when we are initializing a
- // struct decl. In this case, mark the region as having default value.
- if (VI == VE) {
- GRStateRef state(St, StateMgr);
- const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false);
- St = state.set<RegionDefaultValue>(R, Idx);
- break;
- }
-
- QualType FTy = (*FI)->getType();
- FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
-
- if (Loc::IsLocType(FTy) || FTy->isIntegerType())
- St = Bind(St, Loc::MakeVal(FR), *VI);
-
- else if (FTy->isArrayType())
- St = BindArray(St, FR, *VI);
-
- else if (FTy->isStructureType())
- St = BindStruct(St, FR, *VI);
- }
-
- return St;
-}
-
-const GRState* RegionStoreManager::KillStruct(const GRState* St,
- const TypedRegion* R){
- GRStateRef state(St, StateMgr);
-
- // Kill the struct region because it is assigned "unknown".
- St = state.add<RegionKills>(R);
-
- // Set the default value of the struct region to "unknown".
- St = state.set<RegionDefaultValue>(R, UnknownVal());
-
- Store store = St->getStore();
- RegionBindingsTy B = GetRegionBindings(store);
-
- // Remove all bindings for the subregions of the struct.
- for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion* r = I.getKey();
- if (const SubRegion* sr = dyn_cast<SubRegion>(r))
- if (sr->isSubRegionOf(R))
- store = Remove(store, Loc::MakeVal(sr));
- // FIXME: Maybe we should also remove the bindings for the "views" of the
- // subregions.
- }
-
- return StateMgr.MakeStateWithStore(St, store);
-}
-
-const GRState* RegionStoreManager::AddRegionView(const GRState* St,
- const MemRegion* View,
- const MemRegion* Base) {
- GRStateRef state(St, StateMgr);
-
- // First, retrieve the region view of the base region.
- const RegionViews* d = state.get<RegionViewMap>(Base);
- RegionViews L = d ? *d : RVFactory.GetEmptySet();
-
- // Now add View to the region view.
- L = RVFactory.Add(L, View);
-
- // Create a new state with the new region view.
- return state.set<RegionViewMap>(Base, L);
-}
-
-const GRState* RegionStoreManager::RemoveRegionView(const GRState* St,
- const MemRegion* View,
- const MemRegion* Base) {
- GRStateRef state(St, StateMgr);
-
- // Retrieve the region view of the base region.
- const RegionViews* d = state.get<RegionViewMap>(Base);
-
- // If the base region has no view, return.
- if (!d)
- return St;
-
- // Remove the view.
- RegionViews V = *d;
- V = RVFactory.Remove(V, View);
-
- return state.set<RegionViewMap>(Base, V);
-}
-
-const GRState* RegionStoreManager::setCastType(const GRState* St,
- const MemRegion* R, QualType T) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionCasts>(R, T);
-}
-
-const GRState* RegionStoreManager::setDefaultValue(const GRState* St,
- const MemRegion* R, SVal V) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionDefaultValue>(R, V);
-}
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index e19b168..77c3c8f 100644
--- a/lib/Analysis/SVals.cpp
+++ b/lib/Analysis/SVals.cpp
@@ -294,7 +294,7 @@ NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) {
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
}
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I) {
+NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral* I) {
return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(),
I->getType()->isUnsignedIntegerType())));
@@ -322,11 +322,12 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
}
-SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R) {
- SymbolRef sym = SymMgr.getRegionValueSymbol(R);
+SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
+ SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
- QualType T = TR->getValueType(SymMgr.getContext());
+ if (T.isNull())
+ T = TR->getValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
@@ -401,7 +402,9 @@ nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V,
Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
-Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); }
+Loc Loc::MakeVal(const AddrLabelExpr *E) {
+ return loc::GotoLabel(E->getLabel());
+}
Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
diff --git a/lib/Analysis/SimpleConstraintManager.cpp b/lib/Analysis/SimpleConstraintManager.cpp
index f79dba0..82801eb 100644
--- a/lib/Analysis/SimpleConstraintManager.cpp
+++ b/lib/Analysis/SimpleConstraintManager.cpp
@@ -55,60 +55,55 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
return true;
}
-const GRState*
-SimpleConstraintManager::Assume(const GRState* St, SVal Cond, bool Assumption,
- bool& isFeasible) {
+const GRState *SimpleConstraintManager::Assume(const GRState *state,
+ SVal Cond, bool Assumption) {
if (Cond.isUnknown()) {
- isFeasible = true;
- return St;
+ return state;
}
if (isa<NonLoc>(Cond))
- return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible);
+ return Assume(state, cast<NonLoc>(Cond), Assumption);
else
- return Assume(St, cast<Loc>(Cond), Assumption, isFeasible);
+ return Assume(state, cast<Loc>(Cond), Assumption);
}
-const GRState*
-SimpleConstraintManager::Assume(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible) {
- St = AssumeAux(St, Cond, Assumption, isFeasible);
-
- if (!isFeasible)
- return St;
-
+const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
+ bool Assumption) {
+
+ state = AssumeAux(state, Cond, Assumption);
+
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
- // true or false.
- return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
- isFeasible);
+ // true or false.
+ return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
+ : NULL;
}
-const GRState*
-SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible) {
- BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
+ Loc Cond, bool Assumption) {
+
+ BasicValueFactory &BasicVals = state->getBasicVals();
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this Loc.");
- return St;
+ return state;
case loc::MemRegionKind: {
// FIXME: Should this go into the storemanager?
- const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion();
- const SubRegion* SubR = dyn_cast<SubRegion>(R);
+ const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
+ const SubRegion *SubR = dyn_cast<SubRegion>(R);
while (SubR) {
// FIXME: now we only find the first symbolic region.
- if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(SubR)) {
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
if (Assumption)
- return AssumeSymNE(St, SymR->getSymbol(),
- BasicVals.getZeroWithPtrWidth(), isFeasible);
+ return AssumeSymNE(state, SymR->getSymbol(),
+ BasicVals.getZeroWithPtrWidth());
else
- return AssumeSymEQ(St, SymR->getSymbol(),
- BasicVals.getZeroWithPtrWidth(), isFeasible);
+ return AssumeSymEQ(state, SymR->getSymbol(),
+ BasicVals.getZeroWithPtrWidth());
}
SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
}
@@ -117,43 +112,42 @@ SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
}
case loc::GotoLabelKind:
- isFeasible = Assumption;
- return St;
+ return Assumption ? state : NULL;
case loc::ConcreteIntKind: {
- bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
- isFeasible = b ? Assumption : !Assumption;
- return St;
+ bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
+ bool isFeasible = b ? Assumption : !Assumption;
+ return isFeasible ? state : NULL;
}
} // end switch
}
-const GRState*
-SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
- bool& isFeasible) {
- St = AssumeAux(St, Cond, Assumption, isFeasible);
-
- if (!isFeasible)
- return St;
-
+const GRState *SimpleConstraintManager::Assume(const GRState *state,
+ NonLoc Cond,
+ bool Assumption) {
+
+ state = AssumeAux(state, Cond, Assumption);
+
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
- // true or false.
- return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
- isFeasible);
+ // true or false.
+ return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
+ : NULL;
}
-const GRState*
-SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
- bool Assumption, bool& isFeasible) {
+const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
+ NonLoc Cond,
+ bool Assumption) {
+
// We cannot reason about SymIntExpr and SymSymExpr.
if (!canReasonAbout(Cond)) {
- isFeasible = true;
- return St;
+ // Just return the current state indicating that the path is feasible.
+ // This may be an over-approximation of what is possible.
+ return state;
}
- BasicValueFactory& BasicVals = StateMgr.getBasicVals();
- SymbolManager& SymMgr = StateMgr.getSymbolManager();
+ BasicValueFactory &BasicVals = state->getBasicVals();
+ SymbolManager &SymMgr = state->getSymbolManager();
switch (Cond.getSubKind()) {
default:
@@ -162,38 +156,38 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
case nonloc::SymbolValKind: {
nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
SymbolRef sym = SV.getSymbol();
- QualType T = SymMgr.getType(sym);
-
- if (Assumption)
- return AssumeSymNE(St, sym, BasicVals.getValue(0, T), isFeasible);
- else
- return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible);
+ QualType T = SymMgr.getType(sym);
+ const llvm::APSInt &zero = BasicVals.getValue(0, T);
+
+ return Assumption ? AssumeSymNE(state, sym, zero)
+ : AssumeSymEQ(state, sym, zero);
}
case nonloc::SymExprValKind: {
nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
- return AssumeSymInt(St, Assumption, SE, isFeasible);
+ return AssumeSymInt(state, Assumption, SE);
- isFeasible = true;
- return St;
+ // For all other symbolic expressions, over-approximate and consider
+ // the constraint feasible.
+ return state;
}
case nonloc::ConcreteIntKind: {
bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
- isFeasible = b ? Assumption : !Assumption;
- return St;
+ bool isFeasible = b ? Assumption : !Assumption;
+ return isFeasible ? state : NULL;
}
case nonloc::LocAsIntegerKind:
- return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(),
- Assumption, isFeasible);
+ return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
+ Assumption);
} // end switch
}
-const GRState*
-SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
- const SymIntExpr *SE, bool& isFeasible) {
+const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state,
+ bool Assumption,
+ const SymIntExpr *SE) {
// Here we assume that LHS is a symbol. This is consistent with the
@@ -203,47 +197,44 @@ SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
switch (SE->getOpcode()) {
default:
- // No logic yet for other operators.
- isFeasible = true;
- return St;
+ // No logic yet for other operators. Assume the constraint is feasible.
+ return state;
case BinaryOperator::EQ:
- return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible)
- : AssumeSymNE(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymEQ(state, Sym, Int)
+ : AssumeSymNE(state, Sym, Int);
case BinaryOperator::NE:
- return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible)
- : AssumeSymEQ(St, Sym, Int, isFeasible);
-
+ return Assumption ? AssumeSymNE(state, Sym, Int)
+ : AssumeSymEQ(state, Sym, Int);
case BinaryOperator::GT:
- return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible)
- : AssumeSymLE(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymGT(state, Sym, Int)
+ : AssumeSymLE(state, Sym, Int);
case BinaryOperator::GE:
- return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible)
- : AssumeSymLT(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymGE(state, Sym, Int)
+ : AssumeSymLT(state, Sym, Int);
case BinaryOperator::LT:
- return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible)
- : AssumeSymGE(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymLT(state, Sym, Int)
+ : AssumeSymGE(state, Sym, Int);
case BinaryOperator::LE:
- return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible)
- : AssumeSymGT(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymLE(state, Sym, Int)
+ : AssumeSymGT(state, Sym, Int);
} // end switch
}
-const GRState*
-SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
- SVal UpperBound, bool Assumption,
- bool& isFeasible) {
+const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
+ SVal Idx,
+ SVal UpperBound,
+ bool Assumption) {
+
// Only support ConcreteInt for now.
- if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){
- isFeasible = true;
- return St;
- }
+ if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
+ return state;
- const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false);
+ const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
// IdxV might be too narrow.
if (IdxV.getBitWidth() < Zero.getBitWidth())
@@ -254,10 +245,8 @@ SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
UBV.extend(Zero.getBitWidth());
bool InBound = (Zero <= IdxV) && (IdxV < UBV);
-
- isFeasible = Assumption ? InBound : !InBound;
-
- return St;
+ bool isFeasible = Assumption ? InBound : !InBound;
+ return isFeasible ? state : NULL;
}
} // end of namespace clang
diff --git a/lib/Analysis/SimpleConstraintManager.h b/lib/Analysis/SimpleConstraintManager.h
index fb41e2f..1e1a10d 100644
--- a/lib/Analysis/SimpleConstraintManager.h
+++ b/lib/Analysis/SimpleConstraintManager.h
@@ -20,63 +20,59 @@
namespace clang {
class SimpleConstraintManager : public ConstraintManager {
-protected:
- GRStateManager& StateMgr;
public:
- SimpleConstraintManager(GRStateManager& statemgr)
- : StateMgr(statemgr) {}
- virtual ~SimpleConstraintManager();
-
- bool canReasonAbout(SVal X) const;
+ SimpleConstraintManager() {}
+ virtual ~SimpleConstraintManager();
- virtual const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
- bool& isFeasible);
-
- const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible);
+ //===------------------------------------------------------------------===//
+ // Common implementation for the interface provided by ConstraintManager.
+ //===------------------------------------------------------------------===//
- const GRState* AssumeAux(const GRState* St, Loc Cond,bool Assumption,
- bool& isFeasible);
-
- const GRState* Assume(const GRState* St, NonLoc Cond, bool Assumption,
- bool& isFeasible);
-
- const GRState* AssumeAux(const GRState* St, NonLoc Cond, bool Assumption,
- bool& isFeasible);
+ bool canReasonAbout(SVal X) const;
- const GRState* AssumeSymInt(const GRState* St, bool Assumption,
- const SymIntExpr *SE, bool& isFeasible);
+ const GRState *Assume(const GRState *state, SVal Cond, bool Assumption);
- virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ const GRState *Assume(const GRState *state, Loc Cond, bool Assumption);
- virtual const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ const GRState *Assume(const GRState *state, NonLoc Cond, bool Assumption);
- virtual const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ const GRState *AssumeSymInt(const GRState *state, bool Assumption,
+ const SymIntExpr *SE);
+
+ const GRState *AssumeInBound(const GRState *state, SVal Idx, SVal UpperBound,
+ bool Assumption);
+
+protected:
+
+ //===------------------------------------------------------------------===//
+ // Interface that subclasses must implement.
+ //===------------------------------------------------------------------===//
+
+ virtual const GRState *AssumeSymNE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- virtual const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeSymEQ(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- virtual const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeSymLT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- virtual const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeSymGT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
- bool Assumption, bool& isFeasible);
+ virtual const GRState *AssumeSymLE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
-private:
- BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
- SymbolManager& getSymbolManager() const { return StateMgr.getSymbolManager(); }
+ virtual const GRState *AssumeSymGE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
+
+ //===------------------------------------------------------------------===//
+ // Internal implementation.
+ //===------------------------------------------------------------------===//
+
+ const GRState *AssumeAux(const GRState *state, Loc Cond,bool Assumption);
+
+ const GRState *AssumeAux(const GRState *state, NonLoc Cond, bool Assumption);
};
} // end clang namespace
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp
index 13326ab..5aa756e 100644
--- a/lib/Analysis/Store.cpp
+++ b/lib/Analysis/Store.cpp
@@ -90,7 +90,8 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R,
// FIXME: Is this the right thing to do in all cases?
const TypedRegion *Base = isa<ElementRegion>(TR) ?
cast<TypedRegion>(TR->getSuperRegion()) : TR;
- ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base);
+ ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base,
+ StateMgr.getContext());
return CastResult(state, ER);
}
}
diff --git a/lib/Analysis/SymbolManager.cpp b/lib/Analysis/SymbolManager.cpp
index 5c885cd..4e38a34 100644
--- a/lib/Analysis/SymbolManager.cpp
+++ b/lib/Analysis/SymbolManager.cpp
@@ -92,14 +92,14 @@ std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) {
}
const SymbolRegionValue*
-SymbolManager::getRegionValueSymbol(const MemRegion* R) {
+SymbolManager::getRegionValueSymbol(const MemRegion* R, QualType T) {
llvm::FoldingSetNodeID profile;
- SymbolRegionValue::Profile(profile, R);
+ SymbolRegionValue::Profile(profile, R, T);
void* InsertPos;
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
if (!SD) {
SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
- new (SD) SymbolRegionValue(SymbolCounter, R);
+ new (SD) SymbolRegionValue(SymbolCounter, R, T);
DataSet.InsertNode(SD, InsertPos);
++SymbolCounter;
}
@@ -166,6 +166,9 @@ QualType SymbolConjured::getType(ASTContext&) const {
}
QualType SymbolRegionValue::getType(ASTContext& C) const {
+ if (!T.isNull())
+ return T;
+
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
return TR->getValueType(C);
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index ebe0514..6cb5dab 100644
--- a/lib/Basic/Builtins.cpp
+++ b/lib/Basic/Builtins.cpp
@@ -30,11 +30,17 @@ const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
return TSRecords[ID - Builtin::FirstTSBuiltin];
}
+Builtin::Context::Context(const TargetInfo &Target) {
+ // Get the target specific builtins from the target.
+ TSRecords = 0;
+ NumTSRecords = 0;
+ Target.getTargetBuiltins(TSRecords, NumTSRecords);
+}
+
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
- const TargetInfo &Target,
bool NoBuiltins) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
@@ -42,9 +48,6 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
- // Get the target specific builtins from the target.
- Target.getTargetBuiltins(TSRecords, NumTSRecords);
-
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 323f7a7..78b8b0a 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -118,7 +118,7 @@ const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
- return Info->SFINAE && Info->Class != CLASS_NOTE;
+ return Info->SFINAE && Info->Class == CLASS_ERROR;
return false;
}
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index ed5eb46..8dfc5d1 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -358,7 +358,10 @@ FileID SourceManager::createFileID(const ContentCache *File,
SLocEntryTable[PreallocatedID]
= SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
SLocEntryLoaded[PreallocatedID] = true;
- return LastFileIDLookup = FileID::get(PreallocatedID);
+ FileID FID = FileID::get(PreallocatedID);
+ if (File->FirstFID.isInvalid())
+ File->FirstFID = FID;
+ return LastFileIDLookup = FID;
}
SLocEntryTable.push_back(SLocEntry::get(NextOffset,
@@ -914,6 +917,43 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
// Other miscellaneous methods.
//===----------------------------------------------------------------------===//
+/// \brief Get the source location for the given file:line:col triplet.
+///
+/// If the source file is included multiple times, the source location will
+/// be based upon the first inclusion.
+SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
+ unsigned Line, unsigned Col) const {
+ assert(SourceFile && "Null source file!");
+ assert(Line && Col && "Line and column should start from 1!");
+
+ fileinfo_iterator FI = FileInfos.find(SourceFile);
+ if (FI == FileInfos.end())
+ return SourceLocation();
+ ContentCache *Content = FI->second;
+
+ // If this is the first use of line information for this buffer, compute the
+ /// SourceLineCache for it on demand.
+ if (Content->SourceLineCache == 0)
+ ComputeLineNumbers(Content, ContentCacheAlloc);
+
+ if (Line > Content->NumLines)
+ return SourceLocation();
+
+ unsigned FilePos = Content->SourceLineCache[Line - 1];
+ const char *Buf = Content->getBuffer()->getBufferStart();
+ unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf;
+ unsigned i = 0;
+
+ // Check that the given column is valid.
+ while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
+ ++i;
+ if (i < Col-1)
+ return SourceLocation();
+
+ return getLocForStartOfFile(Content->FirstFID).
+ getFileLocWithOffset(FilePos + Col - 1);
+}
+
/// PrintStats - Print statistics to stderr.
///
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index a919dfa..66b1f17 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -522,7 +522,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIsqrtf:
case Builtin::BIsqrtl: {
// Rewrite sqrt to intrinsic if allowed.
- if (!FD->hasAttr<ConstAttr>())
+ if (!FD->hasAttr<ConstAttr>(getContext()))
break;
Value *Arg0 = EmitScalarExpr(E->getArg(0));
const llvm::Type *ArgType = Arg0->getType();
@@ -534,7 +534,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIpowf:
case Builtin::BIpowl: {
// Rewrite sqrt to intrinsic if allowed.
- if (!FD->hasAttr<ConstAttr>())
+ if (!FD->hasAttr<ConstAttr>(getContext()))
break;
Value *Base = EmitScalarExpr(E->getArg(0));
Value *Exponent = EmitScalarExpr(E->getArg(1));
diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp
index 141726a..a6e6d11 100644
--- a/lib/CodeGen/CGCXXTemp.cpp
+++ b/lib/CodeGen/CGCXXTemp.cpp
@@ -85,6 +85,11 @@ RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
llvm::Value *AggLoc,
bool isAggLocVolatile) {
+ // If we shouldn't destroy the temporaries, just emit the
+ // child expression.
+ if (!E->shouldDestroyTemporaries())
+ return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
+
// Keep track of the current cleanup stack depth.
size_t CleanupStackDepth = CleanupEntries.size();
(void) CleanupStackDepth;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 4037f32..ec6058a 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -377,13 +377,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// FIXME: handle sseregparm someday...
if (TargetDecl) {
- if (TargetDecl->hasAttr<NoThrowAttr>())
+ if (TargetDecl->hasAttr<NoThrowAttr>(getContext()))
FuncAttrs |= llvm::Attribute::NoUnwind;
- if (TargetDecl->hasAttr<NoReturnAttr>())
+ if (TargetDecl->hasAttr<NoReturnAttr>(getContext()))
FuncAttrs |= llvm::Attribute::NoReturn;
- if (TargetDecl->hasAttr<ConstAttr>())
+ if (TargetDecl->hasAttr<ConstAttr>(getContext()))
FuncAttrs |= llvm::Attribute::ReadNone;
- else if (TargetDecl->hasAttr<PureAttr>())
+ else if (TargetDecl->hasAttr<PureAttr>(getContext()))
FuncAttrs |= llvm::Attribute::ReadOnly;
}
@@ -432,7 +432,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// register variable.
signed RegParm = 0;
if (TargetDecl)
- if (const RegparmAttr *RegParmAttr = TargetDecl->getAttr<RegparmAttr>())
+ if (const RegparmAttr *RegParmAttr
+ = TargetDecl->getAttr<RegparmAttr>(getContext()))
RegParm = RegParmAttr->getNumParams();
unsigned PointerWidth = getContext().Target.getPointerWidth(0);
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 049e716..a2b8d13 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -50,6 +50,24 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
/// one if necessary. This returns null for invalid source locations.
llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
+
+ // Each input file is encoded as a separate compile unit in LLVM
+ // debugging information output. However, many target specific tool chains
+ // prefer to encode only one compile unit in an object file. In this
+ // situation, the LLVM code generator will include debugging information
+ // entities in the compile unit that is marked as main compile unit. The
+ // code generator accepts maximum one main compile unit per module. If a
+ // module does not contain any main compile unit then the code generator
+ // will emit multiple compile units in the output object file. Create main
+ // compile unit if there is not one available.
+ const LangOptions &LO = M->getLangOptions();
+ if (isMainCompileUnitCreated == false) {
+ if (LO.getMainFileName()) {
+ createCompileUnit(LO.getMainFileName(), true /* isMain */);
+ isMainCompileUnitCreated = true;
+ }
+ }
+
// Get source file information.
const char *FileName = "<unknown>";
SourceManager &SM = M->getContext().getSourceManager();
@@ -72,25 +90,26 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
AbsFileName = tmp;
}
- // See if thie compile unit is representing main source file. Each source
- // file has corresponding compile unit. There is only one main source
- // file at a time.
- bool isMain = false;
- const LangOptions &LO = M->getLangOptions();
- const char *MainFileName = LO.getMainFileName();
- if (isMainCompileUnitCreated == false) {
- if (MainFileName) {
- if (!strcmp(AbsFileName.getLast().c_str(), MainFileName))
- isMain = true;
- } else {
- if (Loc.isValid() && SM.isFromMainFile(Loc))
- isMain = true;
- }
- if (isMain)
- isMainCompileUnitCreated = true;
+ // There is only one main source file at a time whose compile unit
+ // is already created.
+ Unit = createCompileUnit(FileName, false /* isMain */);
+ return Unit;
+}
+
+/// createCompileUnit - Create a new unit for the given file.
+llvm::DICompileUnit CGDebugInfo::createCompileUnit(const char *FileName,
+ bool isMain) {
+
+ // Get absolute path name.
+ llvm::sys::Path AbsFileName(FileName);
+ if (!AbsFileName.isAbsolute()) {
+ llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
+ tmp.appendComponent(FileName);
+ AbsFileName = tmp;
}
unsigned LangTag;
+ const LangOptions &LO = M->getLangOptions();
if (LO.CPlusPlus) {
if (LO.ObjC1)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
@@ -114,12 +133,13 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
- return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
- AbsFileName.getDirname(),
- Producer, isMain, isOptimized,
- Flags, RuntimeVers);
+ return DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
+ AbsFileName.getDirname(),
+ Producer, isMain, isOptimized,
+ Flags, RuntimeVers);
}
+
/// CreateType - Get the Basic type from the cache or create a new
/// one if necessary.
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
@@ -761,7 +781,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
case Type::QualifiedName:
// Unsupported types
return llvm::DIType();
- case Type::ObjCQualifiedId: // Encode id<p> in debug info just like id.
+ case Type::ObjCObjectPointer: // Encode id<p> in debug info just like id.
return Slot = getOrCreateType(M->getContext().getObjCIdType(), Unit);
case Type::ObjCQualifiedInterface: // Drop protocols from interface.
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index de65580..8f3368e 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -111,7 +111,9 @@ private:
void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
CGBuilderTy &Builder);
-
+ /// createCompileUnit - Create a new unit for the given file.
+ llvm::DICompileUnit createCompileUnit(const char *FileName, bool isMain);
+
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
/// new one if necessary.
llvm::DICompileUnit getOrCreateCompileUnit(SourceLocation Loc);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 29eaaad..4e603c3 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -60,7 +60,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
/// EmitBlockVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
- if (D.hasAttr<AsmLabelAttr>())
+ if (D.hasAttr<AsmLabelAttr>(getContext()))
CGM.ErrorUnsupported(&D, "__asm__");
switch (D.getStorageClass()) {
@@ -171,7 +171,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
}
// FIXME: Merge attribute handling.
- if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
+ if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>(getContext())) {
SourceManager &SM = CGM.getContext().getSourceManager();
llvm::Constant *Ann =
CGM.EmitAnnotateAttr(GV, AA,
@@ -179,10 +179,10 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
CGM.AddAnnotation(Ann);
}
- if (const SectionAttr *SA = D.getAttr<SectionAttr>())
+ if (const SectionAttr *SA = D.getAttr<SectionAttr>(getContext()))
GV->setSection(SA->getName());
- if (D.hasAttr<UsedAttr>())
+ if (D.hasAttr<UsedAttr>(getContext()))
CGM.AddUsedGlobal(GV);
// We may have to cast the constant because of the initializer
@@ -244,7 +244,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty,
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
QualType Ty = D.getType();
- bool isByRef = D.hasAttr<BlocksAttr>();
+ bool isByRef = D.hasAttr<BlocksAttr>(getContext());
bool needsDispose = false;
unsigned Align = 0;
@@ -414,7 +414,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
}
// Handle the cleanup attribute
- if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
+ if (const CleanupAttr *CA = D.getAttr<CleanupAttr>(getContext())) {
const FunctionDecl *FD = CA->getFunctionDecl();
llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD));
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index eb0db61..51c5b3d 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -668,7 +668,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD) ||
isa<ImplicitParamDecl>(VD))) {
LValue LV;
- bool NonGCable = VD->hasLocalStorage() && !VD->hasAttr<BlocksAttr>();
+ bool NonGCable = VD->hasLocalStorage() &&
+ !VD->hasAttr<BlocksAttr>(getContext());
if (VD->hasExternalStorage()) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
@@ -684,7 +685,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// local static?
if (!NonGCable)
attr = getContext().getObjCGCAttrKind(E->getType());
- if (VD->hasAttr<BlocksAttr>()) {
+ if (VD->hasAttr<BlocksAttr>(getContext())) {
bool needsCopyDispose = BlockRequiresCopying(VD->getType());
const llvm::Type *PtrStructTy = V->getType();
const llvm::Type *Ty = PtrStructTy;
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index e1332ff..3555c8c 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -365,23 +365,28 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) {
ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
bool isInc, bool isPre) {
LValue LV = CGF.EmitLValue(E->getSubExpr());
- ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+ ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(),
+ LV.isVolatileQualified());
llvm::Value *NextVal;
if (isa<llvm::IntegerType>(InVal.first->getType())) {
uint64_t AmountVal = isInc ? 1 : -1;
NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true);
+
+ // Add the inc/dec to the real part.
+ NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
+
} else {
QualType ElemTy = E->getType()->getAsComplexType()->getElementType();
llvm::APFloat FVal(CGF.getContext().getFloatTypeSemantics(ElemTy), 1);
if (!isInc)
FVal.changeSign();
NextVal = llvm::ConstantFP::get(FVal);
+
+ // Add the inc/dec to the real part.
+ NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
}
- // Add the inc/dec to the real part.
- NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
-
ComplexPairTy IncVal(NextVal, InVal.second);
// Store the updated result through the lvalue.
@@ -398,8 +403,15 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
TestAndClearIgnoreRealAssign();
TestAndClearIgnoreImagAssign();
ComplexPairTy Op = Visit(E->getSubExpr());
- llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r");
- llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i");
+
+ llvm::Value *ResR, *ResI;
+ if (Op.first->getType()->isFloatingPoint()) {
+ ResR = Builder.CreateFNeg(Op.first, "neg.r");
+ ResI = Builder.CreateFNeg(Op.second, "neg.i");
+ } else {
+ ResR = Builder.CreateNeg(Op.first, "neg.r");
+ ResI = Builder.CreateNeg(Op.second, "neg.i");
+ }
return ComplexPairTy(ResR, ResI);
}
@@ -410,31 +422,62 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
TestAndClearIgnoreImagAssign();
// ~(a+ib) = a + i*-b
ComplexPairTy Op = Visit(E->getSubExpr());
- llvm::Value *ResI = Builder.CreateNeg(Op.second, "conj.i");
+ llvm::Value *ResI;
+ if (Op.second->getType()->isFloatingPoint())
+ ResI = Builder.CreateFNeg(Op.second, "conj.i");
+ else
+ ResI = Builder.CreateNeg(Op.second, "conj.i");
+
return ComplexPairTy(Op.first, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
- llvm::Value *ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
- llvm::Value *ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ llvm::Value *ResR, *ResI;
+
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
+ ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ } else {
+ ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
+ ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ }
return ComplexPairTy(ResR, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
- llvm::Value *ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
- llvm::Value *ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ llvm::Value *ResR, *ResI;
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
+ ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ } else {
+ ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
+ ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ }
return ComplexPairTy(ResR, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
- llvm::Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
- llvm::Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
- llvm::Value *ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
+ using llvm::Value;
+ Value *ResR, *ResI;
- llvm::Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
- llvm::Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
- llvm::Value *ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ Value *ResRl = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
+ Value *ResRr = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,"mul.rr");
+ ResR = Builder.CreateFSub(ResRl, ResRr, "mul.r");
+
+ Value *ResIl = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il");
+ Value *ResIr = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
+ ResI = Builder.CreateFAdd(ResIl, ResIr, "mul.i");
+ } else {
+ Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
+ Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
+ ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
+
+ Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
+ Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
+ ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
+ }
return ComplexPairTy(ResR, ResI);
}
@@ -442,24 +485,38 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
- // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
- llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
- llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
- llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
-
- llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
- llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
- llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
-
- llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
- llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
- llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
llvm::Value *DSTr, *DSTi;
- if (Tmp3->getType()->isFloatingPoint()) {
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr, "tmp"); // a*c
+ llvm::Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi, "tmp"); // b*d
+ llvm::Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2, "tmp"); // ac+bd
+
+ llvm::Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr, "tmp"); // c*c
+ llvm::Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi, "tmp"); // d*d
+ llvm::Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5, "tmp"); // cc+dd
+
+ llvm::Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr, "tmp"); // b*c
+ llvm::Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi, "tmp"); // a*d
+ llvm::Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8, "tmp"); // bc-ad
+
DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp");
DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp");
} else {
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
+ llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
+ llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
+
+ llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
+ llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
+ llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
+
+ llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
+ llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
+ llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
+
if (Op.Ty->getAsComplexType()->getElementType()->isUnsignedIntegerType()) {
DSTr = Builder.CreateUDiv(Tmp3, Tmp6, "tmp");
DSTi = Builder.CreateUDiv(Tmp9, Tmp6, "tmp");
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 0e21a00..0b109f9 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -198,16 +198,13 @@ public:
// Copy initializer elements. Skip padding fields.
unsigned EltNo = 0; // Element no in ILE
- int FieldNo = 0; // Field no in RecordDecl
bool RewriteType = false;
for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()),
FieldEnd = RD->field_end(CGM.getContext());
EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
- FieldNo++;
- if (!Field->getIdentifier())
- continue;
-
if (Field->isBitField()) {
+ if (!Field->getIdentifier())
+ continue;
InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));
} else {
unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index ed18d32..2af0639 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -294,6 +294,8 @@ public:
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
+ if (Ops.LHS->getType()->isFPOrFPVector())
+ return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
}
/// Create a binary op that checks for overflow.
@@ -699,11 +701,12 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
// An interesting aspect of this is that increment is always true.
// Decrement does not have this property.
NextVal = llvm::ConstantInt::getTrue();
+ } else if (isa<llvm::IntegerType>(InVal->getType())) {
+ NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
+ NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
} else {
// Add the inc/dec to the real part.
- if (isa<llvm::IntegerType>(InVal->getType()))
- NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
- else if (InVal->getType() == llvm::Type::FloatTy)
+ if (InVal->getType() == llvm::Type::FloatTy)
NextVal =
llvm::ConstantFP::get(llvm::APFloat(static_cast<float>(AmountVal)));
else if (InVal->getType() == llvm::Type::DoubleTy)
@@ -716,7 +719,7 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
&ignored);
NextVal = llvm::ConstantFP::get(F);
}
- NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
+ NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec");
}
// Store the updated result through the lvalue.
@@ -735,6 +738,8 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
TestAndClearIgnoreResultAssign();
Value *Op = Visit(E->getSubExpr());
+ if (Op->getType()->isFPOrFPVector())
+ return Builder.CreateFNeg(Op, "neg");
return Builder.CreateNeg(Op, "neg");
}
@@ -982,9 +987,13 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
if (!Ops.Ty->isPointerType()) {
- if (CGF.getContext().getLangOptions().OverflowChecking
- && Ops.Ty->isSignedIntegerType())
+ if (CGF.getContext().getLangOptions().OverflowChecking &&
+ Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
+
+ if (Ops.LHS->getType()->isFPOrFPVector())
+ return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add");
+
return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
}
@@ -1050,6 +1059,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
+
+ if (Ops.LHS->getType()->isFPOrFPVector())
+ return Builder.CreateFSub(Ops.LHS, Ops.RHS, "sub");
return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 51f9a76..e7cf8e6 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -126,7 +126,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
/// its pointer, name, and types registered in the class struture.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
// Check if we should generate debug info for this method.
- if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>())
+ if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>(getContext()))
DebugInfo = CGM.getDebugInfo();
StartObjCMethod(OMD, OMD->getClassInterface());
EmitStmt(OMD->getBody(getContext()));
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index a70f718..912479f 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -104,6 +104,7 @@ private:
std::vector<llvm::Constant*> &V, const std::string &Name="");
llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
+ void EmitClassRef(const std::string &className);
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
@@ -168,15 +169,31 @@ public:
} // end anonymous namespace
+/// Emits a reference to a dummy variable which is emitted with each class.
+/// This ensures that a linker error will be generated when trying to link
+/// together modules where a referenced class is not defined.
+void CGObjCGNU::EmitClassRef(const std::string &className){
+ std::string symbolRef = "__objc_class_ref_" + className;
+ // Don't emit two copies of the same symbol
+ if (TheModule.getGlobalVariable(symbolRef)) return;
+ std::string symbolName = "__objc_class_name_" + className;
+ llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
+ if (!ClassSymbol) {
+ ClassSymbol = new llvm::GlobalVariable(LongTy, false,
+ llvm::GlobalValue::ExternalLinkage, 0, symbolName, &TheModule);
+ }
+ new llvm::GlobalVariable(ClassSymbol->getType(), true,
+ llvm::GlobalValue::CommonLinkage, ClassSymbol, symbolRef, &TheModule);
+}
static std::string SymbolNameForClass(const std::string &ClassName) {
- return "___objc_class_name_" + ClassName;
+ return "_OBJC_CLASS_" + ClassName;
}
static std::string SymbolNameForMethod(const std::string &ClassName, const
std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
{
- return "._objc_method_" + ClassName +"("+CategoryName+")"+
+ return "_OBJC_METHOD_" + ClassName + "("+CategoryName+")"+
(isClassMethod ? "+" : "-") + MethodName;
}
@@ -217,6 +234,7 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *OID) {
llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
+ EmitClassRef(OID->getNameAsString());
ClassName = Builder.CreateStructGEP(ClassName, 0);
std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
@@ -831,14 +849,21 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
const ObjCInterfaceDecl * SuperClassDecl =
OID->getClassInterface()->getSuperClass();
std::string SuperClassName;
- if (SuperClassDecl)
+ if (SuperClassDecl) {
SuperClassName = SuperClassDecl->getNameAsString();
+ EmitClassRef(SuperClassName);
+ }
// Get the class name
ObjCInterfaceDecl *ClassDecl =
const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
std::string ClassName = ClassDecl->getNameAsString();
-
+ // Emit the symbol that is used to generate linker errors if this class is
+ // referenced in other modules but not declared.
+ new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage,
+ llvm::ConstantInt::get(LongTy, 0), "__objc_class_name_" + ClassName,
+ &TheModule);
+
// Get the size of instances.
int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index bd5b05a..6ffca81 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1356,11 +1356,12 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C,
/// hasObjCExceptionAttribute - Return true if this class or any super
/// class has the __objc_exception__ attribute.
-static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
- if (OID->hasAttr<ObjCExceptionAttr>())
+static bool hasObjCExceptionAttribute(ASTContext &Context,
+ const ObjCInterfaceDecl *OID) {
+ if (OID->hasAttr<ObjCExceptionAttr>(Context))
return true;
if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
- return hasObjCExceptionAttribute(Super);
+ return hasObjCExceptionAttribute(Context, Super);
return false;
}
@@ -4402,7 +4403,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
- if (hasObjCExceptionAttribute(ID->getClassInterface()))
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
flags |= CLS_EXCEPTION;
if (!ID->getClassInterface()->getSuperClass()) {
@@ -5686,7 +5687,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
// If this type (or a super class) has the __objc_exception__
// attribute, emit an external reference.
- if (hasObjCExceptionAttribute(ID))
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID))
return Entry =
new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::ExternalLinkage,
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 672f6da..f10a08f 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -199,7 +199,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
llvm::Function *Fn) {
// Check if we should generate debug info for this function.
- if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>())
+ if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>(getContext()))
DebugInfo = CGM.getDebugInfo();
FunctionArgList Args;
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 82156e9..f926c05 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -102,7 +102,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
if (VD->getStorageClass() == VarDecl::PrivateExtern)
return LangOptions::Hidden;
- if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
+ if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>(getContext())) {
switch (attr->getVisibility()) {
default: assert(0 && "Unknown visibility!");
case VisibilityAttr::DefaultVisibility:
@@ -241,10 +241,11 @@ void CodeGenModule::EmitAnnotations() {
}
static CodeGenModule::GVALinkage
-GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
+GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
+ const LangOptions &Features) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
// C++ member functions defined inside the class are always inline.
- if (MD->isInline() || !MD->isOutOfLineDefinition())
+ if (MD->isInline() || !MD->isOutOfLine())
return CodeGenModule::GVA_CXXInline;
return CodeGenModule::GVA_StrongExternal;
@@ -265,11 +266,11 @@ GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
return CodeGenModule::GVA_C99Inline;
// Normal inline is a strong symbol.
return CodeGenModule::GVA_StrongExternal;
- } else if (FD->hasActiveGNUInlineAttribute()) {
+ } else if (FD->hasActiveGNUInlineAttribute(Context)) {
// GCC in C99 mode seems to use a different decision-making
// process for extern inline, which factors in previous
// declarations.
- if (FD->isExternGNUInline())
+ if (FD->isExternGNUInline(Context))
return CodeGenModule::GVA_C99Inline;
// Normal inline is a strong symbol.
return CodeGenModule::GVA_StrongExternal;
@@ -293,13 +294,13 @@ GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
/// variables (these details are set in EmitGlobalVarDefinition for variables).
void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::GlobalValue *GV) {
- GVALinkage Linkage = GetLinkageForFunction(D, Features);
+ GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
if (Linkage == GVA_Internal) {
GV->setLinkage(llvm::Function::InternalLinkage);
- } else if (D->hasAttr<DLLExportAttr>()) {
+ } else if (D->hasAttr<DLLExportAttr>(getContext())) {
GV->setLinkage(llvm::Function::DLLExportLinkage);
- } else if (D->hasAttr<WeakAttr>()) {
+ } else if (D->hasAttr<WeakAttr>(getContext())) {
GV->setLinkage(llvm::Function::WeakAnyLinkage);
} else if (Linkage == GVA_C99Inline) {
// In C99 mode, 'inline' functions are guaranteed to have a strong
@@ -332,10 +333,10 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
AttributeList.size()));
// Set the appropriate calling convention for the Function.
- if (D->hasAttr<FastCallAttr>())
+ if (D->hasAttr<FastCallAttr>(getContext()))
F->setCallingConv(llvm::CallingConv::X86_FastCall);
- if (D->hasAttr<StdCallAttr>())
+ if (D->hasAttr<StdCallAttr>(getContext()))
F->setCallingConv(llvm::CallingConv::X86_StdCall);
}
@@ -344,10 +345,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (!Features.Exceptions && !Features.ObjCNonFragileABI)
F->addFnAttr(llvm::Attribute::NoUnwind);
- if (D->hasAttr<AlwaysInlineAttr>())
+ if (D->hasAttr<AlwaysInlineAttr>(getContext()))
F->addFnAttr(llvm::Attribute::AlwaysInline);
- if (D->hasAttr<NoinlineAttr>())
+ if (D->hasAttr<NoinlineAttr>(getContext()))
F->addFnAttr(llvm::Attribute::NoInline);
}
@@ -355,10 +356,10 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
setGlobalVisibility(GV, D);
- if (D->hasAttr<UsedAttr>())
+ if (D->hasAttr<UsedAttr>(getContext()))
AddUsedGlobal(GV);
- if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+ if (const SectionAttr *SA = D->getAttr<SectionAttr>(getContext()))
GV->setSection(SA->getName());
}
@@ -382,9 +383,10 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
// Only a few attributes are set on declarations; these may later be
// overridden by a definition.
- if (FD->hasAttr<DLLImportAttr>()) {
+ if (FD->hasAttr<DLLImportAttr>(getContext())) {
F->setLinkage(llvm::Function::DLLImportLinkage);
- } else if (FD->hasAttr<WeakAttr>() || FD->hasAttr<WeakImportAttr>()) {
+ } else if (FD->hasAttr<WeakAttr>(getContext()) ||
+ FD->hasAttr<WeakImportAttr>(getContext())) {
// "extern_weak" is overloaded in LLVM; we probably should have
// separate linkage types for this.
F->setLinkage(llvm::Function::ExternalWeakLinkage);
@@ -392,7 +394,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
F->setLinkage(llvm::Function::ExternalLinkage);
}
- if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
+ if (const SectionAttr *SA = FD->getAttr<SectionAttr>(getContext()))
F->setSection(SA->getName());
}
@@ -499,15 +501,16 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified or the decl has
// attribute used.
- if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>())
+ if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>(getContext()))
return false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
// Constructors and destructors should never be deferred.
- if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+ if (FD->hasAttr<ConstructorAttr>(getContext()) ||
+ FD->hasAttr<DestructorAttr>(getContext()))
return false;
- GVALinkage Linkage = GetLinkageForFunction(FD, Features);
+ GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
@@ -528,7 +531,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// If this is an alias definition (which otherwise looks like a declaration)
// emit it now.
- if (Global->hasAttr<AliasAttr>())
+ if (Global->hasAttr<AliasAttr>(getContext()))
return EmitAliasDefinition(Global);
// Ignore declarations, they will be emitted on their first use.
@@ -717,7 +720,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
if (D->getStorageClass() == VarDecl::PrivateExtern)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>())
+ if (D->hasAttr<WeakAttr>(getContext()) ||
+ D->hasAttr<WeakImportAttr>(getContext()))
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
GV->setThreadLocal(D->isThreadSpecified());
@@ -837,7 +841,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
cast<llvm::GlobalValue>(Entry)->eraseFromParent();
}
- if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
+ if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>(getContext())) {
SourceManager &SM = Context.getSourceManager();
AddAnnotation(EmitAnnotateAttr(GV, AA,
SM.getInstantiationLineNumber(D->getLocation())));
@@ -850,11 +854,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// Set the llvm linkage type as appropriate.
if (D->getStorageClass() == VarDecl::Static)
GV->setLinkage(llvm::Function::InternalLinkage);
- else if (D->hasAttr<DLLImportAttr>())
+ else if (D->hasAttr<DLLImportAttr>(getContext()))
GV->setLinkage(llvm::Function::DLLImportLinkage);
- else if (D->hasAttr<DLLExportAttr>())
+ else if (D->hasAttr<DLLExportAttr>(getContext()))
GV->setLinkage(llvm::Function::DLLExportLinkage);
- else if (D->hasAttr<WeakAttr>())
+ else if (D->hasAttr<WeakAttr>(getContext()))
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
else if (!CompileOpts.NoCommon &&
(!D->hasExternalStorage() && !D->getInit()))
@@ -1017,14 +1021,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
SetFunctionDefinitionAttributes(D, Fn);
SetLLVMFunctionAttributesForDefinition(D, Fn);
- if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
+ if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>(getContext()))
AddGlobalCtor(Fn, CA->getPriority());
- if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
+ if (const DestructorAttr *DA = D->getAttr<DestructorAttr>(getContext()))
AddGlobalDtor(Fn, DA->getPriority());
}
void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
- const AliasAttr *AA = D->getAttr<AliasAttr>();
+ const AliasAttr *AA = D->getAttr<AliasAttr>(getContext());
assert(AA && "Not an alias?");
const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
@@ -1080,7 +1084,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
// Set attributes which are particular to an alias; this is a
// specialization of the attributes which may be set on a global
// variable/function.
- if (D->hasAttr<DLLExportAttr>()) {
+ if (D->hasAttr<DLLExportAttr>(getContext())) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// The dllexport attribute is ignored for undefined symbols.
if (FD->getBody(getContext()))
@@ -1088,7 +1092,8 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
} else {
GA->setLinkage(llvm::Function::DLLExportLinkage);
}
- } else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>()) {
+ } else if (D->hasAttr<WeakAttr>(getContext()) ||
+ D->hasAttr<WeakImportAttr>(getContext())) {
GA->setLinkage(llvm::Function::WeakAnyLinkage);
}
@@ -1476,6 +1481,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Namespace:
EmitNamespace(cast<NamespaceDecl>(D));
break;
+ // No code generation needed.
+ case Decl::Using:
+ break;
case Decl::CXXConstructor:
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index af791f6..f31c610 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -353,7 +353,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
return T;
}
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
// Protocols don't influence the LLVM type.
return ConvertTypeRecursive(Context.getObjCIdType());
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 14392ab..24e441a 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -87,7 +87,7 @@ static bool isInCLinkageSpecification(const Decl *D) {
bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
// Clang's "overloadable" attribute extension to C/C++ implies
// name mangling (always).
- if (!FD->hasAttr<OverloadableAttr>()) {
+ if (!FD->hasAttr<OverloadableAttr>(Context)) {
// C functions are not mangled, and "main" is never mangled.
if (!Context.getLangOptions().CPlusPlus || FD->isMain())
return false;
@@ -111,7 +111,7 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
bool CXXNameMangler::mangle(const NamedDecl *D) {
// Any decl can be declared with __asm("foo") on it, and this takes
// precedence over all other naming in the .o file.
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
+ if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>(Context)) {
// If we have an asm name, then we use it as the mangling.
Out << '\01'; // LLVM IR Marker for __asm("foo")
Out << ALA->getLabel();
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 7147d8f..42cbff9 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -17,3 +17,5 @@ add_clang_library(clangDriver
Tools.cpp
Types.cpp
)
+
+add_dependencies(clangSema ClangDiagnosticDriver)
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index d8c6a0a..8c2676b8 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -356,10 +356,15 @@ void Driver::PrintVersion(const Compilation &C) const {
// don't know what the client would like to do.
llvm::errs() << "clang version " CLANG_VERSION_STRING " ("
- << vers << " " << revision << ")" << "\n";
+ << vers << " " << revision << ")" << '\n';
const ToolChain &TC = C.getDefaultToolChain();
llvm::errs() << "Target: " << TC.getTripleString() << '\n';
+
+ // Print the threading model.
+ //
+ // FIXME: Implement correctly.
+ llvm::errs() << "Thread model: " << "posix" << '\n';
}
bool Driver::HandleImmediateArgs(const Compilation &C) {
@@ -429,6 +434,47 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
+ // FIXME: We need tool chain support for this.
+ llvm::outs() << ".;\n";
+
+ switch (C.getDefaultToolChain().getTriple().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::x86_64:
+ llvm::outs() << "x86_64;@m64" << "\n";
+ break;
+
+ case llvm::Triple::ppc64:
+ llvm::outs() << "ppc64;@m64" << "\n";
+ break;
+ }
+ return false;
+ }
+
+ // FIXME: What is the difference between print-multi-directory and
+ // print-multi-os-directory?
+ if (C.getArgs().hasArg(options::OPT_print_multi_directory) ||
+ C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
+ switch (C.getDefaultToolChain().getTriple().getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::ppc:
+ llvm::outs() << "." << "\n";
+ break;
+
+ case llvm::Triple::x86_64:
+ llvm::outs() << "x86_64" << "\n";
+ break;
+
+ case llvm::Triple::ppc64:
+ llvm::outs() << "ppc64" << "\n";
+ break;
+ }
+ return false;
+ }
+
return true;
}
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 2d577f8..831e11b 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -108,16 +108,34 @@ ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args,
const char *ArchName) const {
std::string Arch;
if (!ArchName) {
- Arch = getArchName();
+ // If we aren't looking for a specific arch, infer the default architecture
+ // based on -arch and -m32/-m64 command line options.
+ if (Arg *A = Args.getLastArg(options::OPT_arch)) {
+ // The gcc driver behavior with multiple -arch flags wasn't consistent for
+ // things which rely on a default architecture. We just use the last -arch
+ // to find the default tool chain.
+ Arch = A->getValue(Args);
+
+ // Normalize arch name; we shouldn't be doing this here.
+ //
+ // FIXME: This should be unnecessary once everything moves over to using
+ // the ID based Triple interface.
+ if (Arch == "ppc")
+ Arch = "powerpc";
+ else if (Arch == "ppc64")
+ Arch = "powerpc64";
+ } else {
+ // Otherwise default to the arch of the host.
+ Arch = getArchName();
+ }
ArchName = Arch.c_str();
-
- // If no arch name is specified, infer it from the host and
- // -m32/-m64.
+
+ // Honor -m32 and -m64 when finding the default tool chain.
if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
- if (getArchName() == "i386" || getArchName() == "x86_64") {
- ArchName =
- (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
- } else if (getArchName() == "powerpc" || getArchName() == "powerpc64") {
+ if (Arch == "i386" || Arch == "x86_64") {
+ ArchName = (A->getOption().getId() == options::OPT_m32) ? "i386" :
+ "x86_64";
+ } else if (Arch == "powerpc" || Arch == "powerpc64") {
ArchName = (A->getOption().getId() == options::OPT_m32) ? "powerpc" :
"powerpc64";
}
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 11c9251..5844be8 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -243,7 +243,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXMethod: {
const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ method] ";
else if (D->isImplicit())
Out << "(c++ method) ";
@@ -273,7 +273,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConstructor: {
const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ ctor] ";
else if (D->isImplicit())
Out << "(c++ ctor) ";
@@ -302,7 +302,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXDestructor: {
const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ dtor] ";
else if (D->isImplicit())
Out << "(c++ dtor) ";
@@ -318,7 +318,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConversion: {
const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ conversion] ";
else if (D->isImplicit())
Out << "(c++ conversion) ";
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
new file mode 100644
index 0000000..a7fbcda
--- /dev/null
+++ b/lib/Frontend/ASTUnit.cpp
@@ -0,0 +1,159 @@
+//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit Implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+
+ASTUnit::ASTUnit() { }
+ASTUnit::~ASTUnit() { }
+
+namespace {
+
+/// \brief Gathers information from PCHReader that will be used to initialize
+/// a Preprocessor.
+class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener {
+ LangOptions &LangOpt;
+ HeaderSearch &HSI;
+ std::string &TargetTriple;
+ std::string &Predefines;
+ unsigned &Counter;
+
+ unsigned NumHeaderInfos;
+
+public:
+ PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
+ std::string &TargetTriple, std::string &Predefines,
+ unsigned &Counter)
+ : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
+ Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ LangOpt = LangOpts;
+ return false;
+ }
+
+ virtual bool ReadTargetTriple(const std::string &Triple) {
+ TargetTriple = Triple;
+ return false;
+ }
+
+ virtual bool ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines) {
+ Predefines = PCHPredef;
+ return false;
+ }
+
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+ HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ }
+
+ virtual void ReadCounter(unsigned Value) {
+ Counter = Value;
+ }
+};
+
+} // anonymous namespace
+
+
+ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
+ FileManager &FileMgr,
+ std::string *ErrMsg) {
+
+ llvm::OwningPtr<ASTUnit> AST(new ASTUnit());
+
+ AST->DiagClient.reset(new TextDiagnosticBuffer());
+ AST->Diags.reset(new Diagnostic(AST->DiagClient.get()));
+
+ AST->HeaderInfo.reset(new HeaderSearch(FileMgr));
+ AST->SourceMgr.reset(new SourceManager());
+
+ Diagnostic &Diags = *AST->Diags.get();
+ SourceManager &SourceMgr = *AST->SourceMgr.get();
+
+ // Gather Info for preprocessor construction later on.
+
+ LangOptions LangInfo;
+ HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
+ std::string TargetTriple;
+ std::string Predefines;
+ unsigned Counter;
+
+ llvm::OwningPtr<PCHReader> Reader;
+ llvm::OwningPtr<ExternalASTSource> Source;
+
+ Reader.reset(new PCHReader(SourceMgr, FileMgr, Diags));
+ Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
+ Predefines, Counter));
+
+ switch (Reader->ReadPCH(Filename)) {
+ case PCHReader::Success:
+ break;
+
+ case PCHReader::Failure:
+ // Unrecoverable failure: don't even try to process the input
+ // file.
+ if (ErrMsg)
+ *ErrMsg = "Could not load PCH file";
+ return NULL;
+
+ case PCHReader::IgnorePCH:
+ assert(0 && "Is there a validation that should not have happened ?");
+ }
+
+ // PCH loaded successfully. Now create the preprocessor.
+
+ // Get information about the target being compiled for.
+ AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
+ AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(),
+ SourceMgr, HeaderInfo));
+ Preprocessor &PP = *AST->PP.get();
+
+ PP.setPredefines(Predefines);
+ PP.setCounterValue(Counter);
+ Reader->setPreprocessor(PP);
+
+ // Create and initialize the ASTContext.
+
+ AST->Ctx.reset(new ASTContext(LangInfo,
+ SourceMgr,
+ *AST->Target.get(),
+ PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ PP.getBuiltinInfo(),
+ /* FreeMemory = */ true,
+ /* size_reserve = */0));
+ ASTContext &Context = *AST->Ctx.get();
+
+ Reader->InitializeContext(Context);
+
+ // Attach the PCH reader to the AST context as an external AST
+ // source, so that declarations will be deserialized from the
+ // PCH file as needed.
+ Source.reset(Reader.take());
+ Context.setExternalSource(Source);
+
+ return AST.take();
+}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 649f9da..330b4db 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@ add_clang_library(clangFrontend
ASTConsumers.cpp
Backend.cpp
CacheTokens.cpp
+ DeclXML.cpp
DependencyFile.cpp
DiagChecker.cpp
DocumentXML.cpp
@@ -31,5 +32,8 @@ add_clang_library(clangFrontend
StmtXML.cpp
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
+ TypeXML.cpp
Warnings.cpp
)
+
+add_dependencies(clangSema ClangDiagnosticFrontend)
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
new file mode 100644
index 0000000..5c21999
--- /dev/null
+++ b/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,161 @@
+//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter>
+{
+ DocumentXML& Doc;
+
+ void addSubNodes(FunctionDecl* FD)
+ {
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
+ {
+ Visit(FD->getParamDecl(i));
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(RecordDecl* RD)
+ {
+ for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumDecl* ED)
+ {
+ for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumConstantDecl* ECD)
+ {
+ if (ECD->getInitExpr())
+ {
+ Doc.PrintStmt(ECD->getInitExpr());
+ }
+ }
+
+ void addSubNodes(FieldDecl* FdD)
+ {
+ if (FdD->isBitField())
+ {
+ Doc.PrintStmt(FdD->getBitWidth());
+ }
+ }
+
+ void addSubNodes(VarDecl* V)
+ {
+ if (V->getInit())
+ {
+ Doc.PrintStmt(V->getInit());
+ }
+ }
+
+ void addSubNodes(ParmVarDecl* argDecl)
+ {
+ if (argDecl->getDefaultArg())
+ {
+ Doc.PrintStmt(argDecl->getDefaultArg());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, EnumDecl* ED)
+ {
+ const QualType& enumType = ED->getIntegerType();
+ if (!enumType.isNull())
+ {
+ Doc.addAttribute(pName, enumType);
+ }
+ }
+
+ void addIdAttribute(LinkageSpecDecl* ED)
+ {
+ Doc.addAttribute("id", ED);
+ }
+
+ void addIdAttribute(NamedDecl* ND)
+ {
+ Doc.addAttribute("id", ND);
+ }
+
+public:
+ DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define SUB_NODE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//---------------------------------------------------------
+void DocumentXML::writeDeclToXML(Decl *D)
+{
+ DeclPrinter(*this).Visit(D);
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ {
+ if (Stmt *Body = FD->getBody(*Ctx)) {
+ addSubNode("Body");
+ PrintStmt(Body);
+ toParent();
+ }
+ }
+ toParent();
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index 7562d2a..19a7573 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -14,92 +14,66 @@
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
namespace clang {
//---------------------------------------------------------
-struct DocumentXML::NodeXML
-{
- std::string Name;
- NodeXML* Parent;
-
- NodeXML(const std::string& name, NodeXML* parent) :
- Name(name),
- Parent(parent)
- {}
-};
-
-//---------------------------------------------------------
DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
- Root(new NodeXML(rootName, 0)),
- CurrentNode(Root),
Out(out),
Ctx(0),
- CurrentIndent(0),
HasCurrentNodeSubNodes(false)
{
+ NodeStack.push(rootName);
Out << "<?xml version=\"1.0\"?>\n<" << rootName;
}
//---------------------------------------------------------
-DocumentXML::~DocumentXML()
-{
- assert(CurrentNode == Root && "not completely backtracked");
- delete Root;
-}
-
-//---------------------------------------------------------
DocumentXML& DocumentXML::addSubNode(const std::string& name)
{
if (!HasCurrentNodeSubNodes)
{
Out << ">\n";
}
- CurrentNode = new NodeXML(name, CurrentNode);
+ NodeStack.push(name);
HasCurrentNodeSubNodes = false;
- CurrentIndent += 2;
Indent();
- Out << "<" << CurrentNode->Name;
+ Out << "<" << NodeStack.top();
return *this;
}
//---------------------------------------------------------
void DocumentXML::Indent()
{
- for (int i = 0; i < CurrentIndent; ++i)
+ for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
Out << ' ';
}
//---------------------------------------------------------
DocumentXML& DocumentXML::toParent()
{
- assert(CurrentNode != Root && "to much backtracking");
+ assert(NodeStack.size() > 1 && "to much backtracking");
if (HasCurrentNodeSubNodes)
{
Indent();
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
else
{
Out << "/>\n";
}
- NodeXML* NodeToDelete = CurrentNode;
- CurrentNode = CurrentNode->Parent;
- delete NodeToDelete;
+ NodeStack.pop();
HasCurrentNodeSubNodes = true;
- CurrentIndent -= 2;
return *this;
}
//---------------------------------------------------------
namespace {
-enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
unsigned getNewId(tIdType idType)
{
@@ -110,7 +84,7 @@ unsigned getNewId(tIdType idType)
//---------------------------------------------------------
inline std::string getPrefixedId(unsigned uId, tIdType idType)
{
- static const char idPrefix[ID_LAST] = { '_', 'f' };
+ static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
char buffer[20];
char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
*--BufPtr = idPrefix[idType];
@@ -132,6 +106,7 @@ bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL)
} // anon NS
+
//---------------------------------------------------------
std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len)
{
@@ -170,7 +145,7 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l
//---------------------------------------------------------
void DocumentXML::finalize()
{
- assert(CurrentNode == Root && "not completely backtracked");
+ assert(NodeStack.size() == 1 && "not completely backtracked");
addSubNode("ReferenceSection");
addSubNode("Types");
@@ -179,71 +154,15 @@ void DocumentXML::finalize()
{
if (i->first.getCVRQualifiers() != 0)
{
- addSubNode("CvQualifiedType");
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
- addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL));
- if (i->first.isConstQualified()) addAttribute("const", "1");
- if (i->first.isVolatileQualified()) addAttribute("volatile", "1");
- if (i->first.isRestrictQualified()) addAttribute("restrict", "1");
toParent();
}
}
for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i)
{
- // don't use the get methods as they strip of typedef infos
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(i->first)) {
- addSubNode("FundamentalType");
- addAttribute("name", BT->getName(Ctx->getLangOptions().CPlusPlus));
- }
- else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) {
- addSubNode("PointerType");
- addTypeAttribute(PT->getPointeeType());
- }
- else if (dyn_cast<FunctionType>(i->first) != 0) {
- addSubNode("FunctionType");
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(i->first)) {
- addSubNode("ReferenceType");
- addTypeAttribute(RT->getPointeeType());
- }
- else if (const TypedefType * TT = dyn_cast<TypedefType>(i->first)) {
- addSubNode("Typedef");
- addAttribute("name", TT->getDecl()->getNameAsString());
- addTypeAttribute(TT->getDecl()->getUnderlyingType());
- addContextAttribute(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(i->first)) {
- addSubNode("QualifiedNameType");
- addTypeAttribute(QT->getNamedType());
- }
- else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(i->first)) {
- addSubNode("ArrayType");
- addAttribute("min", 0);
- addAttribute("max", (CAT->getSize() - 1).toString(10, false));
- addTypeAttribute(CAT->getElementType());
- }
- else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(i->first)) {
- addSubNode("VariableArrayType");
- addTypeAttribute(VAT->getElementType());
- }
- else if (const TagType *RET = dyn_cast<TagType>(i->first)) {
- const TagDecl *tagDecl = RET->getDecl();
- std::string tagKind = tagDecl->getKindName();
- tagKind[0] = std::toupper(tagKind[0]);
- addSubNode(tagKind);
- addAttribute("name", tagDecl->getNameAsString());
- addContextAttribute(tagDecl->getDeclContext());
- }
- else if (const VectorType* VT = dyn_cast<VectorType>(i->first)) {
- addSubNode("VectorType");
- addTypeAttribute(VT->getElementType());
- addAttribute("num_elements", VT->getNumElements());
- }
- else
- {
- addSubNode("FIXMEType");
- }
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
}
@@ -267,7 +186,7 @@ void DocumentXML::finalize()
if (const DeclContext* parent = i->first->getParent())
{
- addContextAttribute(parent);
+ addAttribute("context", parent);
}
toParent();
}
@@ -285,21 +204,21 @@ void DocumentXML::finalize()
toParent().toParent();
// write the root closing node (which has always subnodes)
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
//---------------------------------------------------------
-void DocumentXML::addTypeAttribute(const QualType& pType)
+void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType)
{
addTypeRecursively(pType);
- addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL));
+ addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
}
//---------------------------------------------------------
-void DocumentXML::addTypeIdAttribute(const Type* pType)
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType)
{
- addBasicTypeRecursively(pType);
- addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL));
+ addTypeRecursively(pType);
+ addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
}
//---------------------------------------------------------
@@ -307,7 +226,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
{
if (addToMap(Types, pType))
{
- addBasicTypeRecursively(pType.getTypePtr());
+ addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
if (pType.getCVRQualifiers() == 0)
{
@@ -317,43 +236,49 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
}
//---------------------------------------------------------
-void DocumentXML::addBasicTypeRecursively(const Type* pType)
+void DocumentXML::addTypeRecursively(const Type* pType)
{
if (addToMap(BasicTypes, pType))
{
- if (const PointerType *PT = dyn_cast<PointerType>(pType)) {
- addTypeRecursively(PT->getPointeeType());
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(pType)) {
- addTypeRecursively(RT->getPointeeType());
- }
- else if (const TypedefType *TT = dyn_cast<TypedefType>(pType)) {
- addTypeRecursively(TT->getDecl()->getUnderlyingType());
- addContextsRecursively(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(pType)) {
- addTypeRecursively(QT->getNamedType());
- // FIXME: what to do with NestedNameSpecifier or shall this type be transparent?
- }
- else if (const ArrayType *AT = dyn_cast<ArrayType>(pType)) {
- addTypeRecursively(AT->getElementType());
- // FIXME: doesn't work in the immediate streaming approach
- /*if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT))
- {
- addSubNode("VariableArraySizeExpression");
- PrintStmt(VAT->getSizeExpr());
- toParent();
- }*/
+ addParentTypes(pType);
+/*
+ // FIXME: doesn't work in the immediate streaming approach
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
+ {
+ addSubNode("VariableArraySizeExpression");
+ PrintStmt(VAT->getSizeExpr());
+ toParent();
}
+*/
}
}
//---------------------------------------------------------
-void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage)
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
{
addContextsRecursively(DC);
- const char* pAttributeTags[2] = { "context", "id" };
- addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL));
+ addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+ if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+ {
+ addContextsRecursively(DC);
+ addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+ }
+ else
+ {
+ addToMap(Decls, D);
+ addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+ addPtrAttribute(pName, static_cast<const DeclContext*>(D));
}
//---------------------------------------------------------
@@ -372,6 +297,15 @@ void DocumentXML::addSourceFileAttribute(const std::string& fileName)
addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+ addToMap(Labels, L, ID_LABEL);
+ addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
//---------------------------------------------------------
PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
{
@@ -417,161 +351,9 @@ void DocumentXML::addLocationRange(const SourceRange& R)
}
//---------------------------------------------------------
-void DocumentXML::PrintFunctionDecl(FunctionDecl *FD)
-{
- switch (FD->getStorageClass()) {
- default: assert(0 && "Unknown storage class");
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break;
- case FunctionDecl::Static: addAttribute("storage_class", "static"); break;
- case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break;
- }
-
- if (FD->isInline())
- addAttribute("inline", "1");
-
- const FunctionType *AFT = FD->getType()->getAsFunctionType();
- addTypeAttribute(AFT->getResultType());
- addBasicTypeRecursively(AFT);
-
- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) {
- addAttribute("num_args", FD->getNumParams());
- for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
- addSubNode("Argument");
- ParmVarDecl *argDecl = FD->getParamDecl(i);
- addAttribute("name", argDecl->getNameAsString());
- addTypeAttribute(FT->getArgType(i));
- addDeclIdAttribute(argDecl);
- if (argDecl->getDefaultArg())
- {
- addAttribute("default_arg", "1");
- PrintStmt(argDecl->getDefaultArg());
- }
- toParent();
- }
-
- if (FT->isVariadic()) {
- addSubNode("Ellipsis").toParent();
- }
- } else {
- assert(isa<FunctionNoProtoType>(AFT));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addRefAttribute(const NamedDecl* D)
-{
- // FIXME: in case of CXX inline member functions referring to a member defined
- // after the function it needs to be tested, if the ids are already there
- // (should work, but I couldn't test it)
- if (const DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addAttribute("ref", getPrefixedId(Contexts[DC], ID_NORMAL));
- }
- else
- {
- addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addDeclIdAttribute(const NamedDecl* D)
-{
- addToMap(Decls, D);
- addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL));
-}
-
-//---------------------------------------------------------
void DocumentXML::PrintDecl(Decl *D)
{
- addSubNode(D->getDeclKindName());
- addContextAttribute(D->getDeclContext());
- addLocation(D->getLocation());
- if (DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addContextAttribute(DC, CONTEXT_AS_ID);
- }
-
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- addAttribute("name", ND->getNameAsString());
-
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- PrintFunctionDecl(FD);
- if (Stmt *Body = FD->getBody(*Ctx)) {
- addSubNode("Body");
- PrintStmt(Body);
- toParent();
- }
- } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
- addBasicTypeRecursively(RD->getTypeForDecl());
- addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL));
- if (!RD->isDefinition())
- {
- addAttribute("forward", "1");
- }
-
- for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- const QualType& enumType = ED->getIntegerType();
- if (!enumType.isNull())
- {
- addTypeAttribute(enumType);
- for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- }
- } else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
- addTypeAttribute(ECD->getType());
- addAttribute("value", ECD->getInitVal().toString(10, true));
- if (ECD->getInitExpr())
- {
- PrintStmt(ECD->getInitExpr());
- }
- } else if (FieldDecl *FdD = dyn_cast<FieldDecl>(D)) {
- addTypeAttribute(FdD->getType());
- addDeclIdAttribute(ND);
- if (FdD->isMutable())
- addAttribute("mutable", "1");
- if (FdD->isBitField())
- {
- addAttribute("bitfield", "1");
- PrintStmt(FdD->getBitWidth());
- }
- } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
- addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr());
- addTypeAttribute(TD->getUnderlyingType());
- } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
- addTypeAttribute(VD->getType());
- addDeclIdAttribute(ND);
-
- VarDecl *V = dyn_cast<VarDecl>(VD);
- if (V && V->getStorageClass() != VarDecl::None)
- {
- addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass()));
- }
-
- if (V && V->getInit())
- {
- PrintStmt(V->getInit());
- }
- }
- } else if (LinkageSpecDecl* LSD = dyn_cast<LinkageSpecDecl>(D)) {
- switch (LSD->getLanguage())
- {
- case LinkageSpecDecl::lang_c: addAttribute("lang", "C"); break;
- case LinkageSpecDecl::lang_cxx: addAttribute("lang", "CXX"); break;
- default: assert(0 && "Unexpected lang id");
- }
- } else if (isa<FileScopeAsmDecl>(D)) {
- // FIXME: Implement this
- } else {
- assert(0 && "Unexpected decl");
- }
- toParent();
+ writeDeclToXML(D);
}
//---------------------------------------------------------
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 6383c20..7a2b3a7 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -138,6 +138,12 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) {
false);
AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false);
+ // Ubuntu 9.04
+ AddPath("/usr/include/c++/4.3.3", System, true, false, false);
+ AddPath("/usr/include/c++/4.3.3/x86_64-linux-gnu/", System, true, false,
+ false);
+ AddPath("/usr/include/c++/4.3.3/backward", System, true, false, false);
+
// Fedora 8
AddPath("/usr/include/c++/4.1.2", System, true, false, false);
AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false,
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 6cff75d..41908ad 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -472,11 +472,7 @@ bool InitializePreprocessor(Preprocessor &PP,
AddImplicitIncludePTH(PredefineBuffer, PP, I->first);
else
AddImplicitInclude(PredefineBuffer, I->first);
- }
-
- LineDirective = "# 2 \"<built-in>\" 2 3\n";
- PredefineBuffer.insert(PredefineBuffer.end(),
- LineDirective, LineDirective+strlen(LineDirective));
+ }
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 87fc839..96f21f1 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -36,11 +36,321 @@
using namespace clang;
//===----------------------------------------------------------------------===//
+// PCH reader validator implementation
+//===----------------------------------------------------------------------===//
+
+PCHReaderListener::~PCHReaderListener() {}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
+ const LangOptions &PPLangOpts = PP.getLangOptions();
+#define PARSE_LANGOPT_BENIGN(Option)
+#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
+ if (PPLangOpts.Option != LangOpts.Option) { \
+ Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
+ return true; \
+ }
+
+ PARSE_LANGOPT_BENIGN(Trigraphs);
+ PARSE_LANGOPT_BENIGN(BCPLComment);
+ PARSE_LANGOPT_BENIGN(DollarIdents);
+ PARSE_LANGOPT_BENIGN(AsmPreprocessor);
+ PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+ PARSE_LANGOPT_BENIGN(ImplicitInt);
+ PARSE_LANGOPT_BENIGN(Digraphs);
+ PARSE_LANGOPT_BENIGN(HexFloats);
+ PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
+ PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
+ PARSE_LANGOPT_BENIGN(CXXOperatorName);
+ PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
+ PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
+ PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
+ PARSE_LANGOPT_BENIGN(PascalStrings);
+ PARSE_LANGOPT_BENIGN(WritableStrings);
+ PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
+ diag::warn_pch_lax_vector_conversions);
+ PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
+ PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
+ PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
+ PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
+ PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
+ diag::warn_pch_thread_safe_statics);
+ PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
+ PARSE_LANGOPT_BENIGN(EmitAllDecls);
+ PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
+ PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
+ PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
+ diag::warn_pch_heinous_extensions);
+ // FIXME: Most of the options below are benign if the macro wasn't
+ // used. Unfortunately, this means that a PCH compiled without
+ // optimization can't be used with optimization turned on, even
+ // though the only thing that changes is whether __OPTIMIZE__ was
+ // defined... but if __OPTIMIZE__ never showed up in the header, it
+ // doesn't matter. We could consider making this some special kind
+ // of check.
+ PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
+ PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
+ PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
+ PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
+ PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
+ PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
+ PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
+ PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+ if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
+ Reader.Diag(diag::warn_pch_gc_mode)
+ << LangOpts.getGCMode() << PPLangOpts.getGCMode();
+ return true;
+ }
+ PARSE_LANGOPT_BENIGN(getVisibilityMode());
+ PARSE_LANGOPT_BENIGN(InstantiationDepth);
+#undef PARSE_LANGOPT_IRRELEVANT
+#undef PARSE_LANGOPT_BENIGN
+
+ return false;
+}
+
+bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
+ if (Triple != PP.getTargetInfo().getTargetTriple()) {
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTargetTriple();
+ return true;
+ }
+ return false;
+}
+
+/// \brief Split the given string into a vector of lines, eliminating
+/// any empty lines in the process.
+///
+/// \param Str the string to split.
+/// \param Len the length of Str.
+/// \param KeepEmptyLines true if empty lines should be included
+/// \returns a vector of lines, with the line endings removed
+static std::vector<std::string> splitLines(const char *Str, unsigned Len,
+ bool KeepEmptyLines = false) {
+ std::vector<std::string> Lines;
+ for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
+ unsigned LineEnd = LineStart;
+ while (LineEnd < Len && Str[LineEnd] != '\n')
+ ++LineEnd;
+ if (LineStart != LineEnd || KeepEmptyLines)
+ Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
+ LineStart = LineEnd;
+ }
+ return Lines;
+}
+
+/// \brief Determine whether the string Haystack starts with the
+/// substring Needle.
+static bool startsWith(const std::string &Haystack, const char *Needle) {
+ for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
+ if (I == N)
+ return false;
+ if (Haystack[I] != Needle[I])
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Determine whether the string Haystack starts with the
+/// substring Needle.
+static inline bool startsWith(const std::string &Haystack,
+ const std::string &Needle) {
+ return startsWith(Haystack, Needle.c_str());
+}
+
+bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines) {
+ const char *Predef = PP.getPredefines().c_str();
+ unsigned PredefLen = PP.getPredefines().size();
+
+ // If the two predefines buffers compare equal, we're done!
+ if (PredefLen == PCHPredefLen &&
+ strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+ return false;
+
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // The predefines buffers are different. Determine what the
+ // differences are, and whether they require us to reject the PCH
+ // file.
+ std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
+ std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
+
+ // Sort both sets of predefined buffer lines, since
+ std::sort(CmdLineLines.begin(), CmdLineLines.end());
+ std::sort(PCHLines.begin(), PCHLines.end());
+
+ // Determine which predefines that where used to build the PCH file
+ // are missing from the command line.
+ std::vector<std::string> MissingPredefines;
+ std::set_difference(PCHLines.begin(), PCHLines.end(),
+ CmdLineLines.begin(), CmdLineLines.end(),
+ std::back_inserter(MissingPredefines));
+
+ bool MissingDefines = false;
+ bool ConflictingDefines = false;
+ for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
+ const std::string &Missing = MissingPredefines[I];
+ if (!startsWith(Missing, "#define ") != 0) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is a macro definition. Determine the name of the macro
+ // we're defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = Missing.find_first_of("( \n\r", StartOfMacroName);
+ assert(EndOfMacroName != std::string::npos &&
+ "Couldn't find the end of the macro name");
+ std::string MacroName = Missing.substr(StartOfMacroName,
+ EndOfMacroName - StartOfMacroName);
+
+ // Determine whether this macro was given a different definition
+ // on the command line.
+ std::string MacroDefStart = "#define " + MacroName;
+ std::string::size_type MacroDefLen = MacroDefStart.size();
+ std::vector<std::string>::iterator ConflictPos
+ = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
+ MacroDefStart);
+ for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
+ if (!startsWith(*ConflictPos, MacroDefStart)) {
+ // Different macro; we're done.
+ ConflictPos = CmdLineLines.end();
+ break;
+ }
+
+ assert(ConflictPos->size() > MacroDefLen &&
+ "Invalid #define in predefines buffer?");
+ if ((*ConflictPos)[MacroDefLen] != ' ' &&
+ (*ConflictPos)[MacroDefLen] != '(')
+ continue; // Longer macro name; keep trying.
+
+ // We found a conflicting macro definition.
+ break;
+ }
+
+ if (ConflictPos != CmdLineLines.end()) {
+ Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
+ << MacroName;
+
+ // Show the definition of this macro within the PCH file.
+ const char *MissingDef = strstr(PCHPredef, Missing.c_str());
+ unsigned Offset = MissingDef - PCHPredef;
+ SourceLocation PCHMissingLoc
+ = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
+ << MacroName;
+
+ ConflictingDefines = true;
+ continue;
+ }
+
+ // If the macro doesn't conflict, then we'll just pick up the
+ // macro definition from the PCH file. Warn the user that they
+ // made a mistake.
+ if (ConflictingDefines)
+ continue; // Don't complain if there are already conflicting defs
+
+ if (!MissingDefines) {
+ Reader.Diag(diag::warn_cmdline_missing_macro_defs);
+ MissingDefines = true;
+ }
+
+ // Show the definition of this macro within the PCH file.
+ const char *MissingDef = strstr(PCHPredef, Missing.c_str());
+ unsigned Offset = MissingDef - PCHPredef;
+ SourceLocation PCHMissingLoc
+ = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
+ }
+
+ if (ConflictingDefines)
+ return true;
+
+ // Determine what predefines were introduced based on command-line
+ // parameters that were not present when building the PCH
+ // file. Extra #defines are okay, so long as the identifiers being
+ // defined were not used within the precompiled header.
+ std::vector<std::string> ExtraPredefines;
+ std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
+ PCHLines.begin(), PCHLines.end(),
+ std::back_inserter(ExtraPredefines));
+ for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
+ const std::string &Extra = ExtraPredefines[I];
+ if (!startsWith(Extra, "#define ") != 0) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is an extra macro definition. Determine the name of the
+ // macro we're defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = Extra.find_first_of("( \n\r", StartOfMacroName);
+ assert(EndOfMacroName != std::string::npos &&
+ "Couldn't find the end of the macro name");
+ std::string MacroName = Extra.substr(StartOfMacroName,
+ EndOfMacroName - StartOfMacroName);
+
+ // Check whether this name was used somewhere in the PCH file. If
+ // so, defining it as a macro could change behavior, so we reject
+ // the PCH file.
+ if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
+ MacroName.c_str() + MacroName.size())) {
+ Reader.Diag(diag::warn_macro_name_used_in_pch)
+ << II;
+ return true;
+ }
+
+ // Add this definition to the suggested predefines buffer.
+ SuggestedPredefines += Extra;
+ SuggestedPredefines += '\n';
+ }
+
+ // If we get here, it's because the predefines buffer had compatible
+ // contents. Accept the PCH file.
+ return false;
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+ PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+}
+
+void PCHValidator::ReadCounter(unsigned Value) {
+ PP.setCounterValue(Value);
+}
+
+
+
+//===----------------------------------------------------------------------===//
// PCH reader implementation
//===----------------------------------------------------------------------===//
PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
- : SemaObj(0), PP(PP), Context(Context), Consumer(0),
+ : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
+ FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
+ SemaObj(0), PP(&PP), Context(Context), Consumer(0),
+ IdentifierTableData(0), IdentifierLookupTable(0),
+ IdentifierOffsets(0),
+ MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
+ TotalSelectorsInMethodPool(0), SelectorOffsets(0),
+ TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), NumStatementsRead(0),
+ NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
+ NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
+
+PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags)
+ : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
+ SemaObj(0), PP(0), Context(0), Consumer(0),
IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@@ -314,53 +624,11 @@ typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
// FIXME: use the diagnostics machinery
bool PCHReader::Error(const char *Msg) {
- Diagnostic &Diags = PP.getDiagnostics();
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
Diag(DiagID);
return true;
}
-/// \brief Split the given string into a vector of lines, eliminating
-/// any empty lines in the process.
-///
-/// \param Str the string to split.
-/// \param Len the length of Str.
-/// \param KeepEmptyLines true if empty lines should be included
-/// \returns a vector of lines, with the line endings removed
-std::vector<std::string> splitLines(const char *Str, unsigned Len,
- bool KeepEmptyLines = false) {
- std::vector<std::string> Lines;
- for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
- unsigned LineEnd = LineStart;
- while (LineEnd < Len && Str[LineEnd] != '\n')
- ++LineEnd;
- if (LineStart != LineEnd || KeepEmptyLines)
- Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
- LineStart = LineEnd;
- }
- return Lines;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static bool startsWith(const std::string &Haystack, const char *Needle) {
- for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
- if (I == N)
- return false;
- if (Haystack[I] != Needle[I])
- return false;
- }
-
- return true;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static inline bool startsWith(const std::string &Haystack,
- const std::string &Needle) {
- return startsWith(Haystack, Needle.c_str());
-}
-
/// \brief Check the contents of the predefines buffer against the
/// contents of the predefines buffer used to build the PCH file.
///
@@ -381,158 +649,9 @@ static inline bool startsWith(const std::string &Haystack,
bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
unsigned PCHPredefLen,
FileID PCHBufferID) {
- const char *Predef = PP.getPredefines().c_str();
- unsigned PredefLen = PP.getPredefines().size();
-
- // If the two predefines buffers compare equal, we're done!
- if (PredefLen == PCHPredefLen &&
- strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
- return false;
-
- SourceManager &SourceMgr = PP.getSourceManager();
-
- // The predefines buffers are different. Determine what the
- // differences are, and whether they require us to reject the PCH
- // file.
- std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
- std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
-
- // Sort both sets of predefined buffer lines, since
- std::sort(CmdLineLines.begin(), CmdLineLines.end());
- std::sort(PCHLines.begin(), PCHLines.end());
-
- // Determine which predefines that where used to build the PCH file
- // are missing from the command line.
- std::vector<std::string> MissingPredefines;
- std::set_difference(PCHLines.begin(), PCHLines.end(),
- CmdLineLines.begin(), CmdLineLines.end(),
- std::back_inserter(MissingPredefines));
-
- bool MissingDefines = false;
- bool ConflictingDefines = false;
- for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
- const std::string &Missing = MissingPredefines[I];
- if (!startsWith(Missing, "#define ") != 0) {
- Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
-
- // This is a macro definition. Determine the name of the macro
- // we're defining.
- std::string::size_type StartOfMacroName = strlen("#define ");
- std::string::size_type EndOfMacroName
- = Missing.find_first_of("( \n\r", StartOfMacroName);
- assert(EndOfMacroName != std::string::npos &&
- "Couldn't find the end of the macro name");
- std::string MacroName = Missing.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
-
- // Determine whether this macro was given a different definition
- // on the command line.
- std::string MacroDefStart = "#define " + MacroName;
- std::string::size_type MacroDefLen = MacroDefStart.size();
- std::vector<std::string>::iterator ConflictPos
- = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
- MacroDefStart);
- for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
- if (!startsWith(*ConflictPos, MacroDefStart)) {
- // Different macro; we're done.
- ConflictPos = CmdLineLines.end();
- break;
- }
-
- assert(ConflictPos->size() > MacroDefLen &&
- "Invalid #define in predefines buffer?");
- if ((*ConflictPos)[MacroDefLen] != ' ' &&
- (*ConflictPos)[MacroDefLen] != '(')
- continue; // Longer macro name; keep trying.
-
- // We found a conflicting macro definition.
- break;
- }
-
- if (ConflictPos != CmdLineLines.end()) {
- Diag(diag::warn_cmdline_conflicting_macro_def)
- << MacroName;
-
- // Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
- << MacroName;
-
- ConflictingDefines = true;
- continue;
- }
-
- // If the macro doesn't conflict, then we'll just pick up the
- // macro definition from the PCH file. Warn the user that they
- // made a mistake.
- if (ConflictingDefines)
- continue; // Don't complain if there are already conflicting defs
-
- if (!MissingDefines) {
- Diag(diag::warn_cmdline_missing_macro_defs);
- MissingDefines = true;
- }
-
- // Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
- }
-
- if (ConflictingDefines)
- return true;
-
- // Determine what predefines were introduced based on command-line
- // parameters that were not present when building the PCH
- // file. Extra #defines are okay, so long as the identifiers being
- // defined were not used within the precompiled header.
- std::vector<std::string> ExtraPredefines;
- std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
- PCHLines.begin(), PCHLines.end(),
- std::back_inserter(ExtraPredefines));
- for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
- const std::string &Extra = ExtraPredefines[I];
- if (!startsWith(Extra, "#define ") != 0) {
- Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
-
- // This is an extra macro definition. Determine the name of the
- // macro we're defining.
- std::string::size_type StartOfMacroName = strlen("#define ");
- std::string::size_type EndOfMacroName
- = Extra.find_first_of("( \n\r", StartOfMacroName);
- assert(EndOfMacroName != std::string::npos &&
- "Couldn't find the end of the macro name");
- std::string MacroName = Extra.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
-
- // Check whether this name was used somewhere in the PCH file. If
- // so, defining it as a macro could change behavior, so we reject
- // the PCH file.
- if (IdentifierInfo *II = get(MacroName.c_str(),
- MacroName.c_str() + MacroName.size())) {
- Diag(diag::warn_macro_name_used_in_pch)
- << II;
- return true;
- }
-
- // Add this definition to the suggested predefines buffer.
- SuggestedPredefines += Extra;
- SuggestedPredefines += '\n';
- }
-
- // If we get here, it's because the predefines buffer had compatible
- // contents. Accept the PCH file.
+ if (Listener)
+ return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+ SuggestedPredefines);
return false;
}
@@ -714,9 +833,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
return Failure;
}
- SourceManager &SourceMgr = PP.getSourceManager();
RecordData Record;
- unsigned NumHeaderInfos = 0;
while (true) {
unsigned Code = SLocEntryCursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
@@ -761,7 +878,8 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
HFI.DirInfo = Record[1];
HFI.NumIncludes = Record[2];
HFI.ControllingMacroID = Record[3];
- PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ if (Listener)
+ Listener->ReadHeaderFileInfo(HFI);
break;
}
@@ -794,7 +912,6 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
}
- SourceManager &SourceMgr = PP.getSourceManager();
RecordData Record;
const char *BlobStart;
unsigned BlobLen;
@@ -804,9 +921,15 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
case pch::SM_SLOC_FILE_ENTRY: {
- const FileEntry *File
- = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
- // FIXME: Error recovery if file cannot be found.
+ const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen);
+ if (File == 0) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr.append(BlobStart, BlobLen);
+ ErrorStr += "' referenced by PCH file";
+ Error(ErrorStr.c_str());
+ return Failure;
+ }
+
FileID FID = SourceMgr.createFileID(File,
SourceLocation::getFromRawEncoding(Record[1]),
(SrcMgr::CharacteristicKind)Record[2],
@@ -879,6 +1002,8 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
}
void PCHReader::ReadMacroRecord(uint64_t Offset) {
+ assert(PP && "Forgot to set Preprocessor ?");
+
// Keep track of where we are in the stream, then jump back there
// after reading this macro.
SavedStreamPosition SavedPosition(Stream);
@@ -930,7 +1055,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
bool isUsed = Record[2];
- MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+ MacroInfo *MI = PP->AllocateMacroInfo(Loc);
MI->setIsUsed(isUsed);
if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
@@ -947,11 +1072,11 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
if (isC99VarArgs) MI->setIsC99Varargs();
if (isGNUVarArgs) MI->setIsGNUVarargs();
MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
- PP.getPreprocessorAllocator());
+ PP->getPreprocessorAllocator());
}
// Finally, install the macro.
- PP.setMacroInfo(II, MI);
+ PP->setMacroInfo(II, MI);
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
@@ -1092,11 +1217,10 @@ PCHReader::ReadPCHBlock() {
return IgnorePCH;
}
- std::string TargetTriple(BlobStart, BlobLen);
- if (TargetTriple != PP.getTargetInfo().getTargetTriple()) {
- Diag(diag::warn_pch_target_triple)
- << TargetTriple << PP.getTargetInfo().getTargetTriple();
- return IgnorePCH;
+ if (Listener) {
+ std::string TargetTriple(BlobStart, BlobLen);
+ if (Listener->ReadTargetTriple(TargetTriple))
+ return IgnorePCH;
}
break;
}
@@ -1109,7 +1233,8 @@ PCHReader::ReadPCHBlock() {
(const unsigned char *)IdentifierTableData + Record[0],
(const unsigned char *)IdentifierTableData,
PCHIdentifierLookupTrait(*this));
- PP.getIdentifierTable().setExternalIdentifierLookup(this);
+ if (PP)
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
}
break;
@@ -1120,7 +1245,8 @@ PCHReader::ReadPCHBlock() {
}
IdentifierOffsets = (const uint32_t *)BlobStart;
IdentifiersLoaded.resize(Record[0]);
- PP.getHeaderSearchInfo().SetExternalLookup(this);
+ if (PP)
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
break;
case pch::EXTERNAL_DEFINITIONS:
@@ -1176,14 +1302,14 @@ PCHReader::ReadPCHBlock() {
break;
case pch::PP_COUNTER_VALUE:
- if (!Record.empty())
- PP.setCounterValue(Record[0]);
+ if (!Record.empty() && Listener)
+ Listener->ReadCounter(Record[0]);
break;
case pch::SOURCE_LOCATION_OFFSETS:
SLocOffsets = (const uint32_t *)BlobStart;
TotalNumSLocEntries = Record[0];
- PP.getSourceManager().PreallocateSLocEntries(this,
+ SourceMgr.PreallocateSLocEntries(this,
TotalNumSLocEntries,
Record[1]);
break;
@@ -1197,7 +1323,7 @@ PCHReader::ReadPCHBlock() {
break;
case pch::STAT_CACHE:
- PP.getFileManager().setStatCache(
+ FileMgr.setStatCache(
new PCHStatCache((const unsigned char *)BlobStart + Record[0],
(const unsigned char *)BlobStart,
NumStatHits, NumStatMisses));
@@ -1287,10 +1413,10 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
// Clear out any preallocated source location entries, so that
// the source manager does not try to resolve them later.
- PP.getSourceManager().ClearPreallocatedSLocEntries();
+ SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache.
- PP.getFileManager().setStatCache(0);
+ FileMgr.setStatCache(0);
return IgnorePCH;
}
@@ -1303,71 +1429,82 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
break;
}
}
-
- // Load the translation unit declaration
- if (Context)
- ReadDeclRecord(DeclOffsets[0], 0);
// Check the predefines buffer.
if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
PCHPredefinesBufferID))
return IgnorePCH;
- // Initialization of builtins and library builtins occurs before the
- // PCH file is read, so there may be some identifiers that were
- // loaded into the IdentifierTable before we intercepted the
- // creation of identifiers. Iterate through the list of known
- // identifiers and determine whether we have to establish
- // preprocessor definitions or top-level identifier declaration
- // chains for those identifiers.
- //
- // We copy the IdentifierInfo pointers to a small vector first,
- // since de-serializing declarations or macro definitions can add
- // new entries into the identifier table, invalidating the
- // iterators.
- llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
- for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
- IdEnd = PP.getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Identifiers.push_back(Id->second);
- PCHIdentifierLookupTable *IdTable
- = (PCHIdentifierLookupTable *)IdentifierLookupTable;
- for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
- 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());
- PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
- if (Pos == IdTable->end())
- continue;
-
- // Dereferencing the iterator has the effect of populating the
- // IdentifierInfo node with the various declarations it needs.
- (void)*Pos;
+ if (PP) {
+ // Initialization of builtins and library builtins occurs before the
+ // PCH file is read, so there may be some identifiers that were
+ // loaded into the IdentifierTable before we intercepted the
+ // creation of identifiers. Iterate through the list of known
+ // identifiers and determine whether we have to establish
+ // preprocessor definitions or top-level identifier declaration
+ // chains for those identifiers.
+ //
+ // We copy the IdentifierInfo pointers to a small vector first,
+ // since de-serializing declarations or macro definitions can add
+ // new entries into the identifier table, invalidating the
+ // iterators.
+ llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+ for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+ IdEnd = PP->getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Identifiers.push_back(Id->second);
+ PCHIdentifierLookupTable *IdTable
+ = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+ for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+ 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());
+ PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of populating the
+ // IdentifierInfo node with the various declarations it needs.
+ (void)*Pos;
+ }
}
- // Load the special types.
- if (Context) {
- Context->setBuiltinVaListType(
- GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
- if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
- Context->setObjCIdType(GetType(Id));
- if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
- Context->setObjCSelType(GetType(Sel));
- if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
- Context->setObjCProtoType(GetType(Proto));
- if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
- Context->setObjCClassType(GetType(Class));
- if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
- Context->setCFConstantStringType(GetType(String));
- if (unsigned FastEnum
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
- Context->setObjCFastEnumerationStateType(GetType(FastEnum));
- }
+ if (Context)
+ InitializeContext(*Context);
return Success;
}
+void PCHReader::InitializeContext(ASTContext &Ctx) {
+ Context = &Ctx;
+ assert(Context && "Passed null context!");
+
+ assert(PP && "Forgot to set Preprocessor ?");
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
+
+ // Load the translation unit declaration
+ ReadDeclRecord(DeclOffsets[0], 0);
+
+ // Load the special types.
+ Context->setBuiltinVaListType(
+ GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
+ if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+ Context->setObjCIdType(GetType(Id));
+ if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+ Context->setObjCSelType(GetType(Sel));
+ if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+ Context->setObjCProtoType(GetType(Proto));
+ if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+ Context->setObjCClassType(GetType(Class));
+ if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+ Context->setCFConstantStringType(GetType(String));
+ if (unsigned FastEnum
+ = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+ Context->setObjCFastEnumerationStateType(GetType(FastEnum));
+}
+
/// \brief Retrieve the name of the original source file name
/// directly from the PCH file, without actually loading the PCH
/// file.
@@ -1465,73 +1602,60 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
/// \returns true if the PCH file is unacceptable, false otherwise.
bool PCHReader::ParseLanguageOptions(
const llvm::SmallVectorImpl<uint64_t> &Record) {
- const LangOptions &LangOpts = PP.getLangOptions();
-#define PARSE_LANGOPT_BENIGN(Option) ++Idx
-#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
- if (Record[Idx] != LangOpts.Option) { \
- Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
- return true; \
- } \
- ++Idx
-
- unsigned Idx = 0;
- PARSE_LANGOPT_BENIGN(Trigraphs);
- PARSE_LANGOPT_BENIGN(BCPLComment);
- PARSE_LANGOPT_BENIGN(DollarIdents);
- PARSE_LANGOPT_BENIGN(AsmPreprocessor);
- PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
- PARSE_LANGOPT_BENIGN(ImplicitInt);
- PARSE_LANGOPT_BENIGN(Digraphs);
- PARSE_LANGOPT_BENIGN(HexFloats);
- PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
- PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
- PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
- PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
- PARSE_LANGOPT_BENIGN(CXXOperatorName);
- PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
- PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
- PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
- PARSE_LANGOPT_BENIGN(PascalStrings);
- PARSE_LANGOPT_BENIGN(WritableStrings);
- PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
- diag::warn_pch_lax_vector_conversions);
- PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
- PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
- PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
- PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
- PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
- diag::warn_pch_thread_safe_statics);
- PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
- PARSE_LANGOPT_BENIGN(EmitAllDecls);
- PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
- PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
- PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
- diag::warn_pch_heinous_extensions);
- // FIXME: Most of the options below are benign if the macro wasn't
- // used. Unfortunately, this means that a PCH compiled without
- // optimization can't be used with optimization turned on, even
- // though the only thing that changes is whether __OPTIMIZE__ was
- // defined... but if __OPTIMIZE__ never showed up in the header, it
- // doesn't matter. We could consider making this some special kind
- // of check.
- PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
- PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
- PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
- PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
- PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
- PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
- PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
- PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
- if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
- Diag(diag::warn_pch_gc_mode)
- << (unsigned)Record[Idx] << LangOpts.getGCMode();
- return true;
+ if (Listener) {
+ LangOptions LangOpts;
+
+ #define PARSE_LANGOPT(Option) \
+ LangOpts.Option = Record[Idx]; \
+ ++Idx
+
+ unsigned Idx = 0;
+ PARSE_LANGOPT(Trigraphs);
+ PARSE_LANGOPT(BCPLComment);
+ PARSE_LANGOPT(DollarIdents);
+ PARSE_LANGOPT(AsmPreprocessor);
+ PARSE_LANGOPT(GNUMode);
+ PARSE_LANGOPT(ImplicitInt);
+ PARSE_LANGOPT(Digraphs);
+ PARSE_LANGOPT(HexFloats);
+ PARSE_LANGOPT(C99);
+ PARSE_LANGOPT(Microsoft);
+ PARSE_LANGOPT(CPlusPlus);
+ PARSE_LANGOPT(CPlusPlus0x);
+ PARSE_LANGOPT(CXXOperatorNames);
+ PARSE_LANGOPT(ObjC1);
+ PARSE_LANGOPT(ObjC2);
+ PARSE_LANGOPT(ObjCNonFragileABI);
+ PARSE_LANGOPT(PascalStrings);
+ PARSE_LANGOPT(WritableStrings);
+ PARSE_LANGOPT(LaxVectorConversions);
+ PARSE_LANGOPT(Exceptions);
+ PARSE_LANGOPT(NeXTRuntime);
+ PARSE_LANGOPT(Freestanding);
+ PARSE_LANGOPT(NoBuiltin);
+ PARSE_LANGOPT(ThreadsafeStatics);
+ PARSE_LANGOPT(Blocks);
+ PARSE_LANGOPT(EmitAllDecls);
+ PARSE_LANGOPT(MathErrno);
+ PARSE_LANGOPT(OverflowChecking);
+ PARSE_LANGOPT(HeinousExtensions);
+ PARSE_LANGOPT(Optimize);
+ PARSE_LANGOPT(OptimizeSize);
+ PARSE_LANGOPT(Static);
+ PARSE_LANGOPT(PICLevel);
+ PARSE_LANGOPT(GNUInline);
+ PARSE_LANGOPT(NoInline);
+ PARSE_LANGOPT(AccessControl);
+ PARSE_LANGOPT(CharIsSigned);
+ LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
+ ++Idx;
+ LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
+ ++Idx;
+ PARSE_LANGOPT(InstantiationDepth);
+ #undef PARSE_LANGOPT
+
+ return Listener->ReadLanguageOptions(LangOpts);
}
- ++Idx;
- PARSE_LANGOPT_BENIGN(getVisibilityMode());
- PARSE_LANGOPT_BENIGN(InstantiationDepth);
-#undef PARSE_LANGOPT_IRRELEVANT
-#undef PARSE_LANGOPT_BENIGN
return false;
}
@@ -1722,13 +1846,15 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getObjCQualifiedInterfaceType(ItfD, Protos.data(), NumProtos);
}
- case pch::TYPE_OBJC_QUALIFIED_ID: {
+ case pch::TYPE_OBJC_OBJECT_POINTER: {
unsigned Idx = 0;
+ ObjCInterfaceDecl *ItfD =
+ cast_or_null<ObjCInterfaceDecl>(GetDecl(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->getObjCQualifiedIdType(Protos.data(), NumProtos);
+ return Context->getObjCObjectPointerType(ItfD, Protos.data(), NumProtos);
}
}
// Suppress a GCC warning
@@ -2056,6 +2182,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
return 0;
}
+ assert(PP && "Forgot to set Preprocessor ?");
if (!IdentifiersLoaded[ID - 1]) {
uint32_t Offset = IdentifierOffsets[ID - 1];
const char *Str = IdentifierTableData + Offset;
@@ -2067,7 +2194,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
unsigned StrLen = (((unsigned) StrLenPtr[0])
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
IdentifiersLoaded[ID - 1]
- = &PP.getIdentifierTable().get(Str, Str + StrLen);
+ = &PP->getIdentifierTable().get(Str, Str + StrLen);
}
return IdentifiersLoaded[ID - 1];
@@ -2170,15 +2297,14 @@ DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
}
DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
- return PP.getDiagnostics().Report(FullSourceLoc(Loc,
- PP.getSourceManager()),
- DiagID);
+ return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
}
/// \brief Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &PCHReader::getIdentifierTable() {
- return PP.getIdentifierTable();
+ assert(PP && "Forgot to set Preprocessor ?");
+ return PP->getIdentifierTable();
}
/// \brief Record that the given ID maps to the given switch-case
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 6856623..3dd84c7 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -80,8 +80,9 @@ void PCHDeclReader::VisitDecl(Decl *D) {
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setInvalidDecl(Record[Idx++]);
if (Record[Idx++])
- D->addAttr(Reader.ReadAttributes());
+ D->addAttr(*Reader.getContext(), Reader.ReadAttributes());
D->setImplicit(Record[Idx++]);
+ D->setUsed(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]);
}
@@ -156,6 +157,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setHasWrittenPrototype(Record[Idx++]);
FD->setDeleted(Record[Idx++]);
FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
// FIXME: C++ TemplateOrInstantiation
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index e6871e3..d096388 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -667,6 +667,7 @@ unsigned PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setByRef(Record[Idx++]);
+ E->setConstQualAdded(Record[Idx++]);
return 0;
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 765fecb..3b1eb08 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -229,12 +229,14 @@ PCHTypeWriter::VisitObjCQualifiedInterfaceType(
Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
}
-void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
+void
+PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
Record.push_back(T->getNumProtocols());
- for (ObjCQualifiedIdType::qual_iterator I = T->qual_begin(),
+ for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
E = T->qual_end(); I != E; ++I)
Writer.AddDeclRef(*I, Record);
- Code = pch::TYPE_OBJC_QUALIFIED_ID;
+ Code = pch::TYPE_OBJC_OBJECT_POINTER;
}
//===----------------------------------------------------------------------===//
@@ -407,7 +409,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(TYPE_ENUM);
RECORD(TYPE_OBJC_INTERFACE);
RECORD(TYPE_OBJC_QUALIFIED_INTERFACE);
- RECORD(TYPE_OBJC_QUALIFIED_ID);
+ RECORD(TYPE_OBJC_OBJECT_POINTER);
// Statements and Exprs can occur in the Types block.
AddStmtsExprs(Stream, Record);
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 6734661..44da4d7 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -82,6 +82,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->isInvalidDecl());
Record.push_back(D->hasAttrs());
Record.push_back(D->isImplicit());
+ Record.push_back(D->isUsed());
Record.push_back(D->getAccess());
}
@@ -156,6 +157,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->hasWrittenPrototype());
Record.push_back(D->isDeleted());
Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
// FIXME: C++ TemplateOrInstantiation
Record.push_back(D->param_size());
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
@@ -360,6 +362,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// know are true of all PARM_VAR_DECLs.
if (!D->hasAttrs() &&
!D->isImplicit() &&
+ !D->isUsed() &&
D->getAccess() == AS_none &&
D->getStorageClass() == 0 &&
!D->hasCXXDirectInitializer() && // Can params have this ever?
@@ -434,6 +437,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?)
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
+ Abv->Add(BitCodeAbbrevOp(0)); // isUsed
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
// NamedDecl
@@ -516,7 +520,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
// If the declaration had any attributes, write them now.
if (D->hasAttrs())
- WriteAttributeRecord(D->getAttrs());
+ WriteAttributeRecord(D->getAttrs(Context));
// Flush any expressions that were written as part of this declaration.
FlushStmts();
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 73dea10..c63c03c 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -602,6 +602,7 @@ void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->isByRef());
+ Record.push_back(E->isConstQualAdded());
Code = pch::EXPR_BLOCK_DECL_REF;
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 89d099c..d63d9cb 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -123,6 +123,8 @@ public:
}
void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+ void HandleNewlinesInToken(const char *TokStr, unsigned Len);
+
/// MacroDefined - This hook is called whenever a macro definition is seen.
void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
@@ -327,6 +329,29 @@ bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
return true;
}
+void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
+ unsigned Len) {
+ unsigned NumNewlines = 0;
+ for (; Len; --Len, ++TokStr) {
+ if (*TokStr != '\n' &&
+ *TokStr != '\r')
+ continue;
+
+ ++NumNewlines;
+
+ // If we have \n\r or \r\n, skip both and count as one line.
+ if (Len != 1 &&
+ (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+ TokStr[0] != TokStr[1])
+ ++TokStr, --Len;
+ }
+
+ if (NumNewlines == 0) return;
+
+ CurLine += NumNewlines;
+}
+
+
namespace {
struct UnknownPragmaHandler : public PragmaHandler {
const char *Prefix;
@@ -382,9 +407,19 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OS.write(TokPtr, Len);
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
OS.write(&S[0], S.size());
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(&S[0], S.size());
}
Callbacks->SetEmittedTokensOnThisLine();
diff --git a/lib/Frontend/RewriteBlocks.cpp b/lib/Frontend/RewriteBlocks.cpp
index 8393574..d20d5cd 100644
--- a/lib/Frontend/RewriteBlocks.cpp
+++ b/lib/Frontend/RewriteBlocks.cpp
@@ -132,7 +132,7 @@ public:
if (const PointerType *PT = OCT->getAsPointerType()) {
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- isa<ObjCQualifiedIdType>(PT->getPointeeType()))
+ PT->getPointeeType()->isObjCQualifiedIdType())
return true;
}
return false;
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index f382704..dce2710 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -356,7 +356,7 @@ namespace {
if (const PointerType *PT = OCT->getAsPointerType()) {
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- isa<ObjCQualifiedIdType>(PT->getPointeeType()))
+ PT->getPointeeType()->isObjCQualifiedIdType())
return true;
}
return false;
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index c861881..6ba0a28 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -28,8 +28,31 @@ namespace {
class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
DocumentXML& Doc;
- static const char *getOpcodeStr(UnaryOperator::Opcode Op);
- static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+ void addSpecialAttribute(const char* pName, StringLiteral* Str)
+ {
+ Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+ }
+
+ void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S)
+ {
+ if (S->isArgumentType())
+ {
+ Doc.addAttribute(pName, S->getArgumentType());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, CXXTypeidExpr* S)
+ {
+ if (S->isTypeOperand())
+ {
+ Doc.addAttribute(pName, S->getTypeOperand());
+ }
+ }
+
public:
StmtXML(DocumentXML& doc)
@@ -39,12 +62,21 @@ namespace {
void DumpSubTree(Stmt *S) {
if (S)
{
- Doc.addSubNode(S->getStmtClassName());
- Doc.addLocationRange(S->getSourceRange());
- if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
- VisitDeclStmt(DS);
- } else {
- Visit(S);
+ Visit(S);
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI)
+ {
+ Doc.PrintDecl(*DI);
+ }
+ }
+ else
+ {
+ if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
+ {
+ Doc.PrintDecl(CCDE->getVarDecl());
+ }
for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
{
DumpSubTree(*i);
@@ -56,17 +88,46 @@ namespace {
}
}
- void DumpTypeExpr(const QualType& T)
- {
- Doc.addSubNode("TypeExpr");
- Doc.addTypeAttribute(T);
- Doc.toParent();
- }
- void DumpExpr(const Expr *Node) {
- Doc.addTypeAttribute(Node->getType());
- }
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* S) \
+ { \
+ typedef CLASS tStmtType; \
+ Doc.addSubNode(NAME);
+
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN);
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange());
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
// Stmts.
void VisitStmt(Stmt *Node);
void VisitDeclStmt(DeclStmt *Node);
@@ -105,13 +166,14 @@ namespace {
void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+#endif
};
}
//===----------------------------------------------------------------------===//
// Stmt printing methods.
//===----------------------------------------------------------------------===//
-
+#if (0)
void StmtXML::VisitStmt(Stmt *Node)
{
// nothing special to do
@@ -396,7 +458,7 @@ void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
if (Node->isFreeIvar())
Doc.addAttribute("isFreeIvar", "1");
}
-
+#endif
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 6699c65..d4c7e0f 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -640,9 +640,18 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
SourceLocation B = Info.getRange(i).getBegin();
SourceLocation E = Info.getRange(i).getEnd();
- std::pair<FileID, unsigned> BInfo=SM.getDecomposedInstantiationLoc(B);
-
+ B = SM.getInstantiationLoc(B);
E = SM.getInstantiationLoc(E);
+
+ // If the End location and the start location are the same and are a
+ // macro location, then the range was something that came from a macro
+ // expansion or _Pragma. If this is an object-like macro, the best we
+ // can do is to highlight the range. If this is a function-like
+ // macro, we'd also like to highlight the arguments.
+ if (B == E && Info.getRange(i).getEnd().isMacroID())
+ E = SM.getInstantiationRange(Info.getRange(i).getEnd()).second;
+
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
// If the start or end of the range is in another file, just discard
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
new file mode 100644
index 0000000..f32fbbd
--- /dev/null
+++ b/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,127 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+ namespace XML {
+ namespace {
+
+//---------------------------------------------------------
+class TypeWriter : public TypeVisitor<TypeWriter>
+{
+ DocumentXML& Doc;
+
+public:
+ TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//---------------------------------------------------------
+ } // anon clang
+ } // NS XML
+
+//---------------------------------------------------------
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder>
+{
+ DocumentXML& Doc;
+
+ void addIfType(const Type* pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ void addIfType(const QualType& pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ template<class T> void addIfType(T) {}
+
+public:
+ TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ {
+
+#define ID_ATTRIBUTE_XML
+#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN);
+#define CONTEXT_ATTRIBUTE_XML( FN )
+#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )
+#define ENUM_XML( VALUE, NAME )
+#define END_ENUM_XML
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//---------------------------------------------------------
+void DocumentXML::addParentTypes(const Type* pType)
+{
+ TypeAdder(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const Type* pType)
+{
+ XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const QualType& pType)
+{
+ XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index e44c37a..318685a 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -15,7 +15,12 @@ set(files
xmmintrin.h)
#FIXME: Centralize Clang version info
-set(output_dir ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib/clang/1.0/include)
+if (MSVC_IDE OR XCODE)
+ set(output_dir ${LLVM_BINARY_DIR}/bin/lib/clang/1.0/include)
+else ()
+ set(output_dir ${LLVM_BINARY_DIR}/lib/clang/1.0/include)
+endif ()
+
foreach( f ${files} )
set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 129fa1a..9023b11 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -215,9 +215,7 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart,
const DirectoryLookup *&CurDir,
const FileEntry *CurFileEnt) {
// If 'Filename' is absolute, check to see if it exists and no searching.
- // FIXME: Portability. This should be a sys::Path interface, this doesn't
- // handle things like C:\foo.txt right, nor win32 \\network\device\blah.
- if (FilenameStart[0] == '/') {
+ if (llvm::sys::Path::isAbsolute(FilenameStart, FilenameEnd-FilenameStart)) {
CurDir = 0;
// If this was an #include_next "/absolute/file", fail.
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index ce59341..3227d1c 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -93,7 +93,7 @@ void Preprocessor::HandlePragmaDirective() {
PragmaHandlers->HandlePragma(*this, Tok);
// If the pragma handler didn't read the rest of the line, consume it now.
- if (CurPPLexer->ParsingPreprocessorDirective)
+ if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
DiscardUntilEndOfDirective();
}
@@ -195,8 +195,10 @@ void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
void Preprocessor::HandlePragmaMark() {
assert(CurPPLexer && "No current lexer?");
- if (CurLexer) CurLexer->ReadToEndOfLine();
- else CurPTHLexer->DiscardToEndOfLine();
+ if (CurLexer)
+ CurLexer->ReadToEndOfLine();
+ else
+ CurPTHLexer->DiscardToEndOfLine();
}
@@ -254,6 +256,18 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
// Mark the file as a system header.
HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
+
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
+ unsigned FilenameLen = strlen(PLoc.getFilename());
+ unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(),
+ FilenameLen);
+
+ // Emit a line marker. This will change any source locations from this point
+ // forward to realize they are in a system header.
+ // Create a line note with this information.
+ SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine(), FilenameID,
+ false, false, true, false);
+
// Notify the client, if desired, that we are in a new source file.
if (Callbacks)
Callbacks->FileChanged(SysHeaderTok.getLocation(),
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 0a7d92e..24ee5d8 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -51,7 +51,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
IdentifierInfoLookup* IILookup)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts, IILookup),
- CurPPLexer(0), CurDirLookup(0), Callbacks(0) {
+ BuiltinInfo(Target), CurPPLexer(0), CurDirLookup(0), Callbacks(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp
index ab989ca..be13b27 100644
--- a/lib/Lex/TokenConcatenation.cpp
+++ b/lib/Lex/TokenConcatenation.cpp
@@ -192,7 +192,8 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevTok,
return isalnum(FirstChar) || Tok.is(tok::numeric_constant) ||
FirstChar == '+' || FirstChar == '-' || FirstChar == '.';
case tok::period: // ..., .*, .1234
- return FirstChar == '.' || isdigit(FirstChar) || FirstChar == '*';
+ return FirstChar == '.' || isdigit(FirstChar) ||
+ (PP.getLangOptions().CPlusPlus && FirstChar == '*');
case tok::amp: // &&
return FirstChar == '&';
case tok::plus: // ++
@@ -210,10 +211,11 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevTok,
case tok::percent: // %>, %:
return FirstChar == '>' || FirstChar == ':';
case tok::colon: // ::, :>
- return FirstChar == ':' ||FirstChar == '>';
+ return FirstChar == '>' ||
+ (PP.getLangOptions().CPlusPlus && FirstChar == ':');
case tok::hash: // ##, #@, %:%:
return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
case tok::arrow: // ->*
- return FirstChar == '*';
+ return PP.getLangOptions().CPlusPlus && FirstChar == '*';
}
}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index b018e36..9ded366 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -42,6 +42,22 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
return DeclPtrTy();
}
+// Defined out-of-line here because of dependecy on AttributeList
+Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName) {
+
+ // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+ // passed AttributeList, however other actions don't free it, is it
+ // temporary state or bug?
+ delete AttrList;
+ return DeclPtrTy();
+}
+
void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
if (Loc.isValid()) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9073c6d..6915252 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -402,7 +402,14 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) {
SourceLocation DelLoc = ConsumeToken();
Actions.SetDeclDeleted(ThisDecl, DelLoc);
} else {
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
+
OwningExprResult Init(ParseInitializer());
+
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+
if (Init.isInvalid()) {
SkipUntil(tok::semi, true, true);
return DeclPtrTy();
@@ -2692,8 +2699,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// things like '=' and '*='. Sema rejects these in C89 mode because they
// are not i-c-e's, so we don't need to distinguish between the two here.
- // Parse the assignment-expression now.
- NumElements = ParseAssignmentExpression();
+ // Parse the constant-expression or assignment-expression now (depending
+ // on dialect).
+ if (getLang().CPlusPlus)
+ NumElements = ParseConstantExpression();
+ else
+ NumElements = ParseAssignmentExpression();
}
// If there was an error parsing the assignment-expression, recover.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 498eaf1..44f231a 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -48,6 +48,8 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
SourceLocation IdentLoc;
IdentifierInfo *Ident = 0;
+
+ Token attrTok;
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
@@ -56,13 +58,19 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
// Read label attributes, if present.
Action::AttrTy *AttrList = 0;
- if (Tok.is(tok::kw___attribute))
+ if (Tok.is(tok::kw___attribute)) {
+ attrTok = Tok;
+
// FIXME: save these somewhere.
AttrList = ParseAttributes();
+ }
- if (Tok.is(tok::equal))
- // FIXME: Verify no attributes were present.
+ if (Tok.is(tok::equal)) {
+ if (AttrList)
+ Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+
return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
+ }
if (Tok.isNot(tok::l_brace)) {
Diag(Tok, Ident ? diag::err_expected_lbrace :
@@ -245,15 +253,62 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
///
/// using-declaration: [C++ 7.3.p3: namespace.udecl]
/// 'using' 'typename'[opt] ::[opt] nested-name-specifier
-/// unqualified-id [TODO]
-/// 'using' :: unqualified-id [TODO]
+/// unqualified-id
+/// 'using' :: unqualified-id
///
Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd) {
- assert(false && "Not implemented");
- // FIXME: Implement parsing.
- return DeclPtrTy();
+ CXXScopeSpec SS;
+ bool IsTypeName;
+
+ // Ignore optional 'typename'.
+ if (Tok.is(tok::kw_typename)) {
+ ConsumeToken();
+ IsTypeName = true;
+ }
+ else
+ IsTypeName = false;
+
+ // Parse nested-name-specifier.
+ ParseOptionalCXXScopeSpecifier(SS);
+
+ AttributeList *AttrList = 0;
+ IdentifierInfo *TargetName = 0;
+ SourceLocation IdentLoc = SourceLocation();
+
+ // Check nested-name specifier.
+ if (SS.isInvalid()) {
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+ if (Tok.is(tok::annot_template_id)) {
+ Diag(Tok, diag::err_unexpected_template_spec_in_using);
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident_in_using);
+ // If there was invalid identifier, skip to end of decl, and eat ';'.
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+
+ // Parse identifier.
+ TargetName = Tok.getIdentifierInfo();
+ IdentLoc = ConsumeToken();
+
+ // Parse (optional) attributes (most likely GNU strong-using extension).
+ if (Tok.is(tok::kw___attribute))
+ AttrList = ParseAttributes();
+
+ // Eat ';'.
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ AttrList ? "attributes list" : "namespace name", tok::semi);
+
+ return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS,
+ IdentLoc, TargetName, AttrList, IsTypeName);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
@@ -271,7 +326,7 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
}
SourceLocation LParenLoc = ConsumeParen();
-
+
OwningExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipUntil(tok::semi);
@@ -782,7 +837,23 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
ConsumeToken();
return ParseCXXClassMemberDeclaration(AS);
}
-
+
+ if (Tok.is(tok::kw_using)) {
+ // Eat 'using'.
+ SourceLocation UsingLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_namespace)) {
+ Diag(UsingLoc, diag::err_using_namespace_in_class);
+ SkipUntil(tok::semi, true, true);
+ }
+ else {
+ SourceLocation DeclEnd;
+ // Otherwise, it must be using-declaration.
+ ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd);
+ }
+ return;
+ }
+
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 3fee78b..4a07d05 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -276,6 +276,11 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
Parser::OwningExprResult Parser::ParseConstantExpression() {
+ // C++ [basic.def.odr]p2:
+ // An expression is potentially evaluated unless it appears where an
+ // integral constant expression is required (see 5.19) [...].
+ EnterUnevaluatedOperand Unevaluated(Actions);
+
OwningExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
@@ -971,8 +976,15 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
return ExprError();
}
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
-
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
@@ -980,6 +992,14 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
// expression.
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 681c6ad..87aa5dc 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -377,6 +377,17 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Ty.get(), RParenLoc);
} else {
+ // C++0x [expr.typeid]p3:
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] The expression is an unevaluated
+ // operand (Clause 5).
+ //
+ // Note that we can't tell whether the expression is an lvalue of a
+ // polymorphic class type until after we've parsed the expression, so
+ // we treat the expression as an unevaluated operand and let semantic
+ // analysis cope with case where the expression is not an unevaluated
+ // operand.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Result = ParseExpression();
// Match the ')'.
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index ae863f2..425d804 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -77,11 +77,11 @@ JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
/// diagnostic that should be emitted if control goes over it. If not, return 0.
-static unsigned GetDiagForGotoScopeDecl(const Decl *D) {
+static unsigned GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->getType()->isVariablyModifiedType())
return diag::note_protected_by_vla;
- if (VD->hasAttr<CleanupAttr>())
+ if (VD->hasAttr<CleanupAttr>(Context))
return diag::note_protected_by_cleanup;
} else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
if (TD->getUnderlyingType()->isVariablyModifiedType())
@@ -125,7 +125,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
I != E; ++I) {
// If this decl causes a new scope, push and switch to it.
- if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) {
+ if (unsigned Diag = GetDiagForGotoScopeDecl(this->S.Context, *I)) {
Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation()));
ParentScope = Scopes.size()-1;
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index a5f2438..e756b41 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -125,6 +125,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
if (!PP.getLangOptions().ObjC1) return;
+ // Built-in ObjC types may already be set by PCHReader (hence isNull checks).
if (Context.getObjCSelType().isNull()) {
// Synthesize "typedef struct objc_selector *SEL;"
RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
@@ -163,7 +164,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
// Synthesize "typedef struct objc_object { Class isa; } *id;"
if (Context.getObjCIdType().isNull()) {
RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
-
+
QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
PushOnScopeChains(ObjectTag, TUScope);
TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
@@ -181,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
- GlobalNewDeleteDeclared(false),
+ GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0607a89..560f952 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -18,7 +18,9 @@
#include "IdentifierResolver.h"
#include "CXXFieldCollector.h"
#include "SemaOverload.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/Action.h"
@@ -102,7 +104,7 @@ struct BlockSemaInfo {
/// ReturnType - This will get set to block result type, by looking at
/// return types, if any, in the block body.
- Type *ReturnType;
+ QualType ReturnType;
/// LabelMap - This is a mapping from label identifiers to the LabelStmt for
/// it (which acts like the label decl in some ways). Forward referenced
@@ -245,6 +247,12 @@ public:
/// have been declared.
bool GlobalNewDeleteDeclared;
+ /// A flag that indicates when we are processing an unevaluated operand
+ /// (C++0x [expr]). C99 has the same notion of declarations being
+ /// "used" and C++03 has the notion of "potentially evaluated", but we
+ /// adopt the C++0x terminology since it is most precise.
+ bool InUnevaluatedOperand;
+
/// \brief Whether the code handled by Sema should be considered a
/// complete translation unit or not.
///
@@ -312,24 +320,8 @@ public:
// If we encountered an error during template argument
// deduction, and that error is one of the SFINAE errors,
// suppress the diagnostic.
- bool Fatal = false;
- switch (Diags.getDiagnosticLevel(DiagID)) {
- case Diagnostic::Ignored:
- case Diagnostic::Note:
- case Diagnostic::Warning:
- break;
-
- case Diagnostic::Error:
- ++NumSFINAEErrors;
- break;
-
- case Diagnostic::Fatal:
- Fatal = true;
- break;
- }
-
- if (!Fatal)
- return SemaDiagnosticBuilder(*this);
+ ++NumSFINAEErrors;
+ return SemaDiagnosticBuilder(*this);
}
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
@@ -375,6 +367,8 @@ public:
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
+ QualType BuildExtVectorType(QualType T, ExprArg ArraySize,
+ SourceLocation AttrLoc);
QualType BuildFunctionType(QualType T,
QualType *ParamTypes, unsigned NumParamTypes,
bool Variadic, unsigned Quals,
@@ -468,6 +462,19 @@ public:
virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body);
DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body,
bool IsInstantiation);
+
+ /// \brief Diagnose any unused parameters in the given sequence of
+ /// ParmVarDecl pointers.
+ template<typename InputIterator>
+ void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) {
+ for (; Param != ParamEnd; ++Param) {
+ if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
+ !(*Param)->template hasAttr<UnusedAttr>(Context))
+ Diag((*Param)->getLocation(), diag::warn_unused_parameter)
+ << (*Param)->getDeclName();
+ }
+ }
+
void DiagnoseInvalidJumps(Stmt *Body);
virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
@@ -553,6 +560,12 @@ public:
void PushDeclContext(Scope *S, DeclContext *DC);
void PopDeclContext();
+ /// EnterDeclaratorContext - Used when we must lookup names in the context
+ /// of a declarator's nested name specifier.
+ void EnterDeclaratorContext(Scope *S, DeclContext *DC);
+ void ExitDeclaratorContext(Scope *S);
+
+
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
/// to the function decl for the function being parsed. If we're currently
/// in a 'block', this returns the containing context.
@@ -702,6 +715,7 @@ public:
bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
const OverloadCandidate& Cand2);
OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
+ SourceLocation Loc,
OverloadCandidateSet::iterator& Best);
void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
bool OnlyViable);
@@ -1132,8 +1146,8 @@ public:
// More parsing and symbol table subroutines.
// Decl attributes - this routine is the top level dispatcher.
- void ProcessDeclAttributes(Decl *D, const Declarator &PD);
- void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList);
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList);
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl);
@@ -1320,6 +1334,14 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
+ virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
+ bool Result = InUnevaluatedOperand;
+ InUnevaluatedOperand = UnevaluatedOperand;
+ return Result;
+ }
+
+ void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+
// Primary Expressions.
virtual SourceRange getExprRange(ExprTy *E) const;
@@ -1525,6 +1547,14 @@ public:
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *Ident);
+
+ virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName);
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
@@ -1541,6 +1571,11 @@ public:
CXXConstructorDecl *Constructor,
QualType DeclInitType,
Expr **Exprs, unsigned NumExprs);
+
+ /// DefineImplicitDefaultConstructor - Checks for feasibilityt of
+ /// defining this constructor as the default constructor.
+ void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
@@ -1677,8 +1712,8 @@ public:
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
- Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool DestroyTemps = true);
+ Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
+ bool ShouldDestroyTemporaries);
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr);
@@ -1735,6 +1770,17 @@ public:
/// defining scope.
virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+ /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+ /// initializer for the declaration 'Dcl'.
+ /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+ /// static data member of class X, names should be looked up in the scope of
+ /// class X.
+ virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl);
+
+ /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+ /// initializer for the declaration 'Dcl'.
+ virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl);
+
// ParseObjCStringLiteral - Parse Objective-C string literals.
virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
ExprTy **Strings,
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 1bf8444..cbfa56a 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -205,7 +205,7 @@ void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
// Otherwise, add the 'unused' attribute to each referenced declaration.
for (unsigned i = 0; i < NumExprs; ++i) {
DeclRefExpr *DR = (DeclRefExpr*) Exprs[i];
- DR->getDecl()->addAttr(::new (Context) UnusedAttr());
+ DR->getDecl()->addAttr(Context, ::new (Context) UnusedAttr());
DR->Destroy(Context);
}
}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 11ac0bd..a14bcd5 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -286,11 +286,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
/// The 'SS' should be a non-empty valid CXXScopeSpec.
void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
- PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
- CurContext = computeDeclContext(SS);
- assert(CurContext && "No context?");
- S->setEntity(CurContext);
+ EnterDeclaratorContext(S, computeDeclContext(SS));
}
/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
@@ -301,12 +297,5 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
assert(S->getEntity() == computeDeclContext(SS) && "Context imbalance!");
- S->setEntity(PreDeclaratorDC);
- PreDeclaratorDC = 0;
-
- // Reset CurContext to the nearest enclosing context.
- while (!S->getEntity() && S->getParent())
- S = S->getParent();
- CurContext = static_cast<DeclContext*>(S->getEntity());
- assert(CurContext && "No context?");
+ ExitDeclaratorContext(S);
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 4856e7f..a2ceafa 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -166,7 +166,7 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
// handlers.
// Printf checking.
- if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
+ if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>(Context)) {
if (Format->getType() == "printf") {
bool HasVAListArg = Format->getFirstArg() == 0;
if (!HasVAListArg) {
@@ -178,7 +178,8 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
HasVAListArg ? 0 : Format->getFirstArg() - 1);
}
}
- for (const Attr *attr = FDecl->getAttrs(); attr; attr = attr->getNext()) {
+ for (const Attr *attr = FDecl->getAttrs(Context);
+ attr; attr = attr->getNext()) {
if (const NonNullAttr *NonNull = dyn_cast<NonNullAttr>(attr))
CheckNonNullArguments(NonNull, TheCall);
}
@@ -191,7 +192,7 @@ Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
OwningExprResult TheCallResult(Owned(TheCall));
// Printf checking.
- const FormatAttr *Format = NDecl->getAttr<FormatAttr>();
+ const FormatAttr *Format = NDecl->getAttr<FormatAttr>(Context);
if (!Format)
return move(TheCallResult);
const VarDecl *V = dyn_cast<VarDecl>(NDecl);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b995717..06fd1a1 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -183,7 +183,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
DeclContext *Sema::getContainingDC(DeclContext *DC) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
// A C++ out-of-line method will return to the file declaration context.
- if (MD->isOutOfLineDefinition())
+ if (MD->isOutOfLine())
return MD->getLexicalDeclContext();
// A C++ inline method is parsed *after* the topmost class it was declared
@@ -219,6 +219,27 @@ void Sema::PopDeclContext() {
CurContext = getContainingDC(CurContext);
}
+/// EnterDeclaratorContext - Used when we must lookup names in the context
+/// of a declarator's nested name specifier.
+void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
+ assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
+ PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
+ CurContext = DC;
+ assert(CurContext && "No context?");
+ S->setEntity(CurContext);
+}
+
+void Sema::ExitDeclaratorContext(Scope *S) {
+ S->setEntity(PreDeclaratorDC);
+ PreDeclaratorDC = 0;
+
+ // Reset CurContext to the nearest enclosing context.
+ while (!S->getEntity() && S->getParent())
+ S = S->getParent();
+ CurContext = static_cast<DeclContext*>(S->getEntity());
+ assert(CurContext && "No context?");
+}
+
/// \brief Determine whether we allow overloading of the function
/// PrevDecl with another declaration.
///
@@ -235,7 +256,7 @@ static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) {
if (isa<OverloadedFunctionDecl>(PrevDecl))
return true;
- return PrevDecl->getAttr<OverloadableAttr>() != 0;
+ return PrevDecl->getAttr<OverloadableAttr>(Context) != 0;
}
/// Add this decl to the scope shadowed decl chains.
@@ -590,8 +611,9 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
-static bool DeclHasAttr(const Decl *decl, const Attr *target) {
- for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
+static bool
+DeclHasAttr(ASTContext &Context, const Decl *decl, const Attr *target) {
+ for (const Attr *attr = decl->getAttrs(Context); attr; attr = attr->getNext())
if (attr->getKind() == target->getKind())
return true;
@@ -600,11 +622,11 @@ static bool DeclHasAttr(const Decl *decl, const Attr *target) {
/// MergeAttributes - append attributes from the Old decl to the New one.
static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) {
- for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) {
- if (!DeclHasAttr(New, attr) && attr->isMerged()) {
+ for (const Attr *attr = Old->getAttrs(C); attr; attr = attr->getNext()) {
+ if (!DeclHasAttr(C, New, attr) && attr->isMerged()) {
Attr *NewAttr = attr->clone(C);
NewAttr->setInherited(true);
- New->addAttr(NewAttr);
+ New->addAttr(C, NewAttr);
}
}
}
@@ -1615,7 +1637,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewTD->setInvalidDecl();
// Handle attributes prior to checking for duplicates in MergeVarDecl
- ProcessDeclAttributes(NewTD, D);
+ ProcessDeclAttributes(S, NewTD, D);
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
@@ -1801,13 +1823,14 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewVD->setLexicalDeclContext(CurContext);
// Handle attributes prior to checking for duplicates in MergeVarDecl
- ProcessDeclAttributes(NewVD, D);
+ ProcessDeclAttributes(S, NewVD, D);
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
+ NewVD->addAttr(Context,
+ ::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -1886,11 +1909,11 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
}
if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
- && !NewVD->hasAttr<BlocksAttr>())
+ && !NewVD->hasAttr<BlocksAttr>(Context))
Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
bool isVM = T->isVariablyModifiedType();
- if (isVM || NewVD->hasAttr<CleanupAttr>())
+ if (isVM || NewVD->hasAttr<CleanupAttr>(Context))
CurFunctionNeedsScopeChecking = true;
if ((isVM && NewVD->hasLinkage()) ||
@@ -1945,12 +1968,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
return NewVD->setInvalidDecl();
}
- if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
+ if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>(Context)) {
Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
return NewVD->setInvalidDecl();
}
- if (isVM && NewVD->hasAttr<BlocksAttr>()) {
+ if (isVM && NewVD->hasAttr<BlocksAttr>(Context)) {
Diag(NewVD->getLocation(), diag::err_block_on_vm);
return NewVD->setInvalidDecl();
}
@@ -2180,7 +2203,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
+ NewFD->addAttr(Context,
+ ::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -2260,7 +2284,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
- } else if (!Redeclaration) {
+ } else if (!Redeclaration && (!PrevDecl || !isa<UsingDecl>(PrevDecl))) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
// was no such member function declared (C++ [class.mfct]p2,
@@ -2298,10 +2322,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// (for example to check for conflicts, etc).
// FIXME: This needs to happen before we merge declarations. Then,
// let attribute merging cope with attribute conflicts.
- ProcessDeclAttributes(NewFD, D);
+ ProcessDeclAttributes(S, NewFD, D);
AddKnownFunctionAttributes(NewFD);
- if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
+ if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>(Context)) {
// If a function name is overloadable in C, then every function
// with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
@@ -2309,7 +2333,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (PrevDecl)
Diag(PrevDecl->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr());
+ NewFD->addAttr(Context, ::new (Context) OverloadableAttr());
}
// If this is a locally-scoped extern C function, update the
@@ -2431,7 +2455,8 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
if (PrevDecl &&
(!AllowOverloadingOfFunction(PrevDecl, Context) ||
- !IsOverload(NewFD, PrevDecl, MatchedDecl))) {
+ !IsOverload(NewFD, PrevDecl, MatchedDecl)) &&
+ !isa<UsingDecl>(PrevDecl)) {
Redeclaration = true;
Decl *OldDecl = PrevDecl;
@@ -2708,8 +2733,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
IK_Default);
if (!Constructor)
Var->setInvalidDecl();
- else if (!RD->hasTrivialConstructor())
- InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+ else {
+ if (!RD->hasTrivialConstructor())
+ InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+ // Check for valid construction.
+ DefineImplicitDefaultConstructor(Var->getLocation(), Constructor);
+ }
}
}
@@ -2907,9 +2936,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (II)
IdResolver.AddDecl(New);
- ProcessDeclAttributes(New, D);
+ ProcessDeclAttributes(S, New, D);
- if (New->hasAttr<BlocksAttr>()) {
+ if (New->hasAttr<BlocksAttr>(Context)) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
}
return DeclPtrTy::make(New);
@@ -3035,9 +3064,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// Checking attributes of current function definition
// dllimport attribute.
- if (FD->getAttr<DLLImportAttr>() && (!FD->getAttr<DLLExportAttr>())) {
+ if (FD->getAttr<DLLImportAttr>(Context) &&
+ (!FD->getAttr<DLLExportAttr>(Context))) {
// dllimport attribute cannot be applied to definition.
- if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
+ if (!(FD->getAttr<DLLImportAttr>(Context))->isInherited()) {
Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport";
@@ -3065,10 +3095,23 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
Stmt *Body = BodyArg.takeAs<Stmt>();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
FD->setBody(Body);
+
+ if (!FD->isInvalidDecl())
+ DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+
+ // C++ [basic.def.odr]p2:
+ // [...] A virtual member function is used if it is not pure. [...]
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+ if (Method->isVirtual() && !Method->isPure())
+ MarkDeclarationReferenced(Method->getLocation(), Method);
+
assert(FD == getCurFunctionDecl() && "Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
+
+ if (!MD->isInvalidDecl())
+ DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
} else {
Body->Destroy(Context);
return DeclPtrTy();
@@ -3206,8 +3249,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
unsigned FormatIdx;
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1,
+ if (!FD->getAttr<FormatAttr>(Context))
+ FD->addAttr(Context,
+ ::new (Context) FormatAttr("printf", FormatIdx + 1,
HasVAListArg ? 0 : FormatIdx + 2));
}
@@ -3216,8 +3260,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// IRgen to use LLVM intrinsics for such functions.
if (!getLangOptions().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
- if (!FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr());
+ if (!FD->getAttr<ConstAttr>(Context))
+ FD->addAttr(Context, ::new (Context) ConstAttr());
}
}
@@ -3235,15 +3279,17 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
return;
if (Name->isStr("NSLog") || Name->isStr("NSLogv")) {
- if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) {
+ if (const FormatAttr *Format = FD->getAttr<FormatAttr>(Context)) {
// FIXME: We known better than our headers.
const_cast<FormatAttr *>(Format)->setType("printf");
} else
- FD->addAttr(::new (Context) FormatAttr("printf", 1,
+ FD->addAttr(Context,
+ ::new (Context) FormatAttr("printf", 1,
Name->isStr("NSLogv") ? 0 : 2));
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr("printf", 2,
+ if (!FD->getAttr<FormatAttr>(Context))
+ FD->addAttr(Context,
+ ::new (Context) FormatAttr("printf", 2,
Name->isStr("vasprintf") ? 0 : 3));
}
}
@@ -3599,7 +3645,7 @@ CreateNewDecl:
// the #pragma tokens are effectively skipped over during the
// parsing of the struct).
if (unsigned Alignment = getPragmaPackAlignment())
- New->addAttr(::new (Context) PackedAttr(Alignment * 8));
+ New->addAttr(Context, ::new (Context) PackedAttr(Alignment * 8));
}
if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) {
@@ -3628,7 +3674,7 @@ CreateNewDecl:
New->setInvalidDecl();
if (Attr)
- ProcessDeclAttributeList(New, Attr);
+ ProcessDeclAttributeList(S, New, Attr);
// If we're declaring or defining a tag in function prototype scope
// in C, note that this type can only be used within the function.
@@ -3786,6 +3832,14 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true);
+
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ }
+
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
PrevDecl = 0;
@@ -3878,7 +3932,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// FIXME: We need to pass in the attributes given an AST
// representation, not a parser representation.
if (D)
- ProcessDeclAttributes(NewFD, *D);
+ // FIXME: What to pass instead of TUScope?
+ ProcessDeclAttributes(TUScope, NewFD, *D);
if (T.isObjCGCWeak())
Diag(Loc, diag::warn_attribute_weak_on_field);
@@ -3985,7 +4040,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
}
// Process attributes attached to the ivar.
- ProcessDeclAttributes(NewID, D);
+ ProcessDeclAttributes(S, NewID, D);
if (D.isInvalidType())
NewID->setInvalidDecl();
@@ -4151,7 +4206,7 @@ void Sema::ActOnFields(Scope* S,
}
if (Attr)
- ProcessDeclAttributeList(Record, Attr);
+ ProcessDeclAttributeList(S, Record, Attr);
}
EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
@@ -4441,7 +4496,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
// FIXME: This implementation is an ugly hack!
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) WeakAttr());
+ PrevDecl->addAttr(Context, ::new (Context) WeakAttr());
return;
}
Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
@@ -4457,8 +4512,8 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
// FIXME: This implementation is an ugly hack!
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName()));
- PrevDecl->addAttr(::new (Context) WeakAttr());
+ PrevDecl->addAttr(Context, ::new (Context) AliasAttr(AliasName->getName()));
+ PrevDecl->addAttr(Context, ::new (Context) WeakAttr());
return;
}
Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1afdb60..d57630e 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -156,8 +156,8 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
// least add some helper functions to check most argument patterns (#
// and types of args).
-static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
- Sema &S) {
+static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
+ const AttributeList &Attr, Sema &S) {
TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
if (tDecl == 0) {
S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
@@ -165,37 +165,32 @@ static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
}
QualType curType = tDecl->getUnderlyingType();
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
- llvm::APSInt vecSize(32);
- if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "ext_vector_type" << sizeExpr->getSourceRange();
- return;
- }
- // unlike gcc's vector_size attribute, we do not allow vectors to be defined
- // in conjunction with complex types (pointers, arrays, functions, etc.).
- if (!curType->isIntegerType() && !curType->isRealFloatingType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << curType;
- return;
+
+ Expr *sizeExpr;
+
+ // Special case where the argument is a template id.
+ if (Attr.getParameterName()) {
+ sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(),
+ Attr.getParameterName(),
+ false, 0, false).takeAs<Expr>();
+ } else {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ sizeExpr = static_cast<Expr *>(Attr.getArg(0));
}
- // unlike gcc's vector_size attribute, the size is specified as the
- // number of elements, not the number of bytes.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
-
- if (vectorSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
- << sizeExpr->getSourceRange();
- return;
+
+ // Instantiate/Install the vector type, and let Sema build the type for us.
+ // This will run the reguired checks.
+ QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
+ if (!T.isNull()) {
+ tDecl->setUnderlyingType(T);
+
+ // Remember this typedef decl, we will need it later for diagnostics.
+ S.ExtVectorDecls.push_back(tDecl);
}
- // Instantiate/Install the vector type, the number of elements is > 0.
- tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
- // Remember this typedef decl, we will need it later for diagnostics.
- S.ExtVectorDecls.push_back(tDecl);
}
@@ -289,7 +284,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
if (TagDecl *TD = dyn_cast<TagDecl>(d))
- TD->addAttr(::new (S.Context) PackedAttr(1));
+ TD->addAttr(S.Context, ::new (S.Context) PackedAttr(1));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
// If the alignment is less than or equal to 8 bits, the packed attribute
// has no effect.
@@ -298,7 +293,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
<< Attr.getName() << FD->getType();
else
- FD->addAttr(::new (S.Context) PackedAttr(1));
+ FD->addAttr(S.Context, ::new (S.Context) PackedAttr(1));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -313,7 +308,7 @@ static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// The IBOutlet attribute only applies to instance variables of Objective-C
// classes.
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))
- d->addAttr(::new (S.Context) IBOutletAttr());
+ d->addAttr(S.Context, ::new (S.Context) IBOutletAttr());
else
S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet);
}
@@ -385,7 +380,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned* start = &NonNullArgs[0];
unsigned size = NonNullArgs.size();
std::sort(start, start + size);
- d->addAttr(::new (S.Context) NonNullAttr(start, size));
+ d->addAttr(S.Context, ::new (S.Context) NonNullAttr(start, size));
}
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -410,7 +405,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: check if target symbol exists in current file
- d->addAttr(::new (S.Context) AliasAttr(std::string(Alias, AliasLen)));
+ d->addAttr(S.Context, ::new (S.Context) AliasAttr(std::string(Alias, AliasLen)));
}
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
@@ -427,7 +422,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
return;
}
- d->addAttr(::new (S.Context) AlwaysInlineAttr());
+ d->addAttr(S.Context, ::new (S.Context) AlwaysInlineAttr());
}
static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
@@ -452,13 +447,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (HandleCommonNoReturnAttr(d, Attr, S))
- d->addAttr(::new (S.Context) NoReturnAttr());
+ d->addAttr(S.Context, ::new (S.Context) NoReturnAttr());
}
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
if (HandleCommonNoReturnAttr(d, Attr, S))
- d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
+ d->addAttr(S.Context, ::new (S.Context) AnalyzerNoReturnAttr());
}
static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -474,7 +469,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UnusedAttr());
+ d->addAttr(S.Context, ::new (S.Context) UnusedAttr());
}
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -495,7 +490,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UsedAttr());
+ d->addAttr(S.Context, ::new (S.Context) UsedAttr());
}
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -524,7 +519,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) ConstructorAttr(priority));
+ d->addAttr(S.Context, ::new (S.Context) ConstructorAttr(priority));
}
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -553,7 +548,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) DestructorAttr(priority));
+ d->addAttr(S.Context, ::new (S.Context) DestructorAttr(priority));
}
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -563,7 +558,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) DeprecatedAttr());
+ d->addAttr(S.Context, ::new (S.Context) DeprecatedAttr());
}
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -573,7 +568,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UnavailableAttr());
+ d->addAttr(S.Context, ::new (S.Context) UnavailableAttr());
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -610,7 +605,7 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) VisibilityAttr(type));
+ d->addAttr(S.Context, ::new (S.Context) VisibilityAttr(type));
}
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
@@ -626,7 +621,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
return;
}
- D->addAttr(::new (S.Context) ObjCExceptionAttr());
+ D->addAttr(S.Context, ::new (S.Context) ObjCExceptionAttr());
}
static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -642,7 +637,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
}
- D->addAttr(::new (S.Context) ObjCNSObjectAttr());
+ D->addAttr(S.Context, ::new (S.Context) ObjCNSObjectAttr());
}
static void
@@ -657,7 +652,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) OverloadableAttr());
+ D->addAttr(S.Context, ::new (S.Context) OverloadableAttr());
}
static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -681,7 +676,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) BlocksAttr(type));
+ d->addAttr(S.Context, ::new (S.Context) BlocksAttr(type));
}
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -773,7 +768,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
<< Attr.getName() << 6 /*function, method or block */;
return;
}
- d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
+ d->addAttr(S.Context, ::new (S.Context) SentinelAttr(sentinel, nullPos));
}
static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -791,7 +786,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
return;
}
- Fn->addAttr(::new (S.Context) WarnUnusedResultAttr());
+ Fn->addAttr(S.Context, ::new (S.Context) WarnUnusedResultAttr());
}
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -808,7 +803,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) WeakAttr());
+ D->addAttr(S.Context, ::new (S.Context) WeakAttr());
}
static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -841,7 +836,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) WeakImportAttr());
+ D->addAttr(S.Context, ::new (S.Context) WeakImportAttr());
}
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -853,7 +848,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLImportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLImportAttr());
return;
}
@@ -881,12 +876,12 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
}
- if (D->getAttr<DLLExportAttr>()) {
+ if (D->getAttr<DLLExportAttr>(S.Context)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
return;
}
- D->addAttr(::new (S.Context) DLLImportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLImportAttr());
}
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -898,7 +893,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLExportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLExportAttr());
return;
}
@@ -917,7 +912,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) DLLExportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLExportAttr());
}
static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -936,7 +931,8 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
return;
}
- D->addAttr(::new (S.Context) SectionAttr(std::string(SE->getStrData(),
+ D->addAttr(S.Context,
+ ::new (S.Context) SectionAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -955,13 +951,13 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
// stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<FastCallAttr>()) {
+ if (d->getAttr<FastCallAttr>(S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "stdcall" << "fastcall";
return;
}
- d->addAttr(::new (S.Context) StdCallAttr());
+ d->addAttr(S.Context, ::new (S.Context) StdCallAttr());
}
static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -978,13 +974,13 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
// stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<StdCallAttr>()) {
+ if (d->getAttr<StdCallAttr>(S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "fastcall" << "stdcall";
return;
}
- d->addAttr(::new (S.Context) FastCallAttr());
+ d->addAttr(S.Context, ::new (S.Context) FastCallAttr());
}
static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -994,7 +990,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoThrowAttr());
+ d->addAttr(S.Context, ::new (S.Context) NoThrowAttr());
}
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1004,7 +1000,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) ConstAttr());
+ d->addAttr(S.Context, ::new (S.Context) ConstAttr());
}
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1014,7 +1010,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) PureAttr());
+ d->addAttr(S.Context, ::new (S.Context) PureAttr());
}
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1072,7 +1068,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) CleanupAttr(FD));
+ d->addAttr(S.Context, ::new (S.Context) CleanupAttr(FD));
}
/// Handle __attribute__((format_arg((idx)))) attribute
@@ -1135,7 +1131,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
+ d->addAttr(S.Context, ::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
}
/// Handle __attribute__((format(type,idx,firstarg))) attributes
@@ -1276,7 +1272,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen),
+ d->addAttr(S.Context,
+ ::new (S.Context) FormatAttr(std::string(Format, FormatLen),
Idx.getZExtValue(), FirstArg.getZExtValue()));
}
@@ -1344,7 +1341,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
}
}
- RD->addAttr(::new (S.Context) TransparentUnionAttr());
+ RD->addAttr(S.Context, ::new (S.Context) TransparentUnionAttr());
}
static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1362,7 +1359,8 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
return;
}
- d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(),
+ d->addAttr(S.Context,
+ ::new (S.Context) AnnotateAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -1378,7 +1376,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: This should be the target specific maximum alignment.
// (For now we just use 128 bits which is the maximum on X86).
Align = 128;
- d->addAttr(::new (S.Context) AlignedAttr(Align));
+ d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Align));
return;
}
@@ -1395,7 +1393,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
+ d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
}
/// HandleModeAttr - This attribute modifies the width of a decl with
@@ -1576,7 +1574,7 @@ static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NodebugAttr());
+ d->addAttr(S.Context, ::new (S.Context) NodebugAttr());
}
static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1592,7 +1590,7 @@ static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoinlineAttr());
+ d->addAttr(S.Context, ::new (S.Context) NoinlineAttr());
}
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1614,7 +1612,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) GNUInlineAttr());
+ d->addAttr(S.Context, ::new (S.Context) GNUInlineAttr());
}
static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1650,7 +1648,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
+ d->addAttr(S.Context,
+ ::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
}
//===----------------------------------------------------------------------===//
@@ -1683,10 +1682,10 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
assert(0 && "invalid ownership attribute");
return;
case AttributeList::AT_cf_returns_retained:
- d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
+ d->addAttr(S.Context, ::new (S.Context) CFReturnsRetainedAttr());
return;
case AttributeList::AT_ns_returns_retained:
- d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
+ d->addAttr(S.Context, ::new (S.Context) NSReturnsRetainedAttr());
return;
};
}
@@ -1698,7 +1697,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
/// the attribute applies to decls. If the attribute is a type attribute, just
/// silently ignore it.
-static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
+static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) {
if (Attr.isDeclspecAttribute())
// FIXME: Try to deal with __declspec attributes!
return;
@@ -1721,7 +1720,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
case AttributeList::AT_ext_vector_type:
- HandleExtVectorTypeAttr(D, Attr, S);
+ HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
@@ -1777,9 +1776,9 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
/// attribute list to the specified decl, ignoring any type attributes.
-void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
+void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) {
while (AttrList) {
- ProcessDeclAttribute(D, *AttrList, *this);
+ ProcessDeclAttribute(S, D, *AttrList, *this);
AttrList = AttrList->getNext();
}
}
@@ -1787,10 +1786,10 @@ void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
/// it, apply them to D. This is a bit tricky because PD can have attributes
/// specified in many different places, and we need to find and apply them all.
-void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Apply decl attributes from the DeclSpec if present.
if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
- ProcessDeclAttributeList(D, Attrs);
+ ProcessDeclAttributeList(S, D, Attrs);
// Walk the declarator structure, applying decl attributes that were in a type
// position to the decl itself. This handles cases like:
@@ -1798,9 +1797,9 @@ void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
// when X is a decl attribute.
for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
- ProcessDeclAttributeList(D, Attrs);
+ ProcessDeclAttributeList(S, D, Attrs);
// Finally, apply any attributes on the decl itself.
if (const AttributeList *Attrs = PD.getAttributes())
- ProcessDeclAttributeList(D, Attrs);
+ ProcessDeclAttributeList(S, D, Attrs);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8f64e78..6d740eb 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -147,8 +147,11 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
return;
}
+ DefaultArgPtr = MaybeCreateCXXExprWithTemporaries(DefaultArg.take(),
+ /*DestroyTemps=*/false);
+
// Okay: add the default argument to the parameter
- Param->setDefaultArg(DefaultArg.take());
+ Param->setDefaultArg(DefaultArgPtr);
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
@@ -1031,9 +1034,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
ClassDecl->addDecl(Context, DefaultCon);
-
- // Notify the class that we've added a constructor.
- ClassDecl->addedConstructor(Context, DefaultCon);
}
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
@@ -1110,8 +1110,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*IdentifierInfo=*/0,
ArgType, VarDecl::None, 0);
CopyConstructor->setParams(Context, &FromParam, 1);
-
- ClassDecl->addedConstructor(Context, CopyConstructor);
ClassDecl->addDecl(Context, CopyConstructor);
}
@@ -1750,6 +1748,43 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
S->PushUsingDirective(DeclPtrTy::make(UDir));
}
+
+Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName) {
+ assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+ assert(TargetName && "Invalid TargetName.");
+ assert(IdentLoc.isValid() && "Invalid TargetName location.");
+ assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+ UsingDecl *UsingAlias = 0;
+
+ // Lookup target name.
+ LookupResult R = LookupParsedName(S, &SS, TargetName,
+ LookupOrdinaryName, false);
+
+ if (NamedDecl *NS = R) {
+ if (IsTypeName && !isa<TypeDecl>(NS)) {
+ Diag(IdentLoc, diag::err_using_typename_non_type);
+ }
+ UsingAlias = UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
+ NS->getLocation(), UsingLoc, NS,
+ static_cast<NestedNameSpecifier *>(SS.getScopeRep()),
+ IsTypeName);
+ PushOnScopeChains(UsingAlias, S);
+ } else {
+ Diag(IdentLoc, diag::err_using_requires_qualname) << SS.getRange();
+ }
+
+ // FIXME: We ignore attributes for now.
+ delete AttrList;
+ return DeclPtrTy::make(UsingAlias);
+}
+
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
/// is a namespace alias, returns the namespace it points to.
static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
@@ -1795,7 +1830,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
return DeclPtrTy();
}
- NamespaceAliasDecl *AliasDecl =
+ NamespaceAliasDecl *AliasDecl =
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
Alias, SS.getRange(),
(NestedNameSpecifier *)SS.getScopeRep(),
@@ -1805,6 +1840,81 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
return DeclPtrTy::make(AliasDecl);
}
+void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor) {
+ if (!Constructor->isDefaultConstructor() ||
+ !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined())
+ return;
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(Constructor->getDeclContext());
+ assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
+ // Before the implicitly-declared default constructor for a class is
+ // implicitly defined, all the implicitly-declared default constructors
+ // for its base class and its non-static data members shall have been
+ // implicitly defined.
+ bool err = false;
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ if (!BaseClassDecl->hasTrivialConstructor()) {
+ if (CXXConstructorDecl *BaseCtor =
+ BaseClassDecl->getDefaultConstructor(Context)) {
+ if (BaseCtor->isImplicit())
+ BaseCtor->setImplicitMustBeDefined();
+ }
+ else {
+ Diag(CurrentLocation, diag::err_defining_default_ctor)
+ << Context.getTagDeclType(ClassDecl) << 1
+ << Context.getTagDeclType(BaseClassDecl);
+ Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(BaseClassDecl);
+ err = true;
+ }
+ }
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+ Field != ClassDecl->field_end(Context);
+ ++Field) {
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasTrivialConstructor())
+ if (CXXConstructorDecl *FieldCtor =
+ FieldClassDecl->getDefaultConstructor(Context)) {
+ if (FieldCtor->isImplicit())
+ FieldCtor->setImplicitMustBeDefined();
+ }
+ else {
+ Diag(CurrentLocation, diag::err_defining_default_ctor)
+ << Context.getTagDeclType(ClassDecl) << 0 <<
+ Context.getTagDeclType(FieldClassDecl);
+ Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(FieldClassDecl);
+ err = true;
+ }
+ }
+ else if (FieldType->isReferenceType()) {
+ Diag(CurrentLocation, diag::err_unintialized_member)
+ << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ err = true;
+ }
+ else if (FieldType.isConstQualified()) {
+ Diag(CurrentLocation, diag::err_unintialized_member)
+ << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ err = true;
+ }
+ }
+ if (!err)
+ Constructor->setImplicitMustBeDefined();
+}
+
void Sema::InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
QualType DeclInitType,
@@ -1880,6 +1990,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
VDecl->setCXXDirectInitializer(true);
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
(Expr**)Exprs.release(), NumExprs);
+ // An implicitly-declared default constructor for a class is implicitly
+ // defined when it is used to creat an object of its class type.
+ DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor);
}
return;
}
@@ -1956,7 +2069,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType,
// constructors, we'll need to make them appear here.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Loc, Best)) {
case OR_Success:
// We found a constructor. Return it.
return cast<CXXConstructorDecl>(Best->Function);
@@ -2188,7 +2301,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) {
case OR_Success:
// This is a direct binding.
BindsDirectly = true;
@@ -2668,7 +2781,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
else
CurContext->addDecl(Context, ExDecl);
- ProcessDeclAttributes(ExDecl, D);
+ ProcessDeclAttributes(S, ExDecl, D);
return DeclPtrTy::make(ExDecl);
}
@@ -2830,3 +2943,46 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return false;
}
+
+/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+/// initializer for the declaration 'Dcl'.
+/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+/// static data member of class X, names should be looked up in the scope of
+/// class X.
+void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+ Decl *D = Dcl.getAs<Decl>();
+ // If there is no declaration, there was an error parsing it.
+ if (D == 0)
+ return;
+
+ // Check whether it is a declaration with a nested name specifier like
+ // int foo::bar;
+ if (!D->isOutOfLine())
+ return;
+
+ // C++ [basic.lookup.unqual]p13
+ //
+ // A name used in the definition of a static data member of class X
+ // (after the qualified-id of the static member) is looked up as if the name
+ // was used in a member function of X.
+
+ // Change current context into the context of the initializing declaration.
+ EnterDeclaratorContext(S, D->getDeclContext());
+}
+
+/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+/// initializer for the declaration 'Dcl'.
+void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+ Decl *D = Dcl.getAs<Decl>();
+ // If there is no declaration, there was an error parsing it.
+ if (D == 0)
+ return;
+
+ // Check whether it is a declaration with a nested name specifier like
+ // int foo::bar;
+ if (!D->isOutOfLine())
+ return;
+
+ assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
+ ExitDeclaratorContext(S);
+}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 5d47516..9013726 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -116,7 +116,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
ClassName, ClassLoc);
if (AttrList)
- ProcessDeclAttributeList(IDecl, AttrList);
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
PushOnScopeChains(IDecl, TUScope);
}
@@ -282,7 +282,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PDecl->setForwardDecl(false);
}
if (AttrList)
- ProcessDeclAttributeList(PDecl, AttrList);
+ ProcessDeclAttributeList(TUScope, PDecl, AttrList);
if (NumProtoRefs) {
/// Check then save referenced protocols.
PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context);
@@ -532,7 +532,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
PushOnScopeChains(PDecl, TUScope);
}
if (attrList)
- ProcessDeclAttributeList(PDecl, attrList);
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
Protocols.push_back(PDecl);
}
@@ -1663,7 +1663,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));
// Apply the attributes to the parameter.
- ProcessDeclAttributeList(Param, ArgInfo[i].ArgAttrs);
+ ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
Params.push_back(Param);
}
@@ -1674,7 +1674,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
const ObjCMethodDecl *PrevMethod = 0;
if (AttrList)
- ProcessDeclAttributeList(ObjCMethod, AttrList);
+ ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
// For implementations (which can be very "coarse grain"), we add the
// method now. This allows the AST to implement lookup methods that work
@@ -1877,7 +1877,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
PDecl->setInvalidDecl();
}
- ProcessDeclAttributes(PDecl, FD.D);
+ ProcessDeclAttributes(S, PDecl, FD.D);
// Regardless of setter/getter attribute, we save the default getter/setter
// selector names in anticipation of declaration of setter/getter methods.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c01c812..692502b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -39,7 +39,7 @@ using namespace clang;
/// referenced), false otherwise.
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is deprecated.
- if (D->getAttr<DeprecatedAttr>()) {
+ if (D->getAttr<DeprecatedAttr>(Context)) {
// Implementing deprecated stuff requires referencing deprecated
// stuff. Don't warn if we are implementing a deprecated
// construct.
@@ -48,7 +48,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
if (NamedDecl *ND = getCurFunctionOrMethodDecl()) {
// If this reference happens *in* a deprecated function or method, don't
// warn.
- isSilenced = ND->getAttr<DeprecatedAttr>();
+ isSilenced = ND->getAttr<DeprecatedAttr>(Context);
// If this is an Objective-C method implementation, check to see if the
// method was deprecated on the declaration, not the definition.
@@ -61,7 +61,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
MD = Impl->getClassInterface()->getMethod(Context,
MD->getSelector(),
MD->isInstanceMethod());
- isSilenced |= MD && MD->getAttr<DeprecatedAttr>();
+ isSilenced |= MD && MD->getAttr<DeprecatedAttr>(Context);
}
}
}
@@ -80,7 +80,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
}
// See if the decl is unavailable
- if (D->getAttr<UnavailableAttr>()) {
+ if (D->getAttr<UnavailableAttr>(Context)) {
Diag(Loc, diag::warn_unavailable) << D->getDeclName();
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
}
@@ -95,7 +95,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs)
{
- const SentinelAttr *attr = D->getAttr<SentinelAttr>();
+ const SentinelAttr *attr = D->getAttr<SentinelAttr>(Context);
if (!attr)
return;
int sentinelPos = attr->getSentinel();
@@ -627,6 +627,7 @@ DeclRefExpr *
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
const CXXScopeSpec *SS) {
+ MarkDeclarationReferenced(Loc, D);
if (SS && !SS->isEmpty()) {
return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
ValueDependent, SS->getRange(),
@@ -721,6 +722,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// BaseObject is an anonymous struct/union variable (and is,
// therefore, not part of another non-anonymous record).
if (BaseObjectExpr) BaseObjectExpr->Destroy(Context);
+ MarkDeclarationReferenced(Loc, BaseObject);
BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
SourceLocation());
ExtraQuals
@@ -777,6 +779,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
= MemberType.getCVRQualifiers() | ExtraQuals;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
+ MarkDeclarationReferenced(Loc, *FI);
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
OpLoc, MemberType);
BaseObjectIsPointer = false;
@@ -876,6 +879,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
+ MarkDeclarationReferenced(Loc, IV);
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
SelfExpr.takeAs<Expr>(), true, true));
@@ -1025,6 +1029,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// Build the implicit member access expression.
Expr *This = new (Context) CXXThisExpr(SourceLocation(),
MD->getThisType(Context));
+ MarkDeclarationReferenced(Loc, D);
return Owned(new (Context) MemberExpr(This, true, D,
Loc, MemberType));
}
@@ -1125,14 +1130,18 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// as they do not get snapshotted.
//
if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
+ MarkDeclarationReferenced(Loc, VD);
QualType ExprTy = VD->getType().getNonReferenceType();
// The BlocksAttr indicates the variable is bound by-reference.
- if (VD->getAttr<BlocksAttr>())
+ if (VD->getAttr<BlocksAttr>(Context))
return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true));
-
+ // This is to record that a 'const' was actually synthesize and added.
+ bool constAdded = !ExprTy.isConstQualified();
// Variable will be bound by-copy, make it const within the closure.
+
ExprTy.addConst();
- return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false));
+ return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false,
+ constAdded));
}
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
@@ -1576,7 +1585,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -1686,7 +1695,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, LLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -1969,13 +1978,13 @@ static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
return 0;
}
-static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy,
+static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy,
IdentifierInfo &Member,
const Selector &Sel,
ASTContext &Context) {
// Check protocols on qualified interfaces.
Decl *GDecl = 0;
- for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Context, &Member)) {
GDecl = PD;
@@ -1988,7 +1997,7 @@ static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy,
}
}
if (!GDecl) {
- for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
// Search in the protocol-qualifier list of current protocol.
GDecl = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context);
@@ -2313,7 +2322,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
<< &Member << BaseType);
}
// Handle properties on qualified "id" protocols.
- const ObjCQualifiedIdType *QIdTy;
+ const ObjCObjectPointerType *QIdTy;
if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
// Check protocols on qualified interfaces.
Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
@@ -2491,8 +2500,21 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FDecl << cast<CXXRecordDecl>(FDecl->getDeclContext())->getDeclName();
Diag(UnparsedDefaultArgLocs[FDecl->getParamDecl(i)],
diag::note_default_argument_declared_here);
+ } else {
+ Expr *DefaultExpr = FDecl->getParamDecl(i)->getDefaultArg();
+
+ // If the default expression creates temporaries, we need to
+ // push them to the current stack of expression temporaries so they'll
+ // be properly destroyed.
+ if (CXXExprWithTemporaries *E
+ = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) {
+ assert(!E->shouldDestroyTemporaries() &&
+ "Can't destroy temporaries in a default argument expr!");
+ for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I)
+ ExprTemporaries.push_back(E->getTemporary(I));
+ }
}
-
+
// We already type-checked the argument, so we know it works.
Arg = new (Context) CXXDefaultArgExpr(FDecl->getParamDecl(i));
}
@@ -3395,7 +3417,7 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
// If the ArgType is a Union type, we want to handle a potential
// transparent_union GCC extension.
const RecordType *UT = ArgType->getAsUnionType();
- if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>(Context))
return Incompatible;
// The field to initialize within the transparent union.
@@ -5098,7 +5120,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
BSI->PrevBlockInfo = CurBlock;
CurBlock = BSI;
- BSI->ReturnType = 0;
+ BSI->ReturnType = QualType();
BSI->TheScope = BlockScope;
BSI->hasBlockDeclRefExprs = false;
BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking;
@@ -5113,7 +5135,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
if (ParamInfo.getNumTypeObjects() == 0
|| ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) {
- ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo);
+ ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
if (T->isArrayType()) {
@@ -5129,7 +5151,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
CurBlock->hasPrototype = true;
CurBlock->isVariadic = false;
// Check for a valid sentinel attribute on this block.
- if (CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ if (CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) {
Diag(ParamInfo.getAttributes()->getLoc(),
diag::warn_attribute_sentinel_not_variadic) << 1;
// FIXME: remove the attribute.
@@ -5169,7 +5191,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(),
CurBlock->Params.size());
CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
- ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo);
+ ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
E = CurBlock->TheDecl->param_end(); AI != E; ++AI)
// If this has an identifier, add it to the scope stack.
@@ -5177,7 +5199,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
PushOnScopeChains(*AI, CurBlock->TheScope);
// Check for a valid sentinel attribute on this block.
- if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ if (!CurBlock->isVariadic &&
+ CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) {
Diag(ParamInfo.getAttributes()->getLoc(),
diag::warn_attribute_sentinel_not_variadic) << 1;
// FIXME: remove the attribute.
@@ -5192,7 +5215,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
Diag(ParamInfo.getSourceRange().getBegin(),
diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
} else if (!RetTy->isDependentType())
- CurBlock->ReturnType = RetTy.getTypePtr();
+ CurBlock->ReturnType = RetTy;
}
/// ActOnBlockError - If there is an error parsing a block, this callback
@@ -5226,8 +5249,8 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
CurBlock = CurBlock->PrevBlockInfo;
QualType RetTy = Context.VoidTy;
- if (BSI->ReturnType)
- RetTy = QualType(BSI->ReturnType, 0);
+ if (!BSI->ReturnType.isNull())
+ RetTy = BSI->ReturnType;
llvm::SmallVector<QualType, 8> ArgTypes;
for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
@@ -5241,7 +5264,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BSI->isVariadic, 0);
// FIXME: Check that return/parameter types are complete/non-abstract
-
+ DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end());
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
@@ -5408,3 +5431,49 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
*Result = EvalResult.Val.getInt();
return false;
}
+
+
+/// \brief Note that the given declaration was referenced in the source code.
+///
+/// This routine should be invoke whenever a given declaration is referenced
+/// in the source code, and where that reference occurred. If this declaration
+/// reference means that the the declaration is used (C++ [basic.def.odr]p2,
+/// C99 6.9p3), then the declaration will be marked as used.
+///
+/// \param Loc the location where the declaration was referenced.
+///
+/// \param D the declaration that has been referenced by the source code.
+void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
+ assert(D && "No declaration?");
+
+ // Mark a parameter declaration "used", regardless of whether we're in a
+ // template or not.
+ if (isa<ParmVarDecl>(D))
+ D->setUsed(true);
+
+ // Do not mark anything as "used" within a dependent context; wait for
+ // an instantiation.
+ if (CurContext->isDependentContext())
+ return;
+
+ // If we are in an unevaluated operand, don't mark any definitions as used.
+ if (InUnevaluatedOperand)
+ return;
+
+ // Note that this declaration has been used.
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ // FIXME: implicit template instantiation
+ // FIXME: keep track of references to static functions
+ (void)Function;
+ Function->setUsed(true);
+ return;
+ }
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ (void)Var;
+ // FIXME: implicit template instantiation
+ // FIXME: keep track of references to static data?
+ D->setUsed(true);
+ }
+}
+
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ed4ac55..bec595c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -546,7 +546,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// Do the resolution.
OverloadCandidateSet::iterator Best;
- switch(BestViableFunction(Candidates, Best)) {
+ switch(BestViableFunction(Candidates, StartLoc, Best)) {
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
@@ -1175,7 +1175,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
Self.AddBuiltinOperatorCandidates(OO_Conditional, Args, 2, CandidateSet);
OverloadCandidateSet::iterator Best;
- switch (Self.BestViableFunction(CandidateSet, Best)) {
+ switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
case Sema::OR_Success:
// We found a match. Perform the conversions on the arguments and move on.
if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
@@ -1589,7 +1589,7 @@ Expr *Sema::RemoveOutermostTemporaryBinding(Expr *E) {
}
Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool DestroyTemps) {
+ bool ShouldDestroyTemps) {
assert(SubExpr && "sub expression can't be null!");
if (ExprTemporaries.empty())
@@ -1598,7 +1598,7 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr,
&ExprTemporaries[0],
ExprTemporaries.size(),
- DestroyTemps);
+ ShouldDestroyTemps);
ExprTemporaries.clear();
return E;
@@ -1607,7 +1607,8 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)
- FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr);
+ FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr,
+ /*ShouldDestroyTemps=*/true);
return Owned(FullExpr);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b6cf9d8..f1869f9 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -130,6 +130,14 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation SelLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
+ ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc));
+ if (!Method)
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc));
+ if (!Method)
+ Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+
QualType Ty = Context.getObjCSelType();
return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
}
@@ -582,9 +590,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
// long as one of the protocols implements the selector (if not, warn).
- if (ObjCQualifiedIdType *QIdTy = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) {
+ if (const ObjCObjectPointerType *QIdTy =
+ ReceiverCType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
- for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
ObjCProtocolDecl *PDecl = *I;
if (PDecl && (Method = PDecl->lookupInstanceMethod(Context, Sel)))
@@ -746,8 +755,8 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return true;
}
- if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
- const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
+ if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
+ const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
const ObjCQualifiedInterfaceType *rhsQI = 0;
QualType rtype;
@@ -762,7 +771,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// make sure we check the class hierarchy.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
- for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
E = lhsQID->qual_end(); I != E; ++I) {
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
@@ -775,7 +784,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
}
}
- ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
+ ObjCObjectPointerType::qual_iterator RHSProtoI, RHSProtoE;
if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *").
RHSProtoI = rhsQI->qual_begin();
RHSProtoE = rhsQI->qual_end();
@@ -786,7 +795,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return false;
}
- for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
E = lhsQID->qual_end(); I != E; ++I) {
ObjCProtocolDecl *lhsProto = *I;
bool match = false;
@@ -807,7 +816,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// make sure we check the class hierarchy.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
- for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
E = lhsQID->qual_end(); I != E; ++I) {
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
@@ -826,7 +835,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return true;
}
- const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
+ const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
assert(rhsQID && "One of the LHS/RHS should be id<x>");
if (!lhs->isPointerType())
@@ -835,12 +844,12 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
QualType ltype = lhs->getAsPointerType()->getPointeeType();
if (const ObjCQualifiedInterfaceType *lhsQI =
ltype->getAsObjCQualifiedInterfaceType()) {
- ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin();
- ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end();
+ ObjCObjectPointerType::qual_iterator LHSProtoI = lhsQI->qual_begin();
+ ObjCObjectPointerType::qual_iterator LHSProtoE = lhsQI->qual_end();
for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
bool match = false;
ObjCProtocolDecl *lhsProto = *LHSProtoI;
- for (ObjCQualifiedIdType::qual_iterator I = rhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
E = rhsQID->qual_end(); I != E; ++I) {
ObjCProtocolDecl *rhsProto = *I;
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
@@ -859,7 +868,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// for static type vs. qualified 'id' type, check that class implements
// all of 'id's protocols.
ObjCInterfaceDecl *lhsID = IT->getDecl();
- for (ObjCQualifiedIdType::qual_iterator I = rhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
E = rhsQID->qual_end(); I != E; ++I) {
if (!ClassImplementsProtocol(*I, lhsID, compare, true))
return false;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 1d26845..37e1df3 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -685,7 +685,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name,
// identifier chain.
if (isa<RecordDecl>(Ctx)) {
R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly);
- if (R || RedeclarationOnly)
+ if (R)
return std::make_pair(true, R);
}
if (Ctx->getParent() != Ctx->getLexicalParent()
@@ -697,7 +697,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name,
for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext();
OutOfLineCtx = OutOfLineCtx->getParent()) {
R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly);
- if (R || RedeclarationOnly)
+ if (R)
return std::make_pair(true, R);
}
}
@@ -894,7 +894,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
continue;
}
- if ((*I)->getAttr<OverloadableAttr>()) {
+ if ((*I)->getAttr<OverloadableAttr>(Context)) {
// If this declaration has the "overloadable" attribute, we
// might have a set of overloaded functions.
@@ -1151,8 +1151,10 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
Name, NameKind, RedeclarationOnly);
}
- return LookupName(S, Name, NameKind, RedeclarationOnly,
- AllowBuiltinCreation, Loc);
+ LookupResult result(LookupName(S, Name, NameKind, RedeclarationOnly,
+ AllowBuiltinCreation, Loc));
+
+ return(result);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 98ee13a..11cd510 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1379,7 +1379,7 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) {
case OR_Success:
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
@@ -3445,14 +3445,21 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
return false;
}
-/// BestViableFunction - Computes the best viable function (C++ 13.3.3)
-/// within an overload candidate set. If overloading is successful,
-/// the result will be OR_Success and Best will be set to point to the
-/// best viable function within the candidate set. Otherwise, one of
-/// several kinds of errors will be returned; see
-/// Sema::OverloadingResult.
+/// \brief Computes the best viable function (C++ 13.3.3)
+/// within an overload candidate set.
+///
+/// \param CandidateSet the set of candidate functions.
+///
+/// \param Loc the location of the function name (or operator symbol) for
+/// which overload resolution occurs.
+///
+/// \param Best f overload resolution was successful or found a deleted
+/// function, Best points to the candidate function found.
+///
+/// \returns The result of overload resolution.
Sema::OverloadingResult
Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
+ SourceLocation Loc,
OverloadCandidateSet::iterator& Best)
{
// Find the best viable function.
@@ -3484,12 +3491,17 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
// Best is the best viable function.
if (Best->Function &&
(Best->Function->isDeleted() ||
- Best->Function->getAttr<UnavailableAttr>()))
+ Best->Function->getAttr<UnavailableAttr>(Context)))
return OR_Deleted;
- // If Best refers to a function that is either deleted (C++0x) or
- // unavailable (Clang extension) report an error.
-
+ // C++ [basic.def.odr]p2:
+ // An overloaded function is used if it is selected by overload resolution
+ // when referred to from a potentially-evaluated expression. [Note: this
+ // covers calls to named functions (5.2.2), operator overloading
+ // (clause 13), user-defined conversions (12.3.2), allocation function for
+ // placement new (5.3.4), as well as non-default initialization (8.5).
+ if (Best->Function)
+ MarkDeclarationReferenced(Loc, Best->Function);
return OR_Success;
}
@@ -3506,7 +3518,7 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
if (Cand->Viable || !OnlyViable) {
if (Cand->Function) {
if (Cand->Function->isDeleted() ||
- Cand->Function->getAttr<UnavailableAttr>()) {
+ Cand->Function->getAttr<UnavailableAttr>(Context)) {
// Deleted or "unavailable" function.
Diag(Cand->Function->getLocation(), diag::err_ovl_candidate_deleted)
<< Cand->Function->isDeleted();
@@ -3709,7 +3721,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
CandidateSet);
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
case OR_Success:
return Best->Function;
@@ -3815,7 +3827,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -3968,7 +3980,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -4094,7 +4106,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
break;
@@ -4219,7 +4231,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the appropriate call
// below.
@@ -4388,7 +4400,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the call below.
break;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index aa9b8db..914839c 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -84,7 +84,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
SourceLocation Loc;
SourceRange R1, R2;
- if (!E->isUnusedResultAWarning(Loc, R1, R2))
+ if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
continue;
Diag(Loc, diag::warn_unused_expr) << R1 << R2;
@@ -748,18 +748,25 @@ Action::OwningStmtResult
Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If this is the first return we've seen in the block, infer the type of
// the block from it.
- if (CurBlock->ReturnType == 0) {
+ if (CurBlock->ReturnType.isNull()) {
if (RetValExp) {
// Don't call UsualUnaryConversions(), since we don't want to do
// integer promotions here.
DefaultFunctionArrayConversion(RetValExp);
- CurBlock->ReturnType = RetValExp->getType().getTypePtr();
+ CurBlock->ReturnType = RetValExp->getType();
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
+ // We have to remove a 'const' added to copied-in variable which was
+ // part of the implementation spec. and not the actual qualifier for
+ // the variable.
+ if (CDRE->isConstQualAdded())
+ CurBlock->ReturnType.removeConst();
+ }
} else
- CurBlock->ReturnType = Context.VoidTy.getTypePtr();
+ CurBlock->ReturnType = Context.VoidTy;
}
- QualType FnRetType = QualType(CurBlock->ReturnType, 0);
+ QualType FnRetType = CurBlock->ReturnType;
- if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) {
+ if (CurBlock->TheDecl->hasAttr<NoReturnAttr>(Context)) {
Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
<< getCurFunctionOrMethodDecl()->getDeclName();
return StmtError();
@@ -835,7 +842,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, FullExprArg rex) {
QualType FnRetType;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
FnRetType = FD->getResultType();
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->hasAttr<NoReturnAttr>(Context))
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< getCurFunctionOrMethodDecl()->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl())
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index b2a82ed..fb41b2b 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -444,6 +444,9 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
if (Previous.begin() != Previous.end())
PrevDecl = *Previous.begin();
+ if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
+ PrevDecl = 0;
+
DeclContext *SemanticContext = CurContext;
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS);
@@ -548,7 +551,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
NewClass->startDefinition();
if (Attr)
- ProcessDeclAttributeList(NewClass, Attr);
+ ProcessDeclAttributeList(S, NewClass, Attr);
PushOnScopeChains(NewTemplate, S);
@@ -806,6 +809,10 @@ static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs,
Canonical.push_back(TemplateArgument(SourceLocation(), CanonType));
break;
}
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
}
@@ -846,7 +853,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ConvertedTemplateArgs))
return QualType();
- assert((ConvertedTemplateArgs.size() ==
+ assert((ConvertedTemplateArgs.structuredSize() ==
Template->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -1207,6 +1214,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr);
Diag((*Param)->getLocation(), diag::note_template_param_here);
Invalid = true;
+ break;
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
} else {
// Check template template parameters.
@@ -1251,6 +1263,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Integral:
assert(false && "Integral argument with template template parameter");
break;
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
}
@@ -2288,7 +2304,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
RAngleLoc, ConvertedTemplateArgs))
return true;
- assert((ConvertedTemplateArgs.size() ==
+ assert((ConvertedTemplateArgs.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -2549,7 +2565,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
RAngleLoc, ConvertedTemplateArgs))
return true;
- assert((ConvertedTemplateArgs.size() ==
+ assert((ConvertedTemplateArgs.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 84d802d..784e451 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -46,16 +46,22 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(ASTContext &Context,
NonTypeTemplateParmDecl *NTTP,
- llvm::APInt Value,
+ llvm::APSInt Value,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
if (Deduced[NTTP->getIndex()].isNull()) {
- Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(),
- llvm::APSInt(Value),
- NTTP->getType());
+ QualType T = NTTP->getType();
+
+ // FIXME: Make sure we didn't overflow our data type!
+ unsigned AllowedBits = Context.getTypeSize(T);
+ if (Value.getBitWidth() != AllowedBits)
+ Value.extOrTrunc(AllowedBits);
+ Value.setIsSigned(T->isSignedIntegerType());
+
+ Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T);
return Sema::TDK_Success;
}
@@ -64,18 +70,14 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
// If the template argument was previously deduced to a negative value,
// then our deduction fails.
const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
- if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative()) {
- // FIXME: This is wacky; we should be dealing with APSInts and
- // checking the actual signs.
+ if (PrevValuePtr->isNegative()) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(SourceLocation(),
- llvm::APSInt(Value),
- NTTP->getType());
+ Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
return Sema::TDK_Inconsistent;
}
- llvm::APInt PrevValue = *PrevValuePtr;
+ llvm::APSInt PrevValue = *PrevValuePtr;
if (Value.getBitWidth() > PrevValue.getBitWidth())
PrevValue.zext(Value.getBitWidth());
else if (Value.getBitWidth() < PrevValue.getBitWidth())
@@ -84,9 +86,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
if (Value != PrevValue) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(SourceLocation(),
- llvm::APSInt(Value),
- NTTP->getType());
+ Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
return Sema::TDK_Inconsistent;
}
@@ -329,10 +329,11 @@ DeduceTemplateArguments(ASTContext &Context,
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument at depth > 0");
if (const ConstantArrayType *ConstantArrayArg
- = dyn_cast<ConstantArrayType>(ArrayArg))
- return DeduceNonTypeTemplateArgument(Context, NTTP,
- ConstantArrayArg->getSize(),
+ = dyn_cast<ConstantArrayType>(ArrayArg)) {
+ llvm::APSInt Size(ConstantArrayArg->getSize());
+ return DeduceNonTypeTemplateArgument(Context, NTTP, Size,
Info, Deduced);
+ }
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
return DeduceNonTypeTemplateArgument(Context, NTTP,
@@ -597,6 +598,9 @@ DeduceTemplateArguments(ASTContext &Context,
// Can't deduce anything, but that's okay.
return Sema::TDK_Success;
}
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
return Sema::TDK_Success;
@@ -674,35 +678,6 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
/*FlattenArgs=*/true);
Info.reset(DeducedArgumentList);
- // Now that we have all of the deduced template arguments, take
- // another pass through them to convert any integral template
- // arguments to the appropriate type.
- for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
- TemplateArgument &Arg = Deduced[I];
- if (Arg.getKind() == TemplateArgument::Integral) {
- const NonTypeTemplateParmDecl *Parm
- = cast<NonTypeTemplateParmDecl>(Partial->getTemplateParameters()
- ->getParam(I));
- QualType T = InstantiateType(Parm->getType(), *DeducedArgumentList,
- Parm->getLocation(), Parm->getDeclName());
- if (T.isNull()) {
- Info.Param = const_cast<NonTypeTemplateParmDecl*>(Parm);
- Info.FirstArg = TemplateArgument(Parm->getLocation(), Parm->getType());
- return TDK_SubstitutionFailure;
- }
-
- // FIXME: Make sure we didn't overflow our data type!
- llvm::APSInt &Value = *Arg.getAsIntegral();
- unsigned AllowedBits = Context.getTypeSize(T);
- if (Value.getBitWidth() != AllowedBits)
- Value.extOrTrunc(AllowedBits);
- Value.setIsSigned(T->isSignedIntegerType());
- Arg.setIntegralType(T);
- }
-
- (*DeducedArgumentList)[I] = Arg;
- }
-
// Substitute the deduced template arguments into the template
// arguments of the class template partial specialization, and
// verify that the instantiated template arguments are both valid
@@ -750,12 +725,13 @@ MarkDeducedTemplateParameters(Sema &SemaRef,
/// \brief Mark the template arguments that are deduced by the given
/// expression.
static void
-MarkDeducedTemplateParameters(Expr *E, llvm::SmallVectorImpl<bool> &Deduced) {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+MarkDeducedTemplateParameters(const Expr *E,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!E)
return;
- NonTypeTemplateParmDecl *NTTP
+ const NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
if (!NTTP)
return;
@@ -776,26 +752,26 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
switch (T->getTypeClass()) {
case Type::ExtQual:
MarkDeducedTemplateParameters(SemaRef,
- QualType(cast<ExtQualType>(T.getTypePtr())->getBaseType(), 0),
+ QualType(cast<ExtQualType>(T)->getBaseType(), 0),
Deduced);
break;
case Type::Pointer:
MarkDeducedTemplateParameters(SemaRef,
- cast<PointerType>(T.getTypePtr())->getPointeeType(),
+ cast<PointerType>(T)->getPointeeType(),
Deduced);
break;
case Type::BlockPointer:
MarkDeducedTemplateParameters(SemaRef,
- cast<BlockPointerType>(T.getTypePtr())->getPointeeType(),
+ cast<BlockPointerType>(T)->getPointeeType(),
Deduced);
break;
case Type::LValueReference:
case Type::RValueReference:
MarkDeducedTemplateParameters(SemaRef,
- cast<ReferenceType>(T.getTypePtr())->getPointeeType(),
+ cast<ReferenceType>(T)->getPointeeType(),
Deduced);
break;
@@ -808,27 +784,34 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
}
case Type::DependentSizedArray:
- MarkDeducedTemplateParameters(
- cast<DependentSizedArrayType>(T.getTypePtr())->getSizeExpr(),
+ MarkDeducedTemplateParameters(cast<DependentSizedArrayType>(T)->getSizeExpr(),
Deduced);
// Fall through to check the element type
case Type::ConstantArray:
case Type::IncompleteArray:
MarkDeducedTemplateParameters(SemaRef,
- cast<ArrayType>(T.getTypePtr())->getElementType(),
+ cast<ArrayType>(T)->getElementType(),
Deduced);
break;
case Type::Vector:
case Type::ExtVector:
MarkDeducedTemplateParameters(SemaRef,
- cast<VectorType>(T.getTypePtr())->getElementType(),
+ cast<VectorType>(T)->getElementType(),
Deduced);
break;
+ case Type::DependentSizedExtVector: {
+ const DependentSizedExtVectorType *VecType
+ = cast<DependentSizedExtVectorType>(T);
+ MarkDeducedTemplateParameters(SemaRef, VecType->getElementType(), Deduced);
+ MarkDeducedTemplateParameters(VecType->getSizeExpr(), Deduced);
+ break;
+ }
+
case Type::FunctionProto: {
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T.getTypePtr());
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced);
for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced);
@@ -836,12 +819,12 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
}
case Type::TemplateTypeParm:
- Deduced[cast<TemplateTypeParmType>(T.getTypePtr())->getIndex()] = true;
+ Deduced[cast<TemplateTypeParmType>(T)->getIndex()] = true;
break;
case Type::TemplateSpecialization: {
const TemplateSpecializationType *Spec
- = cast<TemplateSpecializationType>(T.getTypePtr());
+ = cast<TemplateSpecializationType>(T);
if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl())
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Template))
@@ -864,7 +847,7 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
case Type::Typename:
case Type::ObjCInterface:
case Type::ObjCQualifiedInterface:
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
@@ -898,6 +881,9 @@ MarkDeducedTemplateParameters(Sema &SemaRef,
case TemplateArgument::Expression:
MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced);
break;
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 18b2d75a..3992f8c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -431,6 +431,32 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
}
QualType
+TemplateTypeInstantiator::
+InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
+ unsigned Quals) const {
+
+ // Instantiate the element type if needed.
+ QualType ElementType = T->getElementType();
+ if (ElementType->isDependentType()) {
+ ElementType = Instantiate(ElementType);
+ if (ElementType.isNull())
+ return QualType();
+ }
+
+ // Instantiate the size expression.
+ const Expr *SizeExpr = T->getSizeExpr();
+ Sema::OwningExprResult InstantiatedArraySize =
+ SemaRef.InstantiateExpr(const_cast<Expr *>(SizeExpr), TemplateArgs);
+ if (InstantiatedArraySize.isInvalid())
+ return QualType();
+
+ return SemaRef.BuildExtVectorType(ElementType,
+ SemaRef.Owned(
+ InstantiatedArraySize.takeAs<Expr>()),
+ T->getAttributeLoc());
+}
+
+QualType
TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
unsigned Quals) const {
// FIXME: Implement this
@@ -564,6 +590,7 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
// parameter with the template "level" reduced by one.
return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
T->getIndex(),
+ T->isParameterPack(),
T->getName())
.getQualifiedType(Quals);
}
@@ -630,24 +657,24 @@ InstantiateTypenameType(const TypenameType *T, unsigned Quals) const {
QualType
TemplateTypeInstantiator::
-InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
- unsigned Quals) const {
+InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T,
+ unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
-QualType
+QualType
TemplateTypeInstantiator::
-InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
- unsigned Quals) const {
+InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
+ unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
QualType
TemplateTypeInstantiator::
-InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T,
- unsigned Quals) const {
+InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
+ unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
@@ -1153,6 +1180,10 @@ TemplateArgument Sema::Instantiate(TemplateArgument Arg,
return TemplateArgument();
return TemplateArgument(E.takeAs<Expr>());
}
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
assert(false && "Unhandled template argument kind");
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 3c67f2a..bf19701 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -1165,7 +1165,10 @@ TemplateExprInstantiator::VisitCXXExprWithTemporaries(
if (SubExpr.isInvalid())
return SemaRef.ExprError();
- return SemaRef.ActOnFinishFullExpr(move(SubExpr));
+ Expr *Temp =
+ SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(),
+ E->shouldDestroyTemporaries());
+ return SemaRef.Owned(Temp);
}
Sema::OwningExprResult
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 70a9270..967f650 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -543,6 +543,48 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return T;
}
+
+/// \brief Build an ext-vector type.
+///
+/// Run the required checks for the extended vector type.
+QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
+ SourceLocation AttrLoc) {
+
+ Expr *Arg = (Expr *)ArraySize.get();
+
+ // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+ // in conjunction with complex types (pointers, arrays, functions, etc.).
+ if (!T->isDependentType() &&
+ !T->isIntegerType() && !T->isRealFloatingType()) {
+ Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
+ return QualType();
+ }
+
+ if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ llvm::APSInt vecSize(32);
+ if (!Arg->isIntegerConstantExpr(vecSize, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_not_int)
+ << "ext_vector_type" << Arg->getSourceRange();
+ return QualType();
+ }
+
+ // unlike gcc's vector_size attribute, the size is specified as the
+ // number of elements, not the number of bytes.
+ unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
+
+ if (vectorSize == 0) {
+ Diag(AttrLoc, diag::err_attribute_zero_size)
+ << Arg->getSourceRange();
+ return QualType();
+ }
+
+ if (!T->isDependentType())
+ return Context.getExtVectorType(T, vectorSize);
+ }
+
+ return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(),
+ AttrLoc);
+}
/// \brief Build a function type.
///
OpenPOWER on IntegriCloud