diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-05-04 16:12:48 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-05-04 16:12:48 +0000 |
commit | 0883ccd9eac3b974df00e6548ee319a7dd3646f4 (patch) | |
tree | d6a70c3518b8dea8be7062438d7e8676820ed17f /lib/Frontend | |
parent | 60bfabcd8ce617297c0d231f77d14ab507e98796 (diff) | |
download | src-0883ccd9eac3b974df00e6548ee319a7dd3646f4.tar.gz src-0883ccd9eac3b974df00e6548ee319a7dd3646f4.zip |
Notes
Diffstat (limited to 'lib/Frontend')
26 files changed, 1461 insertions, 1078 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index ebbd720ceb63..7b8ebf92032e 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -24,7 +24,6 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/CodeGen/ModuleBuilder.h" #include "llvm/Module.h" -#include "llvm/Support/Format.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" @@ -165,7 +164,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, case Decl::Namespace: { Out << "[namespace] "; const NamespaceDecl* ND = cast<NamespaceDecl>(DC); - Out << ND->getNameAsString(); + Out << ND; break; } case Decl::Enum: { @@ -174,7 +173,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "[enum] "; else Out << "<enum> "; - Out << ED->getNameAsString(); + Out << ED; break; } case Decl::Record: { @@ -183,7 +182,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "[struct] "; else Out << "<struct> "; - Out << RD->getNameAsString(); + Out << RD; break; } case Decl::CXXRecord: { @@ -192,7 +191,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "[class] "; else Out << "<class> "; - Out << RD->getNameAsString() << " " << DC; + Out << RD << ' ' << DC; break; } case Decl::ObjCMethod: @@ -225,7 +224,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "[function] "; else Out << "<function> "; - Out << FD->getNameAsString(); + Out << FD; // Print the parameters. Out << "("; bool PrintComma = false; @@ -235,7 +234,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << ", "; else PrintComma = true; - Out << (*I)->getNameAsString(); + Out << *I; } Out << ")"; break; @@ -248,7 +247,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "(c++ method) "; else Out << "<c++ method> "; - Out << D->getNameAsString(); + Out << D; // Print the parameters. Out << "("; bool PrintComma = false; @@ -258,7 +257,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << ", "; else PrintComma = true; - Out << (*I)->getNameAsString(); + Out << *I; } Out << ")"; @@ -278,7 +277,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "(c++ ctor) "; else Out << "<c++ ctor> "; - Out << D->getNameAsString(); + Out << D; // Print the parameters. Out << "("; bool PrintComma = false; @@ -288,7 +287,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << ", "; else PrintComma = true; - Out << (*I)->getNameAsString(); + Out << *I; } Out << ")"; @@ -307,7 +306,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "(c++ dtor) "; else Out << "<c++ dtor> "; - Out << D->getNameAsString(); + Out << D; // Check the semantic DC. const DeclContext* SemaDC = D->getDeclContext(); const DeclContext* LexicalDC = D->getLexicalDeclContext(); @@ -323,7 +322,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "(c++ conversion) "; else Out << "<c++ conversion> "; - Out << D->getNameAsString(); + Out << D; // Check the semantic DC. const DeclContext* SemaDC = D->getDeclContext(); const DeclContext* LexicalDC = D->getLexicalDeclContext(); @@ -370,42 +369,42 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, } case Decl::Field: { FieldDecl* FD = cast<FieldDecl>(*I); - Out << "<field> " << FD->getNameAsString() << "\n"; + Out << "<field> " << FD << '\n'; break; } case Decl::Typedef: { TypedefDecl* TD = cast<TypedefDecl>(*I); - Out << "<typedef> " << TD->getNameAsString() << "\n"; + Out << "<typedef> " << TD << '\n'; break; } case Decl::EnumConstant: { EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I); - Out << "<enum constant> " << ECD->getNameAsString() << "\n"; + Out << "<enum constant> " << ECD << '\n'; break; } case Decl::Var: { VarDecl* VD = cast<VarDecl>(*I); - Out << "<var> " << VD->getNameAsString() << "\n"; + Out << "<var> " << VD << '\n'; break; } case Decl::ImplicitParam: { ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I); - Out << "<implicit parameter> " << IPD->getNameAsString() << "\n"; + Out << "<implicit parameter> " << IPD << '\n'; break; } case Decl::ParmVar: { ParmVarDecl* PVD = cast<ParmVarDecl>(*I); - Out << "<parameter> " << PVD->getNameAsString() << "\n"; + Out << "<parameter> " << PVD << '\n'; break; } case Decl::ObjCProperty: { ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I); - Out << "<objc property> " << OPD->getNameAsString() << "\n"; + Out << "<objc property> " << OPD << '\n'; break; } case Decl::FunctionTemplate: { FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I); - Out << "<function template> " << FTD->getNameAsString() << "\n"; + Out << "<function template> " << FTD << '\n'; break; } case Decl::FileScopeAsm: { @@ -418,16 +417,16 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, } case Decl::NamespaceAlias: { NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I); - Out << "<namespace alias> " << NAD->getNameAsString() << "\n"; + Out << "<namespace alias> " << NAD << '\n'; break; } case Decl::ClassTemplate: { ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I); - Out << "<class template> " << CTD->getNameAsString() << '\n'; + Out << "<class template> " << CTD << '\n'; break; } default: - Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n"; + Out << "DeclKind: " << DK << '"' << *I << "\"\n"; assert(0 && "decl unhandled"); } } @@ -437,150 +436,6 @@ ASTConsumer *clang::CreateDeclContextPrinter() { } //===----------------------------------------------------------------------===// -/// RecordLayoutDumper - C++ Record Layout Dumping. -namespace { -class RecordLayoutDumper : public ASTConsumer { - llvm::raw_ostream& Out; - - void PrintOffset(uint64_t Offset, unsigned IndentLevel) { - Out << llvm::format("%4d | ", Offset); - for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' '; - } - - void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C, - uint64_t Offset, - unsigned IndentLevel, const char* Description, - bool IncludeVirtualBases) { - const ASTRecordLayout &Info = C.getASTRecordLayout(RD); - - PrintOffset(Offset, IndentLevel); - Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString(); - if (Description) - Out << ' ' << Description; - if (RD->isEmpty()) - Out << " (empty)"; - Out << '\n'; - - IndentLevel++; - - const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase(); - - // Vtable pointer. - if (RD->isDynamicClass() && !PrimaryBase) { - PrintOffset(Offset, IndentLevel); - Out << '(' << RD->getNameAsString() << " vtable pointer)\n"; - } - // Dump (non-virtual) bases - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && - "Cannot layout class with dependent bases."); - if (I->isVirtual()) - continue; - - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8; - - DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel, - Base == PrimaryBase ? "(primary base)" : "(base)", - /*IncludeVirtualBases=*/false); - } - - // Dump fields. - uint64_t FieldNo = 0; - for (CXXRecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); I != E; ++I, ++FieldNo) { - const FieldDecl *Field = *I; - uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8; - - if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { - if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel, - Field->getNameAsCString(), - /*IncludeVirtualBases=*/true); - continue; - } - } - - PrintOffset(FieldOffset, IndentLevel); - Out << Field->getType().getAsString() << ' '; - Out << Field->getNameAsString() << '\n'; - } - - if (!IncludeVirtualBases) - return; - - // Dump virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - assert(I->isVirtual() && "Found non-virtual class!"); - const CXXRecordDecl *VBase = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8; - DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel, - VBase == PrimaryBase ? - "(primary virtual base)" : "(virtual base)", - /*IncludeVirtualBases=*/false); - } - } - - // FIXME: Maybe this could be useful in ASTContext.cpp. - void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) { - const ASTRecordLayout &Info = C.getASTRecordLayout(RD); - - DumpRecordLayoutOffsets(RD, C, 0, 0, 0, - /*IncludeVirtualBases=*/true); - Out << " sizeof=" << Info.getSize() / 8; - Out << ", dsize=" << Info.getDataSize() / 8; - Out << ", align=" << Info.getAlignment() / 8 << '\n'; - Out << " nvsize=" << Info.getNonVirtualSize() / 8; - Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n'; - Out << '\n'; - } - -public: - RecordLayoutDumper() : Out(llvm::errs()) {} - - void HandleTranslationUnit(ASTContext &C) { - for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end(); - I != E; ++I) { - const RecordType *RT = dyn_cast<RecordType>(*I); - if (!RT) - continue; - - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) - continue; - - if (RD->isImplicit()) - continue; - - if (RD->isDependentType()) - continue; - - if (RD->isInvalidDecl()) - continue; - - if (!RD->getDefinition()) - continue; - - // FIXME: Do we really need to hard code this? - if (RD->getQualifiedNameAsString() == "__va_list_tag") - continue; - - DumpRecordLayout(RD, C); - } - } -}; -} // end anonymous namespace -ASTConsumer *clang::CreateRecordLayoutDumper() { - return new RecordLayoutDumper(); -} - -//===----------------------------------------------------------------------===// /// InheritanceViewer - C++ Inheritance Visualization namespace { diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 427bd6a9b803..4730bdc2f161 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -265,8 +265,16 @@ public: TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {} void HandleTopLevelDecl(DeclGroupRef D) { - for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) - Unit.getTopLevelDecls().push_back(*it); + for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) { + Decl *D = *it; + // FIXME: Currently ObjC method declarations are incorrectly being + // reported as top-level declarations, even though their DeclContext + // is the containing ObjC @interface/@implementation. This is a + // fundamental problem in the parser right now. + if (isa<ObjCMethodDecl>(D)) + continue; + Unit.getTopLevelDecls().push_back(D); + } } }; @@ -431,8 +439,10 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, const driver::ArgStringList &CCArgs = Cmd->getArguments(); llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation); - CompilerInvocation::CreateFromArgs(*CI, (const char**) CCArgs.data(), - (const char**) CCArgs.data()+CCArgs.size(), + CompilerInvocation::CreateFromArgs(*CI, + const_cast<const char **>(CCArgs.data()), + const_cast<const char **>(CCArgs.data()) + + CCArgs.size(), *Diags); // Override any files that need remapping diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index d764fd078968..87c3fca24962 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -41,10 +41,6 @@ using namespace clang; static ExplodedNode::Auditor* CreateUbiViz(); //===----------------------------------------------------------------------===// -// Basic type definitions. -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// // Special PathDiagnosticClients. //===----------------------------------------------------------------------===// @@ -62,20 +58,21 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix, namespace { - class AnalysisConsumer : public ASTConsumer { - public: +class AnalysisConsumer : public ASTConsumer { +public: typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D); typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M, TranslationUnitDecl &TU); - private: +private: typedef std::vector<CodeAction> Actions; typedef std::vector<TUAction> TUActions; Actions FunctionActions; Actions ObjCMethodActions; Actions ObjCImplementationActions; - TUActions TranslationUnitActions; + Actions CXXMethodActions; + TUActions TranslationUnitActions; // Remove this. public: ASTContext* Ctx; @@ -150,7 +147,7 @@ public: if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { const NamedDecl *ND = cast<NamedDecl>(D); - llvm::errs() << ' ' << ND->getNameAsString() << '\n'; + llvm::errs() << ' ' << ND << '\n'; } else if (isa<BlockDecl>(D)) { llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" @@ -161,103 +158,100 @@ public: void addCodeAction(CodeAction action) { FunctionActions.push_back(action); ObjCMethodActions.push_back(action); - } - - void addObjCImplementationAction(CodeAction action) { - ObjCImplementationActions.push_back(action); + CXXMethodActions.push_back(action); } void addTranslationUnitAction(TUAction action) { TranslationUnitActions.push_back(action); } + void addObjCImplementationAction(CodeAction action) { + ObjCImplementationActions.push_back(action); + } + virtual void Initialize(ASTContext &Context) { Ctx = &Context; Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), PP.getLangOptions(), PD, CreateStoreMgr, CreateConstraintMgr, + Opts.MaxNodes, Opts.VisualizeEGDot, Opts.VisualizeEGUbi, Opts.PurgeDead, Opts.EagerlyAssume, Opts.TrimGraph)); } - virtual void HandleTopLevelDecl(DeclGroupRef D) { - declDisplayed = false; - for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) - HandleTopLevelSingleDecl(*I); - } - - void HandleTopLevelSingleDecl(Decl *D); virtual void HandleTranslationUnit(ASTContext &C); - - void HandleCode(Decl* D, Stmt* Body, Actions& actions); + void HandleCode(Decl *D, Stmt* Body, Actions& actions); }; } // end anonymous namespace -namespace llvm { - template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> { - static inline void Profile(AnalysisConsumer::CodeAction X, - FoldingSetNodeID& ID) { - ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X))); - } - }; -} - //===----------------------------------------------------------------------===// // AnalysisConsumer implementation. //===----------------------------------------------------------------------===// -void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { - switch (D->getKind()) { - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::CXXMethod: - case Decl::Function: { - FunctionDecl* FD = cast<FunctionDecl>(D); - if (!Opts.AnalyzeSpecificFunction.empty() && - FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) - break; - - if (Stmt *Body = FD->getBody()) - HandleCode(FD, Body, FunctionActions); - break; - } - - case Decl::ObjCMethod: { - ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); +void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { - if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString()) - return; + TranslationUnitDecl *TU = C.getTranslationUnitDecl(); - if (Stmt* Body = MD->getBody()) - HandleCode(MD, Body, ObjCMethodActions); - break; - } + for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end(); + I != E; ++I) { + Decl *D = *I; + + switch (D->getKind()) { + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + case Decl::CXXMethod: + case Decl::Function: { + FunctionDecl* FD = cast<FunctionDecl>(D); + + if (FD->isThisDeclarationADefinition()) { + if (!Opts.AnalyzeSpecificFunction.empty() && + FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) + break; + HandleCode(FD, FD->getBody(), FunctionActions); + } + break; + } - default: - break; - } -} + case Decl::ObjCMethod: { + ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); + + if (MD->isThisDeclarationADefinition()) { + if (!Opts.AnalyzeSpecificFunction.empty() && + Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString()) + break; + HandleCode(MD, MD->getBody(), ObjCMethodActions); + } + break; + } -void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { + case Decl::ObjCImplementation: { + ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I); + HandleCode(ID, 0, ObjCImplementationActions); + + for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(), + ME = ID->meth_end(); MI != ME; ++MI) { + if ((*MI)->isThisDeclarationADefinition()) { + if (!Opts.AnalyzeSpecificFunction.empty() && + Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString()) + break; + HandleCode(*MI, (*MI)->getBody(), ObjCMethodActions); + } + } + break; + } - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + default: + break; + } + } for (TUActions::iterator I = TranslationUnitActions.begin(), E = TranslationUnitActions.end(); I != E; ++I) { (*I)(*this, *Mgr, *TU); } - if (!ObjCImplementationActions.empty()) { - for (DeclContext::decl_iterator I = TU->decls_begin(), - E = TU->decls_end(); - I != E; ++I) - if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I)) - HandleCode(ID, 0, ObjCImplementationActions); - } - // Explicitly destroy the PathDiagnosticClient. This will flush its output. // FIXME: This should be replaced with something that doesn't rely on // side-effects in PathDiagnosticClient's destructor. This is required when @@ -278,7 +272,8 @@ static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) { void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) { // Don't run the actions if an error has occured with parsing the file. - if (PP.getDiagnostics().hasErrorOccurred()) + Diagnostic &Diags = PP.getDiagnostics(); + if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) return; // Don't run the actions on declarations in header files unless @@ -310,7 +305,6 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) { static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (LiveVariables *L = mgr.getLiveVariables(D)) { - C.DisplayFunction(D); BugReporter BR(mgr); CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR); } @@ -319,7 +313,6 @@ static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr, static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (CFG* c = mgr.getCFG(D)) { - C.DisplayFunction(D); CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic()); } } @@ -331,15 +324,11 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, llvm::OwningPtr<GRTransferFuncs> TF(tf); - // Display progress. - C.DisplayFunction(D); - // Construct the analysis engine. We first query for the LiveVariables // information to see if the CFG is valid. // FIXME: Inter-procedural analysis will need to handle invalid CFGs. if (!mgr.getLiveVariables(D)) return; - GRExprEngine Eng(mgr, TF.take()); if (C.Opts.EnableExperimentalInternalChecks) @@ -358,7 +347,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, } // Execute the worklist algorithm. - Eng.ExecuteWorkList(mgr.getStackFrame(D)); + Eng.ExecuteWorkList(mgr.getStackFrame(D), mgr.getMaxNodes()); // Release the auditor (if any) so that it doesn't monitor the graph // created BugReporter. @@ -406,28 +395,24 @@ static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr, static void ActionDisplayLiveVariables(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (LiveVariables* L = mgr.getLiveVariables(D)) { - C.DisplayFunction(D); L->dumpBlockLiveness(mgr.getSourceManager()); } } static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (CFG *cfg = mgr.getCFG(D)) { - C.DisplayFunction(D); cfg->dump(mgr.getLangOptions()); } } static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (CFG *cfg = mgr.getCFG(D)) { - C.DisplayFunction(D); cfg->viewCFG(mgr.getLangOptions()); } } static void ActionSecuritySyntacticChecks(AnalysisConsumer &C, AnalysisManager &mgr, Decl *D) { - C.DisplayFunction(D); BugReporter BR(mgr); CheckSecuritySyntaxOnly(D, BR); } @@ -443,86 +428,28 @@ static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly) return; - - C.DisplayFunction(D); BugReporter BR(mgr); CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR); } static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { - C.DisplayFunction(D); BugReporter BR(mgr); CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR); } static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { - C.DisplayFunction(D); BugReporter BR(mgr); CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR); } static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr, Decl *D) { - C.DisplayFunction(D); BugReporter BR(mgr); CheckSizeofPointer(D, BR); } -static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr, - TranslationUnitDecl &TU) { - - // Find the entry function definition (if any). - FunctionDecl *D = 0; - - // Must specify an entry function. - if (!C.Opts.AnalyzeSpecificFunction.empty()) { - for (DeclContext::decl_iterator I=TU.decls_begin(), E=TU.decls_end(); - I != E; ++I) { - if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I)) - if (fd->isThisDeclarationADefinition() && - fd->getNameAsString() == C.Opts.AnalyzeSpecificFunction) { - D = fd; - break; - } - } - } - - if (!D) - return; - - - // FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup. - // Display progress. - C.DisplayFunction(D); - - // FIXME: Make a fake transfer function. The GRTransferFunc interface - // eventually will be removed. - GRExprEngine Eng(mgr, new GRTransferFuncs()); - - if (C.Opts.EnableExperimentalInternalChecks) - RegisterExperimentalInternalChecks(Eng); - - RegisterAppleChecks(Eng, *D); - - if (C.Opts.EnableExperimentalChecks) - RegisterExperimentalChecks(Eng); - - // Register call inliner as the last checker. - RegisterCallInliner(Eng); - - // Execute the worklist algorithm. - Eng.ExecuteWorkList(mgr.getStackFrame(D)); - - // Visualize the exploded graph. - if (mgr.shouldVisualizeGraphviz()) - Eng.ViewGraph(mgr.shouldTrimGraph()); - - // Display warnings. - Eng.getBugReporter().FlushReports(); -} - //===----------------------------------------------------------------------===// // AnalysisConsumer creation. //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index d069e8f42f26..a5fcebe99411 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -475,7 +475,7 @@ void PTHWriter::GeneratePTH(const std::string &MainFile) { if (!P.isAbsolute()) continue; - const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics()); + const llvm::MemoryBuffer *B = C.getBuffer(PP.getDiagnostics(), SM); if (!B) continue; FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); @@ -550,8 +550,7 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { // Lex through the entire file. This will populate SourceManager with // all of the header information. Token Tok; - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); // Generate the PTH file. diff --git a/lib/Frontend/CodeGenAction.cpp b/lib/Frontend/CodeGenAction.cpp index b1795a3aa3b5..79d7d5f4c241 100644 --- a/lib/Frontend/CodeGenAction.cpp +++ b/lib/Frontend/CodeGenAction.cpp @@ -8,16 +8,18 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/CodeGenAction.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclGroup.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/CodeGenOptions.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/ADT/OwningPtr.h" @@ -28,6 +30,8 @@ #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/Timer.h" #include "llvm/Target/SubtargetFeature.h" @@ -87,7 +91,7 @@ namespace { const LangOptions &langopts, const CodeGenOptions &compopts, const TargetOptions &targetopts, bool TimePasses, const std::string &infile, llvm::raw_ostream *OS, - LLVMContext& C) : + LLVMContext &C) : Diags(_Diags), Action(action), CodeGenOpts(compopts), @@ -175,6 +179,15 @@ namespace { virtual void CompleteTentativeDefinition(VarDecl *D) { Gen->CompleteTentativeDefinition(D); } + + static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, + unsigned LocCookie) { + SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); + ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); + } + + void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, + SourceLocation LocCookie); }; } @@ -211,127 +224,122 @@ bool BackendConsumer::AddEmitPasses() { if (Action == Backend_EmitBC) { getPerModulePasses()->add(createBitcodeWriterPass(FormattedOutStream)); - } else if (Action == Backend_EmitLL) { + return true; + } + + if (Action == Backend_EmitLL) { getPerModulePasses()->add(createPrintModulePass(&FormattedOutStream)); + return true; + } + + bool Fast = CodeGenOpts.OptimizationLevel == 0; + + // Create the TargetMachine for generating code. + std::string Error; + std::string Triple = TheModule->getTargetTriple(); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); + if (!TheTarget) { + Diags.Report(diag::err_fe_unable_to_create_target) << Error; + return false; + } + + // FIXME: Expose these capabilities via actual APIs!!!! Aside from just + // being gross, this is also totally broken if we ever care about + // concurrency. + llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim; + if (CodeGenOpts.FloatABI == "soft") + llvm::FloatABIType = llvm::FloatABI::Soft; + else if (CodeGenOpts.FloatABI == "hard") + llvm::FloatABIType = llvm::FloatABI::Hard; + else { + assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!"); + llvm::FloatABIType = llvm::FloatABI::Default; + } + NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; + llvm::UseSoftFloat = CodeGenOpts.SoftFloat; + UnwindTablesMandatory = CodeGenOpts.UnwindTables; + + TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose); + + TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections); + TargetMachine::setDataSections (CodeGenOpts.DataSections); + + // FIXME: Parse this earlier. + if (CodeGenOpts.RelocationModel == "static") { + TargetMachine::setRelocationModel(llvm::Reloc::Static); + } else if (CodeGenOpts.RelocationModel == "pic") { + TargetMachine::setRelocationModel(llvm::Reloc::PIC_); } else { - bool Fast = CodeGenOpts.OptimizationLevel == 0; - - // Create the TargetMachine for generating code. - std::string Error; - std::string Triple = TheModule->getTargetTriple(); - const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); - if (!TheTarget) { - Diags.Report(diag::err_fe_unable_to_create_target) << Error; - return false; - } + assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" && + "Invalid PIC model!"); + TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC); + } + // FIXME: Parse this earlier. + if (CodeGenOpts.CodeModel == "small") { + TargetMachine::setCodeModel(llvm::CodeModel::Small); + } else if (CodeGenOpts.CodeModel == "kernel") { + TargetMachine::setCodeModel(llvm::CodeModel::Kernel); + } else if (CodeGenOpts.CodeModel == "medium") { + TargetMachine::setCodeModel(llvm::CodeModel::Medium); + } else if (CodeGenOpts.CodeModel == "large") { + TargetMachine::setCodeModel(llvm::CodeModel::Large); + } else { + assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!"); + TargetMachine::setCodeModel(llvm::CodeModel::Default); + } - // FIXME: Expose these capabilities via actual APIs!!!! Aside from just - // being gross, this is also totally broken if we ever care about - // concurrency. - llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim; - if (CodeGenOpts.FloatABI == "soft") - llvm::FloatABIType = llvm::FloatABI::Soft; - else if (CodeGenOpts.FloatABI == "hard") - llvm::FloatABIType = llvm::FloatABI::Hard; - else { - assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!"); - llvm::FloatABIType = llvm::FloatABI::Default; - } - NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; - llvm::UseSoftFloat = CodeGenOpts.SoftFloat; - UnwindTablesMandatory = CodeGenOpts.UnwindTables; - - TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose); - - // FIXME: Parse this earlier. - if (CodeGenOpts.RelocationModel == "static") { - TargetMachine::setRelocationModel(llvm::Reloc::Static); - } else if (CodeGenOpts.RelocationModel == "pic") { - TargetMachine::setRelocationModel(llvm::Reloc::PIC_); - } else { - assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" && - "Invalid PIC model!"); - TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC); - } - // FIXME: Parse this earlier. - if (CodeGenOpts.CodeModel == "small") { - TargetMachine::setCodeModel(llvm::CodeModel::Small); - } else if (CodeGenOpts.CodeModel == "kernel") { - TargetMachine::setCodeModel(llvm::CodeModel::Kernel); - } else if (CodeGenOpts.CodeModel == "medium") { - TargetMachine::setCodeModel(llvm::CodeModel::Medium); - } else if (CodeGenOpts.CodeModel == "large") { - TargetMachine::setCodeModel(llvm::CodeModel::Large); - } else { - assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!"); - TargetMachine::setCodeModel(llvm::CodeModel::Default); - } + std::vector<const char *> BackendArgs; + BackendArgs.push_back("clang"); // Fake program name. + if (!CodeGenOpts.DebugPass.empty()) { + BackendArgs.push_back("-debug-pass"); + BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); + } + if (!CodeGenOpts.LimitFloatPrecision.empty()) { + BackendArgs.push_back("-limit-float-precision"); + BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); + } + if (llvm::TimePassesIsEnabled) + BackendArgs.push_back("-time-passes"); + BackendArgs.push_back(0); + llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, + const_cast<char **>(&BackendArgs[0])); + + std::string FeaturesStr; + if (TargetOpts.CPU.size() || TargetOpts.Features.size()) { + SubtargetFeatures Features; + Features.setCPU(TargetOpts.CPU); + for (std::vector<std::string>::const_iterator + it = TargetOpts.Features.begin(), + ie = TargetOpts.Features.end(); it != ie; ++it) + Features.AddFeature(*it); + FeaturesStr = Features.getString(); + } + TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr); - std::vector<const char *> BackendArgs; - BackendArgs.push_back("clang"); // Fake program name. - if (!CodeGenOpts.DebugPass.empty()) { - BackendArgs.push_back("-debug-pass"); - BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); - } - if (!CodeGenOpts.LimitFloatPrecision.empty()) { - BackendArgs.push_back("-limit-float-precision"); - BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); - } - if (llvm::TimePassesIsEnabled) - BackendArgs.push_back("-time-passes"); - BackendArgs.push_back(0); - llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, - (char**) &BackendArgs[0]); - - std::string FeaturesStr; - if (TargetOpts.CPU.size() || TargetOpts.Features.size()) { - SubtargetFeatures Features; - Features.setCPU(TargetOpts.CPU); - for (std::vector<std::string>::const_iterator - it = TargetOpts.Features.begin(), - ie = TargetOpts.Features.end(); it != ie; ++it) - Features.AddFeature(*it); - FeaturesStr = Features.getString(); - } - TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr); - - // Set register scheduler & allocation policy. - RegisterScheduler::setDefault(createDefaultScheduler); - RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator : - createLinearScanRegisterAllocator); - - // From llvm-gcc: - // If there are passes we have to run on the entire module, we do codegen - // as a separate "pass" after that happens. - // FIXME: This is disabled right now until bugs can be worked out. Reenable - // this for fast -O0 compiles! - FunctionPassManager *PM = getCodeGenPasses(); - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; - - switch (CodeGenOpts.OptimizationLevel) { - default: break; - case 0: OptLevel = CodeGenOpt::None; break; - case 3: OptLevel = CodeGenOpt::Aggressive; break; - } + // Set register scheduler & allocation policy. + RegisterScheduler::setDefault(createDefaultScheduler); + RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator : + createLinearScanRegisterAllocator); - // Request that addPassesToEmitFile run the Verifier after running - // passes which modify the IR. -#ifndef NDEBUG - bool DisableVerify = false; -#else - bool DisableVerify = true; -#endif - - // Normal mode, emit a .s or .o file by running the code generator. Note, - // this also adds codegenerator level optimization passes. - TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; - if (Action == Backend_EmitObj) - CGFT = TargetMachine::CGFT_ObjectFile; - if (TM->addPassesToEmitFile(*PM, FormattedOutStream, CGFT, OptLevel, - DisableVerify)) { - Diags.Report(diag::err_fe_unable_to_interface_with_target); - return false; - } + // Create the code generator passes. + FunctionPassManager *PM = getCodeGenPasses(); + CodeGenOpt::Level OptLevel = CodeGenOpt::Default; + + switch (CodeGenOpts.OptimizationLevel) { + default: break; + case 0: OptLevel = CodeGenOpt::None; break; + case 3: OptLevel = CodeGenOpt::Aggressive; break; + } + + // Normal mode, emit a .s or .o file by running the code generator. Note, + // this also adds codegenerator level optimization passes. + TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; + if (Action == Backend_EmitObj) + CGFT = TargetMachine::CGFT_ObjectFile; + if (TM->addPassesToEmitFile(*PM, FormattedOutStream, CGFT, OptLevel, + /*DisableVerify=*/!CodeGenOpts.VerifyModule)) { + Diags.Report(diag::err_fe_unable_to_interface_with_target); + return false; } return true; @@ -432,14 +440,81 @@ void BackendConsumer::EmitAssembly() { if (CodeGenPasses) { PrettyStackTraceString CrashInfo("Code generation"); + + // Install an inline asm handler so that diagnostics get printed through our + // diagnostics hooks. + LLVMContext &Ctx = TheModule->getContext(); + void *OldHandler = Ctx.getInlineAsmDiagnosticHandler(); + void *OldContext = Ctx.getInlineAsmDiagnosticContext(); + Ctx.setInlineAsmDiagnosticHandler((void*)(intptr_t)InlineAsmDiagHandler, + this); + CodeGenPasses->doInitialization(); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isDeclaration()) CodeGenPasses->run(*I); CodeGenPasses->doFinalization(); + + Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); } } +/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr +/// buffer to be a valid FullSourceLoc. +static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, + SourceManager &CSM) { + // Get both the clang and llvm source managers. The location is relative to + // a memory buffer that the LLVM Source Manager is handling, we need to add + // a copy to the Clang source manager. + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + + // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr + // already owns its one and clang::SourceManager wants to own its one. + const MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + + // Create the copy and transfer ownership to clang::SourceManager. + llvm::MemoryBuffer *CBuf = + llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), + LBuf->getBufferIdentifier()); + FileID FID = CSM.createFileIDForMemBuffer(CBuf); + + // Translate the offset into the file. + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + SourceLocation NewLoc = + CSM.getLocForStartOfFile(FID).getFileLocWithOffset(Offset); + return FullSourceLoc(NewLoc, CSM); +} + + +/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an +/// error parsing inline asm. The SMDiagnostic indicates the error relative to +/// the temporary memory buffer that the inline asm parser has set up. +void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, + SourceLocation LocCookie) { + // There are a couple of different kinds of errors we could get here. First, + // we re-format the SMDiagnostic in terms of a clang diagnostic. + + // Strip "error: " off the start of the message string. + llvm::StringRef Message = D.getMessage(); + if (Message.startswith("error: ")) + Message = Message.substr(7); + + // There are two cases: the SMDiagnostic could have a inline asm source + // location or it might not. If it does, translate the location. + FullSourceLoc Loc; + if (D.getLoc() != SMLoc()) + Loc = ConvertBackendLocation(D, Context->getSourceManager()); + Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); + + // This could be a problem with no clang-level source location information. + // In this case, LocCookie is invalid. If there is source level information, + // print an "generated from" note. + if (LocCookie.isValid()) + Diags.Report(FullSourceLoc(LocCookie, Context->getSourceManager()), + diag::note_fe_inline_asm_here); +} + // CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {} diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 1f915e3713d3..5ed9c409a3dc 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -513,11 +513,20 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { } } - if (getDiagnosticOpts().ShowCarets) - if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics()) - OS << NumDiagnostics << " diagnostic" - << (NumDiagnostics == 1 ? "" : "s") - << " generated.\n"; + if (getDiagnosticOpts().ShowCarets) { + unsigned NumWarnings = getDiagnostics().getNumWarnings(); + unsigned NumErrors = getDiagnostics().getNumErrors() - + getDiagnostics().getNumErrorsSuppressed(); + + if (NumWarnings) + OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); + if (NumWarnings && NumErrors) + OS << " and "; + if (NumErrors) + OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); + if (NumWarnings || NumErrors) + OS << " generated.\n"; + } if (getFrontendOpts().ShowStats) { getFileManager().PrintStats(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index dc2c6bf3614a..8ffdde2aa9b5 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -145,9 +145,12 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, // TimePasses is only derived. // UnitAtATime is unused. // UnrollLoops is only derived. - // VerifyModule is only derived. // Inlining is only derived. + if (Opts.DataSections) + Res.push_back("-fdata-sections"); + if (Opts.FunctionSections) + Res.push_back("-ffunction-sections"); if (Opts.AsmVerbose) Res.push_back("-masm-verbose"); if (!Opts.CodeModel.empty()) { @@ -174,8 +177,16 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, } if (Opts.NoZeroInitializedInBSS) Res.push_back("-mno-zero-initialized-bss"); - if (Opts.ObjCLegacyDispatch) - Res.push_back("-fobjc-legacy-dispatch"); + switch (Opts.getObjCDispatchMethod()) { + case CodeGenOptions::Legacy: + break; + case CodeGenOptions::Mixed: + Res.push_back("-fobjc-dispatch-method=mixed"); + break; + case CodeGenOptions::NonLegacy: + Res.push_back("-fobjc-dispatch-method=non-legacy"); + break; + } if (Opts.SoftFloat) Res.push_back("-msoft-float"); if (Opts.UnwindTables) @@ -232,6 +243,15 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, Res.push_back("-fdiagnostics-binary"); if (Opts.ShowOptionNames) Res.push_back("-fdiagnostics-show-option"); + if (Opts.ErrorLimit) { + Res.push_back("-ferror-limit"); + Res.push_back(llvm::utostr(Opts.ErrorLimit)); + } + if (Opts.TemplateBacktraceLimit != 10) { + Res.push_back("-ftemplate-backtrace-limit"); + Res.push_back(llvm::utostr(Opts.TemplateBacktraceLimit)); + } + if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) { Res.push_back("-ftabstop"); Res.push_back(llvm::utostr(Opts.TabStop)); @@ -279,7 +299,6 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::ASTPrintXML: return "-ast-print-xml"; case frontend::ASTView: return "-ast-view"; case frontend::DumpRawTokens: return "-dump-raw-tokens"; - case frontend::DumpRecordLayouts: return "-dump-record-layouts"; case frontend::DumpTokens: return "-dump-tokens"; case frontend::EmitAssembly: return "-S"; case frontend::EmitBC: return "-emit-llvm-bc"; @@ -349,12 +368,6 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-cxx-inheritance-view"); Res.push_back(Opts.ViewClassInheritance); } - for (unsigned i = 0, e = Opts.FixItLocations.size(); i != e; ++i) { - Res.push_back("-fixit-at"); - Res.push_back(Opts.FixItLocations[i].FileName + ":" + - llvm::utostr(Opts.FixItLocations[i].Line) + ":" + - llvm::utostr(Opts.FixItLocations[i].Column)); - } if (!Opts.CodeCompletionAt.FileName.empty()) { Res.push_back("-code-completion-at"); Res.push_back(Opts.CodeCompletionAt.FileName + ":" + @@ -376,6 +389,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-ast-merge"); Res.push_back(Opts.ASTMergeFiles[i]); } + for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i) { + Res.push_back("-mllvm"); + Res.push_back(Opts.LLVMArgs[i]); + } } static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, @@ -389,7 +406,7 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) { const HeaderSearchOptions::Entry &E = Opts.UserEntries[i]; if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied)) - llvm::llvm_report_error("Invalid option set!"); + llvm::report_fatal_error("Invalid option set!"); if (E.IsUserSupplied) { if (E.Group == frontend::After) { Res.push_back("-idirafter"); @@ -403,7 +420,7 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, } } else { if (E.Group != frontend::Angled && E.Group != frontend::System) - llvm::llvm_report_error("Invalid option set!"); + llvm::report_fatal_error("Invalid option set!"); Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" : "-iwithprefix"); } @@ -412,23 +429,23 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, if (!Opts.EnvIncPath.empty()) { // FIXME: Provide an option for this, and move env detection to driver. - llvm::llvm_report_error("Not yet implemented!"); + llvm::report_fatal_error("Not yet implemented!"); } if (!Opts.CEnvIncPath.empty()) { // FIXME: Provide an option for this, and move env detection to driver. - llvm::llvm_report_error("Not yet implemented!"); + llvm::report_fatal_error("Not yet implemented!"); } if (!Opts.ObjCEnvIncPath.empty()) { // FIXME: Provide an option for this, and move env detection to driver. - llvm::llvm_report_error("Not yet implemented!"); + llvm::report_fatal_error("Not yet implemented!"); } if (!Opts.CXXEnvIncPath.empty()) { // FIXME: Provide an option for this, and move env detection to driver. - llvm::llvm_report_error("Not yet implemented!"); + llvm::report_fatal_error("Not yet implemented!"); } if (!Opts.ObjCXXEnvIncPath.empty()) { // FIXME: Provide an option for this, and move env detection to driver. - llvm::llvm_report_error("Not yet implemented!"); + llvm::report_fatal_error("Not yet implemented!"); } if (!Opts.ResourceDir.empty()) { Res.push_back("-resource-dir"); @@ -462,6 +479,10 @@ static void LangOptsToArgs(const LangOptions &Opts, // BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode if (Opts.DollarIdents) Res.push_back("-fdollars-in-identifiers"); + if (Opts.GNUMode && !Opts.GNUKeywords) + Res.push_back("-fno-gnu-keywords"); + if (!Opts.GNUMode && Opts.GNUKeywords) + Res.push_back("-fgnu-keywords"); if (Opts.Microsoft) Res.push_back("-fms-extensions"); if (Opts.ObjCNonFragileABI) @@ -515,15 +536,24 @@ static void LangOptsToArgs(const LangOptions &Opts, // OptimizeSize is implicit. if (Opts.Static) Res.push_back("-static-define"); + if (Opts.DumpRecordLayouts) + Res.push_back("-fdump-record-layouts"); + if (Opts.DumpVTableLayouts) + Res.push_back("-fdump-vtable-layouts"); + if (Opts.NoBitFieldTypeAlign) + Res.push_back("-fno-bitfield-type-alignment"); + if (Opts.SjLjExceptions) + Res.push_back("-fsjlj-exceptions"); if (Opts.PICLevel) { Res.push_back("-pic-level"); Res.push_back(llvm::utostr(Opts.PICLevel)); } if (Opts.ObjCGCBitmapPrint) Res.push_back("-print-ivar-layout"); - // FIXME: Don't forget to update when the default changes! - if (Opts.AccessControl) - Res.push_back("-faccess-control"); + if (Opts.NoConstantCFStrings) + Res.push_back("-fno-constant-cfstrings"); + if (!Opts.AccessControl) + Res.push_back("-fno-access-control"); if (!Opts.CharIsSigned) Res.push_back("-fno-signed-char"); if (Opts.ShortWChar) @@ -606,7 +636,7 @@ static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts, static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts, std::vector<std::string> &Res) { if (!Opts.ShowCPP && !Opts.ShowMacros) - llvm::llvm_report_error("Invalid option combination!"); + llvm::report_fatal_error("Invalid option combination!"); if (Opts.ShowCPP && Opts.ShowMacros) Res.push_back("-dD"); @@ -756,6 +786,7 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.EnableExperimentalInternalChecks = Args.hasArg(OPT_analyzer_experimental_internal_checks); Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); + Opts.MaxNodes = getLastArgIntValue(Args, OPT_analyzer_max_nodes,150000,Diags); } static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, @@ -796,13 +827,28 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.FloatABI = getLastArgValue(Args, OPT_mfloat_abi); Opts.LimitFloatPrecision = getLastArgValue(Args, OPT_mlimit_float_precision); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); - Opts.ObjCLegacyDispatch = Args.hasArg(OPT_fobjc_legacy_dispatch); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); Opts.RelocationModel = getLastArgValue(Args, OPT_mrelocation_model, "pic"); + Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections); + Opts.DataSections = Args.hasArg(OPT_fdata_sections); + Opts.MainFileName = getLastArgValue(Args, OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); + + if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) { + llvm::StringRef Name = A->getValue(Args); + unsigned Method = llvm::StringSwitch<unsigned>(Name) + .Case("legacy", CodeGenOptions::Legacy) + .Case("non-legacy", CodeGenOptions::NonLegacy) + .Case("mixed", CodeGenOptions::Mixed) + .Default(~0U); + if (Method == ~0U) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + else + Opts.ObjCDispatchMethod = Method; + } } static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, @@ -830,6 +876,9 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary); + Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); + Opts.TemplateBacktraceLimit + = getLastArgIntValue(Args, OPT_ftemplate_backtrace_limit, 0, Diags); Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { @@ -860,8 +909,6 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { Opts.ProgramAction = frontend::ASTView; break; case OPT_dump_raw_tokens: Opts.ProgramAction = frontend::DumpRawTokens; break; - case OPT_dump_record_layouts: - Opts.ProgramAction = frontend::DumpRecordLayouts; break; case OPT_dump_tokens: Opts.ProgramAction = frontend::DumpTokens; break; case OPT_S: @@ -876,6 +923,9 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { Opts.ProgramAction = frontend::EmitLLVMOnly; break; case OPT_emit_obj: Opts.ProgramAction = frontend::EmitObj; break; + case OPT_fixit_EQ: + Opts.FixItSuffix = A->getValue(Args); + // fall-through! case OPT_fixit: Opts.ProgramAction = frontend::FixIt; break; case OPT_emit_pch: @@ -922,20 +972,6 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { !Args.hasArg(OPT_no_code_completion_debug_printer); Opts.DisableFree = Args.hasArg(OPT_disable_free); - Opts.FixItLocations.clear(); - for (arg_iterator it = Args.filtered_begin(OPT_fixit_at), - ie = Args.filtered_end(); it != ie; ++it) { - const char *Loc = it->getValue(Args); - ParsedSourceLocation PSL = ParsedSourceLocation::FromString(Loc); - - if (PSL.FileName.empty()) { - Diags.Report(diag::err_drv_invalid_value) << it->getAsString(Args) << Loc; - continue; - } - - Opts.FixItLocations.push_back(PSL); - } - Opts.OutputFile = getLastArgValue(Args, OPT_o); Opts.Plugins = getAllArgValues(Args, OPT_load); Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch); @@ -946,6 +982,7 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ViewClassInheritance = getLastArgValue(Args, OPT_cxx_inheritance_view); Opts.ASTMergeFiles = getAllArgValues(Args, OPT_ast_merge); + Opts.LLVMArgs = getAllArgValues(Args, OPT_mllvm); FrontendOptions::InputKind DashX = FrontendOptions::IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { @@ -1129,6 +1166,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, // OpenCL and C++ both have bool, true, false keywords. Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension + // keywords. This behavior is provided by GCC's poorly named '-fasm' flag, + // while a subset (the non-C++ GNU keywords) is provided by GCC's + // '-fgnu-keywords'. Clang conflates the two for simplicity under the single + // name, as it doesn't seem a useful distinction. + Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords, + Opts.GNUMode); + if (Opts.CPlusPlus) Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); @@ -1139,6 +1184,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, if (Args.hasArg(OPT_print_ivar_layout)) Opts.ObjCGCBitmapPrint = 1; + if (Args.hasArg(OPT_fno_constant_cfstrings)) + Opts.NoConstantCFStrings = 1; if (Args.hasArg(OPT_faltivec)) Opts.AltiVec = 1; @@ -1186,10 +1233,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); - Opts.AccessControl = Args.hasArg(OPT_faccess_control); + Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); Opts.MathErrno = Args.hasArg(OPT_fmath_errno); - Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99, + Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 1024, Diags); Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); Opts.ObjCConstantStringClass = getLastArgValue(Args, @@ -1203,7 +1250,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); Opts.Static = Args.hasArg(OPT_static_define); - Opts.DumpVtableLayouts = Args.hasArg(OPT_fdump_vtable_layouts); + Opts.DumpRecordLayouts = Args.hasArg(OPT_fdump_record_layouts); + Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts); + Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align); Opts.OptimizeSize = 0; // FIXME: Eliminate this dependency. @@ -1268,6 +1317,10 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.Includes.push_back(it->getValue(Args)); } + // Include 'altivec.h' if -faltivec option present + if (Args.hasArg(OPT_faltivec)) + Opts.Includes.push_back("altivec.h"); + for (arg_iterator it = Args.filtered_begin(OPT_remap_file), ie = Args.filtered_end(); it != ie; ++it) { std::pair<llvm::StringRef,llvm::StringRef> Split = diff --git a/lib/Frontend/FixItRewriter.cpp b/lib/Frontend/FixItRewriter.cpp index 20d452e76a64..7c9a566b6f7f 100644 --- a/lib/Frontend/FixItRewriter.cpp +++ b/lib/Frontend/FixItRewriter.cpp @@ -14,6 +14,8 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/FixItRewriter.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/Support/raw_ostream.h" @@ -24,8 +26,12 @@ using namespace clang; FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, - const LangOptions &LangOpts) - : Diags(Diags), Rewrite(SourceMgr, LangOpts), NumFailures(0) { + const LangOptions &LangOpts, + FixItPathRewriter *PathRewriter) + : Diags(Diags), + Rewrite(SourceMgr, LangOpts), + PathRewriter(PathRewriter), + NumFailures(0) { Client = Diags.getClient(); Diags.setClient(this); } @@ -34,92 +40,53 @@ FixItRewriter::~FixItRewriter() { Diags.setClient(Client); } -bool FixItRewriter::WriteFixedFile(const std::string &InFileName, - const std::string &OutFileName) { +bool FixItRewriter::WriteFixedFile(FileID ID, llvm::raw_ostream &OS) { + const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(ID); + if (!RewriteBuf) return true; + RewriteBuf->write(OS); + OS.flush(); + return false; +} + +bool FixItRewriter::WriteFixedFiles() { if (NumFailures > 0) { Diag(FullSourceLoc(), diag::warn_fixit_no_changes); return true; } - llvm::OwningPtr<llvm::raw_ostream> OwnedStream; - llvm::raw_ostream *OutFile; - if (!OutFileName.empty()) { - std::string Err; - OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), Err, - llvm::raw_fd_ostream::F_Binary); - OwnedStream.reset(OutFile); - } else if (InFileName == "-") { - OutFile = &llvm::outs(); - } else { - llvm::sys::Path Path(InFileName); - std::string Suffix = Path.getSuffix(); - Path.eraseSuffix(); - Path.appendSuffix("fixit." + Suffix); + for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { + const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first); + std::string Filename = Entry->getName(); + if (PathRewriter) + Filename = PathRewriter->RewriteFilename(Filename); std::string Err; - OutFile = new llvm::raw_fd_ostream(Path.c_str(), Err, - llvm::raw_fd_ostream::F_Binary); - OwnedStream.reset(OutFile); - } - - FileID MainFileID = Rewrite.getSourceMgr().getMainFileID(); - if (const RewriteBuffer *RewriteBuf = - Rewrite.getRewriteBufferFor(MainFileID)) { - *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); - } else { - Diag(FullSourceLoc(), diag::note_fixit_main_file_unchanged); + llvm::raw_fd_ostream OS(Filename.c_str(), Err, + llvm::raw_fd_ostream::F_Binary); + if (!Err.empty()) { + Diags.Report(clang::diag::err_fe_unable_to_open_output) + << Filename << Err; + continue; + } + RewriteBuffer &RewriteBuf = I->second; + RewriteBuf.write(OS); + OS.flush(); } - OutFile->flush(); return false; } bool FixItRewriter::IncludeInDiagnosticCounts() const { - return Client? Client->IncludeInDiagnosticCounts() : true; + return Client ? Client->IncludeInDiagnosticCounts() : true; } void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info) { Client->HandleDiagnostic(DiagLevel, Info); - // Skip over any diagnostics that are ignored. - if (DiagLevel == Diagnostic::Ignored) + // Skip over any diagnostics that are ignored or notes. + if (DiagLevel <= Diagnostic::Note) return; - if (!FixItLocations.empty()) { - // The user has specified the locations where we should perform - // the various fix-it modifications. - - // If this diagnostic does not have any code modifications, - // completely ignore it, even if it's an error: fix-it locations - // are meant to perform specific fix-ups even in the presence of - // other errors. - if (Info.getNumFixItHints() == 0) - return; - - // See if the location of the error is one that matches what the - // user requested. - bool AcceptableLocation = false; - const FileEntry *File - = Rewrite.getSourceMgr().getFileEntryForID( - Info.getLocation().getFileID()); - unsigned Line = Info.getLocation().getSpellingLineNumber(); - unsigned Column = Info.getLocation().getSpellingColumnNumber(); - for (llvm::SmallVector<RequestedSourceLocation, 4>::iterator - Loc = FixItLocations.begin(), LocEnd = FixItLocations.end(); - Loc != LocEnd; ++Loc) { - if (Loc->File == File && Loc->Line == Line && Loc->Column == Column) { - AcceptableLocation = true; - break; - } - } - - if (!AcceptableLocation) - return; - } else if (DiagLevel == Diagnostic::Note) { - // Don't apply fix-it modifications in notes. - return; - } - // Make sure that we can perform all of the modifications we // in this diagnostic. bool CanRewrite = Info.getNumFixItHints() > 0; @@ -196,3 +163,5 @@ void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) { Diags.Report(Loc, DiagID); Diags.setClient(this); } + +FixItPathRewriter::~FixItPathRewriter() {} diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 251b8e4cb738..6cd960be20d5 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -19,6 +19,7 @@ #include "clang/Frontend/FixItRewriter.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -74,11 +75,6 @@ ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, return CreateDeclContextPrinter(); } -ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile) { - return CreateRecordLayoutDumper(); -} - ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) { const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; @@ -118,43 +114,38 @@ ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, return new ASTConsumer(); } -/// AddFixItLocations - Add any individual user specified "fix-it" locations, -/// and return true on success. -static bool AddFixItLocations(CompilerInstance &CI, - FixItRewriter &FixItRewrite) { - const std::vector<ParsedSourceLocation> &Locs = - CI.getFrontendOpts().FixItLocations; - for (unsigned i = 0, e = Locs.size(); i != e; ++i) { - const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName); - if (!File) { - CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file) - << Locs[i].FileName; - return false; - } - - RequestedSourceLocation Requested; - Requested.File = File; - Requested.Line = Locs[i].Line; - Requested.Column = Locs[i].Column; - FixItRewrite.addFixItLocation(Requested); - } +class FixItActionSuffixInserter : public FixItPathRewriter { + std::string NewSuffix; - return true; -} +public: + explicit FixItActionSuffixInserter(std::string NewSuffix) + : NewSuffix(NewSuffix) {} + + std::string RewriteFilename(const std::string &Filename) { + llvm::sys::Path Path(Filename); + std::string Suffix = Path.getSuffix(); + Path.eraseSuffix(); + Path.appendSuffix(NewSuffix + "." + Suffix); + return Path.c_str(); + } +}; bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, llvm::StringRef Filename) { + const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); + if (!FEOpts.FixItSuffix.empty()) { + PathRewriter.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix)); + } else { + PathRewriter.reset(); + } Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), - CI.getLangOpts())); - if (!AddFixItLocations(CI, *Rewriter)) - return false; - + CI.getLangOpts(), PathRewriter.get())); return true; } void FixItAction::EndSourceFileAction() { - const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); - Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile); + // Otherwise rewrite all files. + Rewriter->WriteFixedFiles(); } ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, @@ -197,8 +188,7 @@ void DumpTokensAction::ExecuteAction() { Preprocessor &PP = getCompilerInstance().getPreprocessor(); // Start preprocessing the specified input file. Token Tok; - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); do { PP.Lex(Tok); PP.DumpToken(Tok, true); @@ -212,7 +202,7 @@ void GeneratePTHAction::ExecuteAction() { CI.getFrontendOpts().OutputFile == "-") { // FIXME: Don't fail this way. // FIXME: Verify that we can actually seek in the given file. - llvm::llvm_report_error("PTH requires a seekable file for output!"); + llvm::report_fatal_error("PTH requires a seekable file for output!"); } llvm::raw_fd_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); @@ -226,8 +216,7 @@ void ParseOnlyAction::ExecuteAction() { llvm::OwningPtr<Action> PA(new MinimalAction(PP)); Parser P(PP, *PA); - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); P.ParseTranslationUnit(); } @@ -236,8 +225,7 @@ void PreprocessOnlyAction::ExecuteAction() { Token Tok; // Start parsing the specified input file. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); @@ -252,8 +240,7 @@ void PrintParseAction::ExecuteAction() { llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS)); Parser P(PP, *PA); - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); P.ParseTranslationUnit(); } diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 9f5bced0d485..12a4d4dbd094 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -355,7 +355,7 @@ static bool getVisualStudioDir(std::string &path) { else if (vs80comntools) vscomntools = vs80comntools; if (vscomntools && *vscomntools) { - char *p = (char*)strstr(vscomntools, "\\Common7\\Tools"); + char *p = const_cast<char *>(strstr(vscomntools, "\\Common7\\Tools")); if (p) *p = '\0'; path = vscomntools; @@ -429,6 +429,49 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) { } } break; + case llvm::Triple::Haiku: + AddPath("/boot/common/include", System, true, false, false); + AddPath("/boot/develop/headers/os", System, true, false, false); + AddPath("/boot/develop/headers/os/app", System, true, false, false); + AddPath("/boot/develop/headers/os/arch", System, true, false, false); + AddPath("/boot/develop/headers/os/device", System, true, false, false); + AddPath("/boot/develop/headers/os/drivers", System, true, false, false); + AddPath("/boot/develop/headers/os/game", System, true, false, false); + AddPath("/boot/develop/headers/os/interface", System, true, false, false); + AddPath("/boot/develop/headers/os/kernel", System, true, false, false); + AddPath("/boot/develop/headers/os/locale", System, true, false, false); + AddPath("/boot/develop/headers/os/mail", System, true, false, false); + AddPath("/boot/develop/headers/os/media", System, true, false, false); + AddPath("/boot/develop/headers/os/midi", System, true, false, false); + AddPath("/boot/develop/headers/os/midi2", System, true, false, false); + AddPath("/boot/develop/headers/os/net", System, true, false, false); + AddPath("/boot/develop/headers/os/storage", System, true, false, false); + AddPath("/boot/develop/headers/os/support", System, true, false, false); + AddPath("/boot/develop/headers/os/translation", + System, true, false, false); + AddPath("/boot/develop/headers/os/add-ons/graphics", + System, true, false, false); + AddPath("/boot/develop/headers/os/add-ons/input_server", + System, true, false, false); + AddPath("/boot/develop/headers/os/add-ons/screen_saver", + System, true, false, false); + AddPath("/boot/develop/headers/os/add-ons/tracker", + System, true, false, false); + AddPath("/boot/develop/headers/os/be_apps/Deskbar", + System, true, false, false); + AddPath("/boot/develop/headers/os/be_apps/NetPositive", + System, true, false, false); + AddPath("/boot/develop/headers/os/be_apps/Tracker", + System, true, false, false); + AddPath("/boot/develop/headers/cpp", System, true, false, false); + AddPath("/boot/develop/headers/cpp/i586-pc-haiku", + System, true, false, false); + AddPath("/boot/develop/headers/3rdparty", System, true, false, false); + AddPath("/boot/develop/headers/bsd", System, true, false, false); + AddPath("/boot/develop/headers/glibc", System, true, false, false); + AddPath("/boot/develop/headers/posix", System, true, false, false); + AddPath("/boot/develop/headers", System, true, false, false); + break; case llvm::Triple::MinGW64: case llvm::Triple::MinGW32: AddPath("c:/mingw/include", System, true, false, false); @@ -521,14 +564,26 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1", "i586-redhat-linux","", "", triple); + // Fedora 11 x86_64 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1", + "x86_64-redhat-linux", "32", "", triple); + // Fedora 12 AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", "i686-redhat-linux","", "", triple); + // Fedora 12 x86_64 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", + "x86_64-redhat-linux", "32", "", triple); + // Fedora 12 (February-2010+) AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3", "i686-redhat-linux","", "", triple); - + + // Fedora 12 (February-2010+) x86_64 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3", + "x86_64-redhat-linux", "32", "", triple); + // openSUSE 11.1 32 bit AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", "i586-suse-linux", "", "", triple); diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 8bcd3a83c00e..f1e9819d83ca 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/Version.h" #include "clang/Frontend/Utils.h" #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetInfo.h" @@ -212,7 +213,20 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // Compiler version introspection macros. Builder.defineMacro("__llvm__"); // LLVM Backend Builder.defineMacro("__clang__"); // Clang Frontend - +#define TOSTR2(X) #X +#define TOSTR(X) TOSTR2(X) + Builder.defineMacro("__clang_major__", TOSTR(CLANG_VERSION_MAJOR)); + Builder.defineMacro("__clang_minor__", TOSTR(CLANG_VERSION_MINOR)); +#ifdef CLANG_VERSION_PATCHLEVEL + Builder.defineMacro("__clang_patchlevel__", TOSTR(CLANG_VERSION_PATCHLEVEL)); +#else + Builder.defineMacro("__clang_patchlevel__", "0"); +#endif + Builder.defineMacro("__clang_version__", + "\"" CLANG_VERSION_STRING " (" + + getClangFullRepositoryVersion() + ")\""); +#undef TOSTR +#undef TOSTR2 // Currently claim to be compatible with GCC 4.2.1-5621. Builder.defineMacro("__GNUC_MINOR__", "2"); Builder.defineMacro("__GNUC_PATCHLEVEL__", "1"); @@ -294,8 +308,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // C++ translation unit. Builder.defineMacro("__cplusplus", "199711L"); Builder.defineMacro("__private_extern__", "extern"); - // Ugly hack to work with GNU libstdc++. - Builder.defineMacro("_GNU_SOURCE"); } if (LangOpts.Microsoft) { @@ -503,7 +515,11 @@ void clang::InitializePreprocessor(Preprocessor &PP, InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(), PP.getFileManager(), InitOpts); - Builder.append("# 1 \"<built-in>\" 3"); + // Emit line markers for various builtin sections of the file. We don't do + // this in asm preprocessor mode, because "# 4" is not a line marker directive + // in this mode. + if (!PP.getLangOptions().AsmPreprocessor) + Builder.append("# 1 \"<built-in>\" 3"); // Install things like __POWERPC__, __GNUC__, etc into the macro table. if (InitOpts.UsePredefines) @@ -512,7 +528,8 @@ void clang::InitializePreprocessor(Preprocessor &PP, // Add on the predefines from the driver. Wrap in a #line directive to report // that they come from the command line. - Builder.append("# 1 \"<command line>\" 1"); + if (!PP.getLangOptions().AsmPreprocessor) + Builder.append("# 1 \"<command line>\" 1"); // Process #define's and #undef's in the order they are given. for (unsigned i = 0, e = InitOpts.Macros.size(); i != e; ++i) { @@ -538,7 +555,8 @@ void clang::InitializePreprocessor(Preprocessor &PP, } // Exit the command line and go back to <built-in> (2 is LC_LEAVE). - Builder.append("# 1 \"<built-in>\" 2"); + if (!PP.getLangOptions().AsmPreprocessor) + Builder.append("# 1 \"<built-in>\" 2"); // Copy PredefinedBuffer into the Preprocessor. PP.setPredefines(Predefines.str()); diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp index ed0ea1f45ef6..af1721d0f9ec 100644 --- a/lib/Frontend/LangStandards.cpp +++ b/lib/Frontend/LangStandards.cpp @@ -22,7 +22,7 @@ const LangStandard &LangStandard::getLangStandardForKind(Kind K) { default: llvm_unreachable("Invalid language kind!"); case lang_unspecified: - llvm::llvm_report_error("getLangStandardForKind() on unspecified kind"); + llvm::report_fatal_error("getLangStandardForKind() on unspecified kind"); #define LANGSTANDARD(id, name, desc, features) \ case lang_##id: return Lang_##id; #include "clang/Frontend/LangStandards.def" diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index b96c04d0a8e0..ae57ce581def 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -62,6 +62,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_BENIGN(DollarIdents); PARSE_LANGOPT_BENIGN(AsmPreprocessor); PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions); + PARSE_LANGOPT_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords); PARSE_LANGOPT_BENIGN(ImplicitInt); PARSE_LANGOPT_BENIGN(Digraphs); PARSE_LANGOPT_BENIGN(HexFloats); @@ -74,6 +75,8 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2); + PARSE_LANGOPT_IMPORTANT(NoConstantCFStrings, + diag::warn_pch_no_constant_cfstrings); PARSE_LANGOPT_BENIGN(PascalStrings); PARSE_LANGOPT_BENIGN(WritableStrings); PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, @@ -910,8 +913,14 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { return Failure; } - if ((off_t)Record[4] != File->getSize() || - (time_t)Record[5] != File->getModificationTime()) { + if ((off_t)Record[4] != File->getSize() +#if !defined(LLVM_ON_WIN32) + // In our regression testing, the Windows file system seems to + // have inconsistent modification times that sometimes + // erroneously trigger this error-handling path. + || (time_t)Record[5] != File->getModificationTime() +#endif + ) { Diag(diag::err_fe_pch_file_modified) << Filename; return Failure; @@ -1757,17 +1766,16 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { if (unsigned ObjCClassRedef = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); -#if 0 - // FIXME. Accommodate for this in several PCH/Index tests - if (unsigned ObjCSelRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) - Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); -#endif if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) Context->setBlockDescriptorType(GetType(String)); if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR]) Context->setBlockDescriptorExtendedType(GetType(String)); + if (unsigned ObjCSelRedef + = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) + Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); + if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_NS_CONSTANT_STRING]) + Context->setNSConstantStringType(GetType(String)); } /// \brief Retrieve the name of the original source file name @@ -1879,6 +1887,7 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(DollarIdents); PARSE_LANGOPT(AsmPreprocessor); PARSE_LANGOPT(GNUMode); + PARSE_LANGOPT(GNUKeywords); PARSE_LANGOPT(ImplicitInt); PARSE_LANGOPT(Digraphs); PARSE_LANGOPT(HexFloats); @@ -1891,6 +1900,7 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(ObjC2); PARSE_LANGOPT(ObjCNonFragileABI); PARSE_LANGOPT(ObjCNonFragileABI2); + PARSE_LANGOPT(NoConstantCFStrings); PARSE_LANGOPT(PascalStrings); PARSE_LANGOPT(WritableStrings); PARSE_LANGOPT(LaxVectorConversions); @@ -2843,6 +2853,14 @@ Selector PCHReader::DecodeSelector(unsigned ID) { return SelectorsLoaded[Index]; } +Selector PCHReader::GetSelector(uint32_t ID) { + return DecodeSelector(ID); +} + +uint32_t PCHReader::GetNumKnownSelectors() { + return TotalNumSelectors + 1; +} + DeclarationName PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index f847becb15b8..14dd2e927c41 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -179,6 +179,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->setPreviousDeclaration( cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); + FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]); FD->setInlineSpecified(Record[Idx++]); FD->setVirtualAsWritten(Record[Idx++]); FD->setPure(Record[Idx++]); @@ -196,6 +197,11 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); FD->setParams(Params.data(), NumParams); + + // FIXME: order this properly w.r.t. friendness + // FIXME: this same thing needs to happen for function templates + if (FD->isOverloadedOperator() && !FD->getDeclContext()->isRecord()) + FD->setNonMemberOperator(); } void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { @@ -212,6 +218,7 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { MD->setSynthesized(Record[Idx++]); MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); + MD->setNumSelectorArgs(unsigned(Record[Idx++])); MD->setResultType(Reader.GetType(Record[Idx++])); MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -220,7 +227,8 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams); + MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams, + NumParams); } void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { @@ -375,6 +383,7 @@ void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); D->setSuperClass( cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); + // FIXME. Add reading of IvarInitializers and NumIvarInitializers. } @@ -397,9 +406,11 @@ void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { void PCHDeclReader::VisitVarDecl(VarDecl *VD) { VisitDeclaratorDecl(VD); VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]); + VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]); VD->setThreadSpecified(Record[Idx++]); VD->setCXXDirectInitializer(Record[Idx++]); VD->setDeclaredInCondition(Record[Idx++]); + VD->setExceptionVariable(Record[Idx++]); VD->setPreviousDeclaration( cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); if (Record[Idx++]) @@ -744,7 +755,7 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { break; case pch::DECL_VAR: D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - VarDecl::None); + VarDecl::None, VarDecl::None); break; case pch::DECL_IMPLICIT_PARAM: @@ -753,7 +764,7 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { case pch::DECL_PARM_VAR: D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, - VarDecl::None, 0); + VarDecl::None, VarDecl::None, 0); break; case pch::DECL_FILE_SCOPE_ASM: D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 7b94805d3999..ef6b77026d7f 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -71,6 +71,7 @@ namespace { unsigned VisitCharacterLiteral(CharacterLiteral *E); unsigned VisitParenExpr(ParenExpr *E); unsigned VisitUnaryOperator(UnaryOperator *E); + unsigned VisitOffsetOfExpr(OffsetOfExpr *E); unsigned VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); unsigned VisitArraySubscriptExpr(ArraySubscriptExpr *E); unsigned VisitCallExpr(CallExpr *E); @@ -432,6 +433,49 @@ unsigned PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) { return 1; } +unsigned PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) { + typedef OffsetOfExpr::OffsetOfNode Node; + VisitExpr(E); + assert(E->getNumComponents() == Record[Idx]); + ++Idx; + assert(E->getNumExpressions() == Record[Idx]); + ++Idx; + E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); + for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { + Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]); + SourceLocation Start = SourceLocation::getFromRawEncoding(Record[Idx++]); + SourceLocation End = SourceLocation::getFromRawEncoding(Record[Idx++]); + switch (Kind) { + case Node::Array: + E->setComponent(I, Node(Start, Record[Idx++], End)); + break; + + case Node::Field: + E->setComponent(I, + Node(Start, + dyn_cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++])), + End)); + break; + + case Node::Identifier: + E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End)); + break; + + case Node::Base: + // FIXME: Implement this! + llvm_unreachable("PCH for offsetof(base-specifier) not implemented"); + break; + } + } + + for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) + E->setIndexExpr(I, cast_or_null<Expr>(StmtStack[StmtStack.size() - N + I])); + + return E->getNumExpressions(); +} + unsigned PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { VisitExpr(E); E->setSizeof(Record[Idx++]); @@ -554,9 +598,9 @@ unsigned PCHStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { unsigned PCHStmtReader::VisitInitListExpr(InitListExpr *E) { VisitExpr(E); unsigned NumInits = Record[Idx++]; - E->reserveInits(NumInits); + E->reserveInits(*Reader.getContext(), NumInits); for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(I, + E->updateInit(*Reader.getContext(), I, cast<Expr>(StmtStack[StmtStack.size() - NumInits - 1 + I])); E->setSyntacticForm(cast_or_null<InitListExpr>(StmtStack.back())); E->setLBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -725,7 +769,7 @@ unsigned PCHStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) { unsigned PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { VisitExpr(E); - E->setEncodedType(Reader.GetType(Record[Idx++])); + E->setEncodedTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); return 0; @@ -782,25 +826,42 @@ unsigned PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr( unsigned PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { VisitExpr(E); - E->setNumArgs(Record[Idx++]); - E->setLeftLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - E->setSelector(Reader.GetSelector(Record, Idx)); - E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - - E->setReceiver( + assert(Record[Idx] == E->getNumArgs()); + ++Idx; + ObjCMessageExpr::ReceiverKind Kind + = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]); + switch (Kind) { + case ObjCMessageExpr::Instance: + E->setInstanceReceiver( cast_or_null<Expr>(StmtStack[StmtStack.size() - E->getNumArgs() - 1])); - if (!E->getReceiver()) { - ObjCMessageExpr::ClassInfo CI; - CI.Decl = cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])); - CI.Name = Reader.GetIdentifierInfo(Record, Idx); - CI.Loc = SourceLocation::getFromRawEncoding(Record[Idx++]); - E->setClassInfo(CI); + break; + + case ObjCMessageExpr::Class: + E->setClassReceiver(Reader.GetTypeSourceInfo(Record, Idx)); + break; + + case ObjCMessageExpr::SuperClass: + case ObjCMessageExpr::SuperInstance: { + QualType T = Reader.GetType(Record[Idx++]); + SourceLocation SuperLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); + E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance); + break; } + } + + assert(Kind == E->getReceiverKind()); + + if (Record[Idx++]) + E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); + else + E->setSelector(Reader.GetSelector(Record, Idx)); + + E->setLeftLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) E->setArg(I, cast<Expr>(StmtStack[StmtStack.size() - N + I])); - return E->getNumArgs() + 1; + return E->getNumArgs() + (Kind == ObjCMessageExpr::Instance); } unsigned PCHStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) { @@ -821,12 +882,11 @@ unsigned PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { unsigned PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { VisitStmt(S); - S->setCatchBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2])); - S->setNextCatchStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1])); - S->setCatchParamDecl(cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); + S->setCatchBody(cast_or_null<Stmt>(StmtStack.back())); + S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); S->setAtCatchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - return 2; + return 1; } unsigned PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { @@ -838,11 +898,21 @@ unsigned PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { unsigned PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { VisitStmt(S); - S->setTryBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 3])); - S->setCatchStmts(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2])); - S->setFinallyStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1])); + assert(Record[Idx] == S->getNumCatchStmts()); + ++Idx; + bool HasFinally = Record[Idx++]; + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { + unsigned Offset = StmtStack.size() - N - HasFinally + I; + S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(StmtStack[Offset])); + } + + unsigned TryOffset + = StmtStack.size() - S->getNumCatchStmts() - HasFinally - 1; + S->setTryBody(cast_or_null<Stmt>(StmtStack[TryOffset])); + if (HasFinally) + S->setFinallyStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1])); S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - return 3; + return 1 + S->getNumCatchStmts() + HasFinally; } unsigned PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { @@ -1079,6 +1149,12 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) UnaryOperator(Empty); break; + case pch::EXPR_OFFSETOF: + S = OffsetOfExpr::CreateEmpty(*Context, + Record[PCHStmtReader::NumExprFields], + Record[PCHStmtReader::NumExprFields + 1]); + break; + case pch::EXPR_SIZEOF_ALIGN_OF: S = new (Context) SizeOfAlignOfExpr(Empty); break; @@ -1124,7 +1200,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { break; case pch::EXPR_INIT_LIST: - S = new (Context) InitListExpr(Empty); + S = new (Context) InitListExpr(*getContext(), Empty); break; case pch::EXPR_DESIGNATED_INIT: @@ -1195,7 +1271,8 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty); break; case pch::EXPR_OBJC_MESSAGE_EXPR: - S = new (Context) ObjCMessageExpr(Empty); + S = ObjCMessageExpr::CreateEmpty(*Context, + Record[PCHStmtReader::NumExprFields]); break; case pch::EXPR_OBJC_SUPER_EXPR: S = new (Context) ObjCSuperExpr(Empty); @@ -1213,7 +1290,9 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) ObjCAtFinallyStmt(Empty); break; case pch::STMT_OBJC_AT_TRY: - S = new (Context) ObjCAtTryStmt(Empty); + S = ObjCAtTryStmt::CreateEmpty(*Context, + Record[PCHStmtReader::NumStmtFields], + Record[PCHStmtReader::NumStmtFields + 1]); break; case pch::STMT_OBJC_AT_SYNCHRONIZED: S = new (Context) ObjCAtSynchronizedStmt(Empty); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 4dd8dc36b760..e56dd3132224 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1,4 +1,4 @@ -//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===// +//===--- PCHWriter.cpp - Precompiled Headers Writer -----------------------===// // // The LLVM Compiler Infrastructure // @@ -63,6 +63,7 @@ namespace { #define ABSTRACT_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" + void VisitInjectedClassNameType(const InjectedClassNameType *T); }; } @@ -240,7 +241,7 @@ void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) { void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { Writer.AddDeclRef(T->getDecl(), Record); - Writer.AddTypeRef(T->getUnderlyingType(), Record); + Writer.AddTypeRef(T->getInjectedSpecializationType(), Record); Code = pch::TYPE_INJECTED_CLASS_NAME; } @@ -745,6 +746,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.DollarIdents); // '$' allowed in identifiers. Record.push_back(LangOpts.AsmPreprocessor); // Preprocessor in asm mode. Record.push_back(LangOpts.GNUMode); // True in gnu99 mode false in c99 mode (etc) + Record.push_back(LangOpts.GNUKeywords); // Allow GNU-extension keywords Record.push_back(LangOpts.ImplicitInt); // C89 implicit 'int'. Record.push_back(LangOpts.Digraphs); // C94, C99 and C++ Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants. @@ -760,6 +762,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { // modern abi enabled. Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced // modern abi enabled. + Record.push_back(LangOpts.NoConstantCFStrings); // non cfstring generation enabled.. Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings Record.push_back(LangOpts.WritableStrings); // Allow writable strings @@ -1103,7 +1106,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // that is required by llvm::MemoryBuffer::getMemBuffer (on // the reader side). const llvm::MemoryBuffer *Buffer - = Content->getBuffer(PP.getDiagnostics()); + = Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager()); const char *Name = Buffer->getBufferIdentifier(); Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, llvm::StringRef(Name, strlen(Name) + 1)); @@ -2093,12 +2096,10 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.getsigjmp_bufType(), Record); AddTypeRef(Context.ObjCIdRedefinitionType, Record); AddTypeRef(Context.ObjCClassRedefinitionType, Record); -#if 0 - // FIXME. Accommodate for this in several PCH/Indexer tests - AddTypeRef(Context.ObjCSelRedefinitionType, Record); -#endif AddTypeRef(Context.getRawBlockdescriptorType(), Record); AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record); + AddTypeRef(Context.ObjCSelRedefinitionType, Record); + AddTypeRef(Context.getRawNSConstantStringType(), Record); Stream.EmitRecord(pch::SPECIAL_TYPES, Record); // Keep writing types and declarations until all types and diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 7917280295ad..7b7806239604 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -176,6 +176,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Writer.AddStmt(D->getBody()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getStorageClass()); // FIXME: stable encoding + Record.push_back(D->getStorageClassAsWritten()); Record.push_back(D->isInlineSpecified()); Record.push_back(D->isVirtualAsWritten()); Record.push_back(D->isPure()); @@ -211,6 +212,7 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Record.push_back(D->getImplementationControl()); // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway Record.push_back(D->getObjCDeclQualifier()); + Record.push_back(D->getNumSelectorArgs()); Writer.AddTypeRef(D->getResultType(), Record); Writer.AddTypeSourceInfo(D->getResultTypeSourceInfo(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); @@ -359,6 +361,7 @@ void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { VisitObjCImplDecl(D); Writer.AddDeclRef(D->getSuperClass(), Record); + // FIXME add writing of IvarInitializers and NumIvarInitializers. Code = pch::DECL_OBJC_IMPLEMENTATION; } @@ -382,9 +385,11 @@ void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { void PCHDeclWriter::VisitVarDecl(VarDecl *D) { VisitDeclaratorDecl(D); Record.push_back(D->getStorageClass()); // FIXME: stable encoding + Record.push_back(D->getStorageClassAsWritten()); Record.push_back(D->isThreadSpecified()); Record.push_back(D->hasCXXDirectInitializer()); Record.push_back(D->isDeclaredInCondition()); + Record.push_back(D->isExceptionVariable()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getInit()? 1 : 0); if (D->getInit()) @@ -425,6 +430,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread"); assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition"); + assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl"); assert(D->getInit() == 0 && "PARM_VAR_DECL never has init"); } @@ -493,9 +499,11 @@ void PCHWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // StorageClass + Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition + Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl Abv->Add(BitCodeAbbrevOp(0)); // HasInit // ParmVarDecl @@ -608,7 +616,7 @@ void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) { if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); if (!W.Code) - llvm::llvm_report_error(llvm::StringRef("unexpected declaration kind '") + + llvm::report_fatal_error(llvm::StringRef("unexpected declaration kind '") + D->getDeclKindName() + "'"); Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 9a5417ca6102..a1993d37f2dc 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -62,6 +62,7 @@ namespace { void VisitCharacterLiteral(CharacterLiteral *E); void VisitParenExpr(ParenExpr *E); void VisitUnaryOperator(UnaryOperator *E); + void VisitOffsetOfExpr(OffsetOfExpr *E); void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); void VisitArraySubscriptExpr(ArraySubscriptExpr *E); void VisitCallExpr(CallExpr *E); @@ -393,6 +394,42 @@ void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) { Code = pch::EXPR_UNARY_OPERATOR; } +void PCHStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) { + VisitExpr(E); + Record.push_back(E->getNumComponents()); + Record.push_back(E->getNumExpressions()); + Writer.AddSourceLocation(E->getOperatorLoc(), Record); + Writer.AddSourceLocation(E->getRParenLoc(), Record); + Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); + for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { + const OffsetOfExpr::OffsetOfNode &ON = E->getComponent(I); + Record.push_back(ON.getKind()); // FIXME: Stable encoding + Writer.AddSourceLocation(ON.getRange().getBegin(), Record); + Writer.AddSourceLocation(ON.getRange().getEnd(), Record); + switch (ON.getKind()) { + case OffsetOfExpr::OffsetOfNode::Array: + Record.push_back(ON.getArrayExprIndex()); + break; + + case OffsetOfExpr::OffsetOfNode::Field: + Writer.AddDeclRef(ON.getField(), Record); + break; + + case OffsetOfExpr::OffsetOfNode::Identifier: + Writer.AddIdentifierRef(ON.getFieldName(), Record); + break; + + case OffsetOfExpr::OffsetOfNode::Base: + // FIXME: Implement this! + llvm_unreachable("PCH for offsetof(base-specifier) not implemented"); + break; + } + } + for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I) + Writer.WriteSubStmt(E->getIndexExpr(I)); + Code = pch::EXPR_OFFSETOF; +} + void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { VisitExpr(E); Record.push_back(E->isSizeOf()); @@ -655,7 +692,7 @@ void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { VisitExpr(E); - Writer.AddTypeRef(E->getEncodedType(), Record); + Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record); Writer.AddSourceLocation(E->getAtLoc(), Record); Writer.AddSourceLocation(E->getRParenLoc(), Record); Code = pch::EXPR_OBJC_ENCODE; @@ -712,18 +749,33 @@ void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr( void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) { VisitExpr(E); Record.push_back(E->getNumArgs()); + Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding + switch (E->getReceiverKind()) { + case ObjCMessageExpr::Instance: + Writer.WriteSubStmt(E->getInstanceReceiver()); + break; + + case ObjCMessageExpr::Class: + Writer.AddTypeSourceInfo(E->getClassReceiverTypeInfo(), Record); + break; + + case ObjCMessageExpr::SuperClass: + case ObjCMessageExpr::SuperInstance: + Writer.AddTypeRef(E->getSuperType(), Record); + Writer.AddSourceLocation(E->getSuperLoc(), Record); + break; + } + + if (E->getMethodDecl()) { + Record.push_back(1); + Writer.AddDeclRef(E->getMethodDecl(), Record); + } else { + Record.push_back(0); + Writer.AddSelectorRef(E->getSelector(), Record); + } + Writer.AddSourceLocation(E->getLeftLoc(), Record); Writer.AddSourceLocation(E->getRightLoc(), Record); - Writer.AddSelectorRef(E->getSelector(), Record); - Writer.AddDeclRef(E->getMethodDecl(), Record); // optional - Writer.WriteSubStmt(E->getReceiver()); - - if (!E->getReceiver()) { - ObjCMessageExpr::ClassInfo CI = E->getClassInfo(); - Writer.AddDeclRef(CI.Decl, Record); - Writer.AddIdentifierRef(CI.Name, Record); - Writer.AddSourceLocation(CI.Loc, Record); - } for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) @@ -749,7 +801,6 @@ void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { Writer.WriteSubStmt(S->getCatchBody()); - Writer.WriteSubStmt(S->getNextCatchStmt()); Writer.AddDeclRef(S->getCatchParamDecl(), Record); Writer.AddSourceLocation(S->getAtCatchLoc(), Record); Writer.AddSourceLocation(S->getRParenLoc(), Record); @@ -763,9 +814,13 @@ void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { } void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { + Record.push_back(S->getNumCatchStmts()); + Record.push_back(S->getFinallyStmt() != 0); Writer.WriteSubStmt(S->getTryBody()); - Writer.WriteSubStmt(S->getCatchStmts()); - Writer.WriteSubStmt(S->getFinallyStmt()); + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) + Writer.WriteSubStmt(S->getCatchStmt(I)); + if (S->getFinallyStmt()) + Writer.WriteSubStmt(S->getFinallyStmt()); Writer.AddSourceLocation(S->getAtTryLoc(), Record); Code = pch::STMT_OBJC_AT_TRY; } diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index 8d64a6413304..4df5c5263c7e 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -197,7 +197,7 @@ namespace { } virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, const CXXScopeSpec &SS, + SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, MultiTemplateParamsArg TemplateParameterLists, @@ -405,8 +405,8 @@ namespace { // Objective-c statements virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, - DeclPtrTy Parm, StmtArg Body, - StmtArg CatchList) { + DeclPtrTy Parm, + StmtArg Body) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } @@ -418,7 +418,8 @@ namespace { } virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, - StmtArg Try, StmtArg Catch, + StmtArg Try, + MultiStmtArg CatchStmts, StmtArg Finally) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 02afd24c246e..b6c18b77316c 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -78,6 +78,7 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, namespace { class PrintPPOutputPPCallbacks : public PPCallbacks { Preprocessor &PP; + SourceManager &SM; TokenConcatenation ConcatInfo; public: llvm::raw_ostream &OS; @@ -94,7 +95,8 @@ private: public: PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os, bool lineMarkers, bool defines) - : PP(pp), ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers), + : PP(pp), SM(PP.getSourceManager()), + ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers), DumpDefines(defines) { CurLine = 0; CurFilename += "<uninit>"; @@ -118,9 +120,14 @@ public: bool HandleFirstTokOnLine(Token &Tok); - bool MoveToLine(SourceLocation Loc); - bool AvoidConcat(const Token &PrevTok, const Token &Tok) { - return ConcatInfo.AvoidConcat(PrevTok, Tok); + bool MoveToLine(SourceLocation Loc) { + return MoveToLine(SM.getPresumedLoc(Loc).getLine()); + } + bool MoveToLine(unsigned LineNo); + + bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, + const Token &Tok) { + return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); } void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0); @@ -166,9 +173,7 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, /// object. We can do this by emitting some number of \n's, or be emitting a /// #line directive. This returns false if already at the specified line, true /// if some newlines were emitted. -bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { - unsigned LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc); - +bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { if (DisableLineMarkers) { if (LineNo == CurLine) return false; @@ -211,27 +216,29 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, SrcMgr::CharacteristicKind NewFileType) { // Unless we are exiting a #include, make sure to skip ahead to the line the // #include directive was at. - SourceManager &SourceMgr = PP.getSourceManager(); + SourceManager &SourceMgr = SM; + + PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); + unsigned NewLine = UserLoc.getLine(); + if (Reason == PPCallbacks::EnterFile) { SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc(); if (IncludeLoc.isValid()) MoveToLine(IncludeLoc); } else if (Reason == PPCallbacks::SystemHeaderPragma) { - MoveToLine(Loc); + MoveToLine(NewLine); // TODO GCC emits the # directive for this directive on the line AFTER the // directive and emits a bunch of spaces that aren't needed. Emulate this // strange behavior. } - - Loc = SourceMgr.getInstantiationLoc(Loc); - // FIXME: Should use presumed line #! - CurLine = SourceMgr.getInstantiationLineNumber(Loc); + + CurLine = NewLine; if (DisableLineMarkers) return; CurFilename.clear(); - CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename(); + CurFilename += UserLoc.getFilename(); Lexer::Stringify(CurFilename); FileType = NewFileType; @@ -318,8 +325,7 @@ bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { // Print out space characters so that the first token on a line is // indented for easy reading. - const SourceManager &SourceMgr = PP.getSourceManager(); - unsigned ColNo = SourceMgr.getInstantiationColumnNumber(Tok.getLocation()); + unsigned ColNo = SM.getInstantiationColumnNumber(Tok.getLocation()); // This hack prevents stuff like: // #define HASH # @@ -391,6 +397,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, PrintPPOutputPPCallbacks *Callbacks, llvm::raw_ostream &OS) { char Buffer[256]; + Token PrevPrevTok; Token PrevTok; while (1) { @@ -402,7 +409,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, // useful to look at and no concatenation could happen anyway. (Callbacks->hasEmittedTokensOnThisLine() && // Don't print "-" next to "-", it would form "--". - Callbacks->AvoidConcat(PrevTok, Tok))) { + Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) { OS << ' '; } @@ -433,6 +440,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, if (Tok.is(tok::eof)) break; + PrevPrevTok = PrevTok; PrevTok = Tok; PP.Lex(Tok); } @@ -448,8 +456,7 @@ static int MacroIDCompare(const void* a, const void* b) { static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) { // -dM mode just scans and ignores all tokens in the files, then dumps out // the macro table at the end. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); Token Tok; do PP.Lex(Tok); @@ -484,8 +491,6 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, // to -C or -CC. PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); - OS->SetBufferSize(64*1024); - PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros); @@ -496,8 +501,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, PP.addPPCallbacks(Callbacks); // After we have configured the preprocessor, enter the main file. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); // Consume all of the tokens that come from the predefines buffer. Those // should not be emitted into the output and are guaranteed to be at the diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp index 4ffb2978db7a..954e8e23cac7 100644 --- a/lib/Frontend/RewriteMacros.cpp +++ b/lib/Frontend/RewriteMacros.cpp @@ -101,8 +101,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { // Get the first preprocessing token. - if (PP.EnterMainSourceFile()) - return; + PP.EnterMainSourceFile(); Token PPTok; PP.Lex(PPTok); diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index cba92987a3d6..11698325e9b1 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -444,7 +444,7 @@ namespace { CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, CastExpr::CastKind Kind, Expr *E) { TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); - return new (Ctx) CStyleCastExpr(Ty, Kind, E, TInfo, + return new (Ctx) CStyleCastExpr(Ty, Kind, E, CXXBaseSpecifierArray(), TInfo, SourceLocation(), SourceLocation()); } } @@ -640,7 +640,9 @@ void RewriteObjC::Initialize(ASTContext &context) { if (LangOpts.Microsoft) { Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; + Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. Preamble += "#define __attribute__(X)\n"; + Preamble += "#endif\n"; Preamble += "#define __weak\n"; } else { @@ -1237,11 +1239,26 @@ Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(*Context, dyn_cast<Expr>(Receiver), - PDecl->getSetterName(), PDecl->getType(), - PDecl->getSetterMethodDecl(), - SourceLocation(), SourceLocation(), - &ExprVec[0], 1); + if (isa<ObjCSuperExpr>(Receiver)) + MsgExpr = ObjCMessageExpr::Create(*Context, + PDecl->getType().getNonReferenceType(), + /*FIXME?*/SourceLocation(), + Receiver->getLocStart(), + /*IsInstanceSuper=*/true, + cast<Expr>(Receiver)->getType(), + PDecl->getSetterName(), + PDecl->getSetterMethodDecl(), + &ExprVec[0], 1, + /*FIXME:*/SourceLocation()); + else + MsgExpr = ObjCMessageExpr::Create(*Context, + PDecl->getType().getNonReferenceType(), + /*FIXME: */SourceLocation(), + cast<Expr>(Receiver), + PDecl->getSetterName(), + PDecl->getSetterMethodDecl(), + &ExprVec[0], 1, + /*FIXME:*/SourceLocation()); Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); // Now do the actual rewrite. @@ -1266,11 +1283,27 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(*Context, dyn_cast<Expr>(Receiver), - PDecl->getGetterName(), PDecl->getType(), - PDecl->getGetterMethodDecl(), - SourceLocation(), SourceLocation(), - 0, 0); + + if (isa<ObjCSuperExpr>(Receiver)) + MsgExpr = ObjCMessageExpr::Create(*Context, + PDecl->getType().getNonReferenceType(), + /*FIXME:*/SourceLocation(), + Receiver->getLocStart(), + /*IsInstanceSuper=*/true, + cast<Expr>(Receiver)->getType(), + PDecl->getGetterName(), + PDecl->getGetterMethodDecl(), + 0, 0, + /*FIXME:*/SourceLocation()); + else + MsgExpr = ObjCMessageExpr::Create(*Context, + PDecl->getType().getNonReferenceType(), + /*FIXME:*/SourceLocation(), + cast<Expr>(Receiver), + PDecl->getGetterName(), + PDecl->getGetterMethodDecl(), + 0, 0, + /*FIXME:*/SourceLocation()); Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); @@ -1828,8 +1861,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { assert((*startBuf == '}') && "bogus @try block"); SourceLocation lastCurlyLoc = startLoc; - ObjCAtCatchStmt *catchList = S->getCatchStmts(); - if (catchList) { + if (S->getNumCatchStmts()) { startLoc = startLoc.getFileLocWithOffset(1); buf = " /* @catch begin */ else {\n"; buf += " id _caught = objc_exception_extract(&_stack);\n"; @@ -1847,26 +1879,27 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } bool sawIdTypedCatch = false; Stmt *lastCatchBody = 0; - while (catchList) { - ParmVarDecl *catchDecl = catchList->getCatchParamDecl(); + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { + ObjCAtCatchStmt *Catch = S->getCatchStmt(I); + VarDecl *catchDecl = Catch->getCatchParamDecl(); - if (catchList == S->getCatchStmts()) + if (I == 0) buf = "if ("; // we are generating code for the first catch clause else buf = "else if ("; - startLoc = catchList->getLocStart(); + startLoc = Catch->getLocStart(); startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @catch location"); const char *lParenLoc = strchr(startBuf, '('); - if (catchList->hasEllipsis()) { + if (Catch->hasEllipsis()) { // Now rewrite the body... - lastCatchBody = catchList->getCatchBody(); + lastCatchBody = Catch->getCatchBody(); SourceLocation bodyLoc = lastCatchBody->getLocStart(); const char *bodyBuf = SM->getCharacterData(bodyLoc); - assert(*SM->getCharacterData(catchList->getRParenLoc()) == ')' && + assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && "bogus @catch paren location"); assert((*bodyBuf == '{') && "bogus @catch body location"); @@ -1890,8 +1923,8 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } } // Now rewrite the body... - lastCatchBody = catchList->getCatchBody(); - SourceLocation rParenLoc = catchList->getRParenLoc(); + lastCatchBody = Catch->getCatchBody(); + SourceLocation rParenLoc = Catch->getRParenLoc(); SourceLocation bodyLoc = lastCatchBody->getLocStart(); const char *bodyBuf = SM->getCharacterData(bodyLoc); const char *rParenBuf = SM->getCharacterData(rParenLoc); @@ -1904,8 +1937,6 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } else { assert(false && "@catch rewrite bug"); } - // make sure all the catch bodies get rewritten! - catchList = catchList->getNextCatchStmt(); } // Complete the catch list... if (lastCatchBody) { @@ -2054,10 +2085,10 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( // Now, we cast the reference to a pointer to the objc_msgSend type. QualType pToFunc = Context->getPointerType(msgSendType); - ImplicitCastExpr *ICE = new (Context) ImplicitCastExpr(pToFunc, - CastExpr::CK_Unknown, - DRE, - /*isLvalue=*/false); + ImplicitCastExpr *ICE = + new (Context) ImplicitCastExpr(pToFunc, CastExpr::CK_Unknown, + DRE, CXXBaseSpecifierArray(), + /*isLvalue=*/false); const FunctionType *FT = msgSendType->getAs<FunctionType>(); @@ -2267,7 +2298,8 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() { SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SelGetUidIdent, getFuncType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { @@ -2364,7 +2396,8 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() { SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); @@ -2385,7 +2418,8 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...); @@ -2409,7 +2443,8 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); @@ -2430,7 +2465,8 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthMsgSendSuperStretFunctionDecl - @@ -2456,7 +2492,8 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); @@ -2477,7 +2514,8 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), msgSendIdent, msgSendType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthGetClassFunctionDecl - id objc_getClass(const char *name); @@ -2493,7 +2531,8 @@ void RewriteObjC::SynthGetClassFunctionDecl() { GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getClassIdent, getClassType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); @@ -2508,9 +2547,12 @@ void RewriteObjC::SynthGetSuperClassFunctionDecl() { false, false, 0, 0, FunctionType::ExtInfo()); GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - getSuperClassIdent, getClassType, 0, - FunctionDecl::Extern, false); + SourceLocation(), + getSuperClassIdent, + getClassType, 0, + FunctionDecl::Extern, + FunctionDecl::None, + false); } // SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name); @@ -2526,7 +2568,8 @@ void RewriteObjC::SynthGetMetaClassFunctionDecl() { GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), getClassIdent, getClassType, 0, - FunctionDecl::Extern, false); + FunctionDecl::Extern, + FunctionDecl::None, false); } Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { @@ -2560,7 +2603,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), &Context->Idents.get(S), strType, 0, - VarDecl::Static); + VarDecl::Static, VarDecl::None); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, Context->getPointerType(DRE->getType()), @@ -2665,7 +2708,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, FunctionDecl *MsgSendStretFlavor = 0; if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { QualType resultType = mDecl->getResultType(); - if (resultType->isStructureType() || resultType->isUnionType()) + if (resultType->isRecordType()) MsgSendStretFlavor = MsgSendStretFunctionDecl; else if (resultType->isRealFloatingType()) MsgSendFlavor = MsgSendFpretFunctionDecl; @@ -2673,203 +2716,211 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // Synthesize a call to objc_msgSend(). llvm::SmallVector<Expr*, 8> MsgExprs; - IdentifierInfo *clsName = Exp->getClassName(); - - // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend(). - if (clsName) { // class message. - // FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle - // the 'super' idiom within a class method. - if (clsName->getName() == "super") { - MsgSendFlavor = MsgSendSuperFunctionDecl; - if (MsgSendStretFlavor) - MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; - assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); - - ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); - - llvm::SmallVector<Expr*, 4> InitExprs; - - // set the receiver to self, the first argument to all methods. - InitExprs.push_back( - NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), - CastExpr::CK_Unknown, - new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), - Context->getObjCIdType(), - SourceLocation())) - ); // set the 'receiver'. - - // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) - llvm::SmallVector<Expr*, 8> ClsExprs; - QualType argType = Context->getPointerType(Context->CharTy); - ClsExprs.push_back(StringLiteral::Create(*Context, - ClassDecl->getIdentifier()->getNameStart(), - ClassDecl->getIdentifier()->getLength(), - false, argType, SourceLocation())); - CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, - &ClsExprs[0], - ClsExprs.size(), - StartLoc, - EndLoc); - // (Class)objc_getClass("CurrentClass") - CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, - Context->getObjCClassType(), - CastExpr::CK_Unknown, Cls); - ClsExprs.clear(); - ClsExprs.push_back(ArgExpr); - Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, - &ClsExprs[0], ClsExprs.size(), - StartLoc, EndLoc); - - // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) - // To turn off a warning, type-cast to 'id' - InitExprs.push_back( // set 'super class', using class_getSuperclass(). - NoTypeInfoCStyleCastExpr(Context, - Context->getObjCIdType(), - CastExpr::CK_Unknown, Cls)); - // struct objc_super - QualType superType = getSuperStructType(); - Expr *SuperRep; - - if (LangOpts.Microsoft) { - SynthSuperContructorFunctionDecl(); - // Simulate a contructor call... - DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, - superType, SourceLocation()); - SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], - InitExprs.size(), - superType, SourceLocation()); - // The code for super is a little tricky to prevent collision with - // 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")) - // - SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, - Context->getPointerType(SuperRep->getType()), - SourceLocation()); - SuperRep = NoTypeInfoCStyleCastExpr(Context, - Context->getPointerType(superType), - CastExpr::CK_Unknown, SuperRep); - } else { - // (struct objc_super) { <exprs from above> } - InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(), - &InitExprs[0], InitExprs.size(), - SourceLocation()); - TypeSourceInfo *superTInfo - = Context->getTrivialTypeSourceInfo(superType); - SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, - superType, ILE, false); - // struct objc_super * - SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, - Context->getPointerType(SuperRep->getType()), - SourceLocation()); - } - MsgExprs.push_back(SuperRep); + switch (Exp->getReceiverKind()) { + case ObjCMessageExpr::SuperClass: { + MsgSendFlavor = MsgSendSuperFunctionDecl; + if (MsgSendStretFlavor) + MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; + assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); + + ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); + + llvm::SmallVector<Expr*, 4> InitExprs; + + // set the receiver to self, the first argument to all methods. + InitExprs.push_back( + NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), + CastExpr::CK_Unknown, + new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + Context->getObjCIdType(), + SourceLocation())) + ); // set the 'receiver'. + + // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) + llvm::SmallVector<Expr*, 8> ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + ClsExprs.push_back(StringLiteral::Create(*Context, + ClassDecl->getIdentifier()->getNameStart(), + ClassDecl->getIdentifier()->getLength(), + false, argType, SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, + EndLoc); + // (Class)objc_getClass("CurrentClass") + CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, + Context->getObjCClassType(), + CastExpr::CK_Unknown, Cls); + ClsExprs.clear(); + ClsExprs.push_back(ArgExpr); + Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, + &ClsExprs[0], ClsExprs.size(), + StartLoc, EndLoc); + + // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) + // To turn off a warning, type-cast to 'id' + InitExprs.push_back( // set 'super class', using class_getSuperclass(). + NoTypeInfoCStyleCastExpr(Context, + Context->getObjCIdType(), + CastExpr::CK_Unknown, Cls)); + // struct objc_super + QualType superType = getSuperStructType(); + Expr *SuperRep; + + if (LangOpts.Microsoft) { + SynthSuperContructorFunctionDecl(); + // Simulate a contructor call... + DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, + superType, SourceLocation()); + SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], + InitExprs.size(), + superType, SourceLocation()); + // The code for super is a little tricky to prevent collision with + // 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")) + // + SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, + Context->getPointerType(SuperRep->getType()), + SourceLocation()); + SuperRep = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(superType), + CastExpr::CK_Unknown, SuperRep); } else { - llvm::SmallVector<Expr*, 8> ClsExprs; - QualType argType = Context->getPointerType(Context->CharTy); - ClsExprs.push_back(StringLiteral::Create(*Context, - clsName->getNameStart(), - clsName->getLength(), - false, argType, - SourceLocation())); - CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, - &ClsExprs[0], - ClsExprs.size(), - StartLoc, EndLoc); - MsgExprs.push_back(Cls); + // (struct objc_super) { <exprs from above> } + InitListExpr *ILE = + new (Context) InitListExpr(*Context, SourceLocation(), + &InitExprs[0], InitExprs.size(), + SourceLocation()); + TypeSourceInfo *superTInfo + = Context->getTrivialTypeSourceInfo(superType); + SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, + superType, ILE, false); + // struct objc_super * + SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, + Context->getPointerType(SuperRep->getType()), + SourceLocation()); } - } else { // instance message. - Expr *recExpr = Exp->getReceiver(); - - if (isSuperReceiver(recExpr)) { - MsgSendFlavor = MsgSendSuperFunctionDecl; - if (MsgSendStretFlavor) - MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; - assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); - ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); - llvm::SmallVector<Expr*, 4> InitExprs; - - InitExprs.push_back( - NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), - CastExpr::CK_Unknown, - new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), - Context->getObjCIdType(), - SourceLocation())) - ); // set the 'receiver'. - - // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) - llvm::SmallVector<Expr*, 8> ClsExprs; - QualType argType = Context->getPointerType(Context->CharTy); - ClsExprs.push_back(StringLiteral::Create(*Context, - ClassDecl->getIdentifier()->getNameStart(), - ClassDecl->getIdentifier()->getLength(), - false, argType, SourceLocation())); - CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, - &ClsExprs[0], - ClsExprs.size(), - StartLoc, EndLoc); - // (Class)objc_getClass("CurrentClass") - CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, - Context->getObjCClassType(), - CastExpr::CK_Unknown, Cls); - ClsExprs.clear(); - ClsExprs.push_back(ArgExpr); - Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, - &ClsExprs[0], ClsExprs.size(), - StartLoc, EndLoc); - - // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) - // To turn off a warning, type-cast to 'id' - InitExprs.push_back( - // set 'super class', using class_getSuperclass(). - NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), - CastExpr::CK_Unknown, Cls)); - // struct objc_super - QualType superType = getSuperStructType(); - Expr *SuperRep; - - if (LangOpts.Microsoft) { - SynthSuperContructorFunctionDecl(); - // Simulate a contructor call... - DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, - superType, SourceLocation()); - SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], - InitExprs.size(), - superType, SourceLocation()); - // The code for super is a little tricky to prevent collision with - // 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")) - // - SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, - Context->getPointerType(SuperRep->getType()), - SourceLocation()); - SuperRep = NoTypeInfoCStyleCastExpr(Context, - Context->getPointerType(superType), - CastExpr::CK_Unknown, SuperRep); - } else { - // (struct objc_super) { <exprs from above> } - InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(), - &InitExprs[0], InitExprs.size(), - SourceLocation()); - TypeSourceInfo *superTInfo - = Context->getTrivialTypeSourceInfo(superType); - SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, - superType, ILE, false); - } - MsgExprs.push_back(SuperRep); + MsgExprs.push_back(SuperRep); + break; + } + + case ObjCMessageExpr::Class: { + llvm::SmallVector<Expr*, 8> ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + ObjCInterfaceDecl *Class + = Exp->getClassReceiver()->getAs<ObjCInterfaceType>()->getDecl(); + IdentifierInfo *clsName = Class->getIdentifier(); + ClsExprs.push_back(StringLiteral::Create(*Context, + clsName->getNameStart(), + clsName->getLength(), + false, argType, + SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, EndLoc); + MsgExprs.push_back(Cls); + break; + } + + case ObjCMessageExpr::SuperInstance:{ + MsgSendFlavor = MsgSendSuperFunctionDecl; + if (MsgSendStretFlavor) + MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; + assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); + ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); + llvm::SmallVector<Expr*, 4> InitExprs; + + InitExprs.push_back( + NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), + CastExpr::CK_Unknown, + new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + Context->getObjCIdType(), + SourceLocation())) + ); // set the 'receiver'. + + // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) + llvm::SmallVector<Expr*, 8> ClsExprs; + QualType argType = Context->getPointerType(Context->CharTy); + ClsExprs.push_back(StringLiteral::Create(*Context, + ClassDecl->getIdentifier()->getNameStart(), + ClassDecl->getIdentifier()->getLength(), + false, argType, SourceLocation())); + CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, + &ClsExprs[0], + ClsExprs.size(), + StartLoc, EndLoc); + // (Class)objc_getClass("CurrentClass") + CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, + Context->getObjCClassType(), + CastExpr::CK_Unknown, Cls); + ClsExprs.clear(); + ClsExprs.push_back(ArgExpr); + Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, + &ClsExprs[0], ClsExprs.size(), + StartLoc, EndLoc); + + // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) + // To turn off a warning, type-cast to 'id' + InitExprs.push_back( + // set 'super class', using class_getSuperclass(). + NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), + CastExpr::CK_Unknown, Cls)); + // struct objc_super + QualType superType = getSuperStructType(); + Expr *SuperRep; + + if (LangOpts.Microsoft) { + SynthSuperContructorFunctionDecl(); + // Simulate a contructor call... + DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, + superType, SourceLocation()); + SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], + InitExprs.size(), + superType, SourceLocation()); + // The code for super is a little tricky to prevent collision with + // 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")) + // + SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, + Context->getPointerType(SuperRep->getType()), + SourceLocation()); + SuperRep = NoTypeInfoCStyleCastExpr(Context, + Context->getPointerType(superType), + CastExpr::CK_Unknown, SuperRep); } else { - // Remove all type-casts because it may contain objc-style types; e.g. - // Foo<Proto> *. - while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) - recExpr = CE->getSubExpr(); - recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), - CastExpr::CK_Unknown, recExpr); - MsgExprs.push_back(recExpr); + // (struct objc_super) { <exprs from above> } + InitListExpr *ILE = + new (Context) InitListExpr(*Context, SourceLocation(), + &InitExprs[0], InitExprs.size(), + SourceLocation()); + TypeSourceInfo *superTInfo + = Context->getTrivialTypeSourceInfo(superType); + SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, + superType, ILE, false); } + MsgExprs.push_back(SuperRep); + break; + } + + case ObjCMessageExpr::Instance: { + // Remove all type-casts because it may contain objc-style types; e.g. + // Foo<Proto> *. + Expr *recExpr = Exp->getInstanceReceiver(); + while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) + recExpr = CE->getSubExpr(); + recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), + CastExpr::CK_Unknown, recExpr); + MsgExprs.push_back(recExpr); + break; } + } + // Create a call to sel_registerName("selName"), it will be the 2nd argument. llvm::SmallVector<Expr*, 8> SelExprs; QualType argType = Context->getPointerType(Context->CharTy); @@ -3070,7 +3121,8 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); IdentifierInfo *ID = &Context->Idents.get(Name); VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - ID, getProtocolType(), 0, VarDecl::Extern); + ID, getProtocolType(), 0, + VarDecl::Extern, VarDecl::None); DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, Context->getPointerType(DRE->getType()), @@ -5066,8 +5118,8 @@ FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(const char *name) { IdentifierInfo *ID = &Context->Idents.get(name); QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); return FunctionDecl::Create(*Context, TUDecl,SourceLocation(), - ID, FType, 0, FunctionDecl::Extern, false, - false); + ID, FType, 0, FunctionDecl::Extern, + FunctionDecl::None, false, false); } Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, @@ -5147,7 +5199,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), &Context->Idents.get(DescData.c_str()), Context->VoidPtrTy, 0, - VarDecl::Static); + VarDecl::Static, VarDecl::None); UnaryOperator *DescRefExpr = new (Context) UnaryOperator( new (Context) DeclRefExpr(NewVD, Context->VoidPtrTy, SourceLocation()), diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index ce474d365390..21dc0ba0a188 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -125,6 +125,7 @@ namespace { void VisitFloatingLiteral(FloatingLiteral *Node); void VisitStringLiteral(StringLiteral *Str); void VisitUnaryOperator(UnaryOperator *Node); + void VisitOffsetOfExpr(OffsetOfExpr *Node); void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node); void VisitMemberExpr(MemberExpr *Node); void VisitExtVectorElementExpr(ExtVectorElementExpr *Node); @@ -308,6 +309,10 @@ void StmtXML::VisitUnaryOperator(UnaryOperator *Node) { Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode())); } +void StmtXML::OffsetOfExpr(OffsetOfExpr *Node) { + DumpExpr(Node); +} + void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { DumpExpr(Node); Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof"); diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 4e91f8d4c221..28bb17ac3efa 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -148,9 +148,16 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, std::string &FixItInsertionLine, unsigned EndOfCaretToken, unsigned Columns) { - if (CaretLine.size() > SourceLine.size()) - SourceLine.resize(CaretLine.size(), ' '); - + 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, ' '); + // Find the slice that we need to display the full caret line // correctly. unsigned CaretStart = 0, CaretEnd = CaretLine.size(); @@ -275,7 +282,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, SourceRange *Ranges, unsigned NumRanges, - SourceManager &SM, + const SourceManager &SM, const FixItHint *Hints, unsigned NumHints, unsigned Columns) { @@ -796,8 +803,13 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, OutStr += " [-W"; OutStr += Opt; OutStr += ']'; - } else if (Diagnostic::isBuiltinExtensionDiag(Info.getID())) { - OutStr += " [-pedantic]"; + } else { + // If the diagnostic is an extension diagnostic and not enabled by default + // then it must have been turned on with -pedantic. + bool EnabledByDefault; + if (Diagnostic::isBuiltinExtensionDiag(Info.getID(), EnabledByDefault) && + !EnabledByDefault) + OutStr += " [-pedantic]"; } } diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp index 99ec910be0af..ae36481444da 100644 --- a/lib/Frontend/VerifyDiagnosticsClient.cpp +++ b/lib/Frontend/VerifyDiagnosticsClient.cpp @@ -16,6 +16,7 @@ #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -71,97 +72,267 @@ bool VerifyDiagnosticsClient::HadErrors() { typedef TextDiagnosticBuffer::DiagList DiagList; typedef TextDiagnosticBuffer::const_iterator const_diag_iterator; -/// FindDiagnostics - Go through the comment and see if it indicates expected -/// diagnostics. If so, then put them in a diagnostic list. +namespace { + +/// Directive - Abstract class representing a parsed verify directive. /// -static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, - DiagList &ExpectedDiags, - Preprocessor &PP, SourceLocation Pos, - const char *ExpectedStr) { - const char *CommentEnd = CommentStart+CommentLen; - unsigned ExpectedStrLen = strlen(ExpectedStr); - - // Find all expected-foo diagnostics in the string and add them to - // ExpectedDiags. - while (CommentStart != CommentEnd) { - CommentStart = std::find(CommentStart, CommentEnd, 'e'); - if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return; - - // If this isn't expected-foo, ignore it. - if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) { - ++CommentStart; - continue; - } +class Directive { +public: + static Directive* Create(bool RegexKind, const SourceLocation &Location, + const std::string &Text, unsigned Count); +public: + SourceLocation Location; + const std::string Text; + unsigned Count; + + virtual ~Directive() { } + + // Returns true if directive text is valid. + // Otherwise returns false and populates E. + virtual bool isValid(std::string &Error) = 0; + + // Returns true on match. + virtual bool Match(const std::string &S) = 0; + +protected: + Directive(const SourceLocation &Location, const std::string &Text, + unsigned Count) + : Location(Location), Text(Text), Count(Count) { } + +private: + Directive(const Directive&); // DO NOT IMPLEMENT + void operator=(const Directive&); // DO NOT IMPLEMENT +}; + +/// StandardDirective - Directive with string matching. +/// +class StandardDirective : public Directive { +public: + StandardDirective(const SourceLocation &Location, const std::string &Text, + unsigned Count) + : Directive(Location, Text, Count) { } + + virtual bool isValid(std::string &Error) { + // all strings are considered valid; even empty ones + return true; + } + + virtual bool Match(const std::string &S) { + return S.find(Text) != std::string::npos || + Text.find(S) != std::string::npos; + } +}; + +/// RegexDirective - Directive with regular-expression matching. +/// +class RegexDirective : public Directive { +public: + RegexDirective(const SourceLocation &Location, const std::string &Text, + unsigned Count) + : Directive(Location, Text, Count), Regex(Text) { } + + virtual bool isValid(std::string &Error) { + if (Regex.isValid(Error)) + return true; + return false; + } + + virtual bool Match(const std::string &S) { + return Regex.match(S); + } - CommentStart += ExpectedStrLen; - - // Skip whitespace. - while (CommentStart != CommentEnd && - isspace(CommentStart[0])) - ++CommentStart; - - // Default, if we find the '{' now, is 1 time. - int Times = 1; - int Temp = 0; - // In extended syntax, there could be a digit now. - while (CommentStart != CommentEnd && - CommentStart[0] >= '0' && CommentStart[0] <= '9') { - Temp *= 10; - Temp += CommentStart[0] - '0'; - ++CommentStart; +private: + llvm::Regex Regex; +}; + +typedef std::vector<Directive*> DirectiveList; + +/// ExpectedData - owns directive objects and deletes on destructor. +/// +struct ExpectedData { + DirectiveList Errors; + DirectiveList Warnings; + DirectiveList Notes; + + ~ExpectedData() { + DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 }; + for (DirectiveList **PL = Lists; *PL; ++PL) { + DirectiveList * const L = *PL; + for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I) + delete *I; } - if (Temp > 0) - Times = Temp; - - // Skip whitespace again. - while (CommentStart != CommentEnd && - isspace(CommentStart[0])) - ++CommentStart; - - // We should have a {{ now. - if (CommentEnd-CommentStart < 2 || - CommentStart[0] != '{' || CommentStart[1] != '{') { - if (std::find(CommentStart, CommentEnd, '{') != CommentEnd) - PP.Diag(Pos, diag::err_verify_bogus_characters); - else - PP.Diag(Pos, diag::err_verify_missing_start); - return; + } +}; + +class ParseHelper +{ +public: + ParseHelper(const char *Begin, const char *End) + : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { } + + // Return true if string literal is next. + bool Next(const std::string &S) { + std::string::size_type LEN = S.length(); + P = C; + PEnd = C + LEN; + if (PEnd > End) + return false; + return !memcmp(P, S.c_str(), LEN); + } + + // Return true if number is next. + // Output N only if number is next. + bool Next(unsigned &N) { + unsigned TMP = 0; + P = C; + for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) { + TMP *= 10; + TMP += P[0] - '0'; } - CommentStart += 2; - - // Find the }}. - const char *ExpectedEnd = CommentStart; - while (1) { - ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}'); - if (CommentEnd-ExpectedEnd < 2) { - PP.Diag(Pos, diag::err_verify_missing_end); - return; - } + if (P == C) + return false; + PEnd = P; + N = TMP; + return true; + } + + // Return true if string literal is found. + // When true, P marks begin-position of S in content. + bool Search(const std::string &S) { + P = std::search(C, End, S.begin(), S.end()); + PEnd = P + S.length(); + return P != End; + } + + // Advance 1-past previous next/search. + // Behavior is undefined if previous next/search failed. + bool Advance() { + C = PEnd; + return C < End; + } + + // Skip zero or more whitespace. + void SkipWhitespace() { + for (; C < End && isspace(*C); ++C) + ; + } + + // Return true if EOF reached. + bool Done() { + return !(C < End); + } + + const char * const Begin; // beginning of expected content + const char * const End; // end of expected content (1-past) + const char *C; // position of next char in content + const char *P; + +private: + const char *PEnd; // previous next/search subject end (1-past) +}; + +} // namespace anonymous + +/// ParseDirective - Go through the comment and see if it indicates expected +/// diagnostics. If so, then put them in the appropriate directive list. +/// +static void ParseDirective(const char *CommentStart, unsigned CommentLen, + ExpectedData &ED, Preprocessor &PP, + SourceLocation Pos) { + // A single comment may contain multiple directives. + for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) { + // search for token: expected + if (!PH.Search("expected")) + break; + PH.Advance(); + + // next token: - + if (!PH.Next("-")) + continue; + PH.Advance(); + + // next token: { error | warning | note } + DirectiveList* DL = NULL; + if (PH.Next("error")) + DL = &ED.Errors; + else if (PH.Next("warning")) + DL = &ED.Warnings; + else if (PH.Next("note")) + DL = &ED.Notes; + else + continue; + PH.Advance(); - if (ExpectedEnd[1] == '}') - break; + // default directive kind + bool RegexKind = false; + const char* KindStr = "string"; - ++ExpectedEnd; // Skip over singular }'s + // next optional token: - + if (PH.Next("-re")) { + PH.Advance(); + RegexKind = true; + KindStr = "regex"; } - std::string Msg(CommentStart, ExpectedEnd); - std::string::size_type FindPos; - while ((FindPos = Msg.find("\\n")) != std::string::npos) - Msg.replace(FindPos, 2, "\n"); - // Add is possibly multiple times. - for (int i = 0; i < Times; ++i) - ExpectedDiags.push_back(std::make_pair(Pos, Msg)); + // skip optional whitespace + PH.SkipWhitespace(); + + // next optional token: positive integer + unsigned Count = 1; + if (PH.Next(Count)) + PH.Advance(); + + // skip optional whitespace + PH.SkipWhitespace(); + + // next token: {{ + if (!PH.Next("{{")) { + PP.Diag(Pos.getFileLocWithOffset(PH.C-PH.Begin), + diag::err_verify_missing_start) << KindStr; + continue; + } + PH.Advance(); + const char* const ContentBegin = PH.C; // mark content begin - CommentStart = ExpectedEnd; + // search for token: }} + if (!PH.Search("}}")) { + PP.Diag(Pos.getFileLocWithOffset(PH.C-PH.Begin), + diag::err_verify_missing_end) << KindStr; + continue; + } + const char* const ContentEnd = PH.P; // mark content end + PH.Advance(); + + // build directive text; convert \n to newlines + std::string Text; + llvm::StringRef NewlineStr = "\\n"; + llvm::StringRef Content(ContentBegin, ContentEnd-ContentBegin); + size_t CPos = 0; + size_t FPos; + while ((FPos = Content.find(NewlineStr, CPos)) != llvm::StringRef::npos) { + Text += Content.substr(CPos, FPos-CPos); + Text += '\n'; + CPos = FPos + NewlineStr.size(); + } + if (Text.empty()) + Text.assign(ContentBegin, ContentEnd); + + // construct new directive + Directive *D = Directive::Create(RegexKind, Pos, Text, Count); + std::string Error; + if (D->isValid(Error)) + DL->push_back(D); + else { + PP.Diag(Pos.getFileLocWithOffset(ContentBegin-PH.Begin), + diag::err_verify_invalid_content) + << KindStr << Error; + } } } /// FindExpectedDiags - Lex the main source file to find all of the // expected errors and warnings. -static void FindExpectedDiags(Preprocessor &PP, - DiagList &ExpectedErrors, - DiagList &ExpectedWarnings, - DiagList &ExpectedNotes) { +static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED) { // Create a raw lexer to pull all the comments out of the main file. We don't // want to look in #include'd headers for expected-error strings. SourceManager &SM = PP.getSourceManager(); @@ -185,17 +356,8 @@ static void FindExpectedDiags(Preprocessor &PP, std::string Comment = PP.getSpelling(Tok); if (Comment.empty()) continue; - // Find all expected errors. - FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP, - Tok.getLocation(), "expected-error"); - - // Find all expected warnings. - FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP, - Tok.getLocation(), "expected-warning"); - - // Find all expected notes. - FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP, - Tok.getLocation(), "expected-note"); + // Find all expected errors/warnings/notes. + ParseDirective(&Comment[0], Comment.size(), ED, PP, Tok.getLocation()); }; } @@ -225,49 +387,68 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr, return std::distance(diag_begin, diag_end); } -/// CompareDiagLists - Compare two diagnostic lists and return the difference -/// between them. +static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr, + DirectiveList &DL, const char *Kind, + bool Expected) { + if (DL.empty()) + return 0; + + llvm::SmallString<256> Fmt; + llvm::raw_svector_ostream OS(Fmt); + for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) { + Directive& D = **I; + if (D.Location.isInvalid() || !SourceMgr) + OS << "\n (frontend)"; + else + OS << "\n Line " << SourceMgr->getInstantiationLineNumber(D.Location); + OS << ": " << D.Text; + } + + Diags.Report(diag::err_verify_inconsistent_diags) + << Kind << !Expected << OS.str(); + return DL.size(); +} + +/// CheckLists - Compare expected to seen diagnostic lists and return the +/// the difference between them. /// -static unsigned CompareDiagLists(Diagnostic &Diags, - SourceManager &SourceMgr, - const_diag_iterator d1_begin, - const_diag_iterator d1_end, - const_diag_iterator d2_begin, - const_diag_iterator d2_end, - const char *Label) { - DiagList LeftOnly; - DiagList Left(d1_begin, d1_end); +static unsigned CheckLists(Diagnostic &Diags, SourceManager &SourceMgr, + const char *Label, + DirectiveList &Left, + const_diag_iterator d2_begin, + const_diag_iterator d2_end) { + DirectiveList LeftOnly; DiagList Right(d2_begin, d2_end); - for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) { - unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first); - const std::string &Diag1 = I->second; + for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) { + Directive& D = **I; + unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(D.Location); - DiagList::iterator II, IE; - for (II = Right.begin(), IE = Right.end(); II != IE; ++II) { - unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first); - if (LineNo1 != LineNo2) continue; + for (unsigned i = 0; i < D.Count; ++i) { + DiagList::iterator II, IE; + for (II = Right.begin(), IE = Right.end(); II != IE; ++II) { + unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first); + if (LineNo1 != LineNo2) + continue; - const std::string &Diag2 = II->second; - if (Diag2.find(Diag1) != std::string::npos || - Diag1.find(Diag2) != std::string::npos) { - break; + const std::string &RightText = II->second; + if (D.Match(RightText)) + break; + } + if (II == IE) { + // Not found. + LeftOnly.push_back(*I); + } else { + // Found. The same cannot be found twice. + Right.erase(II); } - } - if (II == IE) { - // Not found. - LeftOnly.push_back(*I); - } else { - // Found. The same cannot be found twice. - Right.erase(II); } } // Now all that's left in Right are those that were not matched. - return (PrintProblem(Diags, &SourceMgr, - LeftOnly.begin(), LeftOnly.end(), Label, true) + - PrintProblem(Diags, &SourceMgr, - Right.begin(), Right.end(), Label, false)); + return (PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true) + + PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(), + Label, false)); } /// CheckResults - This compares the expected results to those that @@ -276,9 +457,7 @@ static unsigned CompareDiagLists(Diagnostic &Diags, /// static unsigned CheckResults(Diagnostic &Diags, SourceManager &SourceMgr, const TextDiagnosticBuffer &Buffer, - const DiagList &ExpectedErrors, - const DiagList &ExpectedWarnings, - const DiagList &ExpectedNotes) { + ExpectedData &ED) { // We want to capture the delta between what was expected and what was // seen. // @@ -287,31 +466,22 @@ static unsigned CheckResults(Diagnostic &Diags, SourceManager &SourceMgr, unsigned NumProblems = 0; // See if there are error mismatches. - NumProblems += CompareDiagLists(Diags, SourceMgr, - ExpectedErrors.begin(), ExpectedErrors.end(), - Buffer.err_begin(), Buffer.err_end(), - "error"); + NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors, + Buffer.err_begin(), Buffer.err_end()); // See if there are warning mismatches. - NumProblems += CompareDiagLists(Diags, SourceMgr, - ExpectedWarnings.begin(), - ExpectedWarnings.end(), - Buffer.warn_begin(), Buffer.warn_end(), - "warning"); + NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings, + Buffer.warn_begin(), Buffer.warn_end()); // See if there are note mismatches. - NumProblems += CompareDiagLists(Diags, SourceMgr, - ExpectedNotes.begin(), - ExpectedNotes.end(), - Buffer.note_begin(), Buffer.note_end(), - "note"); + NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes, + Buffer.note_begin(), Buffer.note_end()); return NumProblems; } - void VerifyDiagnosticsClient::CheckDiagnostics() { - DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes; + ExpectedData ED; // Ensure any diagnostics go to the primary client. DiagnosticClient *CurClient = Diags.getClient(); @@ -320,13 +490,11 @@ void VerifyDiagnosticsClient::CheckDiagnostics() { // If we have a preprocessor, scan the source for expected diagnostic // markers. If not then any diagnostics are unexpected. if (CurrentPreprocessor) { - FindExpectedDiags(*CurrentPreprocessor, ExpectedErrors, ExpectedWarnings, - ExpectedNotes); + FindExpectedDiags(*CurrentPreprocessor, ED); // Check that the expected diagnostics occurred. NumErrors += CheckResults(Diags, CurrentPreprocessor->getSourceManager(), - *Buffer, - ExpectedErrors, ExpectedWarnings, ExpectedNotes); + *Buffer, ED); } else { NumErrors += (PrintProblem(Diags, 0, Buffer->err_begin(), Buffer->err_end(), @@ -344,3 +512,10 @@ void VerifyDiagnosticsClient::CheckDiagnostics() { // Reset the buffer, we have processed all the diagnostics in it. Buffer.reset(new TextDiagnosticBuffer()); } + +Directive* Directive::Create(bool RegexKind, const SourceLocation &Location, + const std::string &Text, unsigned Count) { + if (RegexKind) + return new RegexDirective(Location, Text, Count); + return new StandardDirective(Location, Text, Count); +} diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp index ea9635e79849..84c4f5d40faf 100644 --- a/lib/Frontend/Warnings.cpp +++ b/lib/Frontend/Warnings.cpp @@ -35,6 +35,12 @@ void clang::ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts) { Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); + + // Handle -ferror-limit + if (Opts.ErrorLimit) + Diags.setErrorLimit(Opts.ErrorLimit); + if (Opts.TemplateBacktraceLimit) + Diags.setTemplateBacktraceLimit(Opts.TemplateBacktraceLimit); // If -pedantic or -pedantic-errors was specified, then we want to map all // extension diagnostics onto WARNING or ERROR unless the user has futz'd |