summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-05-03 16:53:59 +0000
committerdim <dim@FreeBSD.org>2012-05-03 16:53:59 +0000
commit822bde9df508e0b9afac5e581b0d6ab403417a28 (patch)
tree2e51705e103e92c7be1b21e8bd8ffd5b5d0e4d52 /lib
parent50b73317314e889cf39c7b1d6cbf419fa7502f22 (diff)
downloadFreeBSD-src-822bde9df508e0b9afac5e581b0d6ab403417a28.zip
FreeBSD-src-822bde9df508e0b9afac5e581b0d6ab403417a28.tar.gz
Vendor import of clang release_31 branch r155985:
http://llvm.org/svn/llvm-project/cfe/branches/release_31@155985
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp5
-rw-r--r--lib/AST/Decl.cpp117
-rw-r--r--lib/AST/Expr.cpp335
-rw-r--r--lib/AST/ExprConstant.cpp56
-rw-r--r--lib/AST/ExternalASTSource.cpp5
-rw-r--r--lib/AST/ItaniumMangle.cpp23
-rw-r--r--lib/AST/Stmt.cpp6
-rw-r--r--lib/AST/StmtPrinter.cpp17
-rw-r--r--lib/AST/StmtProfile.cpp6
-rw-r--r--lib/AST/Type.cpp10
-rw-r--r--lib/AST/VTableBuilder.cpp9
-rw-r--r--lib/Analysis/CFG.cpp9
-rw-r--r--lib/Analysis/CMakeLists.txt2
-rw-r--r--lib/Basic/TargetInfo.cpp1
-rw-r--r--lib/Basic/Targets.cpp7
-rw-r--r--lib/Basic/Version.cpp2
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/CodeGen/CGBlocks.cpp2
-rw-r--r--lib/CodeGen/CGCall.cpp132
-rw-r--r--lib/CodeGen/CGClass.cpp13
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp16
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/CodeGen/CGExpr.cpp115
-rw-r--r--lib/CodeGen/CGExprAgg.cpp34
-rw-r--r--lib/CodeGen/CGExprCXX.cpp5
-rw-r--r--lib/CodeGen/CGExprConstant.cpp8
-rw-r--r--lib/CodeGen/CGStmt.cpp7
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp11
-rw-r--r--lib/CodeGen/CodeGenFunction.h11
-rw-r--r--lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp36
-rw-r--r--lib/CodeGen/CodeGenTBAA.h8
-rw-r--r--lib/CodeGen/TargetInfo.cpp24
-rw-r--r--lib/Driver/Compilation.cpp4
-rw-r--r--lib/Driver/Driver.cpp52
-rw-r--r--lib/Driver/ToolChains.cpp7
-rw-r--r--lib/Driver/Tools.cpp10
-rw-r--r--lib/Frontend/ASTUnit.cpp6
-rw-r--r--lib/Frontend/CompilerInstance.cpp4
-rw-r--r--lib/Frontend/CompilerInvocation.cpp3
-rw-r--r--lib/Frontend/FrontendActions.cpp72
-rw-r--r--lib/Frontend/TextDiagnostic.cpp607
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp1
-rw-r--r--lib/Headers/avx2intrin.h14
-rw-r--r--lib/Headers/avxintrin.h26
-rw-r--r--lib/Index/ASTLocation.cpp114
-rw-r--r--lib/Index/ASTVisitor.h143
-rw-r--r--lib/Index/Analyzer.cpp470
-rw-r--r--lib/Index/CMakeLists.txt18
-rw-r--r--lib/Index/DeclReferenceMap.cpp90
-rw-r--r--lib/Index/Entity.cpp270
-rw-r--r--lib/Index/EntityImpl.h71
-rw-r--r--lib/Index/GlobalCallGraph.cpp152
-rw-r--r--lib/Index/GlobalSelector.cpp71
-rw-r--r--lib/Index/Handlers.cpp22
-rw-r--r--lib/Index/IndexProvider.cpp20
-rw-r--r--lib/Index/Indexer.cpp121
-rw-r--r--lib/Index/Makefile18
-rw-r--r--lib/Index/Program.cpp50
-rw-r--r--lib/Index/ProgramImpl.h56
-rw-r--r--lib/Index/SelectorMap.cpp84
-rwxr-xr-xlib/Makefile2
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp94
-rw-r--r--lib/Parse/ParseDecl.cpp54
-rw-r--r--lib/Parse/ParseDeclCXX.cpp103
-rw-r--r--lib/Parse/ParseExpr.cpp6
-rw-r--r--lib/Parse/ParseExprCXX.cpp17
-rw-r--r--lib/Parse/ParseStmt.cpp181
-rw-r--r--lib/Parse/ParseTemplate.cpp3
-rw-r--r--lib/Parse/Parser.cpp28
-rw-r--r--lib/Rewrite/RewriteModernObjC.cpp158
-rw-r--r--lib/Rewrite/RewriteRope.cpp5
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/DeclSpec.cpp5
-rw-r--r--lib/Sema/Sema.cpp1
-rw-r--r--lib/Sema/SemaAccess.cpp7
-rw-r--r--lib/Sema/SemaDecl.cpp26
-rw-r--r--lib/Sema/SemaDeclCXX.cpp341
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp359
-rw-r--r--lib/Sema/SemaExpr.cpp33
-rw-r--r--lib/Sema/SemaExprCXX.cpp73
-rw-r--r--lib/Sema/SemaExprMember.cpp17
-rw-r--r--lib/Sema/SemaLookup.cpp45
-rw-r--r--lib/Sema/SemaOverload.cpp2
-rw-r--r--lib/Sema/SemaPseudoObject.cpp28
-rw-r--r--lib/Sema/SemaStmt.cpp11
-rw-r--r--lib/Sema/SemaStmtAttr.cpp48
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp49
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp101
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp363
-rw-r--r--lib/Sema/SemaType.cpp51
-rw-r--r--lib/Sema/TreeTransform.h66
-rw-r--r--lib/Serialization/ASTReader.cpp144
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp9
-rw-r--r--lib/Serialization/ASTReaderInternals.h10
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp15
-rw-r--r--lib/Serialization/ASTWriter.cpp1
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp3
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp8
-rw-r--r--lib/Serialization/Module.cpp3
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp25
-rw-r--r--lib/StaticAnalyzer/Core/AnalysisManager.cpp24
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp5
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp1
-rw-r--r--lib/Tooling/CompilationDatabase.cpp108
108 files changed, 2861 insertions, 3394 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index acf5e0b..cb4d336 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -481,7 +481,8 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
// Builtin type for __objc_yes and __objc_no
- ObjCBuiltinBoolTy = SignedCharTy;
+ ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
+ SignedCharTy : BoolTy);
ObjCConstantStringType = QualType();
@@ -2193,6 +2194,8 @@ ASTContext::getFunctionType(QualType ResultTy,
Size += EPI.NumExceptions * sizeof(QualType);
else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
Size += sizeof(Expr*);
+ } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
+ Size += 2 * sizeof(FunctionDecl*);
}
if (EPI.ConsumedArguments)
Size += NumArgs * sizeof(bool);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 399f2e4..53032bc 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -69,33 +69,25 @@ typedef NamedDecl::LinkageInfo LinkageInfo;
namespace {
/// Flags controlling the computation of linkage and visibility.
struct LVFlags {
- bool ConsiderGlobalVisibility;
- bool ConsiderVisibilityAttributes;
- bool ConsiderTemplateParameterTypes;
+ const bool ConsiderGlobalVisibility;
+ const bool ConsiderVisibilityAttributes;
+ const bool ConsiderTemplateParameterTypes;
LVFlags() : ConsiderGlobalVisibility(true),
ConsiderVisibilityAttributes(true),
ConsiderTemplateParameterTypes(true) {
}
+ LVFlags(bool Global, bool Attributes, bool Parameters) :
+ ConsiderGlobalVisibility(Global),
+ ConsiderVisibilityAttributes(Attributes),
+ ConsiderTemplateParameterTypes(Parameters) {
+ }
+
/// \brief Returns a set of flags that is only useful for computing the
/// linkage, not the visibility, of a declaration.
static LVFlags CreateOnlyDeclLinkage() {
- LVFlags F;
- F.ConsiderGlobalVisibility = false;
- F.ConsiderVisibilityAttributes = false;
- F.ConsiderTemplateParameterTypes = false;
- return F;
- }
-
- /// Returns a set of flags, otherwise based on these, which ignores
- /// off all sources of visibility except template arguments.
- LVFlags onlyTemplateVisibility() const {
- LVFlags F = *this;
- F.ConsiderGlobalVisibility = false;
- F.ConsiderVisibilityAttributes = false;
- F.ConsiderTemplateParameterTypes = false;
- return F;
+ return LVFlags(false, false, false);
}
};
} // end anonymous namespace
@@ -284,7 +276,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (F.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
LV.setVisibility(*Vis, true);
- F.ConsiderGlobalVisibility = false;
} else {
// If we're declared in a namespace with a visibility attribute,
// use that namespace's visibility, but don't call it explicit.
@@ -295,7 +286,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (!ND) continue;
if (llvm::Optional<Visibility> Vis = ND->getExplicitVisibility()) {
LV.setVisibility(*Vis, true);
- F.ConsiderGlobalVisibility = false;
break;
}
}
@@ -335,8 +325,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
LinkageInfo TypeLV = getLVForType(Var->getType());
if (TypeLV.linkage() != ExternalLinkage)
return LinkageInfo::uniqueExternal();
- LV.mergeVisibilityWithMin(TypeLV.visibility(),
- TypeLV.visibilityExplicit());
+ LV.mergeVisibilityWithMin(TypeLV);
}
if (Var->getStorageClass() == SC_PrivateExtern)
@@ -412,7 +401,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
= Function->getTemplateSpecializationInfo()) {
if (shouldConsiderTemplateLV(Function, specInfo)) {
LV.merge(getLVForDecl(specInfo->getTemplate(),
- F.onlyTemplateVisibility()));
+ LVFlags::CreateOnlyDeclLinkage()));
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
LV.mergeWithMin(getLVForTemplateArgumentList(templateArgs, F));
}
@@ -436,7 +425,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (shouldConsiderTemplateLV(spec)) {
// From the template.
LV.merge(getLVForDecl(spec->getSpecializedTemplate(),
- F.onlyTemplateVisibility()));
+ LVFlags::CreateOnlyDeclLinkage()));
// The arguments at which the template was instantiated.
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
@@ -444,12 +433,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
}
}
- // Consider -fvisibility unless the type has C linkage.
- if (F.ConsiderGlobalVisibility)
- F.ConsiderGlobalVisibility =
- (Context.getLangOpts().CPlusPlus &&
- !Tag->getDeclContext()->isExternCContext());
-
// - an enumerator belonging to an enumeration with external linkage;
} else if (isa<EnumConstantDecl>(D)) {
LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), F);
@@ -501,21 +484,46 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
LinkageInfo LV;
LV.mergeVisibility(D->getASTContext().getLangOpts().getVisibilityMode());
- // The flags we're going to use to compute the class's visibility.
- LVFlags ClassF = F;
-
+ bool DHasExplicitVisibility = false;
// If we have an explicit visibility attribute, merge that in.
if (F.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
LV.mergeVisibility(*Vis, true);
- // Ignore global visibility later, but not this attribute.
- F.ConsiderGlobalVisibility = false;
+ DHasExplicitVisibility = true;
+ }
+ }
+ // Ignore both global visibility and attributes when computing our
+ // parent's visibility if we already have an explicit one.
+ LVFlags ClassF = DHasExplicitVisibility ?
+ LVFlags::CreateOnlyDeclLinkage() : F;
- // Ignore both global visibility and attributes when computing our
- // parent's visibility.
- ClassF = F.onlyTemplateVisibility();
+ // If we're paying attention to global visibility, apply
+ // -finline-visibility-hidden if this is an inline method.
+ //
+ // Note that we do this before merging information about
+ // the class visibility.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ TemplateSpecializationKind TSK = TSK_Undeclared;
+ if (FunctionTemplateSpecializationInfo *spec
+ = MD->getTemplateSpecializationInfo()) {
+ TSK = spec->getTemplateSpecializationKind();
+ } else if (MemberSpecializationInfo *MSI =
+ MD->getMemberSpecializationInfo()) {
+ TSK = MSI->getTemplateSpecializationKind();
}
+
+ const FunctionDecl *Def = 0;
+ // InlineVisibilityHidden only applies to definitions, and
+ // isInlined() only gives meaningful answers on definitions
+ // anyway.
+ if (TSK != TSK_ExplicitInstantiationDeclaration &&
+ TSK != TSK_ExplicitInstantiationDefinition &&
+ F.ConsiderGlobalVisibility &&
+ !LV.visibilityExplicit() &&
+ MD->getASTContext().getLangOpts().InlineVisibilityHidden &&
+ MD->hasBody(Def) && Def->isInlined())
+ LV.mergeVisibility(HiddenVisibility, true);
}
// Class members only have linkage if their class has external
@@ -534,8 +542,6 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
if (MD->getType()->getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
- TemplateSpecializationKind TSK = TSK_Undeclared;
-
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *spec
@@ -547,29 +553,6 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
LV.merge(getLVForTemplateParameterList(
spec->getTemplate()->getTemplateParameters()));
}
-
- TSK = spec->getTemplateSpecializationKind();
- } else if (MemberSpecializationInfo *MSI =
- MD->getMemberSpecializationInfo()) {
- TSK = MSI->getTemplateSpecializationKind();
- }
-
- // If we're paying attention to global visibility, apply
- // -finline-visibility-hidden if this is an inline method.
- //
- // Note that ConsiderGlobalVisibility doesn't yet have information
- // about whether containing classes have visibility attributes,
- // and that's intentional.
- if (TSK != TSK_ExplicitInstantiationDeclaration &&
- TSK != TSK_ExplicitInstantiationDefinition &&
- F.ConsiderGlobalVisibility &&
- MD->getASTContext().getLangOpts().InlineVisibilityHidden) {
- // InlineVisibilityHidden only applies to definitions, and
- // isInlined() only gives meaningful answers on definitions
- // anyway.
- const FunctionDecl *Def = 0;
- if (MD->hasBody(Def) && Def->isInlined())
- LV.setVisibility(HiddenVisibility);
}
// Note that in contrast to basically every other situation, we
@@ -597,7 +580,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
if (TypeLV.linkage() != ExternalLinkage)
LV.mergeLinkage(UniqueExternalLinkage);
if (!LV.visibilityExplicit())
- LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit());
+ LV.mergeVisibility(TypeLV);
}
return LV;
@@ -802,7 +785,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LinkageInfo LV;
if (Flags.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = Function->getExplicitVisibility())
- LV.setVisibility(*Vis);
+ LV.setVisibility(*Vis, true);
}
if (const FunctionDecl *Prev = Function->getPreviousDecl()) {
@@ -823,10 +806,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LinkageInfo LV;
if (Var->getStorageClass() == SC_PrivateExtern)
- LV.setVisibility(HiddenVisibility);
+ LV.setVisibility(HiddenVisibility, true);
else if (Flags.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = Var->getExplicitVisibility())
- LV.setVisibility(*Vis);
+ LV.setVisibility(*Vis, true);
}
if (const VarDecl *Prev = Var->getPreviousDecl()) {
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 868109e..fcde542 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1590,6 +1590,16 @@ void InitListExpr::setArrayFiller(Expr *filler) {
inits[i] = filler;
}
+bool InitListExpr::isStringLiteralInit() const {
+ if (getNumInits() != 1)
+ return false;
+ const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(getType());
+ if (!CAT || !CAT->getElementType()->isIntegerType())
+ return false;
+ const Expr *Init = getInit(0)->IgnoreParenImpCasts();
+ return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
+}
+
SourceRange InitListExpr::getSourceRange() const {
if (SyntacticForm)
return SyntacticForm->getSourceRange();
@@ -1986,331 +1996,6 @@ QualType Expr::findBoundMemberType(const Expr *expr) {
return QualType();
}
-static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1,
- Expr::CanThrowResult CT2) {
- // CanThrowResult constants are ordered so that the maximum is the correct
- // merge result.
- return CT1 > CT2 ? CT1 : CT2;
-}
-
-static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) {
- Expr *E = const_cast<Expr*>(CE);
- Expr::CanThrowResult R = Expr::CT_Cannot;
- for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I) {
- R = MergeCanThrow(R, cast<Expr>(*I)->CanThrow(C));
- }
- return R;
-}
-
-static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Expr *E,
- const Decl *D,
- bool NullThrows = true) {
- if (!D)
- return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
-
- // See if we can get a function type from the decl somehow.
- const ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (!VD) // If we have no clue what we're calling, assume the worst.
- return Expr::CT_Can;
-
- // As an extension, we assume that __attribute__((nothrow)) functions don't
- // throw.
- if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
- return Expr::CT_Cannot;
-
- QualType T = VD->getType();
- const FunctionProtoType *FT;
- if ((FT = T->getAs<FunctionProtoType>())) {
- } else if (const PointerType *PT = T->getAs<PointerType>())
- FT = PT->getPointeeType()->getAs<FunctionProtoType>();
- else if (const ReferenceType *RT = T->getAs<ReferenceType>())
- FT = RT->getPointeeType()->getAs<FunctionProtoType>();
- else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
- FT = MT->getPointeeType()->getAs<FunctionProtoType>();
- else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
- FT = BT->getPointeeType()->getAs<FunctionProtoType>();
-
- if (!FT)
- return Expr::CT_Can;
-
- if (FT->getExceptionSpecType() == EST_Delayed) {
- assert(isa<CXXConstructorDecl>(D) &&
- "only constructor exception specs can be unknown");
- Ctx.getDiagnostics().Report(E->getLocStart(),
- diag::err_exception_spec_unknown)
- << E->getSourceRange();
- return Expr::CT_Can;
- }
-
- return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can;
-}
-
-static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) {
- if (DC->isTypeDependent())
- return Expr::CT_Dependent;
-
- if (!DC->getTypeAsWritten()->isReferenceType())
- return Expr::CT_Cannot;
-
- if (DC->getSubExpr()->isTypeDependent())
- return Expr::CT_Dependent;
-
- return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot;
-}
-
-static Expr::CanThrowResult CanTypeidThrow(ASTContext &C,
- const CXXTypeidExpr *DC) {
- if (DC->isTypeOperand())
- return Expr::CT_Cannot;
-
- Expr *Op = DC->getExprOperand();
- if (Op->isTypeDependent())
- return Expr::CT_Dependent;
-
- const RecordType *RT = Op->getType()->getAs<RecordType>();
- if (!RT)
- return Expr::CT_Cannot;
-
- if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
- return Expr::CT_Cannot;
-
- if (Op->Classify(C).isPRValue())
- return Expr::CT_Cannot;
-
- return Expr::CT_Can;
-}
-
-Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
- // C++ [expr.unary.noexcept]p3:
- // [Can throw] if in a potentially-evaluated context the expression would
- // contain:
- switch (getStmtClass()) {
- case CXXThrowExprClass:
- // - a potentially evaluated throw-expression
- return CT_Can;
-
- case CXXDynamicCastExprClass: {
- // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
- // where T is a reference type, that requires a run-time check
- CanThrowResult CT = CanDynamicCastThrow(cast<CXXDynamicCastExpr>(this));
- if (CT == CT_Can)
- return CT;
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- case CXXTypeidExprClass:
- // - a potentially evaluated typeid expression applied to a glvalue
- // expression whose type is a polymorphic class type
- return CanTypeidThrow(C, cast<CXXTypeidExpr>(this));
-
- // - a potentially evaluated call to a function, member function, function
- // pointer, or member function pointer that does not have a non-throwing
- // exception-specification
- case CallExprClass:
- case CXXMemberCallExprClass:
- case CXXOperatorCallExprClass:
- case UserDefinedLiteralClass: {
- const CallExpr *CE = cast<CallExpr>(this);
- CanThrowResult CT;
- if (isTypeDependent())
- CT = CT_Dependent;
- else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
- CT = CT_Cannot;
- else
- CT = CanCalleeThrow(C, this, CE->getCalleeDecl());
- if (CT == CT_Can)
- return CT;
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- case CXXConstructExprClass:
- case CXXTemporaryObjectExprClass: {
- CanThrowResult CT = CanCalleeThrow(C, this,
- cast<CXXConstructExpr>(this)->getConstructor());
- if (CT == CT_Can)
- return CT;
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- case LambdaExprClass: {
- const LambdaExpr *Lambda = cast<LambdaExpr>(this);
- CanThrowResult CT = Expr::CT_Cannot;
- for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
- CapEnd = Lambda->capture_init_end();
- Cap != CapEnd; ++Cap)
- CT = MergeCanThrow(CT, (*Cap)->CanThrow(C));
- return CT;
- }
-
- case CXXNewExprClass: {
- CanThrowResult CT;
- if (isTypeDependent())
- CT = CT_Dependent;
- else
- CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew());
- if (CT == CT_Can)
- return CT;
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- case CXXDeleteExprClass: {
- CanThrowResult CT;
- QualType DTy = cast<CXXDeleteExpr>(this)->getDestroyedType();
- if (DTy.isNull() || DTy->isDependentType()) {
- CT = CT_Dependent;
- } else {
- CT = CanCalleeThrow(C, this,
- cast<CXXDeleteExpr>(this)->getOperatorDelete());
- if (const RecordType *RT = DTy->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- CT = MergeCanThrow(CT, CanCalleeThrow(C, this, RD->getDestructor()));
- }
- if (CT == CT_Can)
- return CT;
- }
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- case CXXBindTemporaryExprClass: {
- // The bound temporary has to be destroyed again, which might throw.
- CanThrowResult CT = CanCalleeThrow(C, this,
- cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
- if (CT == CT_Can)
- return CT;
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- // ObjC message sends are like function calls, but never have exception
- // specs.
- case ObjCMessageExprClass:
- case ObjCPropertyRefExprClass:
- case ObjCSubscriptRefExprClass:
- return CT_Can;
-
- // All the ObjC literals that are implemented as calls are
- // potentially throwing unless we decide to close off that
- // possibility.
- case ObjCArrayLiteralClass:
- case ObjCDictionaryLiteralClass:
- case ObjCNumericLiteralClass:
- return CT_Can;
-
- // Many other things have subexpressions, so we have to test those.
- // Some are simple:
- case ConditionalOperatorClass:
- case CompoundLiteralExprClass:
- case CXXConstCastExprClass:
- case CXXDefaultArgExprClass:
- case CXXReinterpretCastExprClass:
- case DesignatedInitExprClass:
- case ExprWithCleanupsClass:
- case ExtVectorElementExprClass:
- case InitListExprClass:
- case MemberExprClass:
- case ObjCIsaExprClass:
- case ObjCIvarRefExprClass:
- case ParenExprClass:
- case ParenListExprClass:
- case ShuffleVectorExprClass:
- case VAArgExprClass:
- return CanSubExprsThrow(C, this);
-
- // Some might be dependent for other reasons.
- case ArraySubscriptExprClass:
- case BinaryOperatorClass:
- case CompoundAssignOperatorClass:
- case CStyleCastExprClass:
- case CXXStaticCastExprClass:
- case CXXFunctionalCastExprClass:
- case ImplicitCastExprClass:
- case MaterializeTemporaryExprClass:
- case UnaryOperatorClass: {
- CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot;
- return MergeCanThrow(CT, CanSubExprsThrow(C, this));
- }
-
- // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms.
- case StmtExprClass:
- return CT_Can;
-
- case ChooseExprClass:
- if (isTypeDependent() || isValueDependent())
- return CT_Dependent;
- return cast<ChooseExpr>(this)->getChosenSubExpr(C)->CanThrow(C);
-
- case GenericSelectionExprClass:
- if (cast<GenericSelectionExpr>(this)->isResultDependent())
- return CT_Dependent;
- return cast<GenericSelectionExpr>(this)->getResultExpr()->CanThrow(C);
-
- // Some expressions are always dependent.
- case CXXDependentScopeMemberExprClass:
- case CXXUnresolvedConstructExprClass:
- case DependentScopeDeclRefExprClass:
- return CT_Dependent;
-
- case AtomicExprClass:
- case AsTypeExprClass:
- case BinaryConditionalOperatorClass:
- case BlockExprClass:
- case CUDAKernelCallExprClass:
- case DeclRefExprClass:
- case ObjCBridgedCastExprClass:
- case ObjCIndirectCopyRestoreExprClass:
- case ObjCProtocolExprClass:
- case ObjCSelectorExprClass:
- case OffsetOfExprClass:
- case PackExpansionExprClass:
- case PseudoObjectExprClass:
- case SubstNonTypeTemplateParmExprClass:
- case SubstNonTypeTemplateParmPackExprClass:
- case UnaryExprOrTypeTraitExprClass:
- case UnresolvedLookupExprClass:
- case UnresolvedMemberExprClass:
- // FIXME: Can any of the above throw? If so, when?
- return CT_Cannot;
-
- case AddrLabelExprClass:
- case ArrayTypeTraitExprClass:
- case BinaryTypeTraitExprClass:
- case TypeTraitExprClass:
- case CXXBoolLiteralExprClass:
- case CXXNoexceptExprClass:
- case CXXNullPtrLiteralExprClass:
- case CXXPseudoDestructorExprClass:
- case CXXScalarValueInitExprClass:
- case CXXThisExprClass:
- case CXXUuidofExprClass:
- case CharacterLiteralClass:
- case ExpressionTraitExprClass:
- case FloatingLiteralClass:
- case GNUNullExprClass:
- case ImaginaryLiteralClass:
- case ImplicitValueInitExprClass:
- case IntegerLiteralClass:
- case ObjCEncodeExprClass:
- case ObjCStringLiteralClass:
- case ObjCBoolLiteralExprClass:
- case OpaqueValueExprClass:
- case PredefinedExprClass:
- case SizeOfPackExprClass:
- case StringLiteralClass:
- case UnaryTypeTraitExprClass:
- // These expressions can never throw.
- return CT_Cannot;
-
-#define STMT(CLASS, PARENT) case CLASS##Class:
-#define STMT_RANGE(Base, First, Last)
-#define LAST_STMT_RANGE(BASE, FIRST, LAST)
-#define EXPR(CLASS, PARENT)
-#define ABSTRACT_STMT(STMT)
-#include "clang/AST/StmtNodes.inc"
- case NoStmtClass:
- llvm_unreachable("Invalid class for expression");
- }
- llvm_unreachable("Bogus StmtClass");
-}
-
Expr* Expr::IgnoreParens() {
Expr* E = this;
while (true) {
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 01c9fe7..66a88b0 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -934,6 +934,7 @@ static bool IsGlobalLValue(APValue::LValueBase B) {
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::CXXTypeidExprClass:
+ case Expr::CXXUuidofExprClass:
return true;
case Expr::CallExprClass:
return IsStringLiteralCall(cast<CallExpr>(E));
@@ -1491,15 +1492,19 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,
llvm_unreachable("base class missing from derived class's bases list");
}
-/// Extract the value of a character from a string literal.
+/// Extract the value of a character from a string literal. CharType is used to
+/// determine the expected signedness of the result -- a string literal used to
+/// initialize an array of 'signed char' or 'unsigned char' might contain chars
+/// of the wrong signedness.
static APSInt ExtractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
- uint64_t Index) {
+ uint64_t Index, QualType CharType) {
// FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
const StringLiteral *S = dyn_cast<StringLiteral>(Lit);
assert(S && "unexpected string literal expression kind");
+ assert(CharType->isIntegerType() && "unexpected character type");
APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(),
- Lit->getType()->getArrayElementTypeNoTypeQual()->isUnsignedIntegerType());
+ CharType->isUnsignedIntegerType());
if (Index < S->getLength())
Value = S->getCodeUnit(Index);
return Value;
@@ -1546,7 +1551,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
assert(I == N - 1 && "extracting subobject of character?");
assert(!O->hasLValuePath() || O->getLValuePath().empty());
Obj = APValue(ExtractStringLiteralCharacter(
- Info, O->getLValueBase().get<const Expr*>(), Index));
+ Info, O->getLValueBase().get<const Expr*>(), Index, SubType));
return true;
} else if (O->getArrayInitializedElts() > Index)
O = &O->getArrayInitializedElt(Index);
@@ -2868,6 +2873,7 @@ public:
bool VisitStringLiteral(const StringLiteral *E) { return Success(E); }
bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); }
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
+ bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
bool VisitUnaryDeref(const UnaryOperator *E);
bool VisitUnaryReal(const UnaryOperator *E);
@@ -2973,6 +2979,10 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
return Success(E);
}
+bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
+ return Success(E);
+}
+
bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
// Handle static data members.
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) {
@@ -3849,8 +3859,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...]
// an appropriately-typed string literal enclosed in braces.
- if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() &&
- Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) {
+ if (E->isStringLiteralInit()) {
LValue LV;
if (!EvaluateLValue(E->getInit(0), LV, Info))
return false;
@@ -5079,14 +5088,37 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
}
+ // The comparison here must be unsigned, and performed with the same
+ // width as the pointer.
+ unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy);
+ uint64_t CompareLHS = LHSOffset.getQuantity();
+ uint64_t CompareRHS = RHSOffset.getQuantity();
+ assert(PtrSize <= 64 && "Unexpected pointer width");
+ uint64_t Mask = ~0ULL >> (64 - PtrSize);
+ CompareLHS &= Mask;
+ CompareRHS &= Mask;
+
+ // If there is a base and this is a relational operator, we can only
+ // compare pointers within the object in question; otherwise, the result
+ // depends on where the object is located in memory.
+ if (!LHSValue.Base.isNull() && E->isRelationalOp()) {
+ QualType BaseTy = getType(LHSValue.Base);
+ if (BaseTy->isIncompleteType())
+ return Error(E);
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
+ uint64_t OffsetLimit = Size.getQuantity();
+ if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit)
+ return Error(E);
+ }
+
switch (E->getOpcode()) {
default: llvm_unreachable("missing comparison operator");
- case BO_LT: return Success(LHSOffset < RHSOffset, E);
- case BO_GT: return Success(LHSOffset > RHSOffset, E);
- case BO_LE: return Success(LHSOffset <= RHSOffset, E);
- case BO_GE: return Success(LHSOffset >= RHSOffset, E);
- case BO_EQ: return Success(LHSOffset == RHSOffset, E);
- case BO_NE: return Success(LHSOffset != RHSOffset, E);
+ case BO_LT: return Success(CompareLHS < CompareRHS, E);
+ case BO_GT: return Success(CompareLHS > CompareRHS, E);
+ case BO_LE: return Success(CompareLHS <= CompareRHS, E);
+ case BO_GE: return Success(CompareLHS >= CompareRHS, E);
+ case BO_EQ: return Success(CompareLHS == CompareRHS, E);
+ case BO_NE: return Success(CompareLHS != CompareRHS, E);
}
}
}
diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp
index fd616db..6b9fe26 100644
--- a/lib/AST/ExternalASTSource.cpp
+++ b/lib/AST/ExternalASTSource.cpp
@@ -49,7 +49,10 @@ ExternalASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC,
return DeclContext::lookup_result();
}
-ExternalLoadResult
+void ExternalASTSource::completeVisibleDeclsMap(const DeclContext *DC) {
+}
+
+ExternalLoadResult
ExternalASTSource::FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Result) {
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index d7b6354..0d405f1 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2280,9 +2280,7 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
}
-/// Mangles a member expression. Implicit accesses are not handled,
-/// but that should be okay, because you shouldn't be able to
-/// make an implicit access in a function template declaration.
+/// Mangles a member expression.
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
NestedNameSpecifier *qualifier,
@@ -2291,8 +2289,17 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
- Out << (isArrow ? "pt" : "dt");
- mangleExpression(base);
+ if (base) {
+ if (base->isImplicitCXXThis()) {
+ // Note: GCC mangles member expressions to the implicit 'this' as
+ // *this., whereas we represent them as this->. The Itanium C++ ABI
+ // does not specify anything here, so we follow GCC.
+ Out << "dtdefpT";
+ } else {
+ Out << (isArrow ? "pt" : "dt");
+ mangleExpression(base);
+ }
+ }
mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
}
@@ -2346,6 +2353,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expr-primary> ::= L <type> <value number> E # integer literal
// ::= L <type <value float> E # floating literal
// ::= L <mangled-name> E # external name
+ // ::= fpT # 'this' expression
QualType ImplicitlyConvertedToType;
recurse:
@@ -2361,7 +2369,6 @@ recurse:
// These all can only appear in local or variable-initialization
// contexts and so should never appear in a mangling.
case Expr::AddrLabelExprClass:
- case Expr::CXXThisExprClass:
case Expr::DesignatedInitExprClass:
case Expr::ImplicitValueInitExprClass:
case Expr::ParenListExprClass:
@@ -2919,6 +2926,10 @@ recurse:
mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
break;
}
+
+ case Expr::CXXThisExprClass:
+ Out << "fpT";
+ break;
}
}
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 6af20df..e4d9f0a 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -97,8 +97,8 @@ Stmt *Stmt::IgnoreImplicit() {
/// \brief Strip off all label-like statements.
///
-/// This will strip off label statements, case statements, and default
-/// statements recursively.
+/// This will strip off label statements, case statements, attributed
+/// statements and default statements recursively.
const Stmt *Stmt::stripLabelLikeStatements() const {
const Stmt *S = this;
while (true) {
@@ -106,6 +106,8 @@ const Stmt *Stmt::stripLabelLikeStatements() const {
S = LS->getSubStmt();
else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
S = SC->getSubStmt();
+ else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S))
+ S = AS->getSubStmt();
else
return S;
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 3a44183..0d1066b 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -169,6 +169,23 @@ void StmtPrinter::VisitLabelStmt(LabelStmt *Node) {
PrintStmt(Node->getSubStmt(), 0);
}
+void StmtPrinter::VisitAttributedStmt(AttributedStmt *Node) {
+ OS << "[[";
+ bool first = true;
+ for (AttrVec::const_iterator it = Node->getAttrs().begin(),
+ end = Node->getAttrs().end();
+ it != end; ++it) {
+ if (!first) {
+ OS << ", ";
+ first = false;
+ }
+ // TODO: check this
+ (*it)->printPretty(OS, Context);
+ }
+ OS << "]] ";
+ PrintStmt(Node->getSubStmt(), 0);
+}
+
void StmtPrinter::PrintRawIfStmt(IfStmt *If) {
OS << "if (";
PrintExpr(If->getCond());
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index e5526ce..e50523a 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -109,6 +109,11 @@ void StmtProfiler::VisitLabelStmt(const LabelStmt *S) {
VisitDecl(S->getDecl());
}
+void StmtProfiler::VisitAttributedStmt(const AttributedStmt *S) {
+ VisitStmt(S);
+ // TODO: maybe visit attributes?
+}
+
void StmtProfiler::VisitIfStmt(const IfStmt *S) {
VisitStmt(S);
VisitDecl(S->getConditionVariable());
@@ -758,6 +763,7 @@ void StmtProfiler::VisitCXXUuidofExpr(const CXXUuidofExpr *S) {
void StmtProfiler::VisitCXXThisExpr(const CXXThisExpr *S) {
VisitExpr(S);
+ ID.AddBoolean(S->isImplicit());
}
void StmtProfiler::VisitCXXThrowExpr(const CXXThrowExpr *S) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index c82aeaa..3f6a094 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1546,6 +1546,14 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
else if (epi.NoexceptExpr->isInstantiationDependent())
setInstantiationDependent();
}
+ } else if (getExceptionSpecType() == EST_Uninstantiated) {
+ // Store the function decl from which we will resolve our
+ // exception specification.
+ FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + numArgs);
+ slot[0] = epi.ExceptionSpecDecl;
+ slot[1] = epi.ExceptionSpecTemplate;
+ // This exception specification doesn't make the type dependent, because
+ // it's not instantiated as part of instantiating the type.
}
if (epi.ConsumedArguments) {
@@ -1629,6 +1637,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
} else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
epi.NoexceptExpr->Profile(ID, Context, false);
+ } else if (epi.ExceptionSpecType == EST_Uninstantiated) {
+ ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl());
}
if (epi.ConsumedArguments) {
for (unsigned i = 0; i != NumArgs; ++i)
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 7a45972..107d9fb 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -2157,13 +2157,12 @@ VTableLayout::VTableLayout(uint64_t NumVTableComponents,
VTableThunks(new VTableThunkTy[NumVTableThunks]),
AddressPoints(AddressPoints) {
std::copy(VTableComponents, VTableComponents+NumVTableComponents,
- this->VTableComponents);
- std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks);
+ this->VTableComponents.get());
+ std::copy(VTableThunks, VTableThunks+NumVTableThunks,
+ this->VTableThunks.get());
}
-VTableLayout::~VTableLayout() {
- delete[] VTableComponents;
-}
+VTableLayout::~VTableLayout() { }
VTableContext::~VTableContext() {
llvm::DeleteContainerSeconds(VTableLayouts);
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d1334a5..2f1f1cb 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/CharUnits.h"
+#include "clang/Basic/AttrKinds.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Format.h"
@@ -1069,6 +1070,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
case Stmt::LambdaExprClass:
return VisitLambdaExpr(cast<LambdaExpr>(S), asc);
+ case Stmt::AttributedStmtClass:
+ return Visit(cast<AttributedStmt>(S)->getSubStmt(), asc);
+
case Stmt::MemberExprClass:
return VisitMemberExpr(cast<MemberExpr>(S), asc);
@@ -1131,7 +1135,7 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
/// VisitChildren - Visit the children of a Stmt.
CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) {
- CFGBlock *lastBlock = Block;
+ CFGBlock *lastBlock = Block;
for (Stmt::child_range I = Terminator->children(); I; ++I)
if (Stmt *child = *I)
if (CFGBlock *b = Visit(child))
@@ -1280,7 +1284,8 @@ static bool CanThrow(Expr *E, ASTContext &Ctx) {
const FunctionType *FT = Ty->getAs<FunctionType>();
if (FT) {
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
- if (Proto->isNothrow(Ctx))
+ if (Proto->getExceptionSpecType() != EST_Uninstantiated &&
+ Proto->isNothrow(Ctx))
return false;
}
return true;
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 43c3ffb..ca2392b 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_USED_LIBS clangBasic clangAST clangIndex)
+set(LLVM_USED_LIBS clangBasic clangAST)
add_clang_library(clangAnalysis
AnalysisDeclContext.cpp
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index f938b5a..8c49486 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -58,6 +58,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
Char32Type = UnsignedInt;
Int64Type = SignedLongLong;
SigAtomicType = SignedInt;
+ UseSignedCharForObjCBool = true;
UseBitFieldTypeAlignment = true;
UseZeroLengthBitfieldAlignment = false;
ZeroLengthBitfieldBoundary = 0;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 1ad37c4..dd2a89a 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -365,7 +365,7 @@ protected:
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
- Builder.defineMacro("_POSIX_THREADS");
+ Builder.defineMacro("_REENTRANT");
}
public:
OpenBSDTargetInfo(const std::string &triple)
@@ -3546,7 +3546,10 @@ public:
virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
- if (Name == "soft-float" || Name == "single-float") {
+ if (Name == "soft-float" || Name == "single-float" ||
+ Name == "o32" || Name == "n32" || Name == "n64" || Name == "eabi" ||
+ Name == "mips32" || Name == "mips32r2" ||
+ Name == "mips64" || Name == "mips64r2") {
Features[Name] = Enabled;
return true;
}
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index 331024f..8cb2386 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -32,7 +32,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
+ static StringRef SVNRepository("$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_31/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 7af01ec..dfb9d61 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -14,5 +14,4 @@ add_subdirectory(Serialization)
add_subdirectory(Frontend)
add_subdirectory(FrontendTool)
add_subdirectory(Tooling)
-add_subdirectory(Index)
add_subdirectory(StaticAnalyzer)
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 27bb4ef..f8c7bcd 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -491,6 +491,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
/// a full-expression so that the block's cleanups are pushed at the
/// right place in the stack.
static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
+ assert(CGF.HaveInsertPoint());
+
// Allocate the block info and place it at the head of the list.
CGBlockInfo &blockInfo =
*new CGBlockInfo(block, CGF.CurFn->getName());
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 4455f1a..82ee4fc 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -419,16 +419,37 @@ void CodeGenTypes::GetExpandedTypes(QualType type,
uint64_t NumElts = AT->getSize().getZExtValue();
for (uint64_t Elt = 0; Elt < NumElts; ++Elt)
GetExpandedTypes(AT->getElementType(), expandedTypes);
- } else if (const RecordType *RT = type->getAsStructureType()) {
+ } else if (const RecordType *RT = type->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
assert(!RD->hasFlexibleArrayMember() &&
"Cannot expand structure with flexible array.");
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- const FieldDecl *FD = *i;
- assert(!FD->isBitField() &&
- "Cannot expand structure with bit-field members.");
- GetExpandedTypes(FD->getType(), expandedTypes);
+ if (RD->isUnion()) {
+ // Unions can be here only in degenerative cases - all the fields are same
+ // after flattening. Thus we have to use the "largest" field.
+ const FieldDecl *LargestFD = 0;
+ CharUnits UnionSize = CharUnits::Zero();
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
+ if (UnionSize < FieldSize) {
+ UnionSize = FieldSize;
+ LargestFD = FD;
+ }
+ }
+ if (LargestFD)
+ GetExpandedTypes(LargestFD->getType(), expandedTypes);
+ } else {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ GetExpandedTypes(FD->getType(), expandedTypes);
+ }
}
} else if (const ComplexType *CT = type->getAs<ComplexType>()) {
llvm::Type *EltTy = ConvertType(CT->getElementType());
@@ -443,32 +464,55 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
llvm::Function::arg_iterator AI) {
assert(LV.isSimple() &&
"Unexpected non-simple lvalue during struct expansion.");
- llvm::Value *Addr = LV.getAddress();
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
unsigned NumElts = AT->getSize().getZExtValue();
QualType EltTy = AT->getElementType();
for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt);
+ llvm::Value *EltAddr = Builder.CreateConstGEP2_32(LV.getAddress(), 0, Elt);
LValue LV = MakeAddrLValue(EltAddr, EltTy);
AI = ExpandTypeFromArgs(EltTy, LV, AI);
}
- } else if (const RecordType *RT = Ty->getAsStructureType()) {
+ } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- FieldDecl *FD = *i;
- QualType FT = FD->getType();
-
- // FIXME: What are the right qualifiers here?
- LValue LV = EmitLValueForField(Addr, FD, 0);
- AI = ExpandTypeFromArgs(FT, LV, AI);
+ if (RD->isUnion()) {
+ // Unions can be here only in degenerative cases - all the fields are same
+ // after flattening. Thus we have to use the "largest" field.
+ const FieldDecl *LargestFD = 0;
+ CharUnits UnionSize = CharUnits::Zero();
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
+ if (UnionSize < FieldSize) {
+ UnionSize = FieldSize;
+ LargestFD = FD;
+ }
+ }
+ if (LargestFD) {
+ // FIXME: What are the right qualifiers here?
+ LValue SubLV = EmitLValueForField(LV, LargestFD);
+ AI = ExpandTypeFromArgs(LargestFD->getType(), SubLV, AI);
+ }
+ } else {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ FieldDecl *FD = *i;
+ QualType FT = FD->getType();
+
+ // FIXME: What are the right qualifiers here?
+ LValue SubLV = EmitLValueForField(LV, FD);
+ AI = ExpandTypeFromArgs(FT, SubLV, AI);
+ }
}
} else if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
QualType EltTy = CT->getElementType();
- llvm::Value *RealAddr = Builder.CreateStructGEP(Addr, 0, "real");
+ llvm::Value *RealAddr = Builder.CreateStructGEP(LV.getAddress(), 0, "real");
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(RealAddr, EltTy));
- llvm::Value *ImagAddr = Builder.CreateStructGEP(Addr, 1, "imag");
+ llvm::Value *ImagAddr = Builder.CreateStructGEP(LV.getAddress(), 1, "imag");
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(ImagAddr, EltTy));
} else {
EmitStoreThroughLValue(RValue::get(AI), LV);
@@ -1760,26 +1804,38 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
EltRV = EmitLoadOfLValue(LV);
ExpandTypeToArgs(EltTy, EltRV, Args, IRFuncTy);
}
- } else if (const RecordType *RT = Ty->getAsStructureType()) {
+ } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
- llvm::Value *Addr = RV.getAggregateAddr();
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- FieldDecl *FD = *i;
- QualType FT = FD->getType();
-
- // FIXME: What are the right qualifiers here?
- LValue LV = EmitLValueForField(Addr, FD, 0);
- RValue FldRV;
- if (FT->isAnyComplexType())
- // FIXME: Volatile?
- FldRV = RValue::getComplex(LoadComplexFromAddr(LV.getAddress(), false));
- else if (CodeGenFunction::hasAggregateLLVMType(FT))
- FldRV = LV.asAggregateRValue();
- else
- FldRV = EmitLoadOfLValue(LV);
- ExpandTypeToArgs(FT, FldRV, Args, IRFuncTy);
+ LValue LV = MakeAddrLValue(RV.getAggregateAddr(), Ty);
+
+ if (RD->isUnion()) {
+ const FieldDecl *LargestFD = 0;
+ CharUnits UnionSize = CharUnits::Zero();
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
+ if (UnionSize < FieldSize) {
+ UnionSize = FieldSize;
+ LargestFD = FD;
+ }
+ }
+ if (LargestFD) {
+ RValue FldRV = EmitRValueForField(LV, LargestFD);
+ ExpandTypeToArgs(LargestFD->getType(), FldRV, Args, IRFuncTy);
+ }
+ } else {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ FieldDecl *FD = *i;
+
+ RValue FldRV = EmitRValueForField(LV, FD);
+ ExpandTypeToArgs(FD->getType(), FldRV, Args, IRFuncTy);
+ }
}
} else if (Ty->isAnyComplexType()) {
ComplexPairTy CV = RV.getComplexVal();
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 6303e20..2aedf95 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -555,15 +555,17 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
QualType FieldType = Field->getType();
llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
LValue LHS;
-
+
// If we are initializing an anonymous union field, drill down to the field.
if (MemberInit->isIndirectMemberInitializer()) {
LHS = CGF.EmitLValueForAnonRecordField(ThisPtr,
MemberInit->getIndirectMember(), 0);
FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
} else {
- LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
+ LValue ThisLHSLV = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
+ LHS = CGF.EmitLValueForFieldInitialization(ThisLHSLV, Field);
}
// Special case: if we are in a copy or move constructor, and we are copying
@@ -585,7 +587,8 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
unsigned SrcArgIndex = Args.size() - 1;
llvm::Value *SrcPtr
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
- LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0);
+ LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
+ LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
// Copy the aggregate.
CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
@@ -978,7 +981,9 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) {
// Find the address of the field.
llvm::Value *thisValue = CGF.LoadCXXThis();
- LValue LV = CGF.EmitLValueForField(thisValue, field, /*CVRQualifiers=*/0);
+ QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent());
+ LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
+ LValue LV = CGF.EmitLValueForField(ThisLV, field);
assert(LV.isSimple());
CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 7301d20..d286d24 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -184,7 +184,6 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
const TemplateArgument *Args;
unsigned NumArgs;
- std::string Buffer;
if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
const TemplateSpecializationType *TST =
cast<TemplateSpecializationType>(TAW->getType());
@@ -195,16 +194,17 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
Args = TemplateArgs.data();
NumArgs = TemplateArgs.size();
}
- Buffer = RD->getIdentifier()->getNameStart();
+ StringRef Name = RD->getIdentifier()->getName();
PrintingPolicy Policy(CGM.getLangOpts());
- Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
- NumArgs,
- Policy);
+ std::string TemplateArgList =
+ TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy);
// Copy this name on the side and use its reference.
- char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length());
- memcpy(StrPtr, Buffer.data(), Buffer.length());
- return StringRef(StrPtr, Buffer.length());
+ size_t Length = Name.size() + TemplateArgList.size();
+ char *StrPtr = DebugInfoNames.Allocate<char>(Length);
+ memcpy(StrPtr, Name.data(), Name.size());
+ memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());
+ return StringRef(StrPtr, Length);
}
/// getOrCreateFile - Get the file debug info descriptor for the input location.
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 8c154f0..6447779 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1171,6 +1171,10 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
// If this was emitted as a global constant, we're done.
if (emission.wasEmittedAsGlobal()) return;
+ // If we don't have an insertion point, we're done. Sema prevents
+ // us from jumping into any of these scopes anyway.
+ if (!HaveInsertPoint()) return;
+
const VarDecl &D = *emission.Variable;
// Check the type for a cleanup.
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 08970fd..5f2b1f0 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -24,6 +24,7 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
#include "llvm/LLVMContext.h"
+#include "llvm/Support/MDBuilder.h"
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@@ -398,8 +399,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
break;
case SubobjectAdjustment::FieldAdjustment: {
- LValue LV =
- CGF.EmitLValueForField(Object, Adjustment.Field, 0);
+ LValue LV = CGF.MakeAddrLValue(Object, E->getType());
+ LV = CGF.EmitLValueForField(LV, Adjustment.Field);
if (LV.isSimple()) {
Object = LV.getAddress();
break;
@@ -908,16 +909,8 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
}
}
- if (End == Min)
- return NULL;
-
- llvm::Value *LowAndHigh[2];
- LowAndHigh[0] = llvm::ConstantInt::get(LTy, Min);
- LowAndHigh[1] = llvm::ConstantInt::get(LTy, End);
-
- llvm::LLVMContext &C = getLLVMContext();
- llvm::MDNode *Range = llvm::MDNode::get(C, LowAndHigh);
- return Range;
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ return MDHelper.createRange(Min, End);
}
llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
@@ -1577,8 +1570,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// Use special handling for lambdas.
if (!V) {
- if (FieldDecl *FD = LambdaCaptureFields.lookup(VD))
- return EmitLValueForField(CXXABIThisValue, FD, 0);
+ if (FieldDecl *FD = LambdaCaptureFields.lookup(VD)) {
+ QualType LambdaTagType = getContext().getTagDeclType(FD->getParent());
+ LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
+ LambdaTagType);
+ return EmitLValueForField(LambdaLV, FD);
+ }
assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal());
CharUnits alignment = getContext().getDeclAlign(VD);
@@ -1973,32 +1970,19 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
}
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
- bool isNonGC = false;
Expr *BaseExpr = E->getBase();
- llvm::Value *BaseValue = NULL;
- Qualifiers BaseQuals;
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
- if (E->isArrow()) {
- BaseValue = EmitScalarExpr(BaseExpr);
- const PointerType *PTy =
- BaseExpr->getType()->getAs<PointerType>();
- BaseQuals = PTy->getPointeeType().getQualifiers();
- } else {
- LValue BaseLV = EmitLValue(BaseExpr);
- if (BaseLV.isNonGC())
- isNonGC = true;
- // FIXME: this isn't right for bitfields.
- BaseValue = BaseLV.getAddress();
- QualType BaseTy = BaseExpr->getType();
- BaseQuals = BaseTy.getQualifiers();
- }
+ LValue BaseLV;
+ if (E->isArrow())
+ BaseLV = MakeNaturalAlignAddrLValue(EmitScalarExpr(BaseExpr),
+ BaseExpr->getType()->getPointeeType());
+ else
+ BaseLV = EmitLValue(BaseExpr);
NamedDecl *ND = E->getMemberDecl();
if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
- LValue LV = EmitLValueForField(BaseValue, Field,
- BaseQuals.getCVRQualifiers());
- LV.setNonGC(isNonGC);
+ LValue LV = EmitLValueForField(BaseLV, Field);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
@@ -2032,8 +2016,10 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
IndirectFieldDecl::chain_iterator I = Field->chain_begin(),
IEnd = Field->chain_end();
while (true) {
- LValue LV = EmitLValueForField(BaseValue, cast<FieldDecl>(*I),
- CVRQualifiers);
+ QualType RecordTy =
+ getContext().getTypeDeclType(cast<FieldDecl>(*I)->getParent());
+ LValue LV = EmitLValueForField(MakeAddrLValue(BaseValue, RecordTy),
+ cast<FieldDecl>(*I));
if (++I == IEnd) return LV;
assert(LV.isSimple());
@@ -2042,19 +2028,25 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
}
}
-LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
- const FieldDecl *field,
- unsigned cvr) {
+LValue CodeGenFunction::EmitLValueForField(LValue base,
+ const FieldDecl *field) {
if (field->isBitField())
- return EmitLValueForBitfield(baseAddr, field, cvr);
+ return EmitLValueForBitfield(base.getAddress(), field,
+ base.getVRQualifiers());
const RecordDecl *rec = field->getParent();
QualType type = field->getType();
CharUnits alignment = getContext().getDeclAlign(field);
+ // FIXME: It should be impossible to have an LValue without alignment for a
+ // complete type.
+ if (!base.getAlignment().isZero())
+ alignment = std::min(alignment, base.getAlignment());
+
bool mayAlias = rec->hasAttr<MayAliasAttr>();
- llvm::Value *addr = baseAddr;
+ llvm::Value *addr = base.getAddress();
+ unsigned cvr = base.getVRQualifiers();
if (rec->isUnion()) {
// For unions, there is no pointer adjustment.
assert(!type->isReferenceType() && "union has reference member");
@@ -2117,30 +2109,33 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
}
LValue
-CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value *BaseValue,
- const FieldDecl *Field,
- unsigned CVRQualifiers) {
+CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
+ const FieldDecl *Field) {
QualType FieldType = Field->getType();
if (!FieldType->isReferenceType())
- return EmitLValueForField(BaseValue, Field, CVRQualifiers);
+ return EmitLValueForField(Base, Field);
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field->getParent());
unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx);
+ llvm::Value *V = Builder.CreateStructGEP(Base.getAddress(), idx);
assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
-
// Make sure that the address is pointing to the right type. This is critical
// for both unions and structs. A union needs a bitcast, a struct element
// will need a bitcast if the LLVM type laid out doesn't match the desired
// type.
llvm::Type *llvmType = ConvertTypeForMem(FieldType);
- unsigned AS = cast<llvm::PointerType>(V->getType())->getAddressSpace();
- V = Builder.CreateBitCast(V, llvmType->getPointerTo(AS));
-
+ V = EmitBitCastOfLValueToProperType(*this, V, llvmType, Field->getName());
+
CharUnits Alignment = getContext().getDeclAlign(Field);
+
+ // FIXME: It should be impossible to have an LValue without alignment for a
+ // complete type.
+ if (!Base.getAlignment().isZero())
+ Alignment = std::min(Alignment, Base.getAlignment());
+
return MakeAddrLValue(V, FieldType, Alignment);
}
@@ -2378,6 +2373,19 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
+RValue CodeGenFunction::EmitRValueForField(LValue LV,
+ const FieldDecl *FD) {
+ QualType FT = FD->getType();
+ LValue FieldLV = EmitLValueForField(LV, FD);
+ if (FT->isAnyComplexType())
+ return RValue::getComplex(
+ LoadComplexFromAddr(FieldLV.getAddress(),
+ FieldLV.isVolatileQualified()));
+ else if (CodeGenFunction::hasAggregateLLVMType(FT))
+ return FieldLV.asAggregateRValue();
+
+ return EmitLoadOfLValue(FieldLV);
+}
//===--------------------------------------------------------------------===//
// Expression Emission
@@ -3158,11 +3166,10 @@ void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, float Accuracy) {
if (Accuracy == 0.0 || !isa<llvm::Instruction>(Val))
return;
- llvm::Value *ULPs = llvm::ConstantFP::get(Builder.getFloatTy(), Accuracy);
- llvm::MDNode *Node = llvm::MDNode::get(getLLVMContext(), ULPs);
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ llvm::MDNode *Node = MDHelper.createFPMath(Accuracy);
- cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy,
- Node);
+ cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpmath, Node);
}
namespace {
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index b6efc1c..7b0e0f5 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -238,7 +238,10 @@ void AggExprEmitter::EmitMoveFromReturnSlot(const Expr *E, RValue Src) {
// Otherwise, do a final copy,
assert(Dest.getAddr() != Src.getAggregateAddr());
- EmitFinalDestCopy(E, Src, /*Ignore*/ true);
+ std::pair<CharUnits, CharUnits> TypeInfo =
+ CGF.getContext().getTypeInfoInChars(E->getType());
+ CharUnits Alignment = std::min(TypeInfo.second, Dest.getAlignment());
+ EmitFinalDestCopy(E, Src, /*Ignore*/ true, Alignment.getQuantity());
}
/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
@@ -348,7 +351,8 @@ void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
CGF.ErrorUnsupported(initList, "weird std::initializer_list");
return;
}
- LValue start = CGF.EmitLValueForFieldInitialization(destPtr, *field, 0);
+ LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr, initList->getType());
+ LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field);
llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0, "arraystart");
CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start);
++field;
@@ -357,7 +361,7 @@ void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
CGF.ErrorUnsupported(initList, "weird std::initializer_list");
return;
}
- LValue endOrLength = CGF.EmitLValueForFieldInitialization(destPtr, *field, 0);
+ LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *field);
if (ctx.hasSameType(field->getType(), elementPtr)) {
// End pointer.
llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits, "arrayend");
@@ -912,28 +916,24 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
return;
}
- llvm::Value *DestPtr = EnsureSlot(E->getType()).getAddr();
+ AggValueSlot Dest = EnsureSlot(E->getType());
+ LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
+ Dest.getAlignment());
// Handle initialization of an array.
if (E->getType()->isArrayType()) {
- if (E->getNumInits() > 0) {
- QualType T1 = E->getType();
- QualType T2 = E->getInit(0)->getType();
- if (CGF.getContext().hasSameUnqualifiedType(T1, T2)) {
- EmitAggLoadOfLValue(E->getInit(0));
- return;
- }
- }
+ if (E->isStringLiteralInit())
+ return Visit(E->getInit(0));
QualType elementType =
CGF.getContext().getAsArrayType(E->getType())->getElementType();
llvm::PointerType *APType =
- cast<llvm::PointerType>(DestPtr->getType());
+ cast<llvm::PointerType>(Dest.getAddr()->getType());
llvm::ArrayType *AType =
cast<llvm::ArrayType>(APType->getElementType());
- EmitArrayInit(DestPtr, AType, elementType, E);
+ EmitArrayInit(Dest.getAddr(), AType, elementType, E);
return;
}
@@ -966,7 +966,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// FIXME: volatility
FieldDecl *Field = E->getInitializedFieldInUnion();
- LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestPtr, Field, 0);
+ LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestLV, Field);
if (NumInitElements) {
// Store the initializer into the field
EmitInitializationToLValue(E->getInit(0), FieldLoc);
@@ -1004,8 +1004,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
CGF.getTypes().isZeroInitializable(E->getType()))
break;
- // FIXME: volatility
- LValue LV = CGF.EmitLValueForFieldInitialization(DestPtr, *field, 0);
+
+ LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, *field);
// We never generate write-barries for initialized fields.
LV.setNonGC(true);
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index d3ba770..c69c883 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -1815,13 +1815,16 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
RunCleanupsScope Scope(*this);
+ LValue SlotLV = MakeAddrLValue(Slot.getAddr(), E->getType(),
+ Slot.getAlignment());
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
e = E->capture_init_end();
i != e; ++i, ++CurField) {
// Emit initialization
- LValue LV = EmitLValueForFieldInitialization(Slot.getAddr(), *CurField, 0);
+
+ LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
ArrayRef<VarDecl *> ArrayIndexes;
if (CurField->getType()->isArrayType())
ArrayIndexes = E->getCaptureInitIndexVars(i);
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index d528e0c..bc9f9ef 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -758,17 +758,13 @@ public:
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
- unsigned NumInitElements = ILE->getNumInits();
- if (NumInitElements == 1 &&
- CGM.getContext().hasSameUnqualifiedType(ILE->getType(),
- ILE->getInit(0)->getType()) &&
- (isa<StringLiteral>(ILE->getInit(0)) ||
- isa<ObjCEncodeExpr>(ILE->getInit(0))))
+ if (ILE->isStringLiteralInit())
return Visit(ILE->getInit(0));
llvm::ArrayType *AType =
cast<llvm::ArrayType>(ConvertType(ILE->getType()));
llvm::Type *ElemTy = AType->getElementType();
+ unsigned NumInitElements = ILE->getNumInits();
unsigned NumElements = AType->getNumElements();
// Initialising an array requires us to automatically
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index bf42dcb..a1d0789 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -79,6 +79,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::CompoundStmtClass:
case Stmt::DeclStmtClass:
case Stmt::LabelStmtClass:
+ case Stmt::AttributedStmtClass:
case Stmt::GotoStmtClass:
case Stmt::BreakStmtClass:
case Stmt::ContinueStmtClass:
@@ -173,6 +174,8 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
+ case Stmt::AttributedStmtClass:
+ EmitAttributedStmt(cast<AttributedStmt>(*S)); break;
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
@@ -332,6 +335,10 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
EmitStmt(S.getSubStmt());
}
+void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
+ EmitStmt(S.getSubStmt());
+}
+
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 06e90b6..2939062 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -22,8 +22,9 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/Target/TargetData.h"
#include "llvm/Intrinsics.h"
+#include "llvm/Support/MDBuilder.h"
+#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
@@ -362,8 +363,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
LambdaThisCaptureField);
if (LambdaThisCaptureField) {
// If this lambda captures this, load it.
- LValue ThisLValue = EmitLValueForField(CXXABIThisValue,
- LambdaThisCaptureField, 0);
+ QualType LambdaTagType =
+ getContext().getTagDeclType(LambdaThisCaptureField->getParent());
+ LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
+ LambdaTagType);
+ LValue ThisLValue = EmitLValueForField(LambdaLV,
+ LambdaThisCaptureField);
CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal();
}
} else {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 3e0cd14..83f1e2d 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1948,6 +1948,7 @@ public:
void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt.
void EmitLabelStmt(const LabelStmt &S);
+ void EmitAttributedStmt(const AttributedStmt &S);
void EmitGotoStmt(const GotoStmt &S);
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);
void EmitIfStmt(const IfStmt &S);
@@ -2104,6 +2105,8 @@ public:
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
+ RValue EmitRValueForField(LValue LV, const FieldDecl *FD);
+
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
ConstantEmission(llvm::Constant *C, bool isReference)
@@ -2143,15 +2146,13 @@ public:
LValue EmitLValueForAnonRecordField(llvm::Value* Base,
const IndirectFieldDecl* Field,
unsigned CVRQualifiers);
- LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
- unsigned CVRQualifiers);
+ LValue EmitLValueForField(LValue Base, const FieldDecl* Field);
/// EmitLValueForFieldInitialization - Like EmitLValueForField, except that
/// if the Field is a reference, this will return the address of the reference
/// and not the address of the value stored in the reference.
- LValue EmitLValueForFieldInitialization(llvm::Value* Base,
- const FieldDecl* Field,
- unsigned CVRQualifiers);
+ LValue EmitLValueForFieldInitialization(LValue Base,
+ const FieldDecl* Field);
LValue EmitLValueForIvar(QualType ObjectTy,
llvm::Value* Base, const ObjCIvarDecl *Ivar,
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index c0ccf4d..9a55c08 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1241,7 +1241,7 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
/// given global variable. If Ty is non-null and if the global doesn't exist,
-/// then it will be greated with the specified type instead of whatever the
+/// then it will be created with the specified type instead of whatever the
/// normal requested type would be.
llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
llvm::Type *Ty) {
diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp
index 9ee3f1d..a3cadcf 100644
--- a/lib/CodeGen/CodeGenTBAA.cpp
+++ b/lib/CodeGen/CodeGenTBAA.cpp
@@ -28,7 +28,7 @@ using namespace CodeGen;
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext& VMContext,
const LangOptions &Features, MangleContext &MContext)
: Context(Ctx), VMContext(VMContext), Features(Features), MContext(MContext),
- Root(0), Char(0) {
+ MDHelper(VMContext), Root(0), Char(0) {
}
CodeGenTBAA::~CodeGenTBAA() {
@@ -40,7 +40,7 @@ llvm::MDNode *CodeGenTBAA::getRoot() {
// (or a different version of this front-end), their TBAA trees will
// remain distinct, and the optimizer will treat them conservatively.
if (!Root)
- Root = getTBAAInfoForNamedType("Simple C/C++ TBAA", 0);
+ Root = MDHelper.createTBAARoot("Simple C/C++ TBAA");
return Root;
}
@@ -51,33 +51,11 @@ llvm::MDNode *CodeGenTBAA::getChar() {
// these special powers only cover user-accessible memory, and doesn't
// include things like vtables.
if (!Char)
- Char = getTBAAInfoForNamedType("omnipotent char", getRoot());
+ Char = MDHelper.createTBAANode("omnipotent char", getRoot());
return Char;
}
-/// getTBAAInfoForNamedType - Create a TBAA tree node with the given string
-/// as its identifier, and the given Parent node as its tree parent.
-llvm::MDNode *CodeGenTBAA::getTBAAInfoForNamedType(StringRef NameStr,
- llvm::MDNode *Parent,
- bool Readonly) {
- // Currently there is only one flag defined - the readonly flag.
- llvm::Value *Flags = 0;
- if (Readonly)
- Flags = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), true);
-
- // Set up the mdnode operand list.
- llvm::Value *Ops[] = {
- llvm::MDString::get(VMContext, NameStr),
- Parent,
- Flags
- };
-
- // Create the mdnode.
- unsigned Len = llvm::array_lengthof(Ops) - !Flags;
- return llvm::MDNode::get(VMContext, llvm::makeArrayRef(Ops, Len));
-}
-
static bool TypeHasMayAlias(QualType QTy) {
// Tagged types have declarations, and therefore may have attributes.
if (const TagType *TTy = dyn_cast<TagType>(QTy))
@@ -137,7 +115,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// "underlying types".
default:
return MetadataCache[Ty] =
- getTBAAInfoForNamedType(BTy->getName(Features), getChar());
+ MDHelper.createTBAANode(BTy->getName(Features), getChar());
}
}
@@ -145,7 +123,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
// pointers distinct.
if (Ty->isPointerType())
- return MetadataCache[Ty] = getTBAAInfoForNamedType("any pointer",
+ return MetadataCache[Ty] = MDHelper.createTBAANode("any pointer",
getChar());
// Enum types are distinct types. In C++ they have "underlying types",
@@ -173,7 +151,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
llvm::raw_svector_ostream Out(OutName);
MContext.mangleCXXRTTIName(QualType(ETy, 0), Out);
Out.flush();
- return MetadataCache[Ty] = getTBAAInfoForNamedType(OutName, getChar());
+ return MetadataCache[Ty] = MDHelper.createTBAANode(OutName, getChar());
}
// For now, handle any other kind of type conservatively.
@@ -181,5 +159,5 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) {
}
llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
- return getTBAAInfoForNamedType("vtable pointer", getRoot());
+ return MDHelper.createTBAANode("vtable pointer", getRoot());
}
diff --git a/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h
index 8e08498..4a97852 100644
--- a/lib/CodeGen/CodeGenTBAA.h
+++ b/lib/CodeGen/CodeGenTBAA.h
@@ -17,6 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/MDBuilder.h"
namespace llvm {
class LLVMContext;
@@ -41,6 +42,9 @@ class CodeGenTBAA {
const LangOptions &Features;
MangleContext &MContext;
+ // MDHelper - Helper for creating metadata.
+ llvm::MDBuilder MDHelper;
+
/// MetadataCache - This maps clang::Types to llvm::MDNodes describing them.
llvm::DenseMap<const Type *, llvm::MDNode *> MetadataCache;
@@ -55,10 +59,6 @@ class CodeGenTBAA {
/// considered to be equivalent to it.
llvm::MDNode *getChar();
- llvm::MDNode *getTBAAInfoForNamedType(StringRef NameStr,
- llvm::MDNode *Parent,
- bool Readonly = false);
-
public:
CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext,
const LangOptions &Features,
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 3ed1778..2b71fdd 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -2527,19 +2527,16 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
ASTContext &Context,
uint64_t *HAMembers = 0) {
- uint64_t Members;
+ uint64_t Members = 0;
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
if (!isHomogeneousAggregate(AT->getElementType(), Base, Context, &Members))
return false;
Members *= AT->getSize().getZExtValue();
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
- if (RD->isUnion() || RD->hasFlexibleArrayMember())
+ if (RD->hasFlexibleArrayMember())
return false;
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CXXRD->isAggregate())
- return false;
- }
+
Members = 0;
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
@@ -2547,7 +2544,9 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t FldMembers;
if (!isHomogeneousAggregate(FD->getType(), Base, Context, &FldMembers))
return false;
- Members += FldMembers;
+
+ Members = (RD->isUnion() ?
+ std::max(Members, FldMembers) : Members + FldMembers);
}
} else {
Members = 1;
@@ -2584,7 +2583,8 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
// Homogeneous Aggregates can have at most 4 members of the base type.
if (HAMembers)
*HAMembers = Members;
- return (Members <= 4);
+
+ return (Members > 0 && Members <= 4);
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
@@ -2609,8 +2609,10 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
if (getABIKind() == ARMABIInfo::AAPCS_VFP) {
// Homogeneous Aggregates need to be expanded.
const Type *Base = 0;
- if (isHomogeneousAggregate(Ty, Base, getContext()))
+ if (isHomogeneousAggregate(Ty, Base, getContext())) {
+ assert(Base && "Base class should be set for homogeneous aggregate");
return ABIArgInfo::getExpand();
+ }
}
// Otherwise, pass by coercing to a structure of the appropriate size.
@@ -2776,9 +2778,11 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
// Check for homogeneous aggregates with AAPCS-VFP.
if (getABIKind() == AAPCS_VFP) {
const Type *Base = 0;
- if (isHomogeneousAggregate(RetTy, Base, getContext()))
+ if (isHomogeneousAggregate(RetTy, Base, getContext())) {
+ assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
return ABIArgInfo::getDirect();
+ }
}
// Aggregates <= 4 bytes are returned in r0; other aggregates
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 42c8449..5553fc9 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -230,3 +230,7 @@ void Compilation::initCompilationForDiagnostics(void) {
Redirects[1] = new const llvm::sys::Path();
Redirects[2] = new const llvm::sys::Path();
}
+
+StringRef Compilation::getSysRoot(void) const {
+ return getDriver().SysRoot;
+}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 7ab3278..3ddac69 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -49,8 +49,8 @@ Driver::Driver(StringRef ClangExecutable,
bool IsProduction,
DiagnosticsEngine &Diags)
: Opts(createDriverOptTable()), Diags(Diags),
- ClangExecutable(ClangExecutable), UseStdLib(true),
- DefaultTargetTriple(DefaultTargetTriple),
+ ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
+ UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
DefaultImageName(DefaultImageName),
DriverTitle("clang \"gcc-compatible\" driver"),
CCPrintOptionsFilename(0), CCPrintHeadersFilename(0),
@@ -660,9 +660,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
llvm::outs() << "\n";
llvm::outs() << "libraries: =" << ResourceDir;
- std::string sysroot;
- if (Arg *A = C.getArgs().getLastArg(options::OPT__sysroot_EQ))
- sysroot = A->getValue(C.getArgs());
+ StringRef sysroot = C.getSysRoot();
for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
ie = TC.getFilePaths().end(); it != ie; ++it) {
@@ -872,30 +870,30 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
// Handle debug info queries.
Arg *A = Args.getLastArg(options::OPT_g_Group);
- if (A && !A->getOption().matches(options::OPT_g0) &&
- !A->getOption().matches(options::OPT_gstabs) &&
- ContainsCompileOrAssembleAction(Actions.back())) {
-
- // Add a 'dsymutil' step if necessary, when debug info is enabled and we
- // have a compile input. We need to run 'dsymutil' ourselves in such cases
- // because the debug info will refer to a temporary object file which is
- // will be removed at the end of the compilation process.
- if (Act->getType() == types::TY_Image) {
- ActionList Inputs;
- Inputs.push_back(Actions.back());
- Actions.pop_back();
- Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
- }
+ if (A && !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_gstabs) &&
+ ContainsCompileOrAssembleAction(Actions.back())) {
+
+ // Add a 'dsymutil' step if necessary, when debug info is enabled and we
+ // have a compile input. We need to run 'dsymutil' ourselves in such cases
+ // because the debug info will refer to a temporary object file which is
+ // will be removed at the end of the compilation process.
+ if (Act->getType() == types::TY_Image) {
+ ActionList Inputs;
+ Inputs.push_back(Actions.back());
+ Actions.pop_back();
+ Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
+ }
- // Verify the output (debug information only) if we passed '-verify'.
- if (Args.hasArg(options::OPT_verify)) {
- ActionList VerifyInputs;
- VerifyInputs.push_back(Actions.back());
- Actions.pop_back();
- Actions.push_back(new VerifyJobAction(VerifyInputs,
- types::TY_Nothing));
- }
+ // Verify the output (debug information only) if we passed '-verify'.
+ if (Args.hasArg(options::OPT_verify)) {
+ ActionList VerifyInputs;
+ VerifyInputs.push_back(Actions.back());
+ Actions.pop_back();
+ Actions.push_back(new VerifyJobAction(VerifyInputs,
+ types::TY_Nothing));
}
+ }
}
}
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 6769756..81657d8 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -580,7 +580,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// If no '-miphoneos-version-min' specified on the command line and
// IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default
- // based on isysroot.
+ // based on -isysroot.
if (iOSTarget.empty()) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef first, second;
@@ -1086,6 +1086,7 @@ bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const {
// a patch.
if (RHS.Patch == -1) return true; if (Patch == -1) return false;
if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false;
+ if (PatchSuffix == RHS.PatchSuffix) return false;
// Finally, between completely tied version numbers, the version with the
// suffix loses as we prefer full releases.
@@ -1103,7 +1104,7 @@ static StringRef getGCCToolchainDir(const ArgList &Args) {
/// \brief Construct a GCCInstallationDetector from the driver.
///
/// This performs all of the autodetection and sets up the various paths.
-/// Once constructed, a GCCInstallation is esentially immutable.
+/// Once constructed, a GCCInstallationDetector is essentially immutable.
///
/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and
/// should instead pull the target out of the driver. This is currently
@@ -2063,7 +2064,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// If the GCC installation we found is inside of the sysroot, we want to
// prefer libraries installed in the parent prefix of the GCC installation.
// It is important to *not* use these paths when the GCC installation is
- // outside of the system root as that can pick up un-intented libraries.
+ // outside of the system root as that can pick up unintended libraries.
// This usually happens when there is an external cross compiler on the
// host system, and a more minimal sysroot available that is the target of
// the cross.
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index fbf4f08..47b5294 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -377,10 +377,11 @@ void Clang::AddPreprocessingOptions(Compilation &C,
// If we have a --sysroot, and don't have an explicit -isysroot flag, add an
// -isysroot to the CC1 invocation.
- if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
+ StringRef sysroot = C.getSysRoot();
+ if (sysroot != "") {
if (!Args.hasArg(options::OPT_isysroot)) {
CmdArgs.push_back("-isysroot");
- CmdArgs.push_back(A->getValue(Args));
+ CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
}
}
@@ -4016,9 +4017,10 @@ void darwin::Link::AddLinkArgs(Compilation &C,
// Give --sysroot= preference, over the Apple specific behavior to also use
// --isysroot as the syslibroot.
- if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
+ StringRef sysroot = C.getSysRoot();
+ if (sysroot != "") {
CmdArgs.push_back("-syslibroot");
- CmdArgs.push_back(A->getValue(Args));
+ CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
} else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
CmdArgs.push_back("-syslibroot");
CmdArgs.push_back(A->getValue(Args));
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index e32fa63..7aa9603 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -643,8 +643,10 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
DiagnosticConsumer *Client = 0;
if (CaptureDiagnostics)
Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
- Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd- ArgBegin,
- ArgBegin, Client);
+ Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd-ArgBegin,
+ ArgBegin, Client,
+ /*ShouldOwnClient=*/true,
+ /*ShouldCloneClient=*/false);
} else if (CaptureDiagnostics) {
Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics));
}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index cab6b90..803e418 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -651,6 +651,10 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// created. This complexity should be lifted elsewhere.
getTarget().setForcedLangOptions(getLangOpts());
+ // rewriter project will change target built-in bool type from its default.
+ if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
+ getTarget().noSignedCharForObjCBool();
+
// Validate/process some options.
if (getHeaderSearchOpts().Verbose)
OS << "clang -cc1 version " CLANG_VERSION_STRING
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 02947c7..4c5b063 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -429,7 +429,6 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::PrintDeclContext: return "-print-decl-contexts";
case frontend::PrintPreamble: return "-print-preamble";
case frontend::PrintPreprocessedInput: return "-E";
- case frontend::PubnamesDump: return "-pubnames-dump";
case frontend::RewriteMacros: return "-rewrite-macros";
case frontend::RewriteObjC: return "-rewrite-objc";
case frontend::RewriteTest: return "-rewrite-test";
@@ -1369,8 +1368,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
- case OPT_pubnames_dump:
- Opts.ProgramAction = frontend::PubnamesDump; break;
case OPT_rewrite_macros:
Opts.ProgramAction = frontend::RewriteMacros; break;
case OPT_rewrite_objc:
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index b4a439d..737ee4a 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -25,7 +25,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
-#include <set>
using namespace clang;
@@ -355,77 +354,6 @@ ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
return new ASTConsumer();
}
-namespace {
- class PubnamesDumpConsumer : public ASTConsumer {
- Preprocessor &PP;
-
- /// \brief Determine whether the given identifier provides a 'public' name.
- bool isPublicName(IdentifierInfo *II) {
- // If there are any top-level declarations associated with this
- // identifier, it is a public name.
- if (II->getFETokenInfo<void>())
- return true;
-
- // If this identifier is the name of a non-builtin macro that isn't
- // defined on the command line or implicitly by the front end, it is a
- // public name.
- if (II->hasMacroDefinition()) {
- if (MacroInfo *M = PP.getMacroInfo(II))
- if (!M->isBuiltinMacro()) {
- SourceLocation Loc = M->getDefinitionLoc();
- FileID File = PP.getSourceManager().getFileID(Loc);
- if (PP.getSourceManager().getFileEntryForID(File))
- return true;
- }
- }
-
- return false;
- }
-
- public:
- PubnamesDumpConsumer(Preprocessor &PP) : PP(PP) { }
-
- virtual void HandleTranslationUnit(ASTContext &Ctx) {
- std::set<StringRef> Pubnames;
-
- // Add the names of any non-builtin macros.
- for (IdentifierTable::iterator I = Ctx.Idents.begin(),
- IEnd = Ctx.Idents.end();
- I != IEnd; ++I) {
- if (isPublicName(I->second))
- Pubnames.insert(I->first());
- }
-
- // If there is an external identifier lookup source, consider those
- // identifiers as well.
- if (IdentifierInfoLookup *External
- = Ctx.Idents.getExternalIdentifierLookup()) {
- OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());
- do {
- StringRef Name = Iter->Next();
- if (Name.empty())
- break;
-
- if (isPublicName(PP.getIdentifierInfo(Name)))
- Pubnames.insert(Name);
- } while (true);
- }
-
- // Print the names, in lexicographical order.
- for (std::set<StringRef>::iterator N = Pubnames.begin(),
- NEnd = Pubnames.end();
- N != NEnd; ++N) {
- llvm::outs() << *N << '\n';
- }
- }
- };
-}
-
-ASTConsumer *PubnamesDumpAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return new PubnamesDumpConsumer(CI.getPreprocessor());
-}
-
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 9f5dcb4..65fb1ae 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -10,13 +10,17 @@
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/ConvertUTF.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Locale.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include <algorithm>
+
using namespace clang;
static const enum raw_ostream::Colors noteColor =
@@ -36,23 +40,269 @@ static const enum raw_ostream::Colors savedColor =
/// \brief Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6;
+int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
+ int bytes = 0;
+ while (0<i) {
+ if (SourceLine[--i]=='\t')
+ break;
+ ++bytes;
+ }
+ return bytes;
+}
+
+/// \brief returns a printable representation of first item from input range
+///
+/// This function returns a printable representation of the next item in a line
+/// of source. If the next byte begins a valid and printable character, that
+/// character is returned along with 'true'.
+///
+/// Otherwise, if the next byte begins a valid, but unprintable character, a
+/// printable, escaped representation of the character is returned, along with
+/// 'false'. Otherwise a printable, escaped representation of the next byte
+/// is returned along with 'false'.
+///
+/// \note The index is updated to be used with a subsequent call to
+/// printableTextForNextCharacter.
+///
+/// \param SourceLine The line of source
+/// \param i Pointer to byte index,
+/// \param TabStop used to expand tabs
+/// \return pair(printable text, 'true' iff original text was printable)
+///
+std::pair<SmallString<16>,bool>
+printableTextForNextCharacter(StringRef SourceLine, size_t *i,
+ unsigned TabStop) {
+ assert(i && "i must not be null");
+ assert(*i<SourceLine.size() && "must point to a valid index");
+
+ if (SourceLine[*i]=='\t') {
+ assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
+ "Invalid -ftabstop value");
+ unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i);
+ unsigned NumSpaces = TabStop - col%TabStop;
+ assert(0 < NumSpaces && NumSpaces <= TabStop
+ && "Invalid computation of space amt");
+ ++(*i);
+
+ SmallString<16> expandedTab;
+ expandedTab.assign(NumSpaces, ' ');
+ return std::make_pair(expandedTab, true);
+ }
+
+ // FIXME: this data is copied from the private implementation of ConvertUTF.h
+ static const char trailingBytesForUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+ };
+
+ unsigned char const *begin, *end;
+ begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
+ end = begin + SourceLine.size();
+
+ if (isLegalUTF8Sequence(begin, end)) {
+ UTF32 c;
+ UTF32 *cptr = &c;
+ unsigned char const *original_begin = begin;
+ char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]];
+ unsigned char const *cp_end = begin+trailingBytes+1;
+
+ ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
+ strictConversion);
+ (void)res;
+ assert(conversionOK==res);
+ assert(0 < begin-original_begin
+ && "we must be further along in the string now");
+ *i += begin-original_begin;
+
+ if (!llvm::sys::locale::isPrint(c)) {
+ // If next character is valid UTF-8, but not printable
+ SmallString<16> expandedCP("<U+>");
+ while (c) {
+ expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
+ c/=16;
+ }
+ while (expandedCP.size() < 8)
+ expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
+ return std::make_pair(expandedCP, false);
+ }
+
+ // If next character is valid UTF-8, and printable
+ return std::make_pair(SmallString<16>(original_begin, cp_end), true);
+
+ }
+
+ // If next byte is not valid UTF-8 (and therefore not printable)
+ SmallString<16> expandedByte("<XX>");
+ unsigned char byte = SourceLine[*i];
+ expandedByte[1] = llvm::hexdigit(byte / 16);
+ expandedByte[2] = llvm::hexdigit(byte % 16);
+ ++(*i);
+ return std::make_pair(expandedByte, false);
+}
+
+void expandTabs(std::string &SourceLine, unsigned TabStop) {
+ size_t i = SourceLine.size();
+ while (i>0) {
+ i--;
+ if (SourceLine[i]!='\t')
+ continue;
+ size_t tmp_i = i;
+ std::pair<SmallString<16>,bool> res
+ = printableTextForNextCharacter(SourceLine, &tmp_i, TabStop);
+ SourceLine.replace(i, 1, res.first.c_str());
+ }
+}
+
+/// This function takes a raw source line and produces a mapping from the bytes
+/// of the printable representation of the line to the columns those printable
+/// characters will appear at (numbering the first column as 0).
+///
+/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
+/// character) then the the array will map that byte to the first column the
+/// tab appears at and the next value in the map will have been incremented
+/// more than once.
+///
+/// If a byte is the first in a sequence of bytes that together map to a single
+/// entity in the output, then the array will map that byte to the appropriate
+/// column while the subsequent bytes will be -1.
+///
+/// The last element in the array does not correspond to any byte in the input
+/// and instead is the number of columns needed to display the source
+///
+/// example: (given a tabstop of 8)
+///
+/// "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
+///
+/// (\u3042 is represented in UTF-8 by three bytes and takes two columns to
+/// display)
+void byteToColumn(StringRef SourceLine, unsigned TabStop,
+ SmallVectorImpl<int> &out) {
+ out.clear();
+
+ if (SourceLine.empty()) {
+ out.resize(1u,0);
+ return;
+ }
+
+ out.resize(SourceLine.size()+1, -1);
+
+ int columns = 0;
+ size_t i = 0;
+ while (i<SourceLine.size()) {
+ out[i] = columns;
+ std::pair<SmallString<16>,bool> res
+ = printableTextForNextCharacter(SourceLine, &i, TabStop);
+ columns += llvm::sys::locale::columnWidth(res.first);
+ }
+ out.back() = columns;
+}
+
+/// This function takes a raw source line and produces a mapping from columns
+/// to the byte of the source line that produced the character displaying at
+/// that column. This is the inverse of the mapping produced by byteToColumn()
+///
+/// The last element in the array is the number of bytes in the source string
+///
+/// example: (given a tabstop of 8)
+///
+/// "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
+///
+/// (\u3042 is represented in UTF-8 by three bytes and takes two columns to
+/// display)
+void columnToByte(StringRef SourceLine, unsigned TabStop,
+ SmallVectorImpl<int> &out) {
+ out.clear();
+
+ if (SourceLine.empty()) {
+ out.resize(1u, 0);
+ return;
+ }
+
+ int columns = 0;
+ size_t i = 0;
+ while (i<SourceLine.size()) {
+ out.resize(columns+1, -1);
+ out.back() = i;
+ std::pair<SmallString<16>,bool> res
+ = printableTextForNextCharacter(SourceLine, &i, TabStop);
+ columns += llvm::sys::locale::columnWidth(res.first);
+ }
+ out.resize(columns+1, -1);
+ out.back() = i;
+}
+
+struct SourceColumnMap {
+ SourceColumnMap(StringRef SourceLine, unsigned TabStop)
+ : m_SourceLine(SourceLine) {
+
+ ::byteToColumn(SourceLine, TabStop, m_byteToColumn);
+ ::columnToByte(SourceLine, TabStop, m_columnToByte);
+
+ assert(m_byteToColumn.size()==SourceLine.size()+1);
+ assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
+ assert(m_byteToColumn.size()
+ == static_cast<unsigned>(m_columnToByte.back()+1));
+ assert(static_cast<unsigned>(m_byteToColumn.back()+1)
+ == m_columnToByte.size());
+ }
+ int columns() const { return m_byteToColumn.back(); }
+ int bytes() const { return m_columnToByte.back(); }
+ int byteToColumn(int n) const {
+ assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
+ return m_byteToColumn[n];
+ }
+ int columnToByte(int n) const {
+ assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
+ return m_columnToByte[n];
+ }
+ StringRef getSourceLine() const {
+ return m_SourceLine;
+ }
+
+private:
+ const std::string m_SourceLine;
+ SmallVector<int,200> m_byteToColumn;
+ SmallVector<int,200> m_columnToByte;
+};
+
+// used in assert in selectInterestingSourceRegion()
+namespace {
+struct char_out_of_range {
+ const char lower,upper;
+ char_out_of_range(char lower, char upper) :
+ lower(lower), upper(upper) {}
+ bool operator()(char c) { return c < lower || upper < c; }
+};
+}
+
/// \brief When the source code line we want to print is too long for
/// the terminal, select the "interesting" region.
static void selectInterestingSourceRegion(std::string &SourceLine,
std::string &CaretLine,
std::string &FixItInsertionLine,
- unsigned EndOfCaretToken,
- unsigned Columns) {
- unsigned MaxSize = std::max(SourceLine.size(),
- std::max(CaretLine.size(),
- FixItInsertionLine.size()));
- if (MaxSize > SourceLine.size())
- SourceLine.resize(MaxSize, ' ');
- if (MaxSize > CaretLine.size())
- CaretLine.resize(MaxSize, ' ');
- if (!FixItInsertionLine.empty() && MaxSize > FixItInsertionLine.size())
- FixItInsertionLine.resize(MaxSize, ' ');
-
+ unsigned Columns,
+ const SourceColumnMap &map) {
+ unsigned MaxColumns = std::max<unsigned>(map.columns(),
+ std::max(CaretLine.size(),
+ FixItInsertionLine.size()));
+ // if the number of columns is less than the desired number we're done
+ if (MaxColumns <= Columns)
+ return;
+
+ // no special characters allowed in CaretLine or FixItInsertionLine
+ assert(CaretLine.end() ==
+ std::find_if(CaretLine.begin(), CaretLine.end(),
+ char_out_of_range(' ','~')));
+ assert(FixItInsertionLine.end() ==
+ std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
+ char_out_of_range(' ','~')));
+
// Find the slice that we need to display the full caret line
// correctly.
unsigned CaretStart = 0, CaretEnd = CaretLine.size();
@@ -64,10 +314,8 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
if (!isspace(CaretLine[CaretEnd - 1]))
break;
- // Make sure we don't chop the string shorter than the caret token
- // itself.
- if (CaretEnd < EndOfCaretToken)
- CaretEnd = EndOfCaretToken;
+ // caret has already been inserted into CaretLine so the above whitespace
+ // check is guaranteed to include the caret
// If we have a fix-it line, make sure the slice includes all of the
// fix-it information.
@@ -81,10 +329,8 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
if (!isspace(FixItInsertionLine[FixItEnd - 1]))
break;
- if (FixItStart < CaretStart)
- CaretStart = FixItStart;
- if (FixItEnd > CaretEnd)
- CaretEnd = FixItEnd;
+ CaretStart = std::min(FixItStart, CaretStart);
+ CaretEnd = std::max(FixItEnd, CaretEnd);
}
// CaretLine[CaretStart, CaretEnd) contains all of the interesting
@@ -92,62 +338,72 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// number of columns we have, try to grow the slice to encompass
// more context.
- // If the end of the interesting region comes before we run out of
- // space in the terminal, start at the beginning of the line.
- if (Columns > 3 && CaretEnd < Columns - 3)
- CaretStart = 0;
+ unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
+ map.columns()));
+ unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
+ map.columns()));
+
+ unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
+ - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
+
+ char const *front_ellipse = " ...";
+ char const *front_space = " ";
+ char const *back_ellipse = "...";
+ unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
unsigned TargetColumns = Columns;
- if (TargetColumns > 8)
- TargetColumns -= 8; // Give us extra room for the ellipses.
- unsigned SourceLength = SourceLine.size();
- while ((CaretEnd - CaretStart) < TargetColumns) {
+ // Give us extra room for the ellipses
+ // and any of the caret line that extends past the source
+ if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
+ TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
+
+ while (SourceStart>0 || SourceEnd<SourceLine.size()) {
bool ExpandedRegion = false;
- // Move the start of the interesting region left until we've
- // pulled in something else interesting.
- if (CaretStart == 1)
- CaretStart = 0;
- else if (CaretStart > 1) {
- unsigned NewStart = CaretStart - 1;
+
+ if (SourceStart>0) {
+ unsigned NewStart = SourceStart-1;
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
- while (NewStart && isspace(SourceLine[NewStart]))
+ while (NewStart &&
+ (map.byteToColumn(NewStart)==-1 || isspace(SourceLine[NewStart])))
--NewStart;
// Skip over this bit of "interesting" text.
- while (NewStart && !isspace(SourceLine[NewStart]))
+ while (NewStart &&
+ (map.byteToColumn(NewStart)!=-1 && !isspace(SourceLine[NewStart])))
--NewStart;
// Move up to the non-whitespace character we just saw.
if (NewStart)
++NewStart;
- // If we're still within our limit, update the starting
- // position within the source/caret line.
- if (CaretEnd - NewStart <= TargetColumns) {
- CaretStart = NewStart;
+ unsigned NewColumns = map.byteToColumn(SourceEnd) -
+ map.byteToColumn(NewStart);
+ if (NewColumns <= TargetColumns) {
+ SourceStart = NewStart;
ExpandedRegion = true;
}
}
- // Move the end of the interesting region right until we've
- // pulled in something else interesting.
- if (CaretEnd != SourceLength) {
- assert(CaretEnd < SourceLength && "Unexpected caret position!");
- unsigned NewEnd = CaretEnd;
+ if (SourceEnd<SourceLine.size()) {
+ unsigned NewEnd = SourceEnd+1;
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
- while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1]))
+ while (NewEnd<SourceLine.size() &&
+ (map.byteToColumn(NewEnd)==-1 || isspace(SourceLine[NewEnd])))
++NewEnd;
// Skip over this bit of "interesting" text.
- while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1]))
+ while (NewEnd<SourceLine.size() &&
+ (map.byteToColumn(NewEnd)!=-1 && !isspace(SourceLine[NewEnd])))
++NewEnd;
- if (NewEnd - CaretStart <= TargetColumns) {
- CaretEnd = NewEnd;
+ unsigned NewColumns = map.byteToColumn(NewEnd) -
+ map.byteToColumn(SourceStart);
+ if (NewColumns <= TargetColumns) {
+ SourceEnd = NewEnd;
ExpandedRegion = true;
}
}
@@ -156,21 +412,41 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
break;
}
+ CaretStart = map.byteToColumn(SourceStart);
+ CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
+
// [CaretStart, CaretEnd) is the slice we want. Update the various
// output lines to show only this slice, with two-space padding
// before the lines so that it looks nicer.
- if (CaretEnd < SourceLine.size())
- SourceLine.replace(CaretEnd, std::string::npos, "...");
- if (CaretEnd < CaretLine.size())
- CaretLine.erase(CaretEnd, std::string::npos);
- if (FixItInsertionLine.size() > CaretEnd)
- FixItInsertionLine.erase(CaretEnd, std::string::npos);
-
- if (CaretStart > 2) {
- SourceLine.replace(0, CaretStart, " ...");
- CaretLine.replace(0, CaretStart, " ");
- if (FixItInsertionLine.size() >= CaretStart)
- FixItInsertionLine.replace(0, CaretStart, " ");
+
+ assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
+ SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
+ assert(SourceStart <= SourceEnd);
+ assert(CaretStart <= CaretEnd);
+
+ unsigned BackColumnsRemoved
+ = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
+ unsigned FrontColumnsRemoved = CaretStart;
+ unsigned ColumnsKept = CaretEnd-CaretStart;
+
+ // We checked up front that the line needed truncation
+ assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
+
+ // The line needs some trunctiona, and we'd prefer to keep the front
+ // if possible, so remove the back
+ if (BackColumnsRemoved)
+ SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
+
+ // If that's enough then we're done
+ if (FrontColumnsRemoved+ColumnsKept <= Columns)
+ return;
+
+ // Otherwise remove the front as well
+ if (FrontColumnsRemoved) {
+ SourceLine.replace(0, SourceStart, front_ellipse);
+ CaretLine.replace(0, CaretStart, front_space);
+ if (!FixItInsertionLine.empty())
+ FixItInsertionLine.replace(0, CaretStart, front_space);
}
}
@@ -564,10 +840,13 @@ void TextDiagnostic::emitSnippetAndCaret(
// Get information about the buffer it points into.
bool Invalid = false;
- const char *BufStart = SM.getBufferData(FID, &Invalid).data();
+ StringRef BufData = SM.getBufferData(FID, &Invalid);
if (Invalid)
return;
+ const char *BufStart = BufData.data();
+ const char *BufEnd = BufStart + BufData.size();
+
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
unsigned CaretEndColNo
@@ -581,7 +860,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
- while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
+ while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd!=BufEnd)
++LineEnd;
// FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
@@ -596,19 +875,30 @@ void TextDiagnostic::emitSnippetAndCaret(
// length as the line of source code.
std::string CaretLine(LineEnd-LineStart, ' ');
+ const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
+
// Highlight all of the characters covered by Ranges with ~ characters.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
- highlightRange(*I, LineNo, FID, SourceLine, CaretLine);
+ highlightRange(*I, LineNo, FID, sourceColMap, CaretLine);
// Next, insert the caret itself.
- if (ColNo-1 < CaretLine.size())
- CaretLine[ColNo-1] = '^';
- else
- CaretLine.push_back('^');
+ ColNo = sourceColMap.byteToColumn(ColNo-1);
+ if (CaretLine.size()<ColNo+1)
+ CaretLine.resize(ColNo+1, ' ');
+ CaretLine[ColNo] = '^';
+
+ std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
+ sourceColMap,
+ Hints);
- expandTabs(SourceLine, CaretLine);
+ // If the source line is too long for our terminal, select only the
+ // "interesting" source region within that line.
+ unsigned Columns = DiagOpts.MessageLength;
+ if (Columns)
+ selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
+ Columns, sourceColMap);
// If we are in -fdiagnostics-print-source-range-info mode, we are trying
// to produce easily machine parsable output. Add a space before the
@@ -619,23 +909,12 @@ void TextDiagnostic::emitSnippetAndCaret(
CaretLine = ' ' + CaretLine;
}
- std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
- LineStart, LineEnd,
- Hints);
-
- // If the source line is too long for our terminal, select only the
- // "interesting" source region within that line.
- unsigned Columns = DiagOpts.MessageLength;
- if (Columns && SourceLine.size() > Columns)
- selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
- CaretEndColNo, Columns);
-
// Finally, remove any blank spaces from the end of CaretLine.
while (CaretLine[CaretLine.size()-1] == ' ')
CaretLine.erase(CaretLine.end()-1);
// Emit what we have computed.
- OS << SourceLine << '\n';
+ emitSnippet(SourceLine);
if (DiagOpts.ShowColors)
OS.changeColor(caretColor, true);
@@ -658,13 +937,49 @@ void TextDiagnostic::emitSnippetAndCaret(
emitParseableFixits(Hints);
}
+void TextDiagnostic::emitSnippet(StringRef line)
+{
+ if (line.empty())
+ return;
+
+ size_t i = 0;
+
+ std::string to_print;
+ bool print_reversed = false;
+
+ while (i<line.size()) {
+ std::pair<SmallString<16>,bool> res
+ = printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
+ bool was_printable = res.second;
+
+ if (DiagOpts.ShowColors
+ && was_printable==print_reversed) {
+ if (print_reversed)
+ OS.reverseColor();
+ OS << to_print;
+ to_print.clear();
+ if (DiagOpts.ShowColors)
+ OS.resetColor();
+ }
+
+ print_reversed = !was_printable;
+ to_print += res.first.str();
+ }
+
+ if (print_reversed && DiagOpts.ShowColors)
+ OS.reverseColor();
+ OS << to_print;
+ if (print_reversed && DiagOpts.ShowColors)
+ OS.resetColor();
+
+ OS << '\n';
+}
+
/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
void TextDiagnostic::highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
- const std::string &SourceLine,
+ const SourceColumnMap &map,
std::string &CaretLine) {
- assert(CaretLine.size() == SourceLine.size() &&
- "Expect a correspondence between source and caret line!");
if (!R.isValid()) return;
SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
@@ -694,7 +1009,7 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
}
// Compute the column number of the end.
- unsigned EndColNo = CaretLine.size();
+ unsigned EndColNo = map.getSourceLine().size();
if (EndLineNo == LineNo) {
EndColNo = SM.getExpansionColumnNumber(End);
if (EndColNo) {
@@ -714,15 +1029,17 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
// Check that a token range does not highlight only whitespace.
if (R.isTokenRange()) {
// Pick the first non-whitespace column.
- while (StartColNo < SourceLine.size() &&
- (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
+ while (StartColNo < map.getSourceLine().size() &&
+ (map.getSourceLine()[StartColNo] == ' ' ||
+ map.getSourceLine()[StartColNo] == '\t'))
++StartColNo;
// Pick the last non-whitespace column.
- if (EndColNo > SourceLine.size())
- EndColNo = SourceLine.size();
+ if (EndColNo > map.getSourceLine().size())
+ EndColNo = map.getSourceLine().size();
while (EndColNo-1 &&
- (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
+ (map.getSourceLine()[EndColNo-1] == ' ' ||
+ map.getSourceLine()[EndColNo-1] == '\t'))
--EndColNo;
// If the start/end passed each other, then we are trying to highlight a
@@ -731,15 +1048,24 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
}
+ assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
+ assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
+
// Fill the range with ~'s.
- for (unsigned i = StartColNo; i < EndColNo; ++i)
- CaretLine[i] = '~';
+ StartColNo = map.byteToColumn(StartColNo);
+ EndColNo = map.byteToColumn(EndColNo);
+
+ assert(StartColNo <= EndColNo && "Invalid range!");
+ if (CaretLine.size() < EndColNo)
+ CaretLine.resize(EndColNo,' ');
+ std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
}
-std::string TextDiagnostic::buildFixItInsertionLine(unsigned LineNo,
- const char *LineStart,
- const char *LineEnd,
- ArrayRef<FixItHint> Hints) {
+std::string TextDiagnostic::buildFixItInsertionLine(
+ unsigned LineNo,
+ const SourceColumnMap &map,
+ ArrayRef<FixItHint> Hints) {
+
std::string FixItInsertionLine;
if (Hints.empty() || !DiagOpts.ShowFixits)
return FixItInsertionLine;
@@ -755,13 +1081,32 @@ std::string TextDiagnostic::buildFixItInsertionLine(unsigned LineNo,
// Insert the new code into the line just below the code
// that the user wrote.
unsigned HintColNo
- = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second);
+ = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
+ // hint must start inside the source or right at the end
+ assert(HintColNo<static_cast<unsigned>(map.bytes())+1);
+ HintColNo = map.byteToColumn(HintColNo);
+
+ // FIXME: if the fixit includes tabs or other characters that do not
+ // take up a single column per byte when displayed then
+ // I->CodeToInsert.size() is not a column number and we're mixing
+ // units (columns + bytes). We should get printable versions
+ // of each fixit before using them.
unsigned LastColumnModified
- = HintColNo - 1 + I->CodeToInsert.size();
+ = HintColNo + I->CodeToInsert.size();
+
+ if (LastColumnModified > static_cast<unsigned>(map.bytes())) {
+ unsigned LastExistingColumn = map.byteToColumn(map.bytes());
+ unsigned AddedColumns = LastColumnModified-LastExistingColumn;
+ LastColumnModified = LastExistingColumn + AddedColumns;
+ } else {
+ LastColumnModified = map.byteToColumn(LastColumnModified);
+ }
+
if (LastColumnModified > FixItInsertionLine.size())
FixItInsertionLine.resize(LastColumnModified, ' ');
+ assert(HintColNo+I->CodeToInsert.size() <= FixItInsertionLine.size());
std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
- FixItInsertionLine.begin() + HintColNo - 1);
+ FixItInsertionLine.begin() + HintColNo);
} else {
FixItInsertionLine.clear();
break;
@@ -769,72 +1114,11 @@ std::string TextDiagnostic::buildFixItInsertionLine(unsigned LineNo,
}
}
- if (FixItInsertionLine.empty())
- return FixItInsertionLine;
-
- // Now that we have the entire fixit line, expand the tabs in it.
- // Since we don't want to insert spaces in the middle of a word,
- // find each word and the column it should line up with and insert
- // spaces until they match.
- unsigned FixItPos = 0;
- unsigned LinePos = 0;
- unsigned TabExpandedCol = 0;
- unsigned LineLength = LineEnd - LineStart;
-
- while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) {
- // Find the next word in the FixIt line.
- while (FixItPos < FixItInsertionLine.size() &&
- FixItInsertionLine[FixItPos] == ' ')
- ++FixItPos;
- unsigned CharDistance = FixItPos - TabExpandedCol;
-
- // Walk forward in the source line, keeping track of
- // the tab-expanded column.
- for (unsigned I = 0; I < CharDistance; ++I, ++LinePos)
- if (LinePos >= LineLength || LineStart[LinePos] != '\t')
- ++TabExpandedCol;
- else
- TabExpandedCol =
- (TabExpandedCol/DiagOpts.TabStop + 1) * DiagOpts.TabStop;
-
- // Adjust the fixit line to match this column.
- FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' ');
- FixItPos = TabExpandedCol;
-
- // Walk to the end of the word.
- while (FixItPos < FixItInsertionLine.size() &&
- FixItInsertionLine[FixItPos] != ' ')
- ++FixItPos;
- }
+ expandTabs(FixItInsertionLine, DiagOpts.TabStop);
return FixItInsertionLine;
}
-void TextDiagnostic::expandTabs(std::string &SourceLine,
- std::string &CaretLine) {
- // Scan the source line, looking for tabs. If we find any, manually expand
- // them to spaces and update the CaretLine to match.
- for (unsigned i = 0; i != SourceLine.size(); ++i) {
- if (SourceLine[i] != '\t') continue;
-
- // Replace this tab with at least one space.
- SourceLine[i] = ' ';
-
- // Compute the number of spaces we need to insert.
- unsigned TabStop = DiagOpts.TabStop;
- assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
- "Invalid -ftabstop value");
- unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1);
- assert(NumSpaces < TabStop && "Invalid computation of space amt");
-
- // Insert spaces into the SourceLine.
- SourceLine.insert(i+1, NumSpaces, ' ');
-
- // Insert spaces or ~'s into CaretLine.
- CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
- }
-}
-
void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
if (!DiagOpts.ShowParseableFixits)
return;
@@ -878,4 +1162,3 @@ void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
OS << "\"\n";
}
}
-
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 2066505..07d2b8d 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -72,7 +72,6 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case PrintDeclContext: return new DeclContextPrintAction();
case PrintPreamble: return new PrintPreambleAction();
case PrintPreprocessedInput: return new PrintPreprocessedAction();
- case PubnamesDump: return new PubnamesDumpAction();
case RewriteMacros: return new RewriteMacrosAction();
case RewriteObjC: return new RewriteObjCAction();
case RewriteTest: return new RewriteTestAction();
diff --git a/lib/Headers/avx2intrin.h b/lib/Headers/avx2intrin.h
index d165f1f..884c46d 100644
--- a/lib/Headers/avx2intrin.h
+++ b/lib/Headers/avx2intrin.h
@@ -822,7 +822,9 @@ _mm256_permutevar8x32_epi32(__m256i a, __m256i b)
#define _mm256_permute4x64_pd(V, M) __extension__ ({ \
__m256d __V = (V); \
- (__m256d)__builtin_ia32_permdf256((__v4df)__V, (M)); })
+ (__m256d)__builtin_shufflevector((__v4df)__V, (__v4df) _mm256_setzero_pd(), \
+ (M) & 0x3, ((M) & 0xc) >> 2, \
+ ((M) & 0x30) >> 4, ((M) & 0xc0) >> 6); })
static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))
_mm256_permutevar8x32_ps(__m256 a, __m256 b)
@@ -832,16 +834,14 @@ _mm256_permutevar8x32_ps(__m256 a, __m256 b)
#define _mm256_permute4x64_epi64(V, M) __extension__ ({ \
__m256i __V = (V); \
- (__m256i)__builtin_ia32_permdi256(__V, (M)); })
+ (__m256i)__builtin_shufflevector((__v4di)__V, (__v4di) _mm256_setzero_si256(), \
+ (M) & 0x3, ((M) & 0xc) >> 2, \
+ ((M) & 0x30) >> 4, ((M) & 0xc0) >> 6); })
#define _mm256_permute2x128_si256(V1, V2, M) __extension__ ({ \
__m256i __V1 = (V1); \
__m256i __V2 = (V2); \
- __builtin_shufflevector(__V1, __V2, \
- ((M) & 0x3) * 2, \
- ((M) & 0x3) * 2 + 1, \
- (((M) & 0x30) >> 4) * 2, \
- (((M) & 0x30) >> 4) * 2 + 1); })
+ (__m256i)__builtin_ia32_permti256(__V1, __V2, (M)); })
#define _mm256_extracti128_si256(A, O) __extension__ ({ \
__m256i __A = (A); \
diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h
index 7a0ec3f..ee7f835 100644
--- a/lib/Headers/avxintrin.h
+++ b/lib/Headers/avxintrin.h
@@ -289,37 +289,17 @@ _mm256_permutevar_ps(__m256 a, __m256i c)
#define _mm256_permute2f128_pd(V1, V2, M) __extension__ ({ \
__m256d __V1 = (V1); \
__m256d __V2 = (V2); \
- (__m256d)__builtin_shufflevector((__v4df)__V1, (__v4df)__V2, \
- ((M) & 0x3) * 2, \
- ((M) & 0x3) * 2 + 1, \
- (((M) & 0x30) >> 4) * 2, \
- (((M) & 0x30) >> 4) * 2 + 1); })
+ (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)__V1, (__v4df)__V2, (M)); })
#define _mm256_permute2f128_ps(V1, V2, M) __extension__ ({ \
__m256 __V1 = (V1); \
__m256 __V2 = (V2); \
- (__m256)__builtin_shufflevector((__v8sf)__V1, (__v8sf)__V2, \
- ((M) & 0x3) * 4, \
- ((M) & 0x3) * 4 + 1, \
- ((M) & 0x3) * 4 + 2, \
- ((M) & 0x3) * 4 + 3, \
- (((M) & 0x30) >> 4) * 4, \
- (((M) & 0x30) >> 4) * 4 + 1, \
- (((M) & 0x30) >> 4) * 4 + 2, \
- (((M) & 0x30) >> 4) * 4 + 3); })
+ (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)__V1, (__v8sf)__V2, (M)); })
#define _mm256_permute2f128_si256(V1, V2, M) __extension__ ({ \
__m256i __V1 = (V1); \
__m256i __V2 = (V2); \
- (__m256i)__builtin_shufflevector((__v8si)__V1, (__v8si)__V2, \
- ((M) & 0x3) * 4, \
- ((M) & 0x3) * 4 + 1, \
- ((M) & 0x3) * 4 + 2, \
- ((M) & 0x3) * 4 + 3, \
- (((M) & 0x30) >> 4) * 4, \
- (((M) & 0x30) >> 4) * 4 + 1, \
- (((M) & 0x30) >> 4) * 4 + 2, \
- (((M) & 0x30) >> 4) * 4 + 3); })
+ (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)__V1, (__v8si)__V2, (M)); })
/* Vector Blend */
#define _mm256_blend_pd(V1, V2, M) __extension__ ({ \
diff --git a/lib/Index/ASTLocation.cpp b/lib/Index/ASTLocation.cpp
deleted file mode 100644
index fce6099..0000000
--- a/lib/Index/ASTLocation.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-//===--- ASTLocation.cpp - A <Decl, Stmt> pair ------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// ASTLocation is Decl or a Stmt and its immediate Decl parent.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/ASTLocation.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/Stmt.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprObjC.h"
-using namespace clang;
-using namespace idx;
-
-static Decl *getDeclFromExpr(Stmt *E) {
- if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
- return RefExpr->getDecl();
- if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
- return ME->getMemberDecl();
- if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
- return RE->getDecl();
-
- if (CallExpr *CE = dyn_cast<CallExpr>(E))
- return getDeclFromExpr(CE->getCallee());
- if (CastExpr *CE = dyn_cast<CastExpr>(E))
- return getDeclFromExpr(CE->getSubExpr());
-
- return 0;
-}
-
-Decl *ASTLocation::getReferencedDecl() {
- if (isInvalid())
- return 0;
-
- switch (getKind()) {
- case N_Type:
- return 0;
- case N_Decl:
- return D;
- case N_NamedRef:
- return NDRef.ND;
- case N_Stmt:
- return getDeclFromExpr(Stm);
- }
-
- llvm_unreachable("Invalid ASTLocation Kind!");
-}
-
-SourceRange ASTLocation::getSourceRange() const {
- if (isInvalid())
- return SourceRange();
-
- switch (getKind()) {
- case N_Decl:
- return D->getSourceRange();
- case N_Stmt:
- return Stm->getSourceRange();
- case N_NamedRef:
- return SourceRange(AsNamedRef().Loc, AsNamedRef().Loc);
- case N_Type:
- return AsTypeLoc().getLocalSourceRange();
- }
-
- llvm_unreachable("Invalid ASTLocation Kind!");
-}
-
-void ASTLocation::print(raw_ostream &OS) const {
- if (isInvalid()) {
- OS << "<< Invalid ASTLocation >>\n";
- return;
- }
-
- ASTContext &Ctx = getParentDecl()->getASTContext();
-
- switch (getKind()) {
- case N_Decl:
- OS << "[Decl: " << AsDecl()->getDeclKindName() << " ";
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl()))
- OS << *ND;
- break;
-
- case N_Stmt:
- OS << "[Stmt: " << AsStmt()->getStmtClassName() << " ";
- AsStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOpts()));
- break;
-
- case N_NamedRef:
- OS << "[NamedRef: " << AsNamedRef().ND->getDeclKindName() << " ";
- OS << *AsNamedRef().ND;
- break;
-
- case N_Type: {
- QualType T = AsTypeLoc().getType();
- OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();
- }
- }
-
- OS << "] <";
-
- SourceRange Range = getSourceRange();
- SourceManager &SourceMgr = Ctx.getSourceManager();
- Range.getBegin().print(OS, SourceMgr);
- OS << ", ";
- Range.getEnd().print(OS, SourceMgr);
- OS << ">\n";
-}
diff --git a/lib/Index/ASTVisitor.h b/lib/Index/ASTVisitor.h
deleted file mode 100644
index 0b8425b..0000000
--- a/lib/Index/ASTVisitor.h
+++ /dev/null
@@ -1,143 +0,0 @@
-//===--- ASTVisitor.h - Visitor for an ASTContext ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the ASTVisitor interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INDEX_ASTVISITOR_H
-#define LLVM_CLANG_INDEX_ASTVISITOR_H
-
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeLocVisitor.h"
-
-namespace clang {
-
-namespace idx {
-
-/// \brief Traverses the full AST, both Decls and Stmts.
-template<typename ImplClass>
-class ASTVisitor : public DeclVisitor<ImplClass>,
- public StmtVisitor<ImplClass>,
- public TypeLocVisitor<ImplClass> {
-public:
- ASTVisitor() : CurrentDecl(0) { }
-
- Decl *CurrentDecl;
-
- typedef ASTVisitor<ImplClass> Base;
- typedef DeclVisitor<ImplClass> BaseDeclVisitor;
- typedef StmtVisitor<ImplClass> BaseStmtVisitor;
- typedef TypeLocVisitor<ImplClass> BaseTypeLocVisitor;
-
- using BaseStmtVisitor::Visit;
-
- //===--------------------------------------------------------------------===//
- // DeclVisitor
- //===--------------------------------------------------------------------===//
-
- void Visit(Decl *D) {
- Decl *PrevDecl = CurrentDecl;
- CurrentDecl = D;
- BaseDeclVisitor::Visit(D);
- CurrentDecl = PrevDecl;
- }
-
- void VisitDeclaratorDecl(DeclaratorDecl *D) {
- BaseDeclVisitor::VisitDeclaratorDecl(D);
- if (TypeSourceInfo *TInfo = D->getTypeSourceInfo())
- Visit(TInfo->getTypeLoc());
- }
-
- void VisitFunctionDecl(FunctionDecl *D) {
- BaseDeclVisitor::VisitFunctionDecl(D);
- if (D->isThisDeclarationADefinition())
- Visit(D->getBody());
- }
-
- void VisitObjCMethodDecl(ObjCMethodDecl *D) {
- BaseDeclVisitor::VisitObjCMethodDecl(D);
- if (D->getBody())
- Visit(D->getBody());
- }
-
- void VisitBlockDecl(BlockDecl *D) {
- BaseDeclVisitor::VisitBlockDecl(D);
- Visit(D->getBody());
- }
-
- void VisitVarDecl(VarDecl *D) {
- BaseDeclVisitor::VisitVarDecl(D);
- if (Expr *Init = D->getInit())
- Visit(Init);
- }
-
- void VisitDecl(Decl *D) {
- if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D))
- return;
-
- if (DeclContext *DC = dyn_cast<DeclContext>(D))
- static_cast<ImplClass*>(this)->VisitDeclContext(DC);
- }
-
- void VisitDeclContext(DeclContext *DC) {
- for (DeclContext::decl_iterator
- I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
- Visit(*I);
- }
-
- //===--------------------------------------------------------------------===//
- // StmtVisitor
- //===--------------------------------------------------------------------===//
-
- void VisitDeclStmt(DeclStmt *Node) {
- for (DeclStmt::decl_iterator
- I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I)
- Visit(*I);
- }
-
- void VisitBlockExpr(BlockExpr *Node) {
- // The BlockDecl is also visited by 'VisitDeclContext()'. No need to visit it twice.
- }
-
- void VisitStmt(Stmt *Node) {
- for (Stmt::child_range I = Node->children(); I; ++I)
- if (*I)
- Visit(*I);
- }
-
- //===--------------------------------------------------------------------===//
- // TypeLocVisitor
- //===--------------------------------------------------------------------===//
-
- void Visit(TypeLoc TL) {
- for (; TL; TL = TL.getNextTypeLoc())
- BaseTypeLocVisitor::Visit(TL);
- }
-
- void VisitArrayLoc(ArrayTypeLoc TL) {
- BaseTypeLocVisitor::VisitArrayTypeLoc(TL);
- if (TL.getSizeExpr())
- Visit(TL.getSizeExpr());
- }
-
- void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);
- for (unsigned i = 0; i != TL.getNumArgs(); ++i)
- Visit(TL.getArg(i));
- }
-
-};
-
-} // namespace idx
-
-} // namespace clang
-
-#endif
diff --git a/lib/Index/Analyzer.cpp b/lib/Index/Analyzer.cpp
deleted file mode 100644
index f77e6ef..0000000
--- a/lib/Index/Analyzer.cpp
+++ /dev/null
@@ -1,470 +0,0 @@
-//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
-//
-// 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 Analyzer interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/Analyzer.h"
-#include "clang/Index/Entity.h"
-#include "clang/Index/TranslationUnit.h"
-#include "clang/Index/Handlers.h"
-#include "clang/Index/ASTLocation.h"
-#include "clang/Index/GlobalSelector.h"
-#include "clang/Index/DeclReferenceMap.h"
-#include "clang/Index/SelectorMap.h"
-#include "clang/Index/IndexProvider.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ExprObjC.h"
-#include "llvm/ADT/SmallSet.h"
-using namespace clang;
-using namespace idx;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// DeclEntityAnalyzer Implementation
-//===----------------------------------------------------------------------===//
-
-class DeclEntityAnalyzer : public TranslationUnitHandler {
- Entity Ent;
- TULocationHandler &TULocHandler;
-
-public:
- DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
- : Ent(ent), TULocHandler(handler) { }
-
- virtual void Handle(TranslationUnit *TU) {
- assert(TU && "Passed null translation unit");
-
- Decl *D = Ent.getDecl(TU->getASTContext());
- assert(D && "Couldn't resolve Entity");
-
- for (Decl::redecl_iterator I = D->redecls_begin(),
- E = D->redecls_end(); I != E; ++I)
- TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
- }
-};
-
-//===----------------------------------------------------------------------===//
-// RefEntityAnalyzer Implementation
-//===----------------------------------------------------------------------===//
-
-class RefEntityAnalyzer : public TranslationUnitHandler {
- Entity Ent;
- TULocationHandler &TULocHandler;
-
-public:
- RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
- : Ent(ent), TULocHandler(handler) { }
-
- virtual void Handle(TranslationUnit *TU) {
- assert(TU && "Passed null translation unit");
-
- Decl *D = Ent.getDecl(TU->getASTContext());
- assert(D && "Couldn't resolve Entity");
- NamedDecl *ND = dyn_cast<NamedDecl>(D);
- if (!ND)
- return;
-
- DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
- for (DeclReferenceMap::astlocation_iterator
- I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
- TULocHandler.Handle(TULocation(TU, *I));
- }
-};
-
-//===----------------------------------------------------------------------===//
-// RefSelectorAnalyzer Implementation
-//===----------------------------------------------------------------------===//
-
-/// \brief Accepts an ObjC method and finds all message expressions that this
-/// method may respond to.
-class RefSelectorAnalyzer : public TranslationUnitHandler {
- Program &Prog;
- TULocationHandler &TULocHandler;
-
- // The original ObjCInterface associated with the method.
- Entity IFaceEnt;
- GlobalSelector GlobSel;
- bool IsInstanceMethod;
-
- /// \brief Super classes of the ObjCInterface.
- typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
- EntitiesSetTy HierarchyEntities;
-
-public:
- RefSelectorAnalyzer(ObjCMethodDecl *MD,
- Program &prog, TULocationHandler &handler)
- : Prog(prog), TULocHandler(handler) {
- assert(MD);
-
- // FIXME: Protocol methods.
- assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
- "Protocol methods not supported yet");
-
- ObjCInterfaceDecl *IFD = MD->getClassInterface();
- assert(IFD);
- IFaceEnt = Entity::get(IFD, Prog);
- GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
- IsInstanceMethod = MD->isInstanceMethod();
-
- for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
- Cls; Cls = Cls->getSuperClass())
- HierarchyEntities.insert(Entity::get(Cls, Prog));
- }
-
- virtual void Handle(TranslationUnit *TU) {
- assert(TU && "Passed null translation unit");
-
- ASTContext &Ctx = TU->getASTContext();
- // Null means it doesn't exist in this translation unit.
- ObjCInterfaceDecl *IFace =
- cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
- Selector Sel = GlobSel.getSelector(Ctx);
-
- SelectorMap &SelMap = TU->getSelectorMap();
- for (SelectorMap::astlocation_iterator
- I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
- if (ValidReference(*I, IFace))
- TULocHandler.Handle(TULocation(TU, *I));
- }
- }
-
- /// \brief Determines whether the given message expression is likely to end
- /// up at the given interface decl.
- ///
- /// It returns true "eagerly", meaning it will return false only if it can
- /// "prove" statically that the interface cannot accept this message.
- bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
- assert(ASTLoc.isStmt());
-
- // FIXME: Finding @selector references should be through another Analyzer
- // method, like FindSelectors.
- if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
- return false;
-
- ObjCInterfaceDecl *MsgD = 0;
- ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
-
- switch (Msg->getReceiverKind()) {
- case ObjCMessageExpr::Instance: {
- const ObjCObjectPointerType *OPT =
- Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
-
- // Can be anything! Accept it as a possibility..
- if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
- return true;
-
- // Expecting class method.
- if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
- return !IsInstanceMethod;
-
- MsgD = OPT->getInterfaceDecl();
- assert(MsgD);
-
- // Should be an instance method.
- if (!IsInstanceMethod)
- return false;
- break;
- }
-
- case ObjCMessageExpr::Class: {
- // Expecting class method.
- if (IsInstanceMethod)
- return false;
-
- MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
- break;
- }
-
- case ObjCMessageExpr::SuperClass:
- // Expecting class method.
- if (IsInstanceMethod)
- return false;
-
- MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
- break;
-
- case ObjCMessageExpr::SuperInstance:
- // Expecting instance method.
- if (!IsInstanceMethod)
- return false;
-
- MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
- ->getInterfaceDecl();
- break;
- }
-
- assert(MsgD);
-
- // Same interface ? We have a winner!
- if (declaresSameEntity(MsgD, IFace))
- return true;
-
- // If the message interface is a superclass of the original interface,
- // accept this message as a possibility.
- if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
- return true;
-
- // If the message interface is a subclass of the original interface, accept
- // the message unless there is a subclass in the hierarchy that will
- // "steal" the message (thus the message "will go" to the subclass and not
- /// the original interface).
- if (IFace) {
- Selector Sel = Msg->getSelector();
- for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
- if (declaresSameEntity(Cls, IFace))
- return true;
- if (Cls->getMethod(Sel, IsInstanceMethod))
- return false;
- }
- }
-
- // The interfaces are unrelated, don't accept the message.
- return false;
- }
-};
-
-//===----------------------------------------------------------------------===//
-// MessageAnalyzer Implementation
-//===----------------------------------------------------------------------===//
-
-/// \brief Accepts an ObjC message expression and finds all methods that may
-/// respond to it.
-class MessageAnalyzer : public TranslationUnitHandler {
- Program &Prog;
- TULocationHandler &TULocHandler;
-
- // The ObjCInterface associated with the message. Can be null/invalid.
- Entity MsgIFaceEnt;
- GlobalSelector GlobSel;
- bool CanBeInstanceMethod;
- bool CanBeClassMethod;
-
- /// \brief Super classes of the ObjCInterface.
- typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
- EntitiesSetTy HierarchyEntities;
-
- /// \brief The interface in the message interface hierarchy that "intercepts"
- /// the selector.
- Entity ReceiverIFaceEnt;
-
-public:
- MessageAnalyzer(ObjCMessageExpr *Msg,
- Program &prog, TULocationHandler &handler)
- : Prog(prog), TULocHandler(handler),
- CanBeInstanceMethod(false),
- CanBeClassMethod(false) {
-
- assert(Msg);
-
- ObjCInterfaceDecl *MsgD = 0;
-
- while (true) {
- switch (Msg->getReceiverKind()) {
- case ObjCMessageExpr::Instance: {
- const ObjCObjectPointerType *OPT =
- Msg->getInstanceReceiver()->getType()
- ->getAsObjCInterfacePointerType();
-
- if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
- CanBeInstanceMethod = CanBeClassMethod = true;
- break;
- }
-
- if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
- CanBeClassMethod = true;
- break;
- }
-
- MsgD = OPT->getInterfaceDecl();
- assert(MsgD);
- CanBeInstanceMethod = true;
- break;
- }
-
- case ObjCMessageExpr::Class:
- CanBeClassMethod = true;
- MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
- break;
-
- case ObjCMessageExpr::SuperClass:
- CanBeClassMethod = true;
- MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
- break;
-
- case ObjCMessageExpr::SuperInstance:
- CanBeInstanceMethod = true;
- MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
- ->getInterfaceDecl();
- break;
- }
- }
-
- assert(CanBeInstanceMethod || CanBeClassMethod);
-
- Selector sel = Msg->getSelector();
- assert(!sel.isNull());
-
- MsgIFaceEnt = Entity::get(MsgD, Prog);
- GlobSel = GlobalSelector::get(sel, Prog);
-
- if (MsgD) {
- for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
- Cls; Cls = Cls->getSuperClass())
- HierarchyEntities.insert(Entity::get(Cls, Prog));
-
- // Find the interface in the hierarchy that "receives" the message.
- for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
- bool isReceiver = false;
-
- ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
- for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
- Meth != MethEnd; ++Meth) {
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
- if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
- (MD->isClassMethod() && CanBeClassMethod)) {
- isReceiver = true;
- break;
- }
- }
-
- if (isReceiver) {
- ReceiverIFaceEnt = Entity::get(Cls, Prog);
- break;
- }
- }
- }
- }
-
- virtual void Handle(TranslationUnit *TU) {
- assert(TU && "Passed null translation unit");
- ASTContext &Ctx = TU->getASTContext();
-
- // Null means it doesn't exist in this translation unit or there was no
- // interface that was determined to receive the original message.
- ObjCInterfaceDecl *ReceiverIFace =
- cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
-
- // No subclass for the original receiver interface, so it remains the
- // receiver.
- if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
- return;
-
- // Null means it doesn't exist in this translation unit or there was no
- // interface associated with the message in the first place.
- ObjCInterfaceDecl *MsgIFace =
- cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
-
- Selector Sel = GlobSel.getSelector(Ctx);
- SelectorMap &SelMap = TU->getSelectorMap();
- for (SelectorMap::method_iterator
- I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
- I != E; ++I) {
- ObjCMethodDecl *D = *I;
- if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
- for (ObjCMethodDecl::redecl_iterator
- RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
- TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
- }
- }
- }
-
- /// \brief Determines whether the given method is likely to accept the
- /// original message.
- ///
- /// It returns true "eagerly", meaning it will return false only if it can
- /// "prove" statically that the method cannot accept the original message.
- bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
- ObjCInterfaceDecl *ReceiverIFace) {
- assert(D);
-
- // FIXME: Protocol methods ?
- if (isa<ObjCProtocolDecl>(D->getDeclContext()))
- return false;
-
- // No specific interface associated with the message. Can be anything.
- if (MsgIFaceEnt.isInvalid())
- return true;
-
- if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
- (!CanBeClassMethod && D->isClassMethod()))
- return false;
-
- ObjCInterfaceDecl *IFace = D->getClassInterface();
- assert(IFace);
-
- // If the original message interface is the same or a superclass of the
- // given interface, accept the method as a possibility.
- if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
- return true;
-
- if (ReceiverIFace) {
- // The given interface, "overrides" the receiver.
- if (ReceiverIFace->isSuperClassOf(IFace))
- return true;
- } else {
- // No receiver was found for the original message.
- assert(ReceiverIFaceEnt.isInvalid());
-
- // If the original message interface is a subclass of the given interface,
- // accept the message.
- if (HierarchyEntities.count(Entity::get(IFace, Prog)))
- return true;
- }
-
- // The interfaces are unrelated, or the receiver interface wasn't
- // "overriden".
- return false;
- }
-};
-
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Analyzer Implementation
-//===----------------------------------------------------------------------===//
-
-void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
- assert(D && "Passed null declaration");
- Entity Ent = Entity::get(D, Prog);
- if (Ent.isInvalid())
- return;
-
- DeclEntityAnalyzer DEA(Ent, Handler);
- Idxer.GetTranslationUnitsFor(Ent, DEA);
-}
-
-void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
- assert(D && "Passed null declaration");
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- RefSelectorAnalyzer RSA(MD, Prog, Handler);
- GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
- Idxer.GetTranslationUnitsFor(Sel, RSA);
- return;
- }
-
- Entity Ent = Entity::get(D, Prog);
- if (Ent.isInvalid())
- return;
-
- RefEntityAnalyzer REA(Ent, Handler);
- Idxer.GetTranslationUnitsFor(Ent, REA);
-}
-
-/// \brief Find methods that may respond to the given message and pass them
-/// to Handler.
-void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
- TULocationHandler &Handler) {
- assert(Msg);
- MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
- GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
- Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
-}
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
deleted file mode 100644
index 9bf35e5..0000000
--- a/lib/Index/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-set(LLVM_USED_LIBS clangBasic clangAST)
-
-add_clang_library(clangIndex
- ASTLocation.cpp
- Analyzer.cpp
- GlobalCallGraph.cpp
- DeclReferenceMap.cpp
- Entity.cpp
- GlobalSelector.cpp
- Handlers.cpp
- IndexProvider.cpp
- Indexer.cpp
- Program.cpp
- SelectorMap.cpp
- )
-
-add_dependencies(clangIndex ClangAttrClasses ClangAttrList
- ClangDeclNodes ClangStmtNodes)
diff --git a/lib/Index/DeclReferenceMap.cpp b/lib/Index/DeclReferenceMap.cpp
deleted file mode 100644
index 3fd4336..0000000
--- a/lib/Index/DeclReferenceMap.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-//===--- DeclReferenceMap.cpp - Map Decls to their references -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// DeclReferenceMap creates a mapping from Decls to the ASTLocations that
-// reference them.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/DeclReferenceMap.h"
-#include "clang/Index/ASTLocation.h"
-#include "ASTVisitor.h"
-using namespace clang;
-using namespace idx;
-
-namespace {
-
-class RefMapper : public ASTVisitor<RefMapper> {
- DeclReferenceMap::MapTy &Map;
-
-public:
- RefMapper(DeclReferenceMap::MapTy &map) : Map(map) { }
-
- void VisitDeclRefExpr(DeclRefExpr *Node);
- void VisitMemberExpr(MemberExpr *Node);
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
-
- void VisitTypedefTypeLoc(TypedefTypeLoc TL);
- void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
-};
-
-} // anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// RefMapper Implementation
-//===----------------------------------------------------------------------===//
-
-void RefMapper::VisitDeclRefExpr(DeclRefExpr *Node) {
- NamedDecl *PrimD = cast<NamedDecl>(Node->getDecl()->getCanonicalDecl());
- Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node)));
-}
-
-void RefMapper::VisitMemberExpr(MemberExpr *Node) {
- NamedDecl *PrimD = cast<NamedDecl>(Node->getMemberDecl()->getCanonicalDecl());
- Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node)));
-}
-
-void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
- Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node)));
-}
-
-void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- NamedDecl *ND = TL.getTypedefNameDecl();
- Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
-}
-
-void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- NamedDecl *ND = TL.getIFaceDecl();
- Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
-}
-
-//===----------------------------------------------------------------------===//
-// DeclReferenceMap Implementation
-//===----------------------------------------------------------------------===//
-
-DeclReferenceMap::DeclReferenceMap(ASTContext &Ctx) {
- RefMapper(Map).Visit(Ctx.getTranslationUnitDecl());
-}
-
-DeclReferenceMap::astlocation_iterator
-DeclReferenceMap::refs_begin(NamedDecl *D) const {
- NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
- return astlocation_iterator(Map.lower_bound(Prim));
-}
-
-DeclReferenceMap::astlocation_iterator
-DeclReferenceMap::refs_end(NamedDecl *D) const {
- NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
- return astlocation_iterator(Map.upper_bound(Prim));
-}
-
-bool DeclReferenceMap::refs_empty(NamedDecl *D) const {
- NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
- return refs_begin(Prim) == refs_end(Prim);
-}
diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp
deleted file mode 100644
index fbab6d8..0000000
--- a/lib/Index/Entity.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Entity is a ASTContext-independent way to refer to declarations that are
-// visible across translation units.
-//
-//===----------------------------------------------------------------------===//
-
-#include "EntityImpl.h"
-#include "ProgramImpl.h"
-#include "clang/Index/Program.h"
-#include "clang/Index/GlobalSelector.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclVisitor.h"
-using namespace clang;
-using namespace idx;
-
-// FIXME: Entity is really really basic currently, mostly written to work
-// on variables and functions. Should support types and other decls eventually..
-
-
-//===----------------------------------------------------------------------===//
-// EntityGetter
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-namespace idx {
-
-/// \brief Gets the Entity associated with a Decl.
-class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
- Program &Prog;
- ProgramImpl &ProgImpl;
-
-public:
- EntityGetter(Program &prog, ProgramImpl &progImpl)
- : Prog(prog), ProgImpl(progImpl) { }
-
- // Get an Entity.
- Entity getEntity(Entity Parent, DeclarationName Name,
- unsigned IdNS, bool isObjCInstanceMethod);
-
- // Get an Entity associated with the name in the global namespace.
- Entity getGlobalEntity(StringRef Name);
-
- Entity VisitNamedDecl(NamedDecl *D);
- Entity VisitVarDecl(VarDecl *D);
- Entity VisitFieldDecl(FieldDecl *D);
- Entity VisitFunctionDecl(FunctionDecl *D);
- Entity VisitTypeDecl(TypeDecl *D);
-};
-
-}
-}
-
-Entity EntityGetter::getEntity(Entity Parent, DeclarationName Name,
- unsigned IdNS, bool isObjCInstanceMethod) {
- llvm::FoldingSetNodeID ID;
- EntityImpl::Profile(ID, Parent, Name, IdNS, isObjCInstanceMethod);
-
- ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
- void *InsertPos = 0;
- if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
- return Entity(Ent);
-
- void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
- EntityImpl *New =
- new (Buf) EntityImpl(Parent, Name, IdNS, isObjCInstanceMethod);
- Entities.InsertNode(New, InsertPos);
-
- return Entity(New);
-}
-
-Entity EntityGetter::getGlobalEntity(StringRef Name) {
- IdentifierInfo *II = &ProgImpl.getIdents().get(Name);
- DeclarationName GlobName(II);
- unsigned IdNS = Decl::IDNS_Ordinary;
- return getEntity(Entity(), GlobName, IdNS, false);
-}
-
-Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
- Entity Parent;
- if (!D->getDeclContext()->isTranslationUnit()) {
- Parent = Visit(cast<Decl>(D->getDeclContext()));
- // FIXME: Anonymous structs ?
- if (Parent.isInvalid())
- return Entity();
- }
- if (Parent.isValid() && Parent.isInternalToTU())
- return Entity(D);
-
- // FIXME: Only works for DeclarationNames that are identifiers and selectors.
- // Treats other DeclarationNames as internal Decls for now..
-
- DeclarationName LocalName = D->getDeclName();
- if (!LocalName)
- return Entity(D);
-
- DeclarationName GlobName;
-
- if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
- IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
- GlobName = DeclarationName(GlobII);
- } else {
- Selector LocalSel = LocalName.getObjCSelector();
-
- // Treats other DeclarationNames as internal Decls for now..
- if (LocalSel.isNull())
- return Entity(D);
-
- Selector GlobSel =
- (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
- GlobName = DeclarationName(GlobSel);
- }
-
- assert(GlobName);
-
- unsigned IdNS = D->getIdentifierNamespace();
-
- ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
- bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
- return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod);
-}
-
-Entity EntityGetter::VisitVarDecl(VarDecl *D) {
- // Local variables have no linkage, make invalid Entities.
- if (D->hasLocalStorage())
- return Entity();
-
- // If it's static it cannot be referred to by another translation unit.
- if (D->getStorageClass() == SC_Static)
- return Entity(D);
-
- return VisitNamedDecl(D);
-}
-
-Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
- // If it's static it cannot be referred to by another translation unit.
- if (D->getStorageClass() == SC_Static)
- return Entity(D);
-
- return VisitNamedDecl(D);
-}
-
-Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
- // Make FieldDecl an invalid Entity since it has no linkage.
- return Entity();
-}
-
-Entity EntityGetter::VisitTypeDecl(TypeDecl *D) {
- // Although in C++ class name has external linkage, usually the definition of
- // the class is available in the same translation unit when it's needed. So we
- // make all of them invalid Entity.
- return Entity();
-}
-
-//===----------------------------------------------------------------------===//
-// EntityImpl Implementation
-//===----------------------------------------------------------------------===//
-
-Decl *EntityImpl::getDecl(ASTContext &AST) {
- DeclContext *DC =
- Parent.isInvalid() ? AST.getTranslationUnitDecl()
- : cast<DeclContext>(Parent.getDecl(AST));
- if (!DC)
- return 0; // Couldn't get the parent context.
-
- DeclarationName LocalName;
-
- if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
- IdentifierInfo &II = AST.Idents.get(GlobII->getName());
- LocalName = DeclarationName(&II);
- } else {
- Selector GlobSel = Name.getObjCSelector();
- assert(!GlobSel.isNull() && "A not handled yet declaration name");
- GlobalSelector GSel =
- GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
- LocalName = GSel.getSelector(AST);
- }
-
- assert(LocalName);
-
- DeclContext::lookup_result Res = DC->lookup(LocalName);
- for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
- Decl *D = *I;
- if (D->getIdentifierNamespace() == IdNS) {
- if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- if (MD->isInstanceMethod() == IsObjCInstanceMethod)
- return MD;
- } else
- return D;
- }
- }
-
- return 0; // Failed to find a decl using this Entity.
-}
-
-/// \brief Get an Entity associated with the given Decl.
-/// \returns Null if an Entity cannot refer to this Decl.
-Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
- assert(D && "Passed null Decl");
- return EntityGetter(Prog, ProgImpl).Visit(D);
-}
-
-/// \brief Get an Entity associated with a global name.
-Entity EntityImpl::get(StringRef Name, Program &Prog,
- ProgramImpl &ProgImpl) {
- return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name);
-}
-
-std::string EntityImpl::getPrintableName() {
- return Name.getAsString();
-}
-
-//===----------------------------------------------------------------------===//
-// Entity Implementation
-//===----------------------------------------------------------------------===//
-
-Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
-
-/// \brief Find the Decl that can be referred to by this entity.
-Decl *Entity::getDecl(ASTContext &AST) const {
- if (isInvalid())
- return 0;
-
- if (Decl *D = Val.dyn_cast<Decl *>())
- // Check that the passed AST is actually the one that this Decl belongs to.
- return (&D->getASTContext() == &AST) ? D : 0;
-
- return Val.get<EntityImpl *>()->getDecl(AST);
-}
-
-std::string Entity::getPrintableName() const {
- if (isInvalid())
- return "<< Invalid >>";
-
- if (Decl *D = Val.dyn_cast<Decl *>()) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
- return ND->getNameAsString();
- else
- return std::string();
- }
-
- return Val.get<EntityImpl *>()->getPrintableName();
-}
-
-/// \brief Get an Entity associated with the given Decl.
-/// \returns Null if an Entity cannot refer to this Decl.
-Entity Entity::get(Decl *D, Program &Prog) {
- if (D == 0)
- return Entity();
- ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
- return EntityImpl::get(D, Prog, ProgImpl);
-}
-
-Entity Entity::get(StringRef Name, Program &Prog) {
- ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
- return EntityImpl::get(Name, Prog, ProgImpl);
-}
-
-unsigned
-llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
- return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
-}
diff --git a/lib/Index/EntityImpl.h b/lib/Index/EntityImpl.h
deleted file mode 100644
index 6d6a0c6..0000000
--- a/lib/Index/EntityImpl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//===--- EntityImpl.h - Internal Entity implementation---------*- C++ -*-=====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Internal implementation for the Entity class
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INDEX_ENTITYIMPL_H
-#define LLVM_CLANG_INDEX_ENTITYIMPL_H
-
-#include "clang/Index/Entity.h"
-#include "clang/AST/DeclarationName.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/StringSet.h"
-
-namespace clang {
-
-namespace idx {
- class ProgramImpl;
-
-class EntityImpl : public llvm::FoldingSetNode {
- Entity Parent;
- DeclarationName Name;
-
- /// \brief Identifier namespace.
- unsigned IdNS;
-
- /// \brief If Name is a selector, this keeps track whether it's for an
- /// instance method.
- bool IsObjCInstanceMethod;
-
-public:
- EntityImpl(Entity parent, DeclarationName name, unsigned idNS,
- bool isObjCInstanceMethod)
- : Parent(parent), Name(name), IdNS(idNS),
- IsObjCInstanceMethod(isObjCInstanceMethod) { }
-
- /// \brief Find the Decl that can be referred to by this entity.
- Decl *getDecl(ASTContext &AST);
-
- /// \brief Get an Entity associated with the given Decl.
- /// \returns Null if an Entity cannot refer to this Decl.
- static Entity get(Decl *D, Program &Prog, ProgramImpl &ProgImpl);
- static Entity get(StringRef Name, Program &Prog, ProgramImpl &ProgImpl);
-
- std::string getPrintableName();
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, Parent, Name, IdNS, IsObjCInstanceMethod);
- }
- static void Profile(llvm::FoldingSetNodeID &ID, Entity Parent,
- DeclarationName Name, unsigned IdNS,
- bool isObjCInstanceMethod) {
- ID.AddPointer(Parent.getAsOpaquePtr());
- ID.AddPointer(Name.getAsOpaquePtr());
- ID.AddInteger(IdNS);
- ID.AddBoolean(isObjCInstanceMethod);
- }
-};
-
-} // namespace idx
-
-} // namespace clang
-
-#endif
diff --git a/lib/Index/GlobalCallGraph.cpp b/lib/Index/GlobalCallGraph.cpp
deleted file mode 100644
index a21b52a..0000000
--- a/lib/Index/GlobalCallGraph.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-//== GlobalCallGraph.cpp - Call graph building ------------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defined the CallGraph and CGBuilder classes.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/GlobalCallGraph.h"
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/StmtVisitor.h"
-
-#include "llvm/Support/GraphWriter.h"
-
-using namespace clang::idx;
-using clang::FunctionDecl;
-using clang::DeclContext;
-using clang::ASTContext;
-
-namespace {
-class CGBuilder : public StmtVisitor<CGBuilder> {
-
- CallGraph &G;
- FunctionDecl *FD;
-
- Entity CallerEnt;
-
- CallGraphNode *CallerNode;
-
-public:
- CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
- : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
-
- void VisitStmt(Stmt *S) { VisitChildren(S); }
-
- void VisitCallExpr(CallExpr *CE);
-
- void VisitChildren(Stmt *S) {
- for (Stmt::child_range I = S->children(); I; ++I)
- if (*I)
- static_cast<CGBuilder*>(this)->Visit(*I);
- }
-};
-}
-
-void CGBuilder::VisitCallExpr(CallExpr *CE) {
- if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
- Entity Ent = Entity::get(CalleeDecl, G.getProgram());
- CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
- CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
- }
-}
-
-CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
- ExternalCallingNode = getOrInsertFunction(Entity());
-}
-
-CallGraph::~CallGraph() {
- if (!FunctionMap.empty()) {
- for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
- I != E; ++I)
- delete I->second;
- FunctionMap.clear();
- }
-}
-
-void CallGraph::addTU(ASTContext& Ctx) {
- DeclContext *DC = Ctx.getTranslationUnitDecl();
- for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
- I != E; ++I) {
-
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
- if (FD->doesThisDeclarationHaveABody()) {
- // Set caller's ASTContext.
- Entity Ent = Entity::get(FD, Prog);
- CallGraphNode *Node = getOrInsertFunction(Ent);
- CallerCtx[Node] = &Ctx;
-
- // If this function has external linkage, anything could call it.
- if (FD->isGlobal())
- ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
-
- // Set root node to 'main' function.
- if (FD->getNameAsString() == "main")
- Root = Node;
-
- CGBuilder builder(*this, FD, Ent, Node);
- builder.Visit(FD->getBody());
- }
- }
- }
-}
-
-CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
- CallGraphNode *&Node = FunctionMap[F];
- if (Node)
- return Node;
-
- return Node = new CallGraphNode(F);
-}
-
-Decl *CallGraph::getDecl(CallGraphNode *Node) {
- // Get the function's context.
- ASTContext *Ctx = CallerCtx[Node];
-
- return Node->getDecl(*Ctx);
-}
-
-void CallGraph::print(raw_ostream &os) {
- for (iterator I = begin(), E = end(); I != E; ++I) {
- if (I->second->hasCallee()) {
- os << "function: " << I->first.getPrintableName()
- << " calls:\n";
- for (CallGraphNode::iterator CI = I->second->begin(),
- CE = I->second->end(); CI != CE; ++CI) {
- os << " " << CI->second->getName();
- }
- os << '\n';
- }
- }
-}
-
-void CallGraph::dump() {
- print(llvm::errs());
-}
-
-void CallGraph::ViewCallGraph() const {
- llvm::ViewGraph(*this, "CallGraph");
-}
-
-namespace llvm {
-
-template <>
-struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
-
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
-
- static std::string getNodeLabel(const CallGraphNode *Node,
- const CallGraph &CG) {
- return Node->getName();
-
- }
-
-};
-
-}
diff --git a/lib/Index/GlobalSelector.cpp b/lib/Index/GlobalSelector.cpp
deleted file mode 100644
index 2fe6f95..0000000
--- a/lib/Index/GlobalSelector.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===-- GlobalSelector.cpp - Cross-translation-unit "token" for selectors -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// GlobalSelector is a ASTContext-independent way to refer to selectors.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/GlobalSelector.h"
-#include "ProgramImpl.h"
-#include "clang/Index/Program.h"
-#include "clang/AST/ASTContext.h"
-using namespace clang;
-using namespace idx;
-
-/// \brief Get the ASTContext-specific selector.
-Selector GlobalSelector::getSelector(ASTContext &AST) const {
- if (isInvalid())
- return Selector();
-
- Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val));
-
- SmallVector<IdentifierInfo *, 8> Ids;
- for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();
- i != e; ++i) {
- IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i);
- IdentifierInfo *II = &AST.Idents.get(GlobII->getName());
- Ids.push_back(II);
- }
-
- return AST.Selectors.getSelector(GlobSel.getNumArgs(), Ids.data());
-}
-
-/// \brief Get a printable name for debugging purpose.
-std::string GlobalSelector::getPrintableName() const {
- if (isInvalid())
- return "<< Invalid >>";
-
- Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val));
- return GlobSel.getAsString();
-}
-
-/// \brief Get a GlobalSelector for the ASTContext-specific selector.
-GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {
- if (Sel.isNull())
- return GlobalSelector();
-
- ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
-
- SmallVector<IdentifierInfo *, 8> Ids;
- for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();
- i != e; ++i) {
- IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i);
- IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
- Ids.push_back(GlobII);
- }
-
- Selector GlobSel = ProgImpl.getSelectors().getSelector(Sel.getNumArgs(),
- Ids.data());
- return GlobalSelector(GlobSel.getAsOpaquePtr());
-}
-
-unsigned
-llvm::DenseMapInfo<GlobalSelector>::getHashValue(GlobalSelector Sel) {
- return DenseMapInfo<void*>::getHashValue(Sel.getAsOpaquePtr());
-}
diff --git a/lib/Index/Handlers.cpp b/lib/Index/Handlers.cpp
deleted file mode 100644
index 1e9a27d..0000000
--- a/lib/Index/Handlers.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===--- Handlers.cpp - Interfaces for receiving information ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Abstract interfaces for receiving information.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/Handlers.h"
-#include "clang/Index/Entity.h"
-using namespace clang;
-using namespace idx;
-
-// Out-of-line to give the virtual tables a home.
-EntityHandler::~EntityHandler() { }
-TranslationUnitHandler::~TranslationUnitHandler() { }
-TULocationHandler::~TULocationHandler() { }
diff --git a/lib/Index/IndexProvider.cpp b/lib/Index/IndexProvider.cpp
deleted file mode 100644
index eea0988..0000000
--- a/lib/Index/IndexProvider.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-//===- IndexProvider.cpp - Maps information to translation units -*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Maps information to TranslationUnits.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/IndexProvider.h"
-#include "clang/Index/Entity.h"
-using namespace clang;
-using namespace idx;
-
-// Out-of-line to give the virtual table a home.
-IndexProvider::~IndexProvider() { }
diff --git a/lib/Index/Indexer.cpp b/lib/Index/Indexer.cpp
deleted file mode 100644
index ebba43c..0000000
--- a/lib/Index/Indexer.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-//===--- Indexer.cpp - IndexProvider implementation -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// IndexProvider implementation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/Indexer.h"
-#include "clang/Index/Program.h"
-#include "clang/Index/Handlers.h"
-#include "clang/Index/TranslationUnit.h"
-#include "ASTVisitor.h"
-#include "clang/AST/DeclBase.h"
-using namespace clang;
-using namespace idx;
-
-namespace {
-
-class EntityIndexer : public EntityHandler {
- TranslationUnit *TU;
- Indexer::MapTy &Map;
- Indexer::DefMapTy &DefMap;
-
-public:
- EntityIndexer(TranslationUnit *tu, Indexer::MapTy &map,
- Indexer::DefMapTy &defmap)
- : TU(tu), Map(map), DefMap(defmap) { }
-
- virtual void Handle(Entity Ent) {
- if (Ent.isInternalToTU())
- return;
- Map[Ent].insert(TU);
-
- Decl *D = Ent.getDecl(TU->getASTContext());
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- if (FD->doesThisDeclarationHaveABody())
- DefMap[Ent] = std::make_pair(FD, TU);
- }
-};
-
-class SelectorIndexer : public ASTVisitor<SelectorIndexer> {
- Program &Prog;
- TranslationUnit *TU;
- Indexer::SelMapTy &Map;
-
-public:
- SelectorIndexer(Program &prog, TranslationUnit *tu, Indexer::SelMapTy &map)
- : Prog(prog), TU(tu), Map(map) { }
-
- void VisitObjCMethodDecl(ObjCMethodDecl *D) {
- Map[GlobalSelector::get(D->getSelector(), Prog)].insert(TU);
- Base::VisitObjCMethodDecl(D);
- }
-
- void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
- Map[GlobalSelector::get(Node->getSelector(), Prog)].insert(TU);
- Base::VisitObjCMessageExpr(Node);
- }
-};
-
-} // anonymous namespace
-
-void Indexer::IndexAST(TranslationUnit *TU) {
- assert(TU && "Passed null TranslationUnit");
- ASTContext &Ctx = TU->getASTContext();
- CtxTUMap[&Ctx] = TU;
- EntityIndexer Idx(TU, Map, DefMap);
- Prog.FindEntities(Ctx, Idx);
-
- SelectorIndexer SelIdx(Prog, TU, SelMap);
- SelIdx.Visit(Ctx.getTranslationUnitDecl());
-}
-
-void Indexer::GetTranslationUnitsFor(Entity Ent,
- TranslationUnitHandler &Handler) {
- assert(Ent.isValid() && "Expected valid Entity");
-
- if (Ent.isInternalToTU()) {
- Decl *D = Ent.getInternalDecl();
- CtxTUMapTy::iterator I = CtxTUMap.find(&D->getASTContext());
- if (I != CtxTUMap.end())
- Handler.Handle(I->second);
- return;
- }
-
- MapTy::iterator I = Map.find(Ent);
- if (I == Map.end())
- return;
-
- TUSetTy &Set = I->second;
- for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I)
- Handler.Handle(*I);
-}
-
-void Indexer::GetTranslationUnitsFor(GlobalSelector Sel,
- TranslationUnitHandler &Handler) {
- assert(Sel.isValid() && "Expected valid GlobalSelector");
-
- SelMapTy::iterator I = SelMap.find(Sel);
- if (I == SelMap.end())
- return;
-
- TUSetTy &Set = I->second;
- for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I)
- Handler.Handle(*I);
-}
-
-std::pair<FunctionDecl *, TranslationUnit *>
-Indexer::getDefinitionFor(Entity Ent) {
- DefMapTy::iterator I = DefMap.find(Ent);
- if (I == DefMap.end())
- return std::make_pair((FunctionDecl *)0, (TranslationUnit *)0);
- else
- return I->second;
-}
diff --git a/lib/Index/Makefile b/lib/Index/Makefile
deleted file mode 100644
index 8607d78..0000000
--- a/lib/Index/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- clang/lib/Index/Makefile ----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-#
-# This implements the Indexer library for the C-Language front-end.
-#
-##===----------------------------------------------------------------------===##
-
-CLANG_LEVEL := ../..
-LIBRARYNAME := clangIndex
-
-include $(CLANG_LEVEL)/Makefile
-
diff --git a/lib/Index/Program.cpp b/lib/Index/Program.cpp
deleted file mode 100644
index 4efad2c..0000000
--- a/lib/Index/Program.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===--- Program.cpp - Entity originator and misc -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Storage for Entities and utility functions
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/Program.h"
-#include "ProgramImpl.h"
-#include "clang/Index/Handlers.h"
-#include "clang/Index/TranslationUnit.h"
-#include "clang/AST/DeclBase.h"
-#include "clang/AST/ASTContext.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace clang;
-using namespace idx;
-
-// Out-of-line to give the virtual tables a home.
-TranslationUnit::~TranslationUnit() { }
-
-Program::Program() : Impl(new ProgramImpl()) { }
-
-Program::~Program() {
- delete static_cast<ProgramImpl *>(Impl);
-}
-
-static void FindEntitiesInDC(DeclContext *DC, Program &Prog,
- EntityHandler &Handler) {
- for (DeclContext::decl_iterator
- I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
- if (I->getLocation().isInvalid())
- continue;
- Entity Ent = Entity::get(*I, Prog);
- if (Ent.isValid())
- Handler.Handle(Ent);
- if (DeclContext *SubDC = dyn_cast<DeclContext>(*I))
- FindEntitiesInDC(SubDC, Prog, Handler);
- }
-}
-
-/// \brief Traverses the AST and passes all the entities to the Handler.
-void Program::FindEntities(ASTContext &Ctx, EntityHandler &Handler) {
- FindEntitiesInDC(Ctx.getTranslationUnitDecl(), *this, Handler);
-}
diff --git a/lib/Index/ProgramImpl.h b/lib/Index/ProgramImpl.h
deleted file mode 100644
index 57b9ce3..0000000
--- a/lib/Index/ProgramImpl.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===--- ProgramImpl.h - Internal Program implementation---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Internal implementation for the Program class
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INDEX_PROGRAMIMPL_H
-#define LLVM_CLANG_INDEX_PROGRAMIMPL_H
-
-#include "EntityImpl.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-
-namespace clang {
-
-namespace idx {
- class EntityListener;
-
-class ProgramImpl {
-public:
- typedef llvm::FoldingSet<EntityImpl> EntitySetTy;
-
-private:
- EntitySetTy Entities;
- llvm::BumpPtrAllocator BumpAlloc;
-
- IdentifierTable Identifiers;
- SelectorTable Selectors;
-
- ProgramImpl(const ProgramImpl&); // do not implement
- ProgramImpl &operator=(const ProgramImpl &); // do not implement
-
-public:
- ProgramImpl() : Identifiers(LangOptions()) { }
-
- EntitySetTy &getEntities() { return Entities; }
- IdentifierTable &getIdents() { return Identifiers; }
- SelectorTable &getSelectors() { return Selectors; }
-
- void *Allocate(unsigned Size, unsigned Align = 8) {
- return BumpAlloc.Allocate(Size, Align);
- }
-};
-
-} // namespace idx
-
-} // namespace clang
-
-#endif
diff --git a/lib/Index/SelectorMap.cpp b/lib/Index/SelectorMap.cpp
deleted file mode 100644
index 0f11e31..0000000
--- a/lib/Index/SelectorMap.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//===- SelectorMap.cpp - Maps selectors to methods and messages -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// SelectorMap creates a mapping from selectors to ObjC method declarations
-// and ObjC message expressions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/SelectorMap.h"
-#include "ASTVisitor.h"
-using namespace clang;
-using namespace idx;
-
-namespace {
-
-class SelMapper : public ASTVisitor<SelMapper> {
- SelectorMap::SelMethMapTy &SelMethMap;
- SelectorMap::SelRefMapTy &SelRefMap;
-
-public:
- SelMapper(SelectorMap::SelMethMapTy &MethMap,
- SelectorMap::SelRefMapTy &RefMap)
- : SelMethMap(MethMap), SelRefMap(RefMap) { }
-
- void VisitObjCMethodDecl(ObjCMethodDecl *D);
- void VisitObjCMessageExpr(ObjCMessageExpr *Node);
- void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
-};
-
-} // anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// SelMapper Implementation
-//===----------------------------------------------------------------------===//
-
-void SelMapper::VisitObjCMethodDecl(ObjCMethodDecl *D) {
- if (D->getCanonicalDecl() == D)
- SelMethMap.insert(std::make_pair(D->getSelector(), D));
- Base::VisitObjCMethodDecl(D);
-}
-
-void SelMapper::VisitObjCMessageExpr(ObjCMessageExpr *Node) {
- ASTLocation ASTLoc(CurrentDecl, Node);
- SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc));
-}
-
-void SelMapper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
- ASTLocation ASTLoc(CurrentDecl, Node);
- SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc));
-}
-
-//===----------------------------------------------------------------------===//
-// SelectorMap Implementation
-//===----------------------------------------------------------------------===//
-
-SelectorMap::SelectorMap(ASTContext &Ctx) {
- SelMapper(SelMethMap, SelRefMap).Visit(Ctx.getTranslationUnitDecl());
-}
-
-SelectorMap::method_iterator
-SelectorMap::methods_begin(Selector Sel) const {
- return method_iterator(SelMethMap.lower_bound(Sel));
-}
-
-SelectorMap::method_iterator
-SelectorMap::methods_end(Selector Sel) const {
- return method_iterator(SelMethMap.upper_bound(Sel));
-}
-
-SelectorMap::astlocation_iterator
-SelectorMap::refs_begin(Selector Sel) const {
- return astlocation_iterator(SelRefMap.lower_bound(Sel));
-}
-
-SelectorMap::astlocation_iterator
-SelectorMap::refs_end(Selector Sel) const {
- return astlocation_iterator(SelRefMap.upper_bound(Sel));
-}
diff --git a/lib/Makefile b/lib/Makefile
index a73c6e6..2eb72a9 100755
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -10,7 +10,7 @@ CLANG_LEVEL := ..
PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \
StaticAnalyzer Edit Rewrite ARCMigrate Serialization Frontend \
- FrontendTool Tooling Index Driver
+ FrontendTool Tooling Driver
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index c000f69..f04d767 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -59,7 +59,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
}
}
- HandleMemberFunctionDefaultArgs(D, FnD);
+ HandleMemberFunctionDeclDelays(D, FnD);
D.complete(FnD);
@@ -348,6 +348,77 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
LM.DefaultArgs[I].Toks = 0;
}
}
+
+ // Parse a delayed exception-specification, if there is one.
+ if (CachedTokens *Toks = LM.ExceptionSpecTokens) {
+ // Save the current token position.
+ SourceLocation origLoc = Tok.getLocation();
+
+ // Parse the default argument from its saved token stream.
+ Toks->push_back(Tok); // So that the current token doesn't get lost
+ PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
+
+ // Consume the previously-pushed token.
+ ConsumeAnyToken();
+
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ CXXMethodDecl *Method;
+ if (FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>(LM.Method))
+ Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = cast<CXXMethodDecl>(LM.Method);
+
+ Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(),
+ Method->getTypeQualifiers(),
+ getLangOpts().CPlusPlus0x);
+
+ // Parse the exception-specification.
+ SourceRange SpecificationRange;
+ SmallVector<ParsedType, 4> DynamicExceptions;
+ SmallVector<SourceRange, 4> DynamicExceptionRanges;
+ ExprResult NoexceptExpr;
+ CachedTokens *ExceptionSpecTokens;
+
+ ExceptionSpecificationType EST
+ = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange,
+ DynamicExceptions,
+ DynamicExceptionRanges, NoexceptExpr,
+ ExceptionSpecTokens);
+
+ // Clean up the remaining tokens.
+ if (Tok.is(tok::cxx_exceptspec_end))
+ ConsumeToken();
+ else if (EST != EST_None)
+ Diag(Tok.getLocation(), diag::err_except_spec_unparsed);
+
+ // Attach the exception-specification to the method.
+ if (EST != EST_None)
+ Actions.actOnDelayedExceptionSpecification(LM.Method, EST,
+ SpecificationRange,
+ DynamicExceptions,
+ DynamicExceptionRanges,
+ NoexceptExpr.isUsable()?
+ NoexceptExpr.get() : 0);
+
+ assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+ Tok.getLocation()) &&
+ "tryParseExceptionSpecification went over the exception tokens!");
+
+ // There could be leftover tokens (e.g. because of an error).
+ // Skip through until we reach the original token position.
+ while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+ ConsumeAnyToken();
+
+ delete LM.ExceptionSpecTokens;
+ LM.ExceptionSpecTokens = 0;
+ }
+
PrototypeScope.Exit();
// Finish the delayed C++ method declaration.
@@ -447,9 +518,9 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
if (HasTemplateScope)
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
- // Set or update the scope flags to include Scope::ThisScope.
+ // Set or update the scope flags.
bool AlreadyHasClassScope = Class.TopLevelClass;
- unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope;
+ unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope;
ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope);
ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope);
@@ -457,10 +528,20 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
- for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
- Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
+ {
+ // C++11 [expr.prim.general]p4:
+ // Otherwise, if a member-declarator declares a non-static data member
+ // (9.2) of a class X, the expression this is a prvalue of type "pointer
+ // to X" within the optional brace-or-equal-initializer. It shall not
+ // appear elsewhere in the member-declarator.
+ Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
+ /*TypeQuals=*/(unsigned)0);
+
+ for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+ Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
+ }
}
-
+
if (!AlreadyHasClassScope)
Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
@@ -481,6 +562,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
ConsumeAnyToken();
SourceLocation EqualLoc;
+
ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
EqualLoc);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cf3dca2..932ffb4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -729,9 +729,9 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) {
if (HasTemplateScope)
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
- // Set or update the scope flags to include Scope::ThisScope.
+ // Set or update the scope flags.
bool AlreadyHasClassScope = Class.TopLevelClass;
- unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope;
+ unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope;
ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope);
ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope);
@@ -739,11 +739,16 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) {
if (!AlreadyHasClassScope)
Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
-
- for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i) {
- Class.LateParsedDeclarations[i]->ParseLexedAttributes();
+ {
+ // Allow 'this' within late-parsed attributes.
+ Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
+ /*TypeQuals=*/0);
+
+ for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){
+ Class.LateParsedDeclarations[i]->ParseLexedAttributes();
+ }
}
-
+
if (!AlreadyHasClassScope)
Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
@@ -756,6 +761,7 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) {
LAs[i]->addDecl(D);
ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition);
+ delete LAs[i];
}
LAs.clear();
}
@@ -958,7 +964,7 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
/// [C++] namespace-definition
/// [C++] using-directive
/// [C++] using-declaration
-/// [C++0x/C11] static_assert-declaration
+/// [C++11/C11] static_assert-declaration
/// others... [FIXME]
///
Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
@@ -4191,6 +4197,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
ExprResult NoexceptExpr;
+ CachedTokens *ExceptionSpecTokens = 0;
ParsedAttributes FnAttrs(AttrFactory);
ParsedType TrailingReturnType;
@@ -4241,11 +4248,34 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
EndLoc = RefQualifierLoc;
}
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ bool IsCXX11MemberFunction =
+ getLangOpts().CPlusPlus0x &&
+ (D.getContext() == Declarator::MemberContext ||
+ (D.getContext() == Declarator::FileContext &&
+ D.getCXXScopeSpec().isValid() &&
+ Actions.CurContext->isRecord()));
+ Sema::CXXThisScopeRAII ThisScope(Actions,
+ dyn_cast<CXXRecordDecl>(Actions.CurContext),
+ DS.getTypeQualifiers(),
+ IsCXX11MemberFunction);
+
// Parse exception-specification[opt].
- ESpecType = MaybeParseExceptionSpecification(ESpecRange,
- DynamicExceptions,
- DynamicExceptionRanges,
- NoexceptExpr);
+ bool Delayed = (D.getContext() == Declarator::MemberContext &&
+ D.getDeclSpec().getStorageClassSpec()
+ != DeclSpec::SCS_typedef &&
+ !D.getDeclSpec().isFriendSpecified());
+ ESpecType = tryParseExceptionSpecification(Delayed,
+ ESpecRange,
+ DynamicExceptions,
+ DynamicExceptionRanges,
+ NoexceptExpr,
+ ExceptionSpecTokens);
if (ESpecType != EST_None)
EndLoc = ESpecRange.getEnd();
@@ -4280,6 +4310,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : 0,
+ ExceptionSpecTokens,
Tracker.getOpenLocation(),
EndLoc, D,
TrailingReturnType),
@@ -4481,7 +4512,6 @@ void Parser::ParseParameterDeclarationClause(
// If we're inside a class definition, cache the tokens
// corresponding to the default argument. We'll actually parse
// them when we see the end of the class definition.
- // FIXME: Templates will require something similar.
// FIXME: Can we use a smart pointer for Toks?
DefArgToks = new CachedTokens;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index b2a65ff..b9b51d7 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1534,13 +1534,35 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
}
}
-void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
- Decl *ThisDecl) {
+/// \brief If the given declarator has any parts for which parsing has to be
+/// delayed, e.g., default arguments or an exception-specification, create a
+/// late-parsed method declaration record to handle the parsing at the end of
+/// the class definition.
+void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
+ Decl *ThisDecl) {
// We just declared a member function. If this member function
- // has any default arguments, we'll need to parse them later.
+ // has any default arguments or an exception-specification, we'll need to
+ // parse them later.
LateParsedMethodDeclaration *LateMethod = 0;
DeclaratorChunk::FunctionTypeInfo &FTI
= DeclaratorInfo.getFunctionTypeInfo();
+
+ // If there was a delayed exception-specification, hold onto its tokens.
+ if (FTI.getExceptionSpecType() == EST_Delayed) {
+ // Push this method onto the stack of late-parsed method
+ // declarations.
+ LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
+ getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
+ LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
+
+ // Stash the exception-specification tokens in the late-pased mthod.
+ LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
+ FTI.ExceptionSpecTokens = 0;
+
+ // Reserve space for the parameters.
+ LateMethod->DefaultArgs.reserve(FTI.NumArgs);
+ }
+
for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
if (!LateMethod) {
@@ -1558,7 +1580,7 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
LateParsedDefaultArgument(FTI.ArgInfo[I].Param));
}
- // Add this parameter to the list of parameters (it or may
+ // Add this parameter to the list of parameters (it may or may
// not have a default argument).
LateMethod->DefaultArgs.push_back(
LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
@@ -1824,7 +1846,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Parse the first declarator.
ParseDeclarator(DeclaratorInfo);
- // Error parsing the declarator?
+ // Error parsin g the declarator?
if (!DeclaratorInfo.hasName()) {
// If so, skip until the semi-colon or a }.
SkipUntil(tok::r_brace, true, true);
@@ -2046,7 +2068,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (DeclaratorInfo.isFunctionDeclarator() &&
DeclaratorInfo.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef) {
- HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
+ HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);
}
DeclaratorInfo.complete(ThisDecl);
@@ -2334,13 +2356,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
T.getCloseLocation(),
attrs.getList());
- // C++0x [class.mem]p2: Within the class member-specification, the class is
- // regarded as complete within function bodies, default arguments, exception-
- // specifications, and brace-or-equal-initializers for non-static data
- // members (including such things in nested classes).
- //
- // FIXME: Only function bodies and brace-or-equal-initializers are currently
- // handled. Fix the others!
+ // C++11 [class.mem]p2:
+ // Within the class member-specification, the class is regarded as complete
+ // within function bodies, default arguments, exception-specifications, and
+ // brace-or-equal-initializers for non-static data members (including such
+ // things in nested classes).
if (TagDecl && NonNestedClass) {
// We are not inside a nested class. This class and its nested classes
// are complete and we can parse the delayed portions of method
@@ -2535,12 +2555,63 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
/// 'noexcept'
/// 'noexcept' '(' constant-expression ')'
ExceptionSpecificationType
-Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange,
+Parser::tryParseExceptionSpecification(bool Delayed,
+ SourceRange &SpecificationRange,
SmallVectorImpl<ParsedType> &DynamicExceptions,
SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
- ExprResult &NoexceptExpr) {
+ ExprResult &NoexceptExpr,
+ CachedTokens *&ExceptionSpecTokens) {
ExceptionSpecificationType Result = EST_None;
-
+ ExceptionSpecTokens = 0;
+
+ // Handle delayed parsing of exception-specifications.
+ if (Delayed) {
+ if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept))
+ return EST_None;
+
+ // Consume and cache the starting token.
+ bool IsNoexcept = Tok.is(tok::kw_noexcept);
+ Token StartTok = Tok;
+ SpecificationRange = SourceRange(ConsumeToken());
+
+ // Check for a '('.
+ if (!Tok.is(tok::l_paren)) {
+ // If this is a bare 'noexcept', we're done.
+ if (IsNoexcept) {
+ Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);
+ NoexceptExpr = 0;
+ return EST_BasicNoexcept;
+ }
+
+ Diag(Tok, diag::err_expected_lparen_after) << "throw";
+ return EST_DynamicNone;
+ }
+
+ // Cache the tokens for the exception-specification.
+ ExceptionSpecTokens = new CachedTokens;
+ ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept'
+ ExceptionSpecTokens->push_back(Tok); // '('
+ SpecificationRange.setEnd(ConsumeParen()); // '('
+
+ if (!ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens,
+ /*StopAtSemi=*/true,
+ /*ConsumeFinalToken=*/true)) {
+ NoexceptExpr = 0;
+ delete ExceptionSpecTokens;
+ ExceptionSpecTokens = 0;
+ return IsNoexcept? EST_BasicNoexcept : EST_DynamicNone;
+ }
+ SpecificationRange.setEnd(Tok.getLocation());
+
+ // Add the 'stop' token.
+ Token End;
+ End.startToken();
+ End.setKind(tok::cxx_exceptspec_end);
+ End.setLocation(Tok.getLocation());
+ ExceptionSpecTokens->push_back(End);
+ return EST_Delayed;
+ }
+
// See if there's a dynamic specification.
if (Tok.is(tok::kw_throw)) {
Result = ParseDynamicExceptionSpecification(SpecificationRange,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 7f3a815..b6a027b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1926,11 +1926,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// unless they've already reported an error.
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
Diag(Tok, diag::ext_gnu_statement_expr);
-
Actions.ActOnStartStmtExpr();
- ParsedAttributes attrs(AttrFactory);
- StmtResult Stmt(ParseCompoundStatement(attrs, true));
+ StmtResult Stmt(ParseCompoundStatement(true));
ExprType = CompoundStmt;
// If the substmt parsed correctly, build the AST node.
@@ -2394,7 +2392,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
SourceLocation(),
EST_None,
SourceLocation(),
- 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
CaretLoc, CaretLoc,
ParamInfo),
attrs, CaretLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 2af7482..ae6ad0b 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -780,10 +780,13 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
llvm::SmallVector<ParsedType, 2> DynamicExceptions;
llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges;
ExprResult NoexceptExpr;
- ESpecType = MaybeParseExceptionSpecification(ESpecRange,
- DynamicExceptions,
- DynamicExceptionRanges,
- NoexceptExpr);
+ CachedTokens *ExceptionSpecTokens;
+ ESpecType = tryParseExceptionSpecification(/*Delayed=*/false,
+ ESpecRange,
+ DynamicExceptions,
+ DynamicExceptionRanges,
+ NoexceptExpr,
+ ExceptionSpecTokens);
if (ESpecType != EST_None)
DeclEndLoc = ESpecRange.getEnd();
@@ -818,6 +821,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DynamicExceptions.size(),
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : 0,
+ 0,
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);
@@ -863,6 +867,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*ExceptionRanges=*/0,
/*NumExceptions=*/0,
/*NoexceptExpr=*/0,
+ /*ExceptionSpecTokens=*/0,
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);
@@ -872,8 +877,6 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
// it.
unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope;
- if (getCurScope()->getFlags() & Scope::ThisScope)
- ScopeFlags |= Scope::ThisScope;
ParseScope BodyScope(this, ScopeFlags);
Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
@@ -1711,7 +1714,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
// Form a parsed representation of the template-id to be stored in the
// UnqualifiedId.
TemplateIdAnnotation *TemplateId
- = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+ = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
if (Id.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = Id.Identifier;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index fdb9788..44320df 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -78,13 +78,30 @@ using namespace clang;
StmtResult
Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
SourceLocation *TrailingElseLoc) {
- const char *SemiError = 0;
- StmtResult Res;
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX0XAttributes(attrs, 0, /*MightBeObjCMessageSend*/ true);
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX0XAttributes(Attrs, 0, /*MightBeObjCMessageSend*/ true);
+
+ StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts,
+ OnlyStatement, TrailingElseLoc, Attrs);
+
+ assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
+ "attributes on empty statement");
+
+ if (Attrs.empty() || Res.isInvalid())
+ return Res;
+
+ return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range);
+}
+
+StmtResult
+Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
+ bool OnlyStatement, SourceLocation *TrailingElseLoc,
+ ParsedAttributesWithRange &Attrs) {
+ const char *SemiError = 0;
+ StmtResult Res;
// Cases in this switch statement should fall through if the parser expects
// the token to end in a semicolon (in which case SemiError should be set),
@@ -95,6 +112,7 @@ Retry:
switch (Kind) {
case tok::at: // May be a @try or @throw statement
{
+ ProhibitAttributes(Attrs); // TODO: is it correct?
AtLoc = ConsumeToken(); // consume @
return ParseObjCAtStatement(AtLoc);
}
@@ -108,7 +126,7 @@ Retry:
Token Next = NextToken();
if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
// identifier ':' statement
- return ParseLabeledStatement(attrs);
+ return ParseLabeledStatement(Attrs);
}
if (Next.isNot(tok::coloncolon)) {
@@ -210,7 +228,7 @@ Retry:
if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext,
- DeclEnd, attrs);
+ DeclEnd, Attrs);
return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
}
@@ -219,54 +237,54 @@ Retry:
return StmtError();
}
- return ParseExprStatement(attrs);
+ return ParseExprStatement();
}
case tok::kw_case: // C99 6.8.1: labeled-statement
- return ParseCaseStatement(attrs);
+ return ParseCaseStatement();
case tok::kw_default: // C99 6.8.1: labeled-statement
- return ParseDefaultStatement(attrs);
+ return ParseDefaultStatement();
case tok::l_brace: // C99 6.8.2: compound-statement
- return ParseCompoundStatement(attrs);
+ return ParseCompoundStatement();
case tok::semi: { // C99 6.8.3p3: expression[opt] ';'
bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
}
case tok::kw_if: // C99 6.8.4.1: if-statement
- return ParseIfStatement(attrs, TrailingElseLoc);
+ return ParseIfStatement(TrailingElseLoc);
case tok::kw_switch: // C99 6.8.4.2: switch-statement
- return ParseSwitchStatement(attrs, TrailingElseLoc);
+ return ParseSwitchStatement(TrailingElseLoc);
case tok::kw_while: // C99 6.8.5.1: while-statement
- return ParseWhileStatement(attrs, TrailingElseLoc);
+ return ParseWhileStatement(TrailingElseLoc);
case tok::kw_do: // C99 6.8.5.2: do-statement
- Res = ParseDoStatement(attrs);
+ Res = ParseDoStatement();
SemiError = "do/while";
break;
case tok::kw_for: // C99 6.8.5.3: for-statement
- return ParseForStatement(attrs, TrailingElseLoc);
+ return ParseForStatement(TrailingElseLoc);
case tok::kw_goto: // C99 6.8.6.1: goto-statement
- Res = ParseGotoStatement(attrs);
+ Res = ParseGotoStatement();
SemiError = "goto";
break;
case tok::kw_continue: // C99 6.8.6.2: continue-statement
- Res = ParseContinueStatement(attrs);
+ Res = ParseContinueStatement();
SemiError = "continue";
break;
case tok::kw_break: // C99 6.8.6.3: break-statement
- Res = ParseBreakStatement(attrs);
+ Res = ParseBreakStatement();
SemiError = "break";
break;
case tok::kw_return: // C99 6.8.6.4: return-statement
- Res = ParseReturnStatement(attrs);
+ Res = ParseReturnStatement();
SemiError = "return";
break;
case tok::kw_asm: {
- ProhibitAttributes(attrs);
+ ProhibitAttributes(Attrs);
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
Res = Actions.ActOnFinishFullStmt(Res.get());
@@ -276,16 +294,19 @@ Retry:
}
case tok::kw_try: // C++ 15: try-block
- return ParseCXXTryBlock(attrs);
+ return ParseCXXTryBlock();
case tok::kw___try:
- return ParseSEHTryBlock(attrs);
+ ProhibitAttributes(Attrs); // TODO: is it correct?
+ return ParseSEHTryBlock();
case tok::annot_pragma_vis:
+ ProhibitAttributes(Attrs);
HandlePragmaVisibility();
return StmtEmpty();
case tok::annot_pragma_pack:
+ ProhibitAttributes(Attrs);
HandlePragmaPack();
return StmtEmpty();
}
@@ -306,11 +327,10 @@ Retry:
}
/// \brief Parse an expression statement.
-StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {
+StmtResult Parser::ParseExprStatement() {
// If a case keyword is missing, this is where it should be inserted.
Token OldToken = Tok;
- // FIXME: Use the attributes
// expression[opt] ';'
ExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
@@ -331,7 +351,7 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {
<< FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
// Recover parsing as a case statement.
- return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr);
+ return ParseCaseStatement(/*MissingCase=*/true, Expr);
}
// Otherwise, eat the semicolon.
@@ -339,7 +359,7 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) {
return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get()));
}
-StmtResult Parser::ParseSEHTryBlock(ParsedAttributes & Attrs) {
+StmtResult Parser::ParseSEHTryBlock() {
assert(Tok.is(tok::kw___try) && "Expected '__try'");
SourceLocation Loc = ConsumeToken();
return ParseSEHTryBlockCommon(Loc);
@@ -358,13 +378,12 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
if(Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok,diag::err_expected_lbrace));
- ParsedAttributesWithRange attrs(AttrFactory);
- StmtResult TryBlock(ParseCompoundStatement(attrs));
+ StmtResult TryBlock(ParseCompoundStatement());
if(TryBlock.isInvalid())
return move(TryBlock);
StmtResult Handler;
- if (Tok.is(tok::identifier) &&
+ if (Tok.is(tok::identifier) &&
Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
SourceLocation Loc = ConsumeToken();
Handler = ParseSEHExceptBlock(Loc);
@@ -418,8 +437,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen))
return StmtError();
- ParsedAttributesWithRange attrs(AttrFactory);
- StmtResult Block(ParseCompoundStatement(attrs));
+ StmtResult Block(ParseCompoundStatement());
if(Block.isInvalid())
return move(Block);
@@ -437,8 +455,7 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
raii2(Ident___abnormal_termination, false),
raii3(Ident_AbnormalTermination, false);
- ParsedAttributesWithRange attrs(AttrFactory);
- StmtResult Block(ParseCompoundStatement(attrs));
+ StmtResult Block(ParseCompoundStatement());
if(Block.isInvalid())
return move(Block);
@@ -451,7 +468,7 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) {
/// identifier ':' statement
/// [GNU] identifier ':' attributes[opt] statement
///
-StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
+StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
"Not an identifier!");
@@ -463,7 +480,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
// identifier ':' statement
SourceLocation ColonLoc = ConsumeToken();
- // Read label attributes, if present.
+ // Read label attributes, if present. attrs will contain both C++11 and GNU
+ // attributes (if present) after this point.
MaybeParseGNUAttributes(attrs);
StmtResult SubStmt(ParseStatement());
@@ -474,8 +492,10 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
IdentTok.getLocation());
- if (AttributeList *Attrs = attrs.getList())
+ if (AttributeList *Attrs = attrs.getList()) {
Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
+ attrs.clear();
+ }
return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
SubStmt.get());
@@ -486,10 +506,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) {
/// 'case' constant-expression ':' statement
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
///
-StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase,
- ExprResult Expr) {
+StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
- // FIXME: Use attributes?
// It is very very common for code to contain many case statements recursively
// nested, as in (but usually without indentation):
@@ -625,9 +643,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase,
/// 'default' ':' statement
/// Note that this does not parse the 'statement' at the end.
///
-StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {
- //FIXME: Use attributes?
-
+StmtResult Parser::ParseDefaultStatement() {
assert(Tok.is(tok::kw_default) && "Not a default stmt!");
SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
@@ -668,9 +684,8 @@ StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) {
SubStmt.get(), getCurScope());
}
-StmtResult Parser::ParseCompoundStatement(ParsedAttributes &Attr,
- bool isStmtExpr) {
- return ParseCompoundStatement(Attr, isStmtExpr, Scope::DeclScope);
+StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
+ return ParseCompoundStatement(isStmtExpr, Scope::DeclScope);
}
/// ParseCompoundStatement - Parse a "{}" block.
@@ -700,11 +715,8 @@ StmtResult Parser::ParseCompoundStatement(ParsedAttributes &Attr,
/// [OMP] barrier-directive
/// [OMP] flush-directive
///
-StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs,
- bool isStmtExpr,
+StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
unsigned ScopeFlags) {
- //FIXME: Use attributes?
-
assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
// Enter a scope to hold everything within the compound stmt. Compound
@@ -894,10 +906,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
/// [C++] 'if' '(' condition ')' statement
/// [C++] 'if' '(' condition ')' statement 'else' statement
///
-StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs,
- SourceLocation *TrailingElseLoc) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
assert(Tok.is(tok::kw_if) && "Not an if stmt!");
SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
@@ -1028,10 +1037,7 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs,
/// switch-statement:
/// 'switch' '(' expression ')' statement
/// [C++] 'switch' '(' condition ')' statement
-StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs,
- SourceLocation *TrailingElseLoc) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
@@ -1119,10 +1125,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs,
/// while-statement: [C99 6.8.5.1]
/// 'while' '(' expression ')' statement
/// [C++] 'while' '(' condition ')' statement
-StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs,
- SourceLocation *TrailingElseLoc) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
assert(Tok.is(tok::kw_while) && "Not a while stmt!");
SourceLocation WhileLoc = Tok.getLocation();
ConsumeToken(); // eat the 'while'.
@@ -1194,9 +1197,7 @@ StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs,
/// do-statement: [C99 6.8.5.2]
/// 'do' statement 'while' '(' expression ')' ';'
/// Note: this lets the caller parse the end ';'.
-StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseDoStatement() {
assert(Tok.is(tok::kw_do) && "Not a do stmt!");
SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
@@ -1277,10 +1278,7 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) {
/// [C++0x] for-range-initializer:
/// [C++0x] expression
/// [C++0x] braced-init-list [TODO]
-StmtResult Parser::ParseForStatement(ParsedAttributes &attrs,
- SourceLocation *TrailingElseLoc) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
assert(Tok.is(tok::kw_for) && "Not a for stmt!");
SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
@@ -1535,9 +1533,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs,
///
/// Note: this lets the caller parse the end ';'.
///
-StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseGotoStatement() {
assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
@@ -1571,9 +1567,7 @@ StmtResult Parser::ParseGotoStatement(ParsedAttributes &attrs) {
///
/// Note: this lets the caller parse the end ';'.
///
-StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseContinueStatement() {
SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
}
@@ -1584,9 +1578,7 @@ StmtResult Parser::ParseContinueStatement(ParsedAttributes &attrs) {
///
/// Note: this lets the caller parse the end ';'.
///
-StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseBreakStatement() {
SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
}
@@ -1594,9 +1586,7 @@ StmtResult Parser::ParseBreakStatement(ParsedAttributes &attrs) {
/// ParseReturnStatement
/// jump-statement:
/// 'return' expression[opt] ';'
-StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) {
- // FIXME: Use attributes?
-
+StmtResult Parser::ParseReturnStatement() {
assert(Tok.is(tok::kw_return) && "Not a return stmt!");
SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
@@ -2043,9 +2033,7 @@ bool Parser::trySkippingFunctionBody() {
/// try-block:
/// 'try' compound-statement handler-seq
///
-StmtResult Parser::ParseCXXTryBlock(ParsedAttributes &attrs) {
- // FIXME: Add attributes?
-
+StmtResult Parser::ParseCXXTryBlock() {
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
@@ -2072,17 +2060,17 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- ParsedAttributesWithRange attrs(AttrFactory);
- StmtResult TryBlock(ParseCompoundStatement(attrs, /*isStmtExpr=*/false,
+
+ StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
Scope::DeclScope|Scope::TryScope));
if (TryBlock.isInvalid())
return move(TryBlock);
// Borland allows SEH-handlers with 'try'
- if((Tok.is(tok::identifier) &&
- Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
- Tok.is(tok::kw___finally)) {
+ if ((Tok.is(tok::identifier) &&
+ Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
+ Tok.is(tok::kw___finally)) {
// TODO: Factor into common return ParseSEHHandlerCommon(...)
StmtResult Handler;
if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
@@ -2103,6 +2091,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
}
else {
StmtVector Handlers(Actions);
+ ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX0XAttributes(attrs);
ProhibitAttributes(attrs);
@@ -2168,8 +2157,7 @@ StmtResult Parser::ParseCXXCatchBlock() {
return StmtError(Diag(Tok, diag::err_expected_lbrace));
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- ParsedAttributes attrs(AttrFactory);
- StmtResult Block(ParseCompoundStatement(attrs));
+ StmtResult Block(ParseCompoundStatement());
if (Block.isInvalid())
return move(Block);
@@ -2188,24 +2176,23 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
if (Result.Behavior == IEB_Dependent) {
if (!Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_expected_lbrace);
- return;
+ return;
}
-
- ParsedAttributes Attrs(AttrFactory);
- StmtResult Compound = ParseCompoundStatement(Attrs);
+
+ StmtResult Compound = ParseCompoundStatement();
if (Compound.isInvalid())
return;
-
+
StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,
Result.IsIfExists,
- Result.SS,
+ Result.SS,
Result.Name,
Compound.get());
if (DepResult.isUsable())
Stmts.push_back(DepResult.get());
return;
}
-
+
BalancedDelimiterTracker Braces(*this, tok::l_brace);
if (Braces.consumeOpen()) {
Diag(Tok, diag::err_expected_lbrace);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 61cd9f2..5c3e2ba 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -652,6 +652,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// end of the template-parameter-list rather than a greater-than
// operator.
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
DefaultArg = ParseAssignmentExpression();
if (DefaultArg.isInvalid())
@@ -838,7 +839,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// later.
Tok.setKind(tok::annot_template_id);
TemplateIdAnnotation *TemplateId
- = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+ = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
TemplateId->TemplateNameLoc = TemplateNameLoc;
if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = TemplateName.Identifier;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 054a8fd..f1b99fb 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -397,6 +397,8 @@ Parser::~Parser() {
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
FPContractHandler.reset();
PP.clearCodeCompletionHandler();
+
+ assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
}
/// Initialize - Warm up the parser.
@@ -470,10 +472,30 @@ void Parser::Initialize() {
}
}
+namespace {
+ /// \brief RAIIObject to destroy the contents of a SmallVector of
+ /// TemplateIdAnnotation pointers and clear the vector.
+ class DestroyTemplateIdAnnotationsRAIIObj {
+ SmallVectorImpl<TemplateIdAnnotation *> &Container;
+ public:
+ DestroyTemplateIdAnnotationsRAIIObj(SmallVectorImpl<TemplateIdAnnotation *>
+ &Container)
+ : Container(Container) {}
+
+ ~DestroyTemplateIdAnnotationsRAIIObj() {
+ for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I =
+ Container.begin(), E = Container.end();
+ I != E; ++I)
+ (*I)->Destroy();
+ Container.clear();
+ }
+ };
+}
+
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
- DelayedCleanupPoint CleanupRAII(TopLevelDeclCleanupPool);
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
// Skip over the EOF token, flagging end of previous input for incremental
// processing
@@ -543,7 +565,7 @@ void Parser::ParseTranslationUnit() {
Parser::DeclGroupPtrTy
Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS) {
- DelayedCleanupPoint CleanupRAII(TopLevelDeclCleanupPool);
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
if (PP.isCodeCompletionReached()) {
@@ -1201,8 +1223,6 @@ TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) {
assert(tok.is(tok::annot_template_id) && "Expected template-id token");
TemplateIdAnnotation *
Id = static_cast<TemplateIdAnnotation *>(tok.getAnnotationValue());
- TopLevelDeclCleanupPool.delayMemberFunc< TemplateIdAnnotation,
- &TemplateIdAnnotation::Destroy>(Id);
return Id;
}
diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp
index 57109de..94fba64 100644
--- a/lib/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Rewrite/RewriteModernObjC.cpp
@@ -304,7 +304,6 @@ namespace {
void RewriteFunctionDecl(FunctionDecl *FD);
void RewriteBlockPointerType(std::string& Str, QualType Type);
void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
- void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
void RewriteTypeOfDecl(VarDecl *VD);
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
@@ -2246,31 +2245,7 @@ void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,
}
}
-
-void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
- SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
- const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
- const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
- if (!proto)
- return;
- QualType Type = proto->getResultType();
- std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
- FdStr += " ";
- FdStr += FD->getName();
- FdStr += "(";
- unsigned numArgs = proto->getNumArgs();
- for (unsigned i = 0; i < numArgs; i++) {
- QualType ArgType = proto->getArgType(i);
- RewriteBlockPointerType(FdStr, ArgType);
- if (i+1 < numArgs)
- FdStr += ", ";
- }
- FdStr += ");\n";
- InsertText(FunLocStart, FdStr);
- CurFunctionDeclToDeclareForBlock = 0;
-}
-
-// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
+// SynthSuperContructorFunctionDecl - id __rw_objc_super(id obj, id super);
void RewriteModernObjC::SynthSuperContructorFunctionDecl() {
if (SuperContructorFunctionDecl)
return;
@@ -2311,21 +2286,13 @@ void RewriteModernObjC::SynthMsgSendFunctionDecl() {
SC_None, false);
}
-// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
+// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);
void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
- SmallVector<QualType, 16> ArgTys;
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get("objc_super"));
- QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
- assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
- ArgTys.push_back(argT);
- argT = Context->getObjCSelType();
- assert(!argT.isNull() && "Can't find 'SEL' type");
- ArgTys.push_back(argT);
+ SmallVector<QualType, 2> ArgTys;
+ ArgTys.push_back(Context->VoidTy);
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
- &ArgTys[0], ArgTys.size(),
+ &ArgTys[0], 1,
true /*isVariadic*/);
MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
@@ -2357,22 +2324,14 @@ void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {
}
// SynthMsgSendSuperStretFunctionDecl -
-// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
+// id objc_msgSendSuper_stret(void);
void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {
IdentifierInfo *msgSendIdent =
&Context->Idents.get("objc_msgSendSuper_stret");
- SmallVector<QualType, 16> ArgTys;
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get("objc_super"));
- QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
- assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
- ArgTys.push_back(argT);
- argT = Context->getObjCSelType();
- assert(!argT.isNull() && "Can't find 'SEL' type");
- ArgTys.push_back(argT);
+ SmallVector<QualType, 2> ArgTys;
+ ArgTys.push_back(Context->VoidTy);
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
- &ArgTys[0], ArgTys.size(),
+ &ArgTys[0], 1,
true /*isVariadic*/);
MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
@@ -2925,18 +2884,20 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral
return CE;
}
-// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
+// struct __rw_objc_super {
+// struct objc_object *object; struct objc_object *superClass;
+// };
QualType RewriteModernObjC::getSuperStructType() {
if (!SuperStructDecl) {
SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
SourceLocation(), SourceLocation(),
- &Context->Idents.get("objc_super"));
+ &Context->Idents.get("__rw_objc_super"));
QualType FieldTypes[2];
- // struct objc_object *receiver;
+ // struct objc_object *object;
FieldTypes[0] = Context->getObjCIdType();
- // struct objc_class *super;
- FieldTypes[1] = Context->getObjCClassType();
+ // struct objc_object *superClass;
+ FieldTypes[1] = Context->getObjCIdType();
// Create fields
for (unsigned i = 0; i < 2; ++i) {
@@ -3073,7 +3034,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
NoTypeInfoCStyleCastExpr(Context,
Context->getObjCIdType(),
CK_BitCast, Cls));
- // struct objc_super
+ // struct __rw_objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
@@ -3091,7 +3052,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
// we need the cast below. For example:
- // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
+ // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
//
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
@@ -3101,7 +3062,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
} else {
- // (struct objc_super) { <exprs from above> }
+ // (struct __rw_objc_super) { <exprs from above> }
InitListExpr *ILE =
new (Context) InitListExpr(*Context, SourceLocation(),
&InitExprs[0], InitExprs.size(),
@@ -3111,7 +3072,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
superType, VK_LValue,
ILE, false);
- // struct objc_super *
+ // struct __rw_objc_super *
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
VK_RValue, OK_Ordinary,
@@ -3183,7 +3144,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CK_BitCast, Cls));
- // struct objc_super
+ // struct __rw_objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
@@ -3200,7 +3161,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// the structure definition in the header. The rewriter has it's own
// internal definition (__rw_objc_super) that is uses. This is why
// we need the cast below. For example:
- // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
+ // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
//
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
@@ -3210,7 +3171,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
Context->getPointerType(superType),
CK_BitCast, SuperRep);
} else {
- // (struct objc_super) { <exprs from above> }
+ // (struct __rw_objc_super) { <exprs from above> }
InitListExpr *ILE =
new (Context) InitListExpr(*Context, SourceLocation(),
&InitExprs[0], InitExprs.size(),
@@ -4022,11 +3983,25 @@ std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
return S;
}
+/// getFunctionSourceLocation - returns start location of a function
+/// definition. Complication arises when function has declared as
+/// extern "C" or extern "C" {...}
+static SourceLocation getFunctionSourceLocation (FunctionDecl *FD) {
+ if (!FD->isExternC() || FD->isMain())
+ return FD->getTypeSpecStartLoc();
+ const DeclContext *DC = FD->getDeclContext();
+ if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
+ SourceLocation BodyRBrace = LSD->getRBraceLoc();
+ // if it is extern "C" {...}, return function decl's own location.
+ if (BodyRBrace.isValid())
+ return FD->getTypeSpecStartLoc();
+ return LSD->getExternLoc();
+ }
+ return FD->getTypeSpecStartLoc();
+}
+
void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
StringRef FunName) {
- // Insert declaration for the function in which block literal is used.
- if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
- RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
bool RewriteSC = (GlobalVarDecl &&
!Blocks.empty() &&
GlobalVarDecl->getStorageClass() == SC_Static &&
@@ -4135,7 +4110,7 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
}
void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
- SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
+ SourceLocation FunLocStart = getFunctionSourceLocation(FD);
StringRef FuncName = FD->getName();
SynthesizeBlockLiterals(FunLocStart, FuncName);
@@ -4170,11 +4145,15 @@ void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
GetBlockDeclRefExprs(*CI);
}
// Handle specific things.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
- if (DRE->refersToEnclosingLocal() &&
- HasLocalVariableExternalStorage(DRE->getDecl())) {
- BlockDeclRefs.push_back(DRE);
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+ if (DRE->refersToEnclosingLocal()) {
+ // FIXME: Handle enums.
+ if (!isa<FunctionDecl>(DRE->getDecl()))
+ BlockDeclRefs.push_back(DRE);
+ if (HasLocalVariableExternalStorage(DRE->getDecl()))
+ BlockDeclRefs.push_back(DRE);
}
+ }
return;
}
@@ -4474,19 +4453,18 @@ void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {
void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
CastKind CastKind = IC->getCastKind();
+ if (CastKind != CK_BlockPointerToObjCPointerCast &&
+ CastKind != CK_AnyPointerToBlockPointerCast)
+ return;
- if (CastKind == CK_BlockPointerToObjCPointerCast) {
- CStyleCastExpr * CastExpr =
- NoTypeInfoCStyleCastExpr(Context, IC->getType(), CK_BitCast, IC);
- ReplaceStmt(IC, CastExpr);
- }
- else if (CastKind == CK_AnyPointerToBlockPointerCast) {
- QualType BlockT = IC->getType();
- (void)convertBlockPointerToFunctionPointer(BlockT);
- CStyleCastExpr * CastExpr =
- NoTypeInfoCStyleCastExpr(Context, BlockT, CK_BitCast, IC);
- ReplaceStmt(IC, CastExpr);
- }
+ QualType QT = IC->getType();
+ (void)convertBlockPointerToFunctionPointer(QT);
+ std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));
+ std::string Str = "(";
+ Str += TypeString;
+ Str += ")";
+ InsertText(IC->getSubExpr()->getLocStart(), &Str[0], Str.size());
+
return;
}
@@ -4742,10 +4720,6 @@ std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
///
///
void RewriteModernObjC::RewriteByRefVar(VarDecl *ND) {
- // Insert declaration for the function in which block literal is
- // used.
- if (CurFunctionDeclToDeclareForBlock)
- RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
int flag = 0;
int isa = 0;
SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
@@ -4784,7 +4758,7 @@ void RewriteModernObjC::RewriteByRefVar(VarDecl *ND) {
// Insert this type in global scope. It is needed by helper function.
SourceLocation FunLocStart;
if (CurFunctionDef)
- FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
+ FunLocStart = getFunctionSourceLocation(CurFunctionDef);
else {
assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
FunLocStart = CurMethodDef->getLocStart();
@@ -5375,6 +5349,7 @@ Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
RewriteImplicitCastObjCExpr(ICE);
}
#if 0
+
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
ICE->getSubExpr(),
@@ -5627,13 +5602,11 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
// These are currently generated.
Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";
- Preamble += "#pragma section(\".objc_protolist$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";
Preamble += "#pragma section(\".objc_protorefs$B\", long, read, write)\n";
// These are generated but not necessary for functionality.
- Preamble += "#pragma section(\".datacoal_nt$B\", long, read, write)\n";
Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";
Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
@@ -6604,7 +6577,7 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
// Writer out root metadata for current protocol: struct _protocol_t
Result += "\n";
if (LangOpts.MicrosoftExt)
- Result += "__declspec(allocate(\".datacoal_nt$B\")) ";
+ Result += "static ";
Result += "struct _protocol_t _OBJC_PROTOCOL_";
Result += PDecl->getNameAsString();
Result += " __attribute__ ((used, section (\"__DATA,__datacoal_nt,coalesced\"))) = {\n";
@@ -6662,11 +6635,8 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
else
Result += "\t0\n};\n";
- // Use this protocol meta-data to build protocol list table in section
- // .objc_protolist$B
- // Unspecified visibility means 'private extern'.
if (LangOpts.MicrosoftExt)
- Result += "__declspec(allocate(\".objc_protolist$B\")) ";
+ Result += "static ";
Result += "struct _protocol_t *";
Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
diff --git a/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp
index 6c211b2..cc8de1b 100644
--- a/lib/Rewrite/RewriteRope.cpp
+++ b/lib/Rewrite/RewriteRope.cpp
@@ -407,6 +407,11 @@ namespace {
Size = LHS->size() + RHS->size();
}
+ ~RopePieceBTreeInterior() {
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ Children[i]->Destroy();
+ }
+
bool isFull() const { return NumChildren == 2*WidthFactor; }
unsigned getNumChildren() const { return NumChildren; }
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 5d297f9..07734c7 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -40,6 +40,7 @@ add_clang_library(clangSema
SemaOverload.cpp
SemaPseudoObject.cpp
SemaStmt.cpp
+ SemaStmtAttr.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
SemaTemplateInstantiate.cpp
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index b531acc..fe63e35 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -162,6 +162,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
Expr *NoexceptExpr,
+ CachedTokens *ExceptionSpecTokens,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
@@ -226,6 +227,10 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
case EST_ComputedNoexcept:
I.Fun.NoexceptExpr = NoexceptExpr;
break;
+
+ case EST_Delayed:
+ I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
+ break;
}
return I;
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fcdfcac..30a9cd7 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -103,6 +103,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
AnalysisWarnings(*this)
{
TUScope = 0;
+
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = 0;
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index dea5e76..01c141e 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -779,6 +779,13 @@ static AccessResult HasAccess(Sema &S,
// that the naming class has to be derived from the effective
// context.
+ // Emulate a MSVC bug where the creation of pointer-to-member
+ // to protected member of base class is allowed but only from
+ // a static function member functions.
+ if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
+ if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
+ if (MD->isStatic()) return AR_accessible;
+
// Despite the standard's confident wording, there is a case
// where you can have an instance member that's neither in a
// pointer-to-member expression nor in a member access: when
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8b314b5..1550993 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4471,6 +4471,11 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
return false;
}
+static bool hasDelayedExceptionSpec(CXXMethodDecl *Method) {
+ const FunctionProtoType *Proto =Method->getType()->getAs<FunctionProtoType>();
+ return Proto && Proto->getExceptionSpecType() == EST_Delayed;
+}
+
/// AddOverriddenMethods - See if a method overrides any in the base classes,
/// and if so, check that it's a valid override and remember it.
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
@@ -4486,7 +4491,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
+ (hasDelayedExceptionSpec(MD) ||
+ !CheckOverridingFunctionExceptionSpec(MD, OldMD)) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
AddedAny = true;
}
@@ -5834,6 +5840,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
}
+
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionType(Method);
}
// Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -7176,8 +7185,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
}
}
-Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
- Declarator &D) {
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
assert(getCurFunctionDecl() == 0 && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
@@ -7350,6 +7358,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
}
}
+ // Ensure that the function's exception specification is instantiated.
+ if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
+ ResolveExceptionSpec(D->getLocation(), FPT);
+
// Checking attributes of current function definition
// dllimport attribute.
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
@@ -7554,7 +7566,11 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
// Always attach attributes to the underlying decl.
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
- ProcessDeclAttributeList(S, D, Attrs.getList());
+ ProcessDeclAttributeList(S, D, Attrs.getList());
+
+ if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionAttributes(Method);
}
@@ -7619,7 +7635,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
SourceLocation(), SourceLocation(),
SourceLocation(),
EST_None, SourceLocation(),
- 0, 0, 0, 0, Loc, Loc, D),
+ 0, 0, 0, 0, 0, Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
D.SetIdentifier(&II, Loc);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 847f03c..1d251b9 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
@@ -124,14 +125,17 @@ namespace {
}
}
-void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
- assert(Context && "ImplicitExceptionSpecification without an ASTContext");
+void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
+ CXXMethodDecl *Method) {
// If we have an MSAny or unknown spec already, don't bother.
if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
return;
const FunctionProtoType *Proto
= Method->getType()->getAs<FunctionProtoType>();
+ Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
+ if (!Proto)
+ return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
@@ -163,7 +167,8 @@ void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
// Check out noexcept specs.
if (EST == EST_ComputedNoexcept) {
- FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(*Context);
+ FunctionProtoType::NoexceptResult NR =
+ Proto->getNoexceptSpec(Self->Context);
assert(NR != FunctionProtoType::NR_NoNoexcept &&
"Must have noexcept result for EST_ComputedNoexcept.");
assert(NR != FunctionProtoType::NR_Dependent &&
@@ -187,7 +192,7 @@ void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
EEnd = Proto->exception_end();
E != EEnd; ++E)
- if (ExceptionsSeen.insert(Context->getCanonicalType(*E)))
+ if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
Exceptions.push_back(*E);
}
@@ -216,7 +221,7 @@ void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
// implicit definition. For now, we assume that any non-nothrow expression can
// throw any exception.
- if (E->CanThrow(*Context))
+ if (Self->canThrow(E))
ComputedEST = EST_None;
}
@@ -3921,7 +3926,7 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) {
HadError = true;
}
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent());
@@ -4030,7 +4035,7 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) {
HadError = true;
}
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent());
@@ -5920,10 +5925,12 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
case UnqualifiedId::IK_ConstructorName:
case UnqualifiedId::IK_ConstructorTemplateId:
- // C++0x inherited constructors.
+ // C++11 inheriting constructors.
Diag(Name.getLocStart(),
getLangOpts().CPlusPlus0x ?
- diag::warn_cxx98_compat_using_decl_constructor :
+ // FIXME: Produce warn_cxx98_compat_using_decl_constructor
+ // instead once inheriting constructors work.
+ diag::err_using_decl_constructor_unsupported :
diag::err_using_decl_constructor)
<< SS.getRange();
@@ -6813,7 +6820,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -6830,7 +6837,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -6844,7 +6851,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -6867,7 +6874,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// might just be ill-formed because this function attempts to refer to
// a deleted function here.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(F->getLocation(), Constructor);
}
}
@@ -6989,6 +6996,7 @@ void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
const FunctionProtoType *CtorTy =
CtorDecl->getType()->castAs<FunctionProtoType>();
if (CtorTy->getExceptionSpecType() == EST_Delayed) {
+ // FIXME: Don't do this unless the exception spec is needed.
ImplicitExceptionSpecification Spec =
ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
@@ -7189,7 +7197,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have
// an exception-specification.
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -7201,7 +7209,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
continue;
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(
+ ExceptSpec.CalledDecl(B->getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
@@ -7210,7 +7218,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
BEnd = ClassDecl->vbases_end();
B != BEnd; ++B) {
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(
+ ExceptSpec.CalledDecl(B->getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
@@ -7220,7 +7228,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
F != FEnd; ++F) {
if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>())
- ExceptSpec.CalledDecl(
+ ExceptSpec.CalledDecl(F->getLocation(),
LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
}
@@ -7545,7 +7553,7 @@ std::pair<Sema::ImplicitExceptionSpecification, bool>
Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
CXXRecordDecl *ClassDecl) {
if (ClassDecl->isInvalidDecl())
- return std::make_pair(ImplicitExceptionSpecification(Context), false);
+ return std::make_pair(ImplicitExceptionSpecification(*this), false);
// C++ [class.copy]p10:
// If the class definition does not explicitly declare a copy
@@ -7618,7 +7626,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
// Based on a similar decision made for constness in C++0x, we're erring on
// the side of assuming such calls to be made regardless of whether they
// actually happen.
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
BaseEnd = ClassDecl->bases_end();
@@ -7630,7 +7638,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(CopyAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
}
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -7640,7 +7648,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(CopyAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -7651,7 +7659,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *CopyAssign =
LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))
- ExceptSpec.CalledDecl(CopyAssign);
+ ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
}
}
@@ -7664,7 +7672,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// for determining the argument type of the operator. Note also that
// operators taking an object instead of a reference are allowed.
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl);
@@ -8031,7 +8039,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -8058,7 +8066,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
false, 0))
- ExceptSpec.CalledDecl(MoveAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
}
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -8068,7 +8076,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
false, 0))
- ExceptSpec.CalledDecl(MoveAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -8079,7 +8087,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(FieldClassDecl,
false, 0))
- ExceptSpec.CalledDecl(MoveAssign);
+ ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
}
}
@@ -8577,7 +8585,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
std::pair<Sema::ImplicitExceptionSpecification, bool>
Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
if (ClassDecl->isInvalidDecl())
- return std::make_pair(ImplicitExceptionSpecification(Context), false);
+ return std::make_pair(ImplicitExceptionSpecification(*this), false);
// C++ [class.copy]p5:
// The implicitly-declared copy constructor for a class X will
@@ -8638,7 +8646,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
BaseEnd = ClassDecl->bases_end();
@@ -8652,7 +8660,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(CopyConstructor);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
}
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
BaseEnd = ClassDecl->vbases_end();
@@ -8662,7 +8670,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(CopyConstructor);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
FieldEnd = ClassDecl->field_end();
@@ -8672,7 +8680,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(FieldClassDecl, Quals))
- ExceptSpec.CalledDecl(CopyConstructor);
+ ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
}
}
@@ -8685,7 +8693,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// If the class definition does not explicitly declare a copy
// constructor, one is declared implicitly.
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl);
@@ -8783,7 +8791,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -8800,7 +8808,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -8814,7 +8822,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -8832,7 +8840,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// might just be ill-formed because this function attempts to refer to
// a deleted function here.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(F->getLocation(), Constructor);
}
}
@@ -11053,6 +11061,265 @@ void Sema::CheckDelegatingCtorCycles() {
(*CI)->setInvalidDecl();
}
+namespace {
+ /// \brief AST visitor that finds references to the 'this' expression.
+ class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
+ Sema &S;
+
+ public:
+ explicit FindCXXThisExpr(Sema &S) : S(S) { }
+
+ bool VisitCXXThisExpr(CXXThisExpr *E) {
+ S.Diag(E->getLocation(), diag::err_this_static_member_func)
+ << E->isImplicit();
+ return false;
+ }
+ };
+}
+
+bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
+ TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+ if (!TSInfo)
+ return false;
+
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ if (!ProtoTL)
+ return false;
+
+ // C++11 [expr.prim.general]p3:
+ // [The expression this] shall not appear before the optional
+ // cv-qualifier-seq and it shall not appear within the declaration of a
+ // static member function (although its type and value category are defined
+ // within a static member function as they are within a non-static member
+ // function). [ Note: this is because declaration matching does not occur
+ // until the complete declarator is known. - end note ]
+ const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ FindCXXThisExpr Finder(*this);
+
+ // If the return type came after the cv-qualifier-seq, check it now.
+ if (Proto->hasTrailingReturn() &&
+ !Finder.TraverseTypeLoc(ProtoTL->getResultLoc()))
+ return true;
+
+ // Check the exception specification.
+ if (checkThisInStaticMemberFunctionExceptionSpec(Method))
+ return true;
+
+ return checkThisInStaticMemberFunctionAttributes(Method);
+}
+
+bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
+ TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+ if (!TSInfo)
+ return false;
+
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ if (!ProtoTL)
+ return false;
+
+ const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ FindCXXThisExpr Finder(*this);
+
+ switch (Proto->getExceptionSpecType()) {
+ case EST_Uninstantiated:
+ case EST_BasicNoexcept:
+ case EST_Delayed:
+ case EST_DynamicNone:
+ case EST_MSAny:
+ case EST_None:
+ break;
+
+ case EST_ComputedNoexcept:
+ if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
+ return true;
+
+ case EST_Dynamic:
+ for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+ EEnd = Proto->exception_end();
+ E != EEnd; ++E) {
+ if (!Finder.TraverseType(*E))
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
+ FindCXXThisExpr Finder(*this);
+
+ // Check attributes.
+ for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end();
+ A != AEnd; ++A) {
+ // FIXME: This should be emitted by tblgen.
+ Expr *Arg = 0;
+ ArrayRef<Expr *> Args;
+ if (GuardedByAttr *G = dyn_cast<GuardedByAttr>(*A))
+ Arg = G->getArg();
+ else if (PtGuardedByAttr *G = dyn_cast<PtGuardedByAttr>(*A))
+ Arg = G->getArg();
+ else if (AcquiredAfterAttr *AA = dyn_cast<AcquiredAfterAttr>(*A))
+ Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
+ else if (AcquiredBeforeAttr *AB = dyn_cast<AcquiredBeforeAttr>(*A))
+ Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
+ else if (ExclusiveLockFunctionAttr *ELF
+ = dyn_cast<ExclusiveLockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
+ else if (SharedLockFunctionAttr *SLF
+ = dyn_cast<SharedLockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
+ else if (ExclusiveTrylockFunctionAttr *ETLF
+ = dyn_cast<ExclusiveTrylockFunctionAttr>(*A)) {
+ Arg = ETLF->getSuccessValue();
+ Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
+ } else if (SharedTrylockFunctionAttr *STLF
+ = dyn_cast<SharedTrylockFunctionAttr>(*A)) {
+ Arg = STLF->getSuccessValue();
+ Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
+ } else if (UnlockFunctionAttr *UF = dyn_cast<UnlockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
+ else if (LockReturnedAttr *LR = dyn_cast<LockReturnedAttr>(*A))
+ Arg = LR->getArg();
+ else if (LocksExcludedAttr *LE = dyn_cast<LocksExcludedAttr>(*A))
+ Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
+ else if (ExclusiveLocksRequiredAttr *ELR
+ = dyn_cast<ExclusiveLocksRequiredAttr>(*A))
+ Args = ArrayRef<Expr *>(ELR->args_begin(), ELR->args_size());
+ else if (SharedLocksRequiredAttr *SLR
+ = dyn_cast<SharedLocksRequiredAttr>(*A))
+ Args = ArrayRef<Expr *>(SLR->args_begin(), SLR->args_size());
+
+ if (Arg && !Finder.TraverseStmt(Arg))
+ return true;
+
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ if (!Finder.TraverseStmt(Args[I]))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr,
+ llvm::SmallVectorImpl<QualType> &Exceptions,
+ FunctionProtoType::ExtProtoInfo &EPI) {
+ Exceptions.clear();
+ EPI.ExceptionSpecType = EST;
+ if (EST == EST_Dynamic) {
+ Exceptions.reserve(DynamicExceptions.size());
+ for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) {
+ // FIXME: Preserve type source info.
+ QualType ET = GetTypeFromParser(DynamicExceptions[ei]);
+
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(ET, Unexpanded);
+ if (!Unexpanded.empty()) {
+ DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),
+ UPPC_ExceptionType,
+ Unexpanded);
+ continue;
+ }
+
+ // Check that the type is valid for an exception spec, and
+ // drop it if not.
+ if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei]))
+ Exceptions.push_back(ET);
+ }
+ EPI.NumExceptions = Exceptions.size();
+ EPI.Exceptions = Exceptions.data();
+ return;
+ }
+
+ if (EST == EST_ComputedNoexcept) {
+ // If an error occurred, there's no expression here.
+ if (NoexceptExpr) {
+ assert((NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+ Context.BoolTy) &&
+ "Parser should have made sure that the expression is boolean");
+ if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+ EPI.ExceptionSpecType = EST_BasicNoexcept;
+ return;
+ }
+
+ if (!NoexceptExpr->isValueDependent())
+ NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0,
+ PDiag(diag::err_noexcept_needs_constant_expression),
+ /*AllowFold*/ false).take();
+ EPI.NoexceptExpr = NoexceptExpr;
+ }
+ return;
+ }
+}
+
+void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
+ ExceptionSpecificationType EST,
+ SourceRange SpecificationRange,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr) {
+ if (!MethodD)
+ return;
+
+ // Dig out the method we're referring to.
+ CXXMethodDecl *Method = 0;
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = dyn_cast<CXXMethodDecl>(MethodD);
+
+ if (!Method)
+ return;
+
+ // Dig out the prototype. This should never fail.
+ const FunctionProtoType *Proto
+ = dyn_cast<FunctionProtoType>(Method->getType());
+ if (!Proto)
+ return;
+
+ // Check the exception specification.
+ llvm::SmallVector<QualType, 4> Exceptions;
+ FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+ checkExceptionSpecification(EST, DynamicExceptions, DynamicExceptionRanges,
+ NoexceptExpr, Exceptions, EPI);
+
+ // Rebuild the function type.
+ QualType T = Context.getFunctionType(Proto->getResultType(),
+ Proto->arg_type_begin(),
+ Proto->getNumArgs(),
+ EPI);
+ if (TypeSourceInfo *TSInfo = Method->getTypeSourceInfo()) {
+ // FIXME: When we get proper type location information for exceptions,
+ // we'll also have to rebuild the TypeSourceInfo. For now, we just patch
+ // up the TypeSourceInfo;
+ assert(TypeLoc::getFullDataSizeForType(T)
+ == TypeLoc::getFullDataSizeForType(Method->getType()) &&
+ "TypeLoc size mismatch with delayed exception specification");
+ TSInfo->overrideType(T);
+ }
+
+ Method->setType(T);
+
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionExceptionSpec(Method);
+
+ if (Method->isVirtual()) {
+ // Check overrides, which we previously had to delay.
+ for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
+ OEnd = Method->end_overridden_methods();
+ O != OEnd; ++O)
+ CheckOverridingFunctionExceptionSpec(Method, *O);
+ }
+}
+
/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
// Implicitly declared functions (e.g. copy constructors) are
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 42221f8..14b2434 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -96,6 +96,26 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
return FnT->hasExceptionSpec();
}
+const FunctionProtoType *
+Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
+ // FIXME: If FD is a special member, we should delay computing its exception
+ // specification until this point.
+ if (FPT->getExceptionSpecType() != EST_Uninstantiated)
+ return FPT;
+
+ FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
+ const FunctionProtoType *SourceFPT =
+ SourceDecl->getType()->castAs<FunctionProtoType>();
+
+ if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
+ return SourceFPT;
+
+ // Instantiate the exception specification now.
+ InstantiateExceptionSpec(Loc, SourceDecl);
+
+ return SourceDecl->getType()->castAs<FunctionProtoType>();
+}
+
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
@@ -104,7 +124,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
unsigned DiagID = diag::err_mismatched_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::warn_mismatched_exception_spec;
-
+
if (!CheckEquivalentExceptionSpec(PDiag(DiagID),
PDiag(diag::note_previous_declaration),
Old->getType()->getAs<FunctionProtoType>(),
@@ -295,6 +315,13 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (MissingEmptyExceptionSpecification)
*MissingEmptyExceptionSpecification = false;
+ Old = ResolveExceptionSpec(NewLoc, Old);
+ if (!Old)
+ return false;
+ New = ResolveExceptionSpec(NewLoc, New);
+ if (!New)
+ return false;
+
// C++0x [except.spec]p3: Two exception-specifications are compatible if:
// - both are non-throwing, regardless of their form,
// - both have the form noexcept(constant-expression) and the constant-
@@ -318,6 +345,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
ExceptionSpecificationType NewEST = New->getExceptionSpecType();
assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
+ OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated &&
"Shouldn't see unknown exception specifications here");
// Shortcut the case where both have no spec.
@@ -483,6 +511,14 @@ bool Sema::CheckExceptionSpecSubset(
if (!SubLoc.isValid())
SubLoc = SuperLoc;
+ // Resolve the exception specifications, if needed.
+ Superset = ResolveExceptionSpec(SuperLoc, Superset);
+ if (!Superset)
+ return false;
+ Subset = ResolveExceptionSpec(SubLoc, Subset);
+ if (!Subset)
+ return false;
+
ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
// If superset contains everything, we're done.
@@ -507,6 +543,7 @@ bool Sema::CheckExceptionSpecSubset(
ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
+ SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated &&
"Shouldn't see unknown exception specifications here");
// It does not. If the subset contains everything, we've failed.
@@ -726,4 +763,324 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
New->getLocation());
}
+static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
+ Expr *E = const_cast<Expr*>(CE);
+ CanThrowResult R = CT_Cannot;
+ for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
+ R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
+ return R;
+}
+
+static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
+ const Decl *D,
+ bool NullThrows = true) {
+ if (!D)
+ return NullThrows ? CT_Can : CT_Cannot;
+
+ // See if we can get a function type from the decl somehow.
+ const ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (!VD) // If we have no clue what we're calling, assume the worst.
+ return CT_Can;
+
+ // As an extension, we assume that __attribute__((nothrow)) functions don't
+ // throw.
+ if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
+ return CT_Cannot;
+
+ QualType T = VD->getType();
+ const FunctionProtoType *FT;
+ if ((FT = T->getAs<FunctionProtoType>())) {
+ } else if (const PointerType *PT = T->getAs<PointerType>())
+ FT = PT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ FT = RT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
+ FT = MT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
+ FT = BT->getPointeeType()->getAs<FunctionProtoType>();
+
+ if (!FT)
+ return CT_Can;
+
+ FT = S.ResolveExceptionSpec(E->getLocStart(), FT);
+ if (!FT)
+ return CT_Can;
+
+ if (FT->getExceptionSpecType() == EST_Delayed) {
+ // FIXME: Try to resolve a delayed exception spec in ResolveExceptionSpec.
+ assert(isa<CXXConstructorDecl>(D) &&
+ "only constructor exception specs can be unknown");
+ S.Diag(E->getLocStart(), diag::err_exception_spec_unknown)
+ << E->getSourceRange();
+ return CT_Can;
+ }
+
+ return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
+}
+
+static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
+ if (DC->isTypeDependent())
+ return CT_Dependent;
+
+ if (!DC->getTypeAsWritten()->isReferenceType())
+ return CT_Cannot;
+
+ if (DC->getSubExpr()->isTypeDependent())
+ return CT_Dependent;
+
+ return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
+}
+
+static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
+ if (DC->isTypeOperand())
+ return CT_Cannot;
+
+ Expr *Op = DC->getExprOperand();
+ if (Op->isTypeDependent())
+ return CT_Dependent;
+
+ const RecordType *RT = Op->getType()->getAs<RecordType>();
+ if (!RT)
+ return CT_Cannot;
+
+ if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
+ return CT_Cannot;
+
+ if (Op->Classify(S.Context).isPRValue())
+ return CT_Cannot;
+
+ return CT_Can;
+}
+
+CanThrowResult Sema::canThrow(const Expr *E) {
+ // C++ [expr.unary.noexcept]p3:
+ // [Can throw] if in a potentially-evaluated context the expression would
+ // contain:
+ switch (E->getStmtClass()) {
+ case Expr::CXXThrowExprClass:
+ // - a potentially evaluated throw-expression
+ return CT_Can;
+
+ case Expr::CXXDynamicCastExprClass: {
+ // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
+ // where T is a reference type, that requires a run-time check
+ CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E));
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXTypeidExprClass:
+ // - a potentially evaluated typeid expression applied to a glvalue
+ // expression whose type is a polymorphic class type
+ return canTypeidThrow(*this, cast<CXXTypeidExpr>(E));
+
+ // - a potentially evaluated call to a function, member function, function
+ // pointer, or member function pointer that does not have a non-throwing
+ // exception-specification
+ case Expr::CallExprClass:
+ case Expr::CXXMemberCallExprClass:
+ case Expr::CXXOperatorCallExprClass:
+ case Expr::UserDefinedLiteralClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+ CanThrowResult CT;
+ if (E->isTypeDependent())
+ CT = CT_Dependent;
+ else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
+ CT = CT_Cannot;
+ else
+ CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXConstructExprClass:
+ case Expr::CXXTemporaryObjectExprClass: {
+ CanThrowResult CT = canCalleeThrow(*this, E,
+ cast<CXXConstructExpr>(E)->getConstructor());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::LambdaExprClass: {
+ const LambdaExpr *Lambda = cast<LambdaExpr>(E);
+ CanThrowResult CT = CT_Cannot;
+ for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
+ CapEnd = Lambda->capture_init_end();
+ Cap != CapEnd; ++Cap)
+ CT = mergeCanThrow(CT, canThrow(*Cap));
+ return CT;
+ }
+
+ case Expr::CXXNewExprClass: {
+ CanThrowResult CT;
+ if (E->isTypeDependent())
+ CT = CT_Dependent;
+ else
+ CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXDeleteExprClass: {
+ CanThrowResult CT;
+ QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType();
+ if (DTy.isNull() || DTy->isDependentType()) {
+ CT = CT_Dependent;
+ } else {
+ CT = canCalleeThrow(*this, E,
+ cast<CXXDeleteExpr>(E)->getOperatorDelete());
+ if (const RecordType *RT = DTy->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor()));
+ }
+ if (CT == CT_Can)
+ return CT;
+ }
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXBindTemporaryExprClass: {
+ // The bound temporary has to be destroyed again, which might throw.
+ CanThrowResult CT = canCalleeThrow(*this, E,
+ cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ // ObjC message sends are like function calls, but never have exception
+ // specs.
+ case Expr::ObjCMessageExprClass:
+ case Expr::ObjCPropertyRefExprClass:
+ case Expr::ObjCSubscriptRefExprClass:
+ return CT_Can;
+
+ // All the ObjC literals that are implemented as calls are
+ // potentially throwing unless we decide to close off that
+ // possibility.
+ case Expr::ObjCArrayLiteralClass:
+ case Expr::ObjCDictionaryLiteralClass:
+ case Expr::ObjCNumericLiteralClass:
+ return CT_Can;
+
+ // Many other things have subexpressions, so we have to test those.
+ // Some are simple:
+ case Expr::ConditionalOperatorClass:
+ case Expr::CompoundLiteralExprClass:
+ case Expr::CXXConstCastExprClass:
+ case Expr::CXXDefaultArgExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::DesignatedInitExprClass:
+ case Expr::ExprWithCleanupsClass:
+ case Expr::ExtVectorElementExprClass:
+ case Expr::InitListExprClass:
+ case Expr::MemberExprClass:
+ case Expr::ObjCIsaExprClass:
+ case Expr::ObjCIvarRefExprClass:
+ case Expr::ParenExprClass:
+ case Expr::ParenListExprClass:
+ case Expr::ShuffleVectorExprClass:
+ case Expr::VAArgExprClass:
+ return canSubExprsThrow(*this, E);
+
+ // Some might be dependent for other reasons.
+ case Expr::ArraySubscriptExprClass:
+ case Expr::BinaryOperatorClass:
+ case Expr::CompoundAssignOperatorClass:
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::ImplicitCastExprClass:
+ case Expr::MaterializeTemporaryExprClass:
+ case Expr::UnaryOperatorClass: {
+ CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms.
+ case Expr::StmtExprClass:
+ return CT_Can;
+
+ case Expr::ChooseExprClass:
+ if (E->isTypeDependent() || E->isValueDependent())
+ return CT_Dependent;
+ return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
+
+ case Expr::GenericSelectionExprClass:
+ if (cast<GenericSelectionExpr>(E)->isResultDependent())
+ return CT_Dependent;
+ return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr());
+
+ // Some expressions are always dependent.
+ case Expr::CXXDependentScopeMemberExprClass:
+ case Expr::CXXUnresolvedConstructExprClass:
+ case Expr::DependentScopeDeclRefExprClass:
+ return CT_Dependent;
+
+ case Expr::AsTypeExprClass:
+ case Expr::BinaryConditionalOperatorClass:
+ case Expr::BlockExprClass:
+ case Expr::CUDAKernelCallExprClass:
+ case Expr::DeclRefExprClass:
+ case Expr::ObjCBridgedCastExprClass:
+ case Expr::ObjCIndirectCopyRestoreExprClass:
+ case Expr::ObjCProtocolExprClass:
+ case Expr::ObjCSelectorExprClass:
+ case Expr::OffsetOfExprClass:
+ case Expr::PackExpansionExprClass:
+ case Expr::PseudoObjectExprClass:
+ case Expr::SubstNonTypeTemplateParmExprClass:
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
+ case Expr::UnaryExprOrTypeTraitExprClass:
+ case Expr::UnresolvedLookupExprClass:
+ case Expr::UnresolvedMemberExprClass:
+ // FIXME: Can any of the above throw? If so, when?
+ return CT_Cannot;
+
+ case Expr::AddrLabelExprClass:
+ case Expr::ArrayTypeTraitExprClass:
+ case Expr::AtomicExprClass:
+ case Expr::BinaryTypeTraitExprClass:
+ case Expr::TypeTraitExprClass:
+ case Expr::CXXBoolLiteralExprClass:
+ case Expr::CXXNoexceptExprClass:
+ case Expr::CXXNullPtrLiteralExprClass:
+ case Expr::CXXPseudoDestructorExprClass:
+ case Expr::CXXScalarValueInitExprClass:
+ case Expr::CXXThisExprClass:
+ case Expr::CXXUuidofExprClass:
+ case Expr::CharacterLiteralClass:
+ case Expr::ExpressionTraitExprClass:
+ case Expr::FloatingLiteralClass:
+ case Expr::GNUNullExprClass:
+ case Expr::ImaginaryLiteralClass:
+ case Expr::ImplicitValueInitExprClass:
+ case Expr::IntegerLiteralClass:
+ case Expr::ObjCEncodeExprClass:
+ case Expr::ObjCStringLiteralClass:
+ case Expr::ObjCBoolLiteralExprClass:
+ case Expr::OpaqueValueExprClass:
+ case Expr::PredefinedExprClass:
+ case Expr::SizeOfPackExprClass:
+ case Expr::StringLiteralClass:
+ case Expr::UnaryTypeTraitExprClass:
+ // These expressions can never throw.
+ return CT_Cannot;
+
+#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
+#define STMT_RANGE(Base, First, Last)
+#define LAST_STMT_RANGE(BASE, FIRST, LAST)
+#define EXPR(CLASS, PARENT)
+#define ABSTRACT_STMT(STMT)
+#include "clang/AST/StmtNodes.inc"
+ case Expr::NoStmtClass:
+ llvm_unreachable("Invalid class for expression");
+ }
+ llvm_unreachable("Bogus StmtClass");
+}
+
} // end namespace clang
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0d0f2f5..d2e0e6b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9438,10 +9438,11 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus);
}
-ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
- PartialDiagnostic NotIceDiag,
- bool AllowFold,
- PartialDiagnostic FoldDiag) {
+ExprResult
+Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ const PartialDiagnostic &NotIceDiag,
+ bool AllowFold,
+ const PartialDiagnostic &FoldDiag) {
SourceLocation DiagLoc = E->getLocStart();
if (getLangOpts().CPlusPlus0x) {
@@ -9773,6 +9774,12 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
// FIXME: Is this really right?
if (CurContext == Func) return;
+ // Instantiate the exception specification for any function which is
+ // used: CodeGen will need it.
+ const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
+ if (FPT && FPT->getExceptionSpecType() == EST_Uninstantiated)
+ InstantiateExceptionSpec(Loc, Func);
+
// Implicit instantiation of function templates and member functions of
// class templates.
if (Func->isImplicitlyInstantiable()) {
@@ -11268,22 +11275,6 @@ ExprResult
Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&
"Unknown Objective-C Boolean value!");
- QualType ObjCBoolLiteralQT = Context.ObjCBuiltinBoolTy;
- // signed char is the default type for boolean literals. Use 'BOOL'
- // instead, if BOOL typedef is visible in its scope instead.
- Decl *TD =
- LookupSingleName(TUScope, &Context.Idents.get("BOOL"),
- SourceLocation(), LookupOrdinaryName);
- if (TypedefDecl *BoolTD = dyn_cast_or_null<TypedefDecl>(TD)) {
- QualType QT = BoolTD->getUnderlyingType();
- if (!QT->isIntegralOrUnscopedEnumerationType()) {
- Diag(OpLoc, diag::warn_bool_for_boolean_literal) << QT;
- Diag(BoolTD->getLocation(), diag::note_previous_declaration);
- }
- else
- ObjCBoolLiteralQT = QT;
- }
-
return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes,
- ObjCBoolLiteralQT, OpLoc));
+ Context.ObjCBuiltinBoolTy, OpLoc));
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 31a8115..af86cb2 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -654,23 +654,44 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
QualType Sema::getCurrentThisType() {
DeclContext *DC = getFunctionLevelDeclContext();
- QualType ThisTy;
+ QualType ThisTy = CXXThisTypeOverride;
if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
if (method && method->isInstance())
ThisTy = method->getThisType(Context);
- } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
- // C++0x [expr.prim]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // of a class X, the expression this is a prvalue of type "pointer to X"
- // within the optional brace-or-equal-initializer.
- Scope *S = getScopeForContext(DC);
- if (!S || S->getFlags() & Scope::ThisScope)
- ThisTy = Context.getPointerType(Context.getRecordType(RD));
}
-
+
return ThisTy;
}
+Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
+ Decl *ContextDecl,
+ unsigned CXXThisTypeQuals,
+ bool Enabled)
+ : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
+{
+ if (!Enabled || !ContextDecl)
+ return;
+
+ CXXRecordDecl *Record = 0;
+ if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl))
+ Record = Template->getTemplatedDecl();
+ else
+ Record = cast<CXXRecordDecl>(ContextDecl);
+
+ S.CXXThisTypeOverride
+ = S.Context.getPointerType(
+ S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
+
+ this->Enabled = true;
+}
+
+
+Sema::CXXThisScopeRAII::~CXXThisScopeRAII() {
+ if (Enabled) {
+ S.CXXThisTypeOverride = OldCXXThisTypeOverride;
+ }
+}
+
void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
// We don't need to capture this in an unevaluated context.
if (ExprEvalContexts.back().Context == Unevaluated && !Explicit)
@@ -739,6 +760,18 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
}
+bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
+ // If we're outside the body of a member function, then we'll have a specified
+ // type for 'this'.
+ if (CXXThisTypeOverride.isNull())
+ return false;
+
+ // Determine whether we're looking into a class that's currently being
+ // defined.
+ CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl();
+ return Class && Class->isBeingDefined();
+}
+
ExprResult
Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
SourceLocation LParenLoc,
@@ -3102,6 +3135,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
FoundAssign = true;
const FunctionProtoType *CPT
= Operator->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT)
+ return false;
if (CPT->getExceptionSpecType() == EST_Delayed)
return false;
if (!CPT->isNothrow(Self.Context))
@@ -3141,6 +3177,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
FoundConstructor = true;
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT)
+ return false;
if (CPT->getExceptionSpecType() == EST_Delayed)
return false;
// FIXME: check whether evaluating default arguments can throw.
@@ -3176,6 +3215,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
if (Constructor->isDefaultConstructor()) {
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT)
+ return false;
if (CPT->getExceptionSpecType() == EST_Delayed)
return false;
// TODO: check whether evaluating default arguments can throw.
@@ -4784,8 +4826,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
return Owned(Base);
}
- // The object type must be complete (or dependent).
+ // The object type must be complete (or dependent), or
+ // C++11 [expr.prim.general]p3:
+ // Unlike the object expression in other contexts, *this is not required to
+ // be of complete type for purposes of class member access (5.2.5) outside
+ // the member function body.
if (!BaseType->isDependentType() &&
+ !isThisOutsideMemberFunctionBody(BaseType) &&
RequireCompleteType(OpLoc, BaseType,
PDiag(diag::err_incomplete_member_access)))
return ExprError();
@@ -5165,9 +5212,9 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen) {
+ CanThrowResult CanThrow = canThrow(Operand);
return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
- Operand->CanThrow(Context),
- KeyLoc, RParen));
+ CanThrow, KeyLoc, RParen));
}
ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 26b88a2..6c84caa 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -101,16 +101,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
- bool isStaticContext =
- (!isa<CXXMethodDecl>(DC) ||
- cast<CXXMethodDecl>(DC)->isStatic());
-
- // C++0x [expr.prim]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // of a class X, the expression this is a prvalue of type "pointer to X"
- // within the optional brace-or-equal-initializer.
- if (CurScope->getFlags() & Scope::ThisScope)
- isStaticContext = false;
+ bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() &&
+ (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic());
if (R.isUnresolvableResult())
return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
@@ -549,12 +541,13 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
}
static bool
-LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
SourceRange BaseRange, const RecordType *RTy,
SourceLocation OpLoc, CXXScopeSpec &SS,
bool HasTemplateArgs) {
RecordDecl *RDecl = RTy->getDecl();
- if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+ if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
+ SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
<< BaseRange))
return true;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 966eb90..f003bdd 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -3165,7 +3165,7 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
namespace {
typedef llvm::StringMap<TypoCorrection, llvm::BumpPtrAllocator> TypoResultsMap;
-typedef std::map<unsigned, TypoResultsMap *> TypoEditDistanceMap;
+typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
static const unsigned MaxTypoDistanceResultSets = 5;
@@ -3187,14 +3187,6 @@ public:
: Typo(Typo->getName()),
SemaRef(SemaRef) { }
- ~TypoCorrectionConsumer() {
- for (TypoEditDistanceMap::iterator I = BestResults.begin(),
- IEnd = BestResults.end();
- I != IEnd;
- ++I)
- delete I->second;
- }
-
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass);
void FoundName(StringRef Name);
@@ -3212,7 +3204,7 @@ public:
bool empty() const { return BestResults.empty(); }
TypoCorrection &operator[](StringRef Name) {
- return (*BestResults.begin()->second)[Name];
+ return BestResults.begin()->second[Name];
}
unsigned getBestEditDistance(bool Normalized) {
@@ -3276,11 +3268,9 @@ void TypoCorrectionConsumer::addName(StringRef Name,
void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
- TypoResultsMap *& Map = BestResults[Correction.getEditDistance(false)];
- if (!Map)
- Map = new TypoResultsMap;
+ TypoResultsMap &Map = BestResults[Correction.getEditDistance(false)];
- TypoCorrection &CurrentCorrection = (*Map)[Name];
+ TypoCorrection &CurrentCorrection = Map[Name];
if (!CurrentCorrection ||
// FIXME: The following should be rolled up into an operator< on
// TypoCorrection with a more principled definition.
@@ -3289,12 +3279,8 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
CurrentCorrection.getAsString(SemaRef.getLangOpts()))
CurrentCorrection = Correction;
- while (BestResults.size() > MaxTypoDistanceResultSets) {
- TypoEditDistanceMap::iterator Last = BestResults.end();
- --Last;
- delete Last->second;
- BestResults.erase(Last);
- }
+ while (BestResults.size() > MaxTypoDistanceResultSets)
+ erase(llvm::prior(BestResults.end()));
}
// Fill the supplied vector with the IdentifierInfo pointers for each piece of
@@ -3882,8 +3868,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
while (!Consumer.empty()) {
TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
unsigned ED = DI->first;
- for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(),
- IEnd = DI->second->end();
+ for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
+ IEnd = DI->second.end();
I != IEnd; /* Increment in loop. */) {
// If the item already has been looked up or is a keyword, keep it.
// If a validator callback object was given, drop the correction
@@ -3892,7 +3878,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
TypoCorrectionConsumer::result_iterator Prev = I;
++I;
if (!isCandidateViable(CCC, Prev->second))
- DI->second->erase(Prev);
+ DI->second.erase(Prev);
continue;
}
@@ -3911,7 +3897,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
{
TypoCorrectionConsumer::result_iterator Next = I;
++Next;
- DI->second->erase(I);
+ DI->second.erase(I);
I = Next;
}
break;
@@ -3929,7 +3915,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
I->second.addCorrectionDecl(*TRD);
++I;
if (!isCandidateViable(CCC, Prev->second))
- DI->second->erase(Prev);
+ DI->second.erase(Prev);
break;
}
@@ -3938,14 +3924,14 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
++I;
if (!isCandidateViable(CCC, Prev->second))
- DI->second->erase(Prev);
+ DI->second.erase(Prev);
break;
}
}
}
- if (DI->second->empty())
+ if (DI->second.empty())
Consumer.erase(DI);
else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED)
// If there are results in the closest possible bucket, stop
@@ -4009,7 +3995,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// No corrections remain...
if (Consumer.empty()) return TypoCorrection();
- TypoResultsMap &BestResults = *Consumer.begin()->second;
+ TypoResultsMap &BestResults = Consumer.begin()->second;
ED = TypoCorrection::NormalizeEditDistance(Consumer.begin()->first);
if (ED > 0 && Typo->getName().size() / ED < 3) {
@@ -4083,7 +4069,8 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
std::string tmpBuffer;
llvm::raw_string_ostream PrefixOStream(tmpBuffer);
CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
- return PrefixOStream.str() + CorrectionName.getAsString();
+ CorrectionName.printName(PrefixOStream);
+ return PrefixOStream.str();
}
return CorrectionName.getAsString();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 284c8de..50230f0 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -11150,6 +11150,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
VK_LValue,
Found.getDecl(),
TemplateArgs);
+ MarkDeclRefReferenced(DRE);
DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
return DRE;
}
@@ -11178,6 +11179,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
VK_LValue,
Found.getDecl(),
TemplateArgs);
+ MarkDeclRefReferenced(DRE);
DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
return DRE;
} else {
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index d52c912..0e66329 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -214,6 +214,7 @@ namespace {
ObjCMethodDecl *Setter;
Selector SetterSelector;
+ Selector GetterSelector;
public:
ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
@@ -475,8 +476,24 @@ bool ObjCPropertyOpBuilder::findGetter() {
// For implicit properties, just trust the lookup we already did.
if (RefExpr->isImplicitProperty()) {
- Getter = RefExpr->getImplicitPropertyGetter();
- return (Getter != 0);
+ if ((Getter = RefExpr->getImplicitPropertyGetter())) {
+ GetterSelector = Getter->getSelector();
+ return true;
+ }
+ else {
+ // Must build the getter selector the hard way.
+ ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
+ assert(setter && "both setter and getter are null - cannot happen");
+ IdentifierInfo *setterName =
+ setter->getSelector().getIdentifierInfoForSlot(0);
+ const char *compStr = setterName->getNameStart();
+ compStr += 3;
+ IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
+ GetterSelector =
+ S.PP.getSelectorTable().getNullarySelector(getterName);
+ return false;
+
+ }
}
ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
@@ -776,7 +793,7 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
assert(RefExpr->isImplicitProperty());
S.Diag(opcLoc, diag::err_nogetter_property_incdec)
<< unsigned(UnaryOperator::isDecrementOp(opcode))
- << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
+ << GetterSelector
<< op->getSourceRange();
return ExprError();
}
@@ -1300,6 +1317,11 @@ static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
Expr *opaqueRef = E->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
+ // Class and super property references don't have opaque values in them.
+ if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
+ return E;
+
+ assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
} else if (ObjCSubscriptRefExpr *refExpr
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 97c8eb0..9052278 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -345,7 +345,6 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
StmtResult
Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt) {
-
// If the label was multiply defined, reject it now.
if (TheDecl->getStmt()) {
Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
@@ -361,6 +360,16 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
return Owned(LS);
}
+StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
+ const AttrVec &Attrs,
+ Stmt *SubStmt) {
+ // Fill in the declaration and return it. Variable length will require to
+ // change this to AttributedStmt::Create(Context, ....);
+ // and probably using ArrayRef
+ AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);
+ return Owned(LS);
+}
+
StmtResult
Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
Stmt *thenStmt, SourceLocation ElseLoc,
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
new file mode 100644
index 0000000..21c3297
--- /dev/null
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -0,0 +1,48 @@
+//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements stmt-related attribute processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "TargetAttributesSema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+
+static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A) {
+ switch (A.getKind()) {
+ default:
+ // if we're here, then we parsed an attribute, but didn't recognize it as a
+ // statement attribute => it is declaration attribute
+ S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt) <<
+ A.getName()->getName();
+ return 0;
+ }
+}
+
+StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
+ SourceRange Range) {
+ AttrVec Attrs;
+ for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+ if (Attr *a = ProcessStmtAttribute(*this, S, *l))
+ Attrs.push_back(a);
+ }
+
+ if (Attrs.empty())
+ return S;
+
+ return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
+}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ff8c4da..51ce2a1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2496,6 +2496,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
+ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
Param->getDefaultArgumentLoc(),
Param->getDeclName());
@@ -2544,6 +2545,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
+ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
}
@@ -2591,6 +2594,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
+ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
// Substitute into the nested-name-specifier first,
QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
if (QualifierLoc) {
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 2ea1e6f..d68e464 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2310,23 +2310,42 @@ Sema::SubstituteExplicitTemplateArguments(
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute
// in lexical order.
- if (Proto->hasTrailingReturn() &&
- SubstParmTypes(Function->getLocation(),
- Function->param_begin(), Function->getNumParams(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- ParamTypes))
- return TDK_SubstitutionFailure;
-
+ if (Proto->hasTrailingReturn()) {
+ if (SubstParmTypes(Function->getLocation(),
+ Function->param_begin(), Function->getNumParams(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ ParamTypes))
+ return TDK_SubstitutionFailure;
+ }
+
// Instantiate the return type.
// FIXME: exception-specifications?
- QualType ResultType
- = SubstType(Proto->getResultType(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- Function->getTypeSpecStartLoc(),
- Function->getDeclName());
- if (ResultType.isNull() || Trap.hasErrorOccurred())
- return TDK_SubstitutionFailure;
-
+ QualType ResultType;
+ {
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ unsigned ThisTypeQuals = 0;
+ CXXRecordDecl *ThisContext = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+
+ CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
+ getLangOpts().CPlusPlus0x);
+
+ ResultType = SubstType(Proto->getResultType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(),
+ Function->getDeclName());
+ if (ResultType.isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+ }
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments if we didn't do so earlier.
if (!Proto->hasTrailingReturn() &&
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4740145..128dc2f 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -153,6 +153,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
switch (Kind) {
case TemplateInstantiation:
+ case ExceptionSpecInstantiation:
case DefaultTemplateArgumentInstantiation:
case DefaultFunctionArgumentInstantiation:
return true;
@@ -190,6 +191,29 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
}
}
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionDecl *Entity, ExceptionSpecification,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+ Inst.TemplateArgs = 0;
+ Inst.NumTemplateArgs = 0;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ }
+}
+
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
SourceLocation PointOfInstantiation,
TemplateDecl *Template,
@@ -592,6 +616,13 @@ void Sema::PrintInstantiationStack() {
<< Active->InstantiationRange;
break;
}
+
+ case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_template_exception_spec_instantiation_here)
+ << cast<FunctionDecl>((Decl *)Active->Entity)
+ << Active->InstantiationRange;
+ break;
}
}
}
@@ -609,6 +640,7 @@ llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
switch(Active->Kind) {
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
case ActiveTemplateInstantiation::TemplateInstantiation:
+ case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
// This is a template instantiation, so there is no SFINAE.
return llvm::Optional<TemplateDeductionInfo *>();
@@ -789,6 +821,11 @@ namespace {
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL);
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions,
@@ -1211,6 +1248,16 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
return inherited::TransformFunctionProtoType(TLB, TL);
}
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
+ // We need a local instantiation scope for this function prototype.
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ return inherited::TransformFunctionProtoType(TLB, TL, ThisContext,
+ ThisTypeQuals);
+}
+
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
@@ -1446,7 +1493,9 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
- DeclarationName Entity) {
+ DeclarationName Entity,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
assert(!ActiveTemplateInstantiations.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
@@ -1461,7 +1510,14 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
TypeLoc TL = T->getTypeLoc();
TLB.reserve(TL.getFullDataSize());
- QualType Result = Instantiator.TransformType(TLB, TL);
+ QualType Result;
+
+ if (FunctionProtoTypeLoc *Proto = dyn_cast<FunctionProtoTypeLoc>(&TL)) {
+ Result = Instantiator.TransformFunctionProtoType(TLB, *Proto, ThisContext,
+ ThisTypeQuals);
+ } else {
+ Result = Instantiator.TransformType(TLB, TL);
+ }
if (Result.isNull())
return 0;
@@ -1878,24 +1934,33 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CheckCompletedCXXClass(Instantiation);
// Attach any in-class member initializers now the class is complete.
- for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
- FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
- FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
- Expr *OldInit = OldField->getInClassInitializer();
-
- ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
- /*CXXDirectInit=*/false);
- if (NewInit.isInvalid())
- NewField->setInvalidDecl();
- else {
- Expr *Init = NewInit.take();
- assert(Init && "no-argument initializer in class");
- assert(!isa<ParenListExpr>(Init) && "call-style init in class");
- ActOnCXXInClassMemberInitializer(NewField,
- Init->getSourceRange().getBegin(), Init);
+ {
+ // C++11 [expr.prim.general]p4:
+ // Otherwise, if a member-declarator declares a non-static data member
+ // (9.2) of a class X, the expression this is a prvalue of type "pointer
+ // to X" within the optional brace-or-equal-initializer. It shall not
+ // appear elsewhere in the member-declarator.
+ CXXThisScopeRAII ThisScope(*this, Instantiation, (unsigned)0);
+
+ for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
+ FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
+ FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
+ Expr *OldInit = OldField->getInClassInitializer();
+
+ ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+ /*CXXDirectInit=*/false);
+ if (NewInit.isInvalid())
+ NewField->setInvalidDecl();
+ else {
+ Expr *Init = NewInit.take();
+ assert(Init && "no-argument initializer in class");
+ assert(!isa<ParenListExpr>(Init) && "call-style init in class");
+ ActOnCXXInClassMemberInitializer(NewField,
+ Init->getSourceRange().getBegin(),
+ Init);
+ }
}
}
-
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8afe7ac..c7bd99c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2141,10 +2141,19 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
assert(OldTInfo && "substituting function without type source info");
assert(Params.empty() && "parameter vector is non-empty at start");
+
+ CXXRecordDecl *ThisContext = 0;
+ unsigned ThisTypeQuals = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+
TypeSourceInfo *NewTInfo
= SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
D->getTypeSpecStartLoc(),
- D->getDeclName());
+ D->getDeclName(),
+ ThisContext, ThisTypeQuals);
if (!NewTInfo)
return 0;
@@ -2206,6 +2215,195 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
return NewTInfo;
}
+/// Introduce the instantiated function parameters into the local
+/// instantiation scope, and set the parameter names to those used
+/// in the template.
+static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
+ const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ unsigned FParamIdx = 0;
+ for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
+ const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
+ if (!PatternParam->isParameterPack()) {
+ // Simple case: not a parameter pack.
+ assert(FParamIdx < Function->getNumParams());
+ ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocal(PatternParam, FunctionParam);
+ ++FParamIdx;
+ continue;
+ }
+
+ // Expand the parameter pack.
+ Scope.MakeInstantiatedLocalArgPack(PatternParam);
+ unsigned NumArgumentsInExpansion
+ = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
+ for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
+ ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+ ++FParamIdx;
+ }
+ }
+}
+
+static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
+ const FunctionProtoType *Proto,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
+
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ CXXRecordDecl *ThisContext = 0;
+ unsigned ThisTypeQuals = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
+ SemaRef.getLangOpts().CPlusPlus0x);
+
+ // The function has an exception specification or a "noreturn"
+ // attribute. Substitute into each of the exception types.
+ SmallVector<QualType, 4> Exceptions;
+ for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
+ // FIXME: Poor location information!
+ if (const PackExpansionType *PackExpansion
+ = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
+ // We have a pack expansion. Instantiate it.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+ Unexpanded);
+ assert(!Unexpanded.empty() &&
+ "Pack expansion without parameter packs?");
+
+ bool Expand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions
+ = PackExpansion->getNumExpansions();
+ if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
+ SourceRange(),
+ Unexpanded,
+ TemplateArgs,
+ Expand,
+ RetainExpansion,
+ NumExpansions))
+ break;
+
+ if (!Expand) {
+ // We can't expand this pack expansion into separate arguments yet;
+ // just substitute into the pattern and create a new pack expansion
+ // type.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+ QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+ TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull())
+ break;
+
+ T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
+ Exceptions.push_back(T);
+ continue;
+ }
+
+ // Substitute into the pack expansion pattern for each template
+ bool Invalid = false;
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
+
+ QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+ TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull()) {
+ Invalid = true;
+ break;
+ }
+
+ Exceptions.push_back(T);
+ }
+
+ if (Invalid)
+ break;
+
+ continue;
+ }
+
+ QualType T
+ = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull() ||
+ SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
+ continue;
+
+ Exceptions.push_back(T);
+ }
+ Expr *NoexceptExpr = 0;
+ if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Sema::ConstantEvaluated);
+ ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
+ if (E.isUsable())
+ E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
+
+ if (E.isUsable()) {
+ NoexceptExpr = E.take();
+ if (!NoexceptExpr->isTypeDependent() &&
+ !NoexceptExpr->isValueDependent())
+ NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
+ 0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
+ /*AllowFold*/ false).take();
+ }
+ }
+
+ // Rebuild the function type
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+ assert(NewProto && "Template instantiation without function prototype?");
+
+ FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ EPI.ExceptionSpecType = Proto->getExceptionSpecType();
+ EPI.NumExceptions = Exceptions.size();
+ EPI.Exceptions = Exceptions.data();
+ EPI.NoexceptExpr = NoexceptExpr;
+
+ New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI));
+}
+
+void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+ FunctionDecl *Decl) {
+ const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();
+ if (Proto->getExceptionSpecType() != EST_Uninstantiated)
+ return;
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
+ InstantiatingTemplate::ExceptionSpecification());
+ if (Inst)
+ return;
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ Sema::ContextRAII savedContext(*this, Decl);
+ LocalInstantiationScope Scope(*this);
+
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
+
+ FunctionDecl *Template = Proto->getExceptionSpecTemplate();
+ addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
+
+ ::InstantiateExceptionSpec(*this, Decl,
+ Template->getType()->castAs<FunctionProtoType>(),
+ TemplateArgs);
+}
+
/// \brief Initializes the common fields of an instantiation function
/// declaration (New) from the corresponding fields of its template (Tmpl).
///
@@ -2243,119 +2441,37 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(Proto && "Function template without prototype?");
if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
- // The function has an exception specification or a "noreturn"
- // attribute. Substitute into each of the exception types.
- SmallVector<QualType, 4> Exceptions;
- for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
- // FIXME: Poor location information!
- if (const PackExpansionType *PackExpansion
- = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
- // We have a pack expansion. Instantiate it.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
- Unexpanded);
- assert(!Unexpanded.empty() &&
- "Pack expansion without parameter packs?");
-
- bool Expand = false;
- bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions
- = PackExpansion->getNumExpansions();
- if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
- SourceRange(),
- Unexpanded,
- TemplateArgs,
- Expand,
- RetainExpansion,
- NumExpansions))
- break;
-
- if (!Expand) {
- // We can't expand this pack expansion into separate arguments yet;
- // just substitute into the pattern and create a new pack expansion
- // type.
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull())
- break;
-
- T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
- Exceptions.push_back(T);
- continue;
- }
-
- // Substitute into the pack expansion pattern for each template
- bool Invalid = false;
- for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
-
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull()) {
- Invalid = true;
- break;
- }
-
- Exceptions.push_back(T);
- }
-
- if (Invalid)
- break;
-
- continue;
- }
-
- QualType T
- = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull() ||
- SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
- continue;
-
- Exceptions.push_back(T);
- }
- Expr *NoexceptExpr = 0;
- if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
- EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Sema::ConstantEvaluated);
- ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
- if (E.isUsable())
- E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
-
- if (E.isUsable()) {
- NoexceptExpr = E.take();
- if (!NoexceptExpr->isTypeDependent() &&
- !NoexceptExpr->isValueDependent())
- NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
- 0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
- /*AllowFold*/ false).take();
- }
- }
-
- // Rebuild the function type
-
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
- EPI.ExceptionSpecType = Proto->getExceptionSpecType();
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
- EPI.NoexceptExpr = NoexceptExpr;
- EPI.ExtInfo = Proto->getExtInfo();
- const FunctionProtoType *NewProto
- = New->getType()->getAs<FunctionProtoType>();
- assert(NewProto && "Template instantiation without function prototype?");
- New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- NewProto->arg_type_begin(),
- NewProto->getNumArgs(),
- EPI));
+ // DR1330: In C++11, defer instantiation of a non-trivial
+ // exception specification.
+ if (SemaRef.getLangOpts().CPlusPlus0x &&
+ EPI.ExceptionSpecType != EST_None &&
+ EPI.ExceptionSpecType != EST_DynamicNone &&
+ EPI.ExceptionSpecType != EST_BasicNoexcept) {
+ FunctionDecl *ExceptionSpecTemplate = Tmpl;
+ if (EPI.ExceptionSpecType == EST_Uninstantiated)
+ ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
+
+ // Mark the function has having an uninstantiated exception specification.
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+ assert(NewProto && "Template instantiation without function prototype?");
+ EPI = NewProto->getExtProtoInfo();
+ EPI.ExceptionSpecType = EST_Uninstantiated;
+ EPI.ExceptionSpecDecl = New;
+ EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
+ New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI));
+ } else {
+ ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
+ }
}
- const FunctionDecl* Definition = Tmpl;
-
// Get the definition. Leaves the variable unchanged if undefined.
+ const FunctionDecl *Definition = Tmpl;
Tmpl->isDefined(Definition);
SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
@@ -2513,33 +2629,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
- // Introduce the instantiated function parameters into the local
- // instantiation scope, and set the parameter names to those used
- // in the template.
- unsigned FParamIdx = 0;
- for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
- const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
- if (!PatternParam->isParameterPack()) {
- // Simple case: not a parameter pack.
- assert(FParamIdx < Function->getNumParams());
- ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
- FunctionParam->setDeclName(PatternParam->getDeclName());
- Scope.InstantiatedLocal(PatternParam, FunctionParam);
- ++FParamIdx;
- continue;
- }
-
- // Expand the parameter pack.
- Scope.MakeInstantiatedLocalArgPack(PatternParam);
- unsigned NumArgumentsInExpansion
- = getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
- for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
- ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
- FunctionParam->setDeclName(PatternParam->getDeclName());
- Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
- ++FParamIdx;
- }
- }
+ addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+ TemplateArgs);
if (PatternDecl->isDefaulted()) {
ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c41df82..d0906de 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -561,7 +561,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*const qualifier*/SourceLocation(),
/*volatile qualifier*/SourceLocation(),
/*mutable qualifier*/SourceLocation(),
- /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
+ /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, 0,
/*parens*/ loc, loc,
declarator));
@@ -2371,34 +2371,33 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.ConsumedArguments = ConsumedArguments.data();
SmallVector<QualType, 4> Exceptions;
- EPI.ExceptionSpecType = FTI.getExceptionSpecType();
+ SmallVector<ParsedType, 2> DynamicExceptions;
+ SmallVector<SourceRange, 2> DynamicExceptionRanges;
+ Expr *NoexceptExpr = 0;
+
if (FTI.getExceptionSpecType() == EST_Dynamic) {
- Exceptions.reserve(FTI.NumExceptions);
- for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
- // FIXME: Preserve type source info.
- QualType ET = S.GetTypeFromParser(FTI.Exceptions[ei].Ty);
- // Check that the type is valid for an exception spec, and
- // drop it if not.
- if (!S.CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
- Exceptions.push_back(ET);
+ // FIXME: It's rather inefficient to have to split into two vectors
+ // here.
+ unsigned N = FTI.NumExceptions;
+ DynamicExceptions.reserve(N);
+ DynamicExceptionRanges.reserve(N);
+ for (unsigned I = 0; I != N; ++I) {
+ DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
+ DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
}
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
} else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
- // If an error occurred, there's no expression here.
- if (Expr *NoexceptExpr = FTI.NoexceptExpr) {
- assert((NoexceptExpr->isTypeDependent() ||
- NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
- Context.BoolTy) &&
- "Parser should have made sure that the expression is boolean");
- if (!NoexceptExpr->isValueDependent())
- NoexceptExpr = S.VerifyIntegerConstantExpression(NoexceptExpr, 0,
- S.PDiag(diag::err_noexcept_needs_constant_expression),
- /*AllowFold*/ false).take();
- EPI.NoexceptExpr = NoexceptExpr;
- }
- } else if (FTI.getExceptionSpecType() == EST_None &&
- ImplicitlyNoexcept && chunkIndex == 0) {
+ NoexceptExpr = FTI.NoexceptExpr;
+ }
+
+ S.checkExceptionSpecification(FTI.getExceptionSpecType(),
+ DynamicExceptions,
+ DynamicExceptionRanges,
+ NoexceptExpr,
+ Exceptions,
+ EPI);
+
+ if (FTI.getExceptionSpecType() == EST_None &&
+ ImplicitlyNoexcept && chunkIndex == 0) {
// Only the outermost chunk is marked noexcept, of course.
EPI.ExceptionSpecType = EST_BasicNoexcept;
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index fdb861e..a66378e 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -522,6 +522,11 @@ public:
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+
StmtResult
TransformSEHHandler(Stmt *Handler);
@@ -1044,6 +1049,15 @@ public:
return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
}
+ /// \brief Build a new label statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
+ Stmt *SubStmt) {
+ return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
+ }
+
/// \brief Build a new "if" statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -4156,12 +4170,18 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
+ return getDerived().TransformFunctionProtoType(TLB, TL, 0, 0);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
// Transform the parameters and return type.
//
- // We instantiate in source order, with the return type first followed by
- // the parameters, because users tend to expect this (even if they shouldn't
- // rely on it!).
- //
+ // We are required to instantiate the params and return type in source order.
// When the function has a trailing return type, we instantiate the
// parameters before the return type, since the return type can then refer
// to the parameters themselves (via decltype, sizeof, etc.).
@@ -4180,9 +4200,19 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParamTypes, &ParamDecls))
return QualType();
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
- if (ResultType.isNull())
- return QualType();
+ {
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals);
+
+ ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+ }
}
else {
ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
@@ -4197,6 +4227,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
return QualType();
}
+ // FIXME: Need to transform the exception-specification too.
+
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ResultType != T->getResultType() ||
@@ -5154,8 +5186,8 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
S->getDecl());
if (!LD)
return StmtError();
-
-
+
+
// FIXME: Pass the real colon location in.
return getDerived().RebuildLabelStmt(S->getIdentLoc(),
cast<LabelDecl>(LD), SourceLocation(),
@@ -5164,6 +5196,22 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
template<typename Derived>
StmtResult
+TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ if (SubStmt.isInvalid())
+ return StmtError();
+
+ // TODO: transform attributes
+ if (SubStmt.get() == S->getSubStmt() /* && attrs are the same */)
+ return S;
+
+ return getDerived().RebuildAttributedStmt(S->getAttrLoc(),
+ S->getAttrs(),
+ SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the condition
ExprResult Cond;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index f91b66c..06b42f3 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -27,7 +27,6 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
-#include "llvm/Support/SaveAndRestore.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
@@ -46,6 +45,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/system_error.h"
#include <algorithm>
#include <iterator>
@@ -664,46 +664,6 @@ ASTDeclContextNameLookupTrait::GetInternalKey(
return Key;
}
-ASTDeclContextNameLookupTrait::external_key_type
-ASTDeclContextNameLookupTrait::GetExternalKey(
- const internal_key_type& Key) const {
- ASTContext &Context = Reader.getContext();
- switch (Key.Kind) {
- case DeclarationName::Identifier:
- return DeclarationName((IdentifierInfo*)Key.Data);
-
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- return DeclarationName(Selector(Key.Data));
-
- case DeclarationName::CXXConstructorName:
- return Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(Reader.getLocalType(F, Key.Data)));
-
- case DeclarationName::CXXDestructorName:
- return Context.DeclarationNames.getCXXDestructorName(
- Context.getCanonicalType(Reader.getLocalType(F, Key.Data)));
-
- case DeclarationName::CXXConversionFunctionName:
- return Context.DeclarationNames.getCXXConversionFunctionName(
- Context.getCanonicalType(Reader.getLocalType(F, Key.Data)));
-
- case DeclarationName::CXXOperatorName:
- return Context.DeclarationNames.getCXXOperatorName(
- (OverloadedOperatorKind)Key.Data);
-
- case DeclarationName::CXXLiteralOperatorName:
- return Context.DeclarationNames.getCXXLiteralOperatorName(
- (IdentifierInfo*)Key.Data);
-
- case DeclarationName::CXXUsingDirective:
- return DeclarationName::getUsingDirectiveName();
- }
-
- llvm_unreachable("Invalid Name Kind ?");
-}
-
std::pair<unsigned, unsigned>
ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
using namespace clang::io;
@@ -749,7 +709,7 @@ ASTDeclContextNameLookupTrait::ReadKey(const unsigned char* d, unsigned) {
ASTDeclContextNameLookupTrait::data_type
ASTDeclContextNameLookupTrait::ReadData(internal_key_type,
const unsigned char* d,
- unsigned DataLen) {
+ unsigned DataLen) {
using namespace clang::io;
unsigned NumDecls = ReadUnalignedLE16(d);
LE32DeclID *Start = (LE32DeclID *)d;
@@ -1911,7 +1871,8 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case UPDATE_VISIBLE: {
unsigned Idx = 0;
serialization::DeclID ID = ReadDeclID(F, Record, Idx);
- void *Table = ASTDeclContextNameLookupTable::Create(
+ ASTDeclContextNameLookupTable *Table =
+ ASTDeclContextNameLookupTable::Create(
(const unsigned char *)BlobStart + Record[Idx++],
(const unsigned char *)BlobStart,
ASTDeclContextNameLookupTrait(*this, F));
@@ -4908,7 +4869,7 @@ namespace {
// Look for this name within this module.
ASTDeclContextNameLookupTable *LookupTable =
- (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData;
+ Info->second.NameLookupTableData;
ASTDeclContextNameLookupTable::iterator Pos
= LookupTable->find(This->Name);
if (Pos == LookupTable->end())
@@ -4972,48 +4933,95 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
}
namespace {
- /// \brief ModuleFile visitor used to complete the visible decls map of a
+ /// \brief ModuleFile visitor used to retrieve all visible names in a
/// declaration context.
- class DeclContextVisibleDeclMapVisitor {
+ class DeclContextAllNamesVisitor {
ASTReader &Reader;
- DeclContext *DC;
+ llvm::SmallVectorImpl<const DeclContext *> &Contexts;
+ const DeclContext *DC;
+ llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls;
public:
- DeclContextVisibleDeclMapVisitor(ASTReader &Reader, DeclContext *DC)
- : Reader(Reader), DC(DC) { }
+ DeclContextAllNamesVisitor(ASTReader &Reader,
+ SmallVectorImpl<const DeclContext *> &Contexts,
+ llvm::DenseMap<DeclarationName,
+ SmallVector<NamedDecl *, 8> > &Decls)
+ : Reader(Reader), Contexts(Contexts), Decls(Decls) { }
static bool visit(ModuleFile &M, void *UserData) {
- return static_cast<DeclContextVisibleDeclMapVisitor*>(UserData)->visit(M);
- }
+ DeclContextAllNamesVisitor *This
+ = static_cast<DeclContextAllNamesVisitor *>(UserData);
- bool visit(ModuleFile &M) {
// Check whether we have any visible declaration information for
// this context in this module.
- ModuleFile::DeclContextInfosMap::iterator
- Info = M.DeclContextInfos.find(DC);
- if (Info == M.DeclContextInfos.end() ||
- !Info->second.NameLookupTableData)
+ ModuleFile::DeclContextInfosMap::iterator Info;
+ bool FoundInfo = false;
+ for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
+ Info = M.DeclContextInfos.find(This->Contexts[I]);
+ if (Info != M.DeclContextInfos.end() &&
+ Info->second.NameLookupTableData) {
+ FoundInfo = true;
+ break;
+ }
+ }
+
+ if (!FoundInfo)
return false;
-
- // Look for this name within this module.
+
ASTDeclContextNameLookupTable *LookupTable =
- (ASTDeclContextNameLookupTable*)Info->second.NameLookupTableData;
- for (ASTDeclContextNameLookupTable::key_iterator
- I = LookupTable->key_begin(),
- E = LookupTable->key_end(); I != E; ++I) {
- DC->lookup(*I); // Force loading of the visible decls for the decl name.
+ Info->second.NameLookupTableData;
+ bool FoundAnything = false;
+ for (ASTDeclContextNameLookupTable::data_iterator
+ I = LookupTable->data_begin(), E = LookupTable->data_end();
+ I != E; ++I) {
+ ASTDeclContextNameLookupTrait::data_type Data = *I;
+ for (; Data.first != Data.second; ++Data.first) {
+ NamedDecl *ND = This->Reader.GetLocalDeclAs<NamedDecl>(M,
+ *Data.first);
+ if (!ND)
+ continue;
+
+ // Record this declaration.
+ FoundAnything = true;
+ This->Decls[ND->getDeclName()].push_back(ND);
+ }
}
- return false;
+ return FoundAnything;
}
};
}
-void ASTReader::completeVisibleDeclsMap(DeclContext *DC) {
+void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
if (!DC->hasExternalVisibleStorage())
return;
- DeclContextVisibleDeclMapVisitor Visitor(*this, DC);
- ModuleMgr.visit(&DeclContextVisibleDeclMapVisitor::visit, &Visitor);
+ llvm::DenseMap<DeclarationName, llvm::SmallVector<NamedDecl*, 8> > Decls;
+
+ // Compute the declaration contexts we need to look into. Multiple such
+ // declaration contexts occur when two declaration contexts from disjoint
+ // modules get merged, e.g., when two namespaces with the same name are
+ // independently defined in separate modules.
+ SmallVector<const DeclContext *, 2> Contexts;
+ Contexts.push_back(DC);
+
+ if (DC->isNamespace()) {
+ MergedDeclsMap::iterator Merged
+ = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Merged != MergedDecls.end()) {
+ for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ }
+ }
+
+ DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls);
+ ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor);
+ ++NumVisibleDeclContextsRead;
+
+ for (llvm::DenseMap<DeclarationName,
+ llvm::SmallVector<NamedDecl*, 8> >::iterator
+ I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+ SetExternalVisibleDeclsForName(DC, I->first, I->second);
+ }
}
/// \brief Under non-PCH compilation the consumer receives the objc methods
@@ -6364,6 +6372,6 @@ ASTReader::~ASTReader() {
for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
F = I->second.end();
J != F; ++J)
- delete static_cast<ASTDeclContextNameLookupTable*>(J->first);
+ delete J->first;
}
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 5db5f92..8dd53ee 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "ASTCommon.h"
+#include "ASTReaderInternals.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/Sema.h"
@@ -955,6 +956,10 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
BD->setParams(Params);
+ BD->setIsVariadic(Record[Idx++]);
+ BD->setBlockMissingReturnType(Record[Idx++]);
+ BD->setIsConversionFromLambda(Record[Idx++]);
+
bool capturesCXXThis = Record[Idx++];
unsigned numCaptures = Record[Idx++];
SmallVector<BlockDecl::Capture, 16> captures;
@@ -2100,7 +2105,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
DeclContextVisibleUpdates &U = I->second;
for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
UI != UE; ++UI) {
- UI->second->DeclContextInfos[DC].NameLookupTableData = UI->first;
+ DeclContextInfo &Info = UI->second->DeclContextInfos[DC];
+ delete Info.NameLookupTableData;
+ Info.NameLookupTableData = UI->first;
}
PendingVisibleUpdates.erase(I);
}
diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h
index 3a1dfcf..e5159e9 100644
--- a/lib/Serialization/ASTReaderInternals.h
+++ b/lib/Serialization/ASTReaderInternals.h
@@ -57,8 +57,7 @@ public:
typedef DeclarationName external_key_type;
typedef DeclNameKey internal_key_type;
- explicit ASTDeclContextNameLookupTrait(ASTReader &Reader,
- ModuleFile &F)
+ explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F)
: Reader(Reader), F(F) { }
static bool EqualKey(const internal_key_type& a,
@@ -68,9 +67,8 @@ public:
unsigned ComputeHash(const DeclNameKey &Key) const;
internal_key_type GetInternalKey(const external_key_type& Name) const;
- external_key_type GetExternalKey(const internal_key_type& Key) const;
- static std::pair<unsigned, unsigned>
+ static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
internal_key_type ReadKey(const unsigned char* d, unsigned);
@@ -79,10 +77,6 @@ public:
unsigned DataLen);
};
-/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
-typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
- ASTDeclContextNameLookupTable;
-
/// \brief Class that performs lookup for an identifier stored in an AST file.
class ASTIdentifierLookupTrait {
ASTReader &Reader;
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 2eeb090..007ecee 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -159,9 +159,18 @@ void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
S->setIdentLoc(ReadSourceLocation(Record, Idx));
}
+void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
+ VisitStmt(S);
+ AttrVec Attrs;
+ Reader.ReadAttributes(F, Attrs, Record, Idx);
+ S->Attrs = Attrs;
+ S->SubStmt = Reader.ReadSubStmt();
+ S->AttrLoc = ReadSourceLocation(Record, Idx);
+}
+
void ASTStmtReader::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
- S->setConditionVariable(Reader.getContext(),
+ S->setConditionVariable(Reader.getContext(),
ReadDeclAs<VarDecl>(Record, Idx));
S->setCond(Reader.ReadSubExpr());
S->setThen(Reader.ReadSubStmt());
@@ -1630,6 +1639,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) LabelStmt(Empty);
break;
+ case STMT_ATTRIBUTED:
+ S = new (Context) AttributedStmt(Empty);
+ break;
+
case STMT_IF:
S = new (Context) IfStmt(Empty);
break;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index a4301b5..81c0a9d 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -651,6 +651,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
RECORD(STMT_CASE);
RECORD(STMT_DEFAULT);
RECORD(STMT_LABEL);
+ RECORD(STMT_ATTRIBUTED);
RECORD(STMT_IF);
RECORD(STMT_SWITCH);
RECORD(STMT_WHILE);
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 7a4ef63..1ee3ac4 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -775,6 +775,9 @@ void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
+ Record.push_back(D->isVariadic());
+ Record.push_back(D->blockMissingReturnType());
+ Record.push_back(D->isConversionFromLambda());
Record.push_back(D->capturesCXXThis());
Record.push_back(D->getNumCaptures());
for (BlockDecl::capture_iterator
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 827caa0..1e31211 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -106,6 +106,14 @@ void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
Code = serialization::STMT_LABEL;
}
+void ASTStmtWriter::VisitAttributedStmt(AttributedStmt *S) {
+ VisitStmt(S);
+ Writer.WriteAttributes(S->getAttrs(), Record);
+ Writer.AddStmt(S->getSubStmt());
+ Writer.AddSourceLocation(S->getAttrLoc(), Record);
+ Code = serialization::STMT_ATTRIBUTED;
+}
+
void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
Writer.AddDeclRef(S->getConditionVariable(), Record);
diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp
index 16b95e2..ff241d3 100644
--- a/lib/Serialization/Module.cpp
+++ b/lib/Serialization/Module.cpp
@@ -45,8 +45,7 @@ ModuleFile::~ModuleFile() {
E = DeclContextInfos.end();
I != E; ++I) {
if (I->second.NameLookupTableData)
- delete static_cast<ASTDeclContextNameLookupTable*>(
- I->second.NameLookupTableData);
+ delete I->second.NameLookupTableData;
}
delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index d15c8ba..97b58cf 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -183,9 +183,6 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
CheckerContext &C) const {
- CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext());
- checkPostStmt(MsgWrapper, C);
-
// When encountering a message that does initialization (init rule),
// tag the return value so that we know later on that if self has this value
// then it is properly initialized.
@@ -209,6 +206,9 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
return;
}
+ CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext());
+ checkPostStmt(MsgWrapper, C);
+
// We don't check for an invalid 'self' in an obj-c message expression to cut
// down false positives where logging functions get information from self
// (like its class) or doing "invalidation" on self when the initialization
@@ -277,6 +277,11 @@ void ObjCSelfInitChecker::checkPreStmt(const CallOrObjCMessage &CE,
CheckerContext &C) const {
ProgramStateRef state = C.getState();
unsigned NumArgs = CE.getNumArgs();
+ // If we passed 'self' as and argument to the call, record it in the state
+ // to be propagated after the call.
+ // Note, we could have just given up, but try to be more optimistic here and
+ // assume that the functions are going to continue initialization or will not
+ // modify self.
for (unsigned i = 0; i < NumArgs; ++i) {
SVal argV = CE.getArgSVal(i);
if (isSelfVar(argV, C)) {
@@ -298,14 +303,24 @@ void ObjCSelfInitChecker::checkPostStmt(const CallOrObjCMessage &CE,
for (unsigned i = 0; i < NumArgs; ++i) {
SVal argV = CE.getArgSVal(i);
if (isSelfVar(argV, C)) {
+ // If the address of 'self' is being passed to the call, assume that the
+ // 'self' after the call will have the same flags.
+ // EX: log(&self)
SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
state = state->remove<PreCallSelfFlags>();
addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
+ // If 'self' is passed to the call by value, assume that the function
+ // returns 'self'. So assign the flags, which were set on 'self' to the
+ // return value.
+ // EX: self = performMoreInitialization(self)
SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
state = state->remove<PreCallSelfFlags>();
- addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
+ const Expr *CallExpr = CE.getOriginExpr();
+ if (CallExpr)
+ addSelfFlag(state, state->getSVal(CallExpr, C.getLocationContext()),
+ prevFlags, C);
return;
}
}
@@ -358,7 +373,7 @@ static bool isSelfVar(SVal location, CheckerContext &C) {
return false;
loc::MemRegionVal MRV = cast<loc::MemRegionVal>(location);
- if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.getRegion()))
+ if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.stripCasts()))
return (DR->getDecl() == analCtx->getSelfDecl());
return false;
diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 82ac8bd..eeaed2d 100644
--- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -8,8 +8,6 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "clang/Index/Entity.h"
-#include "clang/Index/Indexer.h"
using namespace clang;
using namespace ento;
@@ -22,7 +20,6 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
CheckerManager *checkerMgr,
- idx::Indexer *idxer,
unsigned maxnodes, unsigned maxvisit,
bool vizdot, bool vizubi,
AnalysisPurgeMode purge,
@@ -38,7 +35,7 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
: AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, addInitializers),
Ctx(ctx), Diags(diags), LangOpts(lang), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
- CheckerMgr(checkerMgr), Idxer(idxer),
+ CheckerMgr(checkerMgr),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxVisit(maxvisit),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim),
@@ -62,7 +59,6 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
CreateStoreMgr(ParentAM.CreateStoreMgr),
CreateConstraintMgr(ParentAM.CreateConstraintMgr),
CheckerMgr(ParentAM.CheckerMgr),
- Idxer(ParentAM.Idxer),
AScope(ScopeDecl),
MaxNodes(ParentAM.MaxNodes),
MaxVisit(ParentAM.MaxVisit),
@@ -80,21 +76,3 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
{
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
}
-
-
-AnalysisDeclContext *
-AnalysisManager::getAnalysisDeclContextInAnotherTU(const Decl *D) {
- idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D),
- Idxer->getProgram());
- FunctionDecl *FuncDef;
- idx::TranslationUnit *TU;
- llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent);
-
- if (FuncDef == 0)
- return 0;
-
- // This AnalysisDeclContext wraps function definition in another translation unit.
- // But it is still owned by the AnalysisManager associated with the current
- // translation unit.
- return AnaCtxMgr.getContext(FuncDef, TU);
-}
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index eb986af..ca662c7 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -17,7 +17,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/Index/TranslationUnit.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtCXX.h"
#include "llvm/Support/Casting.h"
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index d2da9aa..1fd9068 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -536,6 +536,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::IfStmtClass:
case Stmt::IndirectGotoStmtClass:
case Stmt::LabelStmtClass:
+ case Stmt::AttributedStmtClass:
case Stmt::NoStmtClass:
case Stmt::NullStmtClass:
case Stmt::SwitchStmtClass:
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index b99bd54..b9f4e15 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -134,6 +134,11 @@ bool ExprEngine::shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred) {
AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD);
const CFG *CalleeCFG = CalleeADC->getCFG();
+ // It is possible that the CFG cannot be constructed.
+ // Be safe, and check if the CalleeCFG is valid.
+ if (!CalleeCFG)
+ return false;
+
if (getNumberStackFrames(Pred->getLocationContext())
== AMgr.InlineMaxStackDepth)
return false;
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index c19ebcb..008f744 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -207,7 +207,6 @@ public:
PP.getLangOpts(), PD,
CreateStoreMgr, CreateConstraintMgr,
checkerMgr.get(),
- /* Indexer */ 0,
Opts.MaxNodes, Opts.MaxLoop,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index eea1055..dd9ccc0 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -13,7 +13,7 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/JSONParser.h"
+#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/system_error.h"
@@ -22,10 +22,10 @@ namespace tooling {
namespace {
-/// \brief A parser for JSON escaped strings of command line arguments.
+/// \brief A parser for escaped strings of command line arguments.
///
/// Assumes \-escaping for quoted arguments (see the documentation of
-/// unescapeJSONCommandLine(...)).
+/// unescapeCommandLine(...)).
class CommandLineArgumentParser {
public:
CommandLineArgumentParser(StringRef CommandLine)
@@ -90,9 +90,6 @@ class CommandLineArgumentParser {
bool next() {
++Position;
- if (Position == Input.end()) return false;
- // Remove the JSON escaping first. This is done unconditionally.
- if (*Position == '\\') ++Position;
return Position != Input.end();
}
@@ -101,9 +98,9 @@ class CommandLineArgumentParser {
std::vector<std::string> CommandLine;
};
-std::vector<std::string> unescapeJSONCommandLine(
- StringRef JSONEscapedCommandLine) {
- CommandLineArgumentParser parser(JSONEscapedCommandLine);
+std::vector<std::string> unescapeCommandLine(
+ StringRef EscapedCommandLine) {
+ CommandLineArgumentParser parser(EscapedCommandLine);
return parser.parse();
}
@@ -124,6 +121,33 @@ CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
return Database.take();
}
+FixedCompilationDatabase *
+FixedCompilationDatabase::loadFromCommandLine(int &Argc,
+ const char **Argv,
+ Twine Directory) {
+ const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
+ if (DoubleDash == Argv + Argc)
+ return NULL;
+ std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc);
+ Argc = DoubleDash - Argv;
+ return new FixedCompilationDatabase(Directory, CommandLine);
+}
+
+FixedCompilationDatabase::
+FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
+ std::vector<std::string> ToolCommandLine(1, "clang-tool");
+ ToolCommandLine.insert(ToolCommandLine.end(),
+ CommandLine.begin(), CommandLine.end());
+ CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine));
+}
+
+std::vector<CompileCommand>
+FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
+ std::vector<CompileCommand> Result(CompileCommands);
+ Result[0].CommandLine.push_back(FilePath);
+ return Result;
+}
+
JSONCompilationDatabase *
JSONCompilationDatabase::loadFromFile(StringRef FilePath,
std::string &ErrorMessage) {
@@ -162,65 +186,77 @@ JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
const std::vector<CompileCommandRef> &CommandsRef = CommandsRefI->getValue();
std::vector<CompileCommand> Commands;
for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
+ llvm::SmallString<8> DirectoryStorage;
+ llvm::SmallString<1024> CommandStorage;
Commands.push_back(CompileCommand(
// FIXME: Escape correctly:
- CommandsRef[I].first,
- unescapeJSONCommandLine(CommandsRef[I].second)));
+ CommandsRef[I].first->getValue(DirectoryStorage),
+ unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage))));
}
return Commands;
}
bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
- llvm::SourceMgr SM;
- llvm::JSONParser Parser(Database->getBuffer(), &SM);
- llvm::JSONValue *Root = Parser.parseRoot();
+ llvm::yaml::document_iterator I = YAMLStream.begin();
+ if (I == YAMLStream.end()) {
+ ErrorMessage = "Error while parsing YAML.";
+ return false;
+ }
+ llvm::yaml::Node *Root = I->getRoot();
if (Root == NULL) {
- ErrorMessage = "Error while parsing JSON.";
+ ErrorMessage = "Error while parsing YAML.";
return false;
}
- llvm::JSONArray *Array = dyn_cast<llvm::JSONArray>(Root);
+ llvm::yaml::SequenceNode *Array =
+ llvm::dyn_cast<llvm::yaml::SequenceNode>(Root);
if (Array == NULL) {
ErrorMessage = "Expected array.";
return false;
}
- for (llvm::JSONArray::const_iterator AI = Array->begin(), AE = Array->end();
+ for (llvm::yaml::SequenceNode::iterator AI = Array->begin(),
+ AE = Array->end();
AI != AE; ++AI) {
- const llvm::JSONObject *Object = dyn_cast<llvm::JSONObject>(*AI);
+ llvm::yaml::MappingNode *Object =
+ llvm::dyn_cast<llvm::yaml::MappingNode>(&*AI);
if (Object == NULL) {
ErrorMessage = "Expected object.";
return false;
}
- StringRef EntryDirectory;
- StringRef EntryFile;
- StringRef EntryCommand;
- for (llvm::JSONObject::const_iterator KVI = Object->begin(),
- KVE = Object->end();
+ llvm::yaml::ScalarNode *Directory;
+ llvm::yaml::ScalarNode *Command;
+ llvm::SmallString<8> FileStorage;
+ llvm::StringRef File;
+ for (llvm::yaml::MappingNode::iterator KVI = Object->begin(),
+ KVE = Object->end();
KVI != KVE; ++KVI) {
- const llvm::JSONValue *Value = (*KVI)->Value;
+ llvm::yaml::Node *Value = (*KVI).getValue();
if (Value == NULL) {
ErrorMessage = "Expected value.";
return false;
}
- const llvm::JSONString *ValueString =
- dyn_cast<llvm::JSONString>(Value);
+ llvm::yaml::ScalarNode *ValueString =
+ llvm::dyn_cast<llvm::yaml::ScalarNode>(Value);
if (ValueString == NULL) {
ErrorMessage = "Expected string as value.";
return false;
}
- if ((*KVI)->Key->getRawText() == "directory") {
- EntryDirectory = ValueString->getRawText();
- } else if ((*KVI)->Key->getRawText() == "file") {
- EntryFile = ValueString->getRawText();
- } else if ((*KVI)->Key->getRawText() == "command") {
- EntryCommand = ValueString->getRawText();
+ llvm::yaml::ScalarNode *KeyString =
+ llvm::dyn_cast<llvm::yaml::ScalarNode>((*KVI).getKey());
+ llvm::SmallString<8> KeyStorage;
+ if (KeyString->getValue(KeyStorage) == "directory") {
+ Directory = ValueString;
+ } else if (KeyString->getValue(KeyStorage) == "command") {
+ Command = ValueString;
+ } else if (KeyString->getValue(KeyStorage) == "file") {
+ File = ValueString->getValue(FileStorage);
} else {
- ErrorMessage = (Twine("Unknown key: \"") +
- (*KVI)->Key->getRawText() + "\"").str();
+ ErrorMessage = ("Unknown key: \"" +
+ KeyString->getRawValue() + "\"").str();
return false;
}
}
- IndexByFile[EntryFile].push_back(
- CompileCommandRef(EntryDirectory, EntryCommand));
+ IndexByFile[File].push_back(
+ CompileCommandRef(Directory, Command));
}
return true;
}
OpenPOWER on IntegriCloud