diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-06 15:53:59 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-06 15:53:59 +0000 |
commit | 60bfabcd8ce617297c0d231f77d14ab507e98796 (patch) | |
tree | 59c928209f8007777dd96568b026bdfe200691de | |
parent | 2c56c396ce5990954f85194029eeb391bc3529ff (diff) | |
download | src-60bfabcd8ce617297c0d231f77d14ab507e98796.tar.gz src-60bfabcd8ce617297c0d231f77d14ab507e98796.zip |
Notes
53 files changed, 597 insertions, 315 deletions
diff --git a/examples/wpa/clang-wpa.cpp b/examples/wpa/clang-wpa.cpp index ae789fa9ae3c..b515e3314830 100644 --- a/examples/wpa/clang-wpa.cpp +++ b/examples/wpa/clang-wpa.cpp @@ -17,6 +17,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Index/CallGraph.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -34,12 +35,11 @@ int main(int argc, char **argv) { return 0; DiagnosticOptions DiagOpts; - llvm::OwningPtr<Diagnostic> Diags( - CompilerInstance::createDiagnostics(DiagOpts, argc, argv)); - + llvm::IntrusiveRefCntPtr<Diagnostic> Diags + = CompilerInstance::createDiagnostics(DiagOpts, argc, argv); for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { const std::string &InFile = InputFilenames[i]; - llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, *Diags)); + llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, Diags)); if (!AST) return 1; diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 587b5c2b40f7..70d65d35fef8 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -37,7 +37,8 @@ struct PrintingPolicy { PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), SuppressTag(false), SuppressScope(false), - Dump(false), ConstantArraySizeAsWritten(false) { } + Dump(false), ConstantArraySizeAsWritten(false), + AnonymousTagLocations(true) { } /// \brief The number of spaces to use to indent each line. unsigned Indentation : 8; @@ -97,7 +98,11 @@ struct PrintingPolicy { /// char a[9] = "A string"; /// \endcode bool ConstantArraySizeAsWritten : 1; - + + /// \brief When printing an anonymous tag name, also print the location of + /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just + /// prints "<anonymous>" for the name. + bool AnonymousTagLocations : 1; }; } // end namespace clang diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 643868506d8f..57dd6967fc51 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_DIAGNOSTIC_H #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/type_traits.h" #include <string> @@ -150,7 +151,7 @@ public: /// problems and issues. It massages the diagnostics (e.g. handling things like /// "report warnings as errors" and passes them off to the DiagnosticClient for /// reporting to the user. -class Diagnostic { +class Diagnostic : public llvm::RefCountedBase<Diagnostic> { public: /// Level - The level of the diagnostic, after it has been through mapping. enum Level { diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 61db323a12bb..9252358f42a6 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -16,6 +16,7 @@ #include "clang/Lex/PreprocessingRecord.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "clang/Basic/FileManager.h" #include "clang/Index/ASTLocation.h" @@ -52,10 +53,9 @@ public: typedef std::map<FileID, std::vector<PreprocessedEntity *> > PreprocessedEntitiesByFileMap; private: - - FileManager FileMgr; - - SourceManager SourceMgr; + llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; + llvm::OwningPtr<FileManager> FileMgr; + llvm::OwningPtr<SourceManager> SourceMgr; llvm::OwningPtr<HeaderSearch> HeaderInfo; llvm::OwningPtr<TargetInfo> Target; llvm::OwningPtr<Preprocessor> PP; @@ -90,7 +90,7 @@ private: /// \brief The set of diagnostics produced when creating this /// translation unit. - llvm::SmallVector<StoredDiagnostic, 4> Diagnostics; + llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics; /// \brief Temporary files that should be removed when the ASTUnit is /// destroyed. @@ -118,6 +118,8 @@ private: ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT + explicit ASTUnit(bool MainFileIsAST); + public: class ConcurrencyCheck { volatile ASTUnit &Self; @@ -137,13 +139,15 @@ public: }; friend class ConcurrencyCheck; - ASTUnit(Diagnostic &Diag, bool MainFileIsAST); ~ASTUnit(); bool isMainFileAST() const { return MainFileIsAST; } - const SourceManager &getSourceManager() const { return SourceMgr; } - SourceManager &getSourceManager() { return SourceMgr; } + const Diagnostic &getDiagnostics() const { return *Diagnostics; } + Diagnostic &getDiagnostics() { return *Diagnostics; } + + const SourceManager &getSourceManager() const { return *SourceMgr; } + SourceManager &getSourceManager() { return *SourceMgr; } const Preprocessor &getPreprocessor() const { return *PP.get(); } Preprocessor &getPreprocessor() { return *PP.get(); } @@ -151,8 +155,8 @@ public: const ASTContext &getASTContext() const { return *Ctx.get(); } ASTContext &getASTContext() { return *Ctx.get(); } - const FileManager &getFileManager() const { return FileMgr; } - FileManager &getFileManager() { return FileMgr; } + const FileManager &getFileManager() const { return *FileMgr; } + FileManager &getFileManager() { return *FileMgr; } const std::string &getOriginalSourceFileName(); const std::string &getPCHFileName(); @@ -185,12 +189,17 @@ public: } // Retrieve the diagnostics associated with this AST - typedef const StoredDiagnostic * diag_iterator; - diag_iterator diag_begin() const { return Diagnostics.begin(); } - diag_iterator diag_end() const { return Diagnostics.end(); } - unsigned diag_size() const { return Diagnostics.size(); } - llvm::SmallVector<StoredDiagnostic, 4> &getDiagnostics() { - return Diagnostics; + typedef const StoredDiagnostic *stored_diag_iterator; + stored_diag_iterator stored_diag_begin() const { + return StoredDiagnostics.begin(); + } + stored_diag_iterator stored_diag_end() const { + return StoredDiagnostics.end(); + } + unsigned stored_diag_size() const { return StoredDiagnostics.size(); } + + llvm::SmallVector<StoredDiagnostic, 4> &getStoredDiagnostics() { + return StoredDiagnostics; } /// \brief A mapping from a file name to the memory buffer that stores the @@ -206,7 +215,7 @@ public: /// /// \returns - The initialized ASTUnit or null if the PCH failed to load. static ASTUnit *LoadFromPCHFile(const std::string &Filename, - Diagnostic &Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, @@ -224,7 +233,7 @@ public: // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI, - Diagnostic &Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false); @@ -244,7 +253,7 @@ public: // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, - Diagnostic &Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, llvm::StringRef ResourceFilesPath, bool OnlyLocalDecls = false, RemappedFile *RemappedFiles = 0, diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 3444b640f01d..36720c9d1462 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #include "clang/Frontend/CompilerInvocation.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" #include <cassert> @@ -63,7 +64,7 @@ class CompilerInstance { llvm::OwningPtr<CompilerInvocation> Invocation; /// The diagnostics engine instance. - llvm::OwningPtr<Diagnostic> Diagnostics; + llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; /// The diagnostics client instance. llvm::OwningPtr<DiagnosticClient> DiagClient; @@ -255,10 +256,6 @@ public: return *Diagnostics; } - /// takeDiagnostics - Remove the current diagnostics engine and give ownership - /// to the caller. - Diagnostic *takeDiagnostics() { return Diagnostics.take(); } - /// setDiagnostics - Replace the current diagnostics engine; the compiler /// instance takes ownership of \arg Value. void setDiagnostics(Diagnostic *Value); @@ -469,8 +466,8 @@ public: /// must extend past that of the diagnostic engine. /// /// \return The new object on success, or null on failure. - static Diagnostic *createDiagnostics(const DiagnosticOptions &Opts, - int Argc, char **Argv); + static llvm::IntrusiveRefCntPtr<Diagnostic> + createDiagnostics(const DiagnosticOptions &Opts, int Argc, char **Argv); /// Create the file manager and replace any existing one with it. void createFileManager(); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 411162b18209..9a4634a42085 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1086,7 +1086,8 @@ private: CXX0XAttributeList Attr); DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, SourceLocation &DeclEnd, - AttributeList *Attr); + AttributeList *Attr, + bool RequireSemi); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, SourceLocation *DeclEnd = 0); diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index f7d08e8b77bb..5dfb99ff0889 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3088,8 +3088,7 @@ FileID ASTImporter::Import(FileID FromID) { // FIXME: We want to re-use the existing MemoryBuffer! const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags()); llvm::MemoryBuffer *ToBuf - = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBufferStart(), - FromBuf->getBufferEnd(), + = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); ToID = ToSM.createFileIDForMemBuffer(ToBuf); } diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 8347249a466b..97023820e247 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -249,14 +249,18 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, } char CurChar = *CurPtr++; - if (CurChar == '$') { - CurStringPiece += "$$"; - continue; - } else if (CurChar != '%') { + switch (CurChar) { + case '$': CurStringPiece += "$$"; continue; + case '{': CurStringPiece += "$("; continue; + case '|': CurStringPiece += "$|"; continue; + case '}': CurStringPiece += "$)"; continue; + case '%': + break; + default: CurStringPiece += CurChar; continue; } - + // Escaped "%" character in asm string. if (CurPtr == StrEnd) { // % at end of string is invalid (no escape). diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 4cf0922ee316..340e373af123 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -442,18 +442,21 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { llvm::raw_string_ostream OS(Buffer); OS << "<anonymous"; - // Suppress the redundant tag keyword if we just printed one. - // We don't have to worry about ElaboratedTypes here because you can't - // refer to an anonymous type with one. - if (!HasKindDecoration) - OS << " " << D->getKindName(); - - PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( - D->getLocation()); - OS << " at " << PLoc.getFilename() - << ':' << PLoc.getLine() - << ':' << PLoc.getColumn() - << '>'; + if (Policy.AnonymousTagLocations) { + // Suppress the redundant tag keyword if we just printed one. + // We don't have to worry about ElaboratedTypes here because you can't + // refer to an anonymous type with one. + if (!HasKindDecoration) + OS << " " << D->getKindName(); + + PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( + D->getLocation()); + OS << " at " << PLoc.getFilename() + << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + } + + OS << '>'; OS.flush(); } diff --git a/lib/Checker/BugReporter.cpp b/lib/Checker/BugReporter.cpp index 12e61afa1010..4475872ee2dc 100644 --- a/lib/Checker/BugReporter.cpp +++ b/lib/Checker/BugReporter.cpp @@ -58,7 +58,7 @@ void BugReporterContext::addVisitor(BugReporterVisitor* visitor) { // Helper routines for walking the ExplodedGraph and fetching statements. //===----------------------------------------------------------------------===// -static inline const Stmt* GetStmt(ProgramPoint P) { +static inline const Stmt* GetStmt(const ProgramPoint &P) { if (const StmtPoint* SP = dyn_cast<StmtPoint>(&P)) return SP->getStmt(); else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp index cc71f8569c62..be1a677d9118 100644 --- a/lib/Checker/Environment.cpp +++ b/lib/Checker/Environment.cpp @@ -96,6 +96,19 @@ public: }; } // end anonymous namespace +static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) { + const LocationContext *ParentLC = LC->getParent(); + while (ParentLC) { + CFG &C = *ParentLC->getCFG(); + if (C.isBlkExpr(E)) + return true; + ParentLC = ParentLC->getParent(); + } + + return false; +} + + // RemoveDeadBindings: // - Remove subexpression bindings. // - Remove dead block expression bindings. @@ -122,13 +135,27 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S, I != E; ++I) { const Stmt *BlkExpr = I.getKey(); + const SVal &X = I.getData(); + + // Block-level expressions in callers are assumed always live. + if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) { + NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); + + if (isa<loc::MemRegionVal>(X)) { + const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); + DRoots.push_back(R); + } + + // Mark all symbols in the block expr's value live. + MarkLiveCallback cb(SymReaper); + ST->scanReachableSymbols(X, cb); + continue; + } // Not a block-level expression? if (!C.isBlkExpr(BlkExpr)) continue; - const SVal &X = I.getData(); - if (SymReaper.isLive(S, BlkExpr)) { // Copy the binding to the new map. NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); @@ -137,14 +164,6 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S, if (isa<loc::MemRegionVal>(X)) { const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); DRoots.push_back(R); - // Mark the super region of the RX as live. - // e.g.: int x; char *y = (char*) &x; if (*y) ... - // 'y' => element region. 'x' is its super region. - // We only add one level super region for now. - - // FIXME: maybe multiple level of super regions should be added. - if (const SubRegion *SR = dyn_cast<SubRegion>(R)) - DRoots.push_back(SR->getSuperRegion()); } // Mark all symbols in the block expr's value live. diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a9b0b645a4a6..38c40ed489d2 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -338,38 +338,50 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BIbzero: case Builtin::BI__builtin_bzero: { Value *Address = EmitScalarExpr(E->getArg(0)); - Builder.CreateCall4(CGM.getMemSetFn(), Address, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0), - EmitScalarExpr(E->getArg(1)), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); + Value *SizeVal = EmitScalarExpr(E->getArg(1)); + Builder.CreateCall5(CGM.getMemSetFn(Address->getType(), SizeVal->getType()), + Address, + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0), + SizeVal, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0)); return RValue::get(Address); } case Builtin::BImemcpy: case Builtin::BI__builtin_memcpy: { Value *Address = EmitScalarExpr(E->getArg(0)); - Builder.CreateCall4(CGM.getMemCpyFn(), Address, - EmitScalarExpr(E->getArg(1)), - EmitScalarExpr(E->getArg(2)), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); + Value *SrcAddr = EmitScalarExpr(E->getArg(1)); + Value *SizeVal = EmitScalarExpr(E->getArg(2)); + Builder.CreateCall5(CGM.getMemCpyFn(Address->getType(), SrcAddr->getType(), + SizeVal->getType()), + Address, SrcAddr, SizeVal, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0)); return RValue::get(Address); } case Builtin::BImemmove: case Builtin::BI__builtin_memmove: { Value *Address = EmitScalarExpr(E->getArg(0)); - Builder.CreateCall4(CGM.getMemMoveFn(), Address, - EmitScalarExpr(E->getArg(1)), - EmitScalarExpr(E->getArg(2)), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); + Value *SrcAddr = EmitScalarExpr(E->getArg(1)); + Value *SizeVal = EmitScalarExpr(E->getArg(2)); + Builder.CreateCall5(CGM.getMemMoveFn(Address->getType(), SrcAddr->getType(), + SizeVal->getType()), + Address, SrcAddr, SizeVal, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0)); return RValue::get(Address); } case Builtin::BImemset: case Builtin::BI__builtin_memset: { Value *Address = EmitScalarExpr(E->getArg(0)); - Builder.CreateCall4(CGM.getMemSetFn(), Address, - Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), - llvm::Type::getInt8Ty(VMContext)), - EmitScalarExpr(E->getArg(2)), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); + Value *SizeVal = EmitScalarExpr(E->getArg(2)); + Builder.CreateCall5(CGM.getMemSetFn(Address->getType(), SizeVal->getType()), + Address, + Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), + llvm::Type::getInt8Ty(VMContext)), + SizeVal, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0)); return RValue::get(Address); } case Builtin::BI__builtin_dwarf_cfa: { diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 4f14f94388fc..bcbda8a0a747 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1380,7 +1380,9 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { || (SM.getInstantiationLineNumber(CurLoc) == SM.getInstantiationLineNumber(PrevLoc) && SM.isFromSameFile(CurLoc, PrevLoc))) - return; + // New Builder may not be in sync with CGDebugInfo. + if (!Builder.getCurrentDebugLocation().isUnknown()) + return; // Update last state. PrevLoc = CurLoc; diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 4eb95af8ff61..07d219f1fbfc 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -564,11 +564,15 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { if (Loc->getType() != BP) Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + llvm::Value *NotVolatile = + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0); + // If the initializer is all zeros, codegen with memset. if (isa<llvm::ConstantAggregateZero>(Init)) { llvm::Value *Zero = - llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0); - Builder.CreateCall4(CGM.getMemSetFn(), Loc, Zero, SizeVal, AlignVal); + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0); + Builder.CreateCall5(CGM.getMemSetFn(Loc->getType(), SizeVal->getType()), + Loc, Zero, SizeVal, AlignVal, NotVolatile); } else { // Otherwise, create a temporary global with the initializer then // memcpy from the global to the alloca. @@ -582,8 +586,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { llvm::Value *SrcPtr = GV; if (SrcPtr->getType() != BP) SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); - - Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal); + + Builder.CreateCall5(CGM.getMemCpyFn(Loc->getType(), SrcPtr->getType(), + SizeVal->getType()), + Loc, SrcPtr, SizeVal, AlignVal, NotVolatile); } } else if (Ty->isReferenceType()) { RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 87ec159a6010..0aa4438f4f47 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -345,7 +345,7 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } // Store the updated result through the lvalue. - if (LV.isBitfield()) + if (LV.isBitField()) EmitStoreThroughBitfieldLValue(RValue::get(NextVal), LV, ValTy, &NextVal); else EmitStoreThroughLValue(RValue::get(NextVal), LV, ValTy); @@ -429,7 +429,7 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) { LValue LV = EmitLValue(E); - if (!isa<DeclRefExpr>(E) && !LV.isBitfield() && LV.isSimple()) + if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple()) EmitCheck(LV.getAddress(), getContext().getTypeSize(E->getType()) / 8); return LV; } @@ -593,7 +593,7 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { if (LV.isExtVectorElt()) return EmitLoadOfExtVectorElementLValue(LV, ExprType); - if (LV.isBitfield()) + if (LV.isBitField()) return EmitLoadOfBitfieldLValue(LV, ExprType); if (LV.isPropertyRef()) @@ -605,9 +605,10 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, QualType ExprType) { - unsigned StartBit = LV.getBitfieldStartBit(); - unsigned BitfieldSize = LV.getBitfieldSize(); - llvm::Value *Ptr = LV.getBitfieldAddr(); + const CGBitFieldInfo &Info = LV.getBitFieldInfo(); + unsigned StartBit = Info.Start; + unsigned BitfieldSize = Info.Size; + llvm::Value *Ptr = LV.getBitFieldAddr(); const llvm::Type *EltTy = cast<llvm::PointerType>(Ptr->getType())->getElementType(); @@ -650,7 +651,7 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, } // Sign extend if necessary. - if (LV.isBitfieldSigned()) { + if (Info.IsSigned) { llvm::Value *ExtraBits = llvm::ConstantInt::get(EltTy, EltTySize - BitfieldSize); Val = Builder.CreateAShr(Builder.CreateShl(Val, ExtraBits), @@ -733,7 +734,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, if (Dst.isExtVectorElt()) return EmitStoreThroughExtVectorComponentLValue(Src, Dst, Ty); - if (Dst.isBitfield()) + if (Dst.isBitField()) return EmitStoreThroughBitfieldLValue(Src, Dst, Ty); if (Dst.isPropertyRef()) @@ -781,9 +782,10 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, QualType Ty, llvm::Value **Result) { - unsigned StartBit = Dst.getBitfieldStartBit(); - unsigned BitfieldSize = Dst.getBitfieldSize(); - llvm::Value *Ptr = Dst.getBitfieldAddr(); + const CGBitFieldInfo &Info = Dst.getBitFieldInfo(); + unsigned StartBit = Info.Start; + unsigned BitfieldSize = Info.Size; + llvm::Value *Ptr = Dst.getBitFieldAddr(); const llvm::Type *EltTy = cast<llvm::PointerType>(Ptr->getType())->getElementType(); @@ -805,7 +807,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, "bf.reload.val"); // Sign extend if necessary. - if (Dst.isBitfieldSigned()) { + if (Info.IsSigned) { unsigned SrcTySize = CGM.getTargetData().getTypeSizeInBits(SrcTy); llvm::Value *ExtraBits = llvm::ConstantInt::get(SrcTy, SrcTySize - BitfieldSize); @@ -1471,7 +1473,7 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue, unsigned CVRQualifiers) { const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(Field->getParent()); - const CGRecordLayout::BitFieldInfo &Info = RL.getBitFieldInfo(Field); + const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field); // FIXME: CodeGenTypes should expose a method to get the appropriate type for // FieldTy (the appropriate type is ABI-dependent). @@ -1481,16 +1483,11 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue, cast<llvm::PointerType>(BaseValue->getType()); unsigned AS = BaseTy->getAddressSpace(); BaseValue = Builder.CreateBitCast(BaseValue, - llvm::PointerType::get(FieldTy, AS), - "tmp"); + llvm::PointerType::get(FieldTy, AS)); + llvm::Value *V = Builder.CreateConstGEP1_32(BaseValue, Info.FieldNo); - llvm::Value *Idx = - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Info.FieldNo); - llvm::Value *V = Builder.CreateGEP(BaseValue, Idx, "tmp"); - - return LValue::MakeBitfield(V, Info.Start, Info.Size, - Field->getType()->isSignedIntegerType(), - Field->getType().getCVRQualifiers()|CVRQualifiers); + return LValue::MakeBitfield(V, Info, + Field->getType().getCVRQualifiers()|CVRQualifiers); } LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index e2e2cd050419..4d5160f39b0b 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -771,12 +771,27 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, // a = b; // } // - // we need to use a differnt call here. We use isVolatile to indicate when + // we need to use a different call here. We use isVolatile to indicate when // either the source or the destination is volatile. - Builder.CreateCall4(CGM.getMemCpyFn(), + const llvm::Type *I1Ty = llvm::Type::getInt1Ty(VMContext); + const llvm::Type *I8Ty = llvm::Type::getInt8Ty(VMContext); + const llvm::Type *I32Ty = llvm::Type::getInt32Ty(VMContext); + + const llvm::PointerType *DPT = cast<llvm::PointerType>(DestPtr->getType()); + const llvm::Type *DBP = llvm::PointerType::get(I8Ty, DPT->getAddressSpace()); + if (DestPtr->getType() != DBP) + DestPtr = Builder.CreateBitCast(DestPtr, DBP, "tmp"); + + const llvm::PointerType *SPT = cast<llvm::PointerType>(SrcPtr->getType()); + const llvm::Type *SBP = llvm::PointerType::get(I8Ty, SPT->getAddressSpace()); + if (SrcPtr->getType() != SBP) + SrcPtr = Builder.CreateBitCast(SrcPtr, SBP, "tmp"); + + Builder.CreateCall5(CGM.getMemCpyFn(DestPtr->getType(), SrcPtr->getType(), + IntPtr), DestPtr, SrcPtr, // TypeInfo.first describes size in bits. llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), - TypeInfo.second/8)); + llvm::ConstantInt::get(I32Ty, TypeInfo.second/8), + llvm::ConstantInt::get(I1Ty, isVolatile)); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 42bf68ed52ce..d1c0f8dc3d73 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1140,7 +1140,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, // specially because the result is altered by the store, i.e., [C99 6.5.16p1] // 'An assignment expression has the value of the left operand after the // assignment...'. - if (LHSLV.isBitfield()) { + if (LHSLV.isBitField()) { if (!LHSLV.isVolatileQualified()) { CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy, &Result); @@ -1575,7 +1575,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { // because the result is altered by the store, i.e., [C99 6.5.16p1] // 'An assignment expression has the value of the left operand after // the assignment...'. - if (LHS.isBitfield()) { + if (LHS.isBitField()) { if (!LHS.isVolatileQualified()) { CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType(), &RHS); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 9eaf57c445ed..206d438ced67 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -108,6 +108,10 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD) { FunctionArgList Args; + // Check if we should generate debug info for this method. + if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) + DebugInfo = CGM.getDebugInfo(); + llvm::Function *Fn = CGM.getObjCRuntime().GenerateMethod(OMD, CD); const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); @@ -128,9 +132,6 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, /// Generate an Objective-C method. An Objective-C method is a C function with /// its pointer, name, and types registered in the class struture. void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { - // Check if we should generate debug info for this method. - if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) - DebugInfo = CGM.getDebugInfo(); StartObjCMethod(OMD, OMD->getClassInterface()); EmitStmt(OMD->getBody()); FinishFunction(OMD->getBodyRBrace()); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 5373390ef7e8..ac8fa057a0e7 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -107,24 +107,31 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, Qualifiers Quals = CGF.MakeQualifiers(IvarTy); Quals.addCVRQualifiers(CVRQualifiers); - if (Ivar->isBitField()) { - // We need to compute the bit offset for the bit-field, the offset - // is to the byte. Note, there is a subtle invariant here: we can - // only call this routine on non-sythesized ivars but we may be - // called for synthesized ivars. However, a synthesized ivar can - // never be a bit-field so this is safe. - uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8; - - uint64_t BitFieldSize = - Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); - return LValue::MakeBitfield(V, BitOffset, BitFieldSize, - IvarTy->isSignedIntegerType(), - Quals.getCVRQualifiers()); - } - - - LValue LV = LValue::MakeAddr(V, Quals); - return LV; + if (!Ivar->isBitField()) + return LValue::MakeAddr(V, Quals); + + // We need to compute the bit offset for the bit-field, the offset is to the + // byte. Note, there is a subtle invariant here: we can only call this routine + // on non-synthesized ivars but we may be called for synthesized ivars. + // However, a synthesized ivar can never be a bit-field, so this is safe. + uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8; + uint64_t BitFieldSize = + Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); + + // Allocate a new CGBitFieldInfo object to describe this access. + // + // FIXME: This is incredibly wasteful, these should be uniqued or part of some + // layout object. However, this is blocked on other cleanups to the + // Objective-C code, so for now we just live with allocating a bunch of these + // objects. + unsigned FieldNo = 0; // This value is unused. + CGBitFieldInfo *Info = + new (CGF.CGM.getContext()) CGBitFieldInfo(FieldNo, BitOffset, BitFieldSize, + IvarTy->isSignedIntegerType()); + + // FIXME: We need to set a very conservative alignment on this, or make sure + // that the runtime is doing the right thing. + return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers()); } /// @@ -3128,7 +3135,7 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(Field->getParent()); if (Field->isBitField()) { - const CGRecordLayout::BitFieldInfo &Info = RL.getBitFieldInfo(Field); + const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field); const llvm::Type *Ty = CGM.getTypes().ConvertTypeForMemRecursive(Field->getType()); diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index b781940ffad5..e478394fb1aa 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -61,12 +61,11 @@ namespace CodeGen { /// Implements runtime-specific code generation functions. class CGObjCRuntime { -public: +protected: // Utility functions for unified ivar access. These need to // eventually be folded into other places (the structure layout // code). -protected: /// Compute an offset to the given ivar, suitable for passing to /// EmitValueForIvarAtOffset. Note that the correct handling of /// bit-fields is carefully coordinated by these two, use caution! diff --git a/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h index d0d8f984a9ef..fd1775ea5e6c 100644 --- a/lib/CodeGen/CGRecordLayout.h +++ b/lib/CodeGen/CGRecordLayout.h @@ -19,6 +19,18 @@ namespace llvm { namespace clang { namespace CodeGen { +class CGBitFieldInfo { +public: + CGBitFieldInfo(unsigned FieldNo, unsigned Start, unsigned Size, + bool IsSigned) + : FieldNo(FieldNo), Start(Start), Size(Size), IsSigned(IsSigned) {} + + unsigned FieldNo; + unsigned Start; + unsigned Size; + bool IsSigned : 1; +}; + /// CGRecordLayout - This class handles struct and union layout info while /// lowering AST types to LLVM types. /// @@ -29,18 +41,6 @@ class CGRecordLayout { CGRecordLayout(const CGRecordLayout&); // DO NOT IMPLEMENT void operator=(const CGRecordLayout&); // DO NOT IMPLEMENT -public: - struct BitFieldInfo { - BitFieldInfo(unsigned FieldNo, - unsigned Start, - unsigned Size) - : FieldNo(FieldNo), Start(Start), Size(Size) {} - - unsigned FieldNo; - unsigned Start; - unsigned Size; - }; - private: /// The LLVMType corresponding to this record layout. const llvm::Type *LLVMType; @@ -51,7 +51,7 @@ private: /// Map from (bit-field) struct field to the corresponding llvm struct type /// field no. This info is populated by record builder. - llvm::DenseMap<const FieldDecl *, BitFieldInfo> BitFields; + llvm::DenseMap<const FieldDecl *, CGBitFieldInfo> BitFields; /// Whether one of the fields in this record layout is a pointer to data /// member, or a struct that contains pointer to data member. @@ -80,9 +80,9 @@ public: /// \brief Return llvm::StructType element number that corresponds to the /// field FD. - const BitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const { + const CGBitFieldInfo &getBitFieldInfo(const FieldDecl *FD) const { assert(FD->isBitField() && "Invalid call for non bit-field decl!"); - llvm::DenseMap<const FieldDecl *, BitFieldInfo>::const_iterator + llvm::DenseMap<const FieldDecl *, CGBitFieldInfo>::const_iterator it = BitFields.find(FD); assert(it != BitFields.end() && "Unable to find bitfield info"); return it->second; diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index daebabddc61f..4b9ec66e178c 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -37,17 +37,7 @@ public: llvm::SmallVector<LLVMFieldInfo, 16> LLVMFields; /// LLVMBitFieldInfo - Holds location and size information about a bit field. - struct LLVMBitFieldInfo { - LLVMBitFieldInfo(const FieldDecl *FD, unsigned FieldNo, unsigned Start, - unsigned Size) - : FD(FD), FieldNo(FieldNo), Start(Start), Size(Size) { } - - const FieldDecl *FD; - - unsigned FieldNo; - unsigned Start; - unsigned Size; - }; + typedef std::pair<const FieldDecl *, CGBitFieldInfo> LLVMBitFieldInfo; llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields; /// ContainsPointerToDataMember - Whether one of the fields in this record @@ -188,9 +178,11 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); uint64_t TypeSizeInBits = getTypeSizeInBytes(Ty) * 8; - LLVMBitFields.push_back(LLVMBitFieldInfo(D, FieldOffset / TypeSizeInBits, - FieldOffset % TypeSizeInBits, - FieldSize)); + bool IsSigned = D->getType()->isSignedIntegerType(); + LLVMBitFields.push_back(LLVMBitFieldInfo( + D, CGBitFieldInfo(FieldOffset / TypeSizeInBits, + FieldOffset % TypeSizeInBits, + FieldSize, IsSigned))); AppendBytes(NumBytesToAppend); @@ -288,7 +280,10 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { continue; // Add the bit field info. - LLVMBitFields.push_back(LLVMBitFieldInfo(*Field, 0, 0, FieldSize)); + bool IsSigned = Field->getType()->isSignedIntegerType(); + LLVMBitFields.push_back(LLVMBitFieldInfo( + *Field, CGBitFieldInfo(0, 0, FieldSize, + IsSigned))); } else { LLVMFields.push_back(LLVMFieldInfo(*Field, 0)); } @@ -494,21 +489,12 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember); // Add all the field numbers. - for (unsigned i = 0, e = Builder.LLVMFields.size(); i != e; ++i) { - const FieldDecl *FD = Builder.LLVMFields[i].first; - unsigned FieldNo = Builder.LLVMFields[i].second; - - RL->FieldInfo.insert(std::make_pair(FD, FieldNo)); - } + for (unsigned i = 0, e = Builder.LLVMFields.size(); i != e; ++i) + RL->FieldInfo.insert(Builder.LLVMFields[i]); // Add bitfield info. - for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i) { - const CGRecordLayoutBuilder::LLVMBitFieldInfo &Info = - Builder.LLVMBitFields[i]; - - CGRecordLayout::BitFieldInfo BFI(Info.FieldNo, Info.Start, Info.Size); - RL->BitFields.insert(std::make_pair(Info.FD, BFI)); - } + for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i) + RL->BitFields.insert(Builder.LLVMBitFields[i]); return RL; } diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index fa77471bce0e..91fb714315fc 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -27,6 +27,7 @@ namespace clang { class ObjCImplicitSetterGetterRefExpr; namespace CodeGen { + class CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a @@ -128,14 +129,11 @@ class LValue { llvm::Constant *VectorElts; // BitField start bit and size - struct { - unsigned short StartBit; - unsigned short Size; - bool IsSigned; - } BitfieldData; + const CGBitFieldInfo *BitFieldInfo; // Obj-C property reference expression const ObjCPropertyRefExpr *PropertyRefExpr; + // ObjC 'implicit' property reference expression const ObjCImplicitSetterGetterRefExpr *KVCRefExpr; }; @@ -170,7 +168,7 @@ private: public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } - bool isBitfield() const { return LVType == BitField; } + bool isBitField() const { return LVType == BitField; } bool isExtVectorElt() const { return LVType == ExtVectorElt; } bool isPropertyRef() const { return LVType == PropertyRef; } bool isKVCRef() const { return LVType == KVCRef; } @@ -209,29 +207,28 @@ public: // simple lvalue llvm::Value *getAddress() const { assert(isSimple()); return V; } + // vector elt lvalue llvm::Value *getVectorAddr() const { assert(isVectorElt()); return V; } llvm::Value *getVectorIdx() const { assert(isVectorElt()); return VectorIdx; } + // extended vector elements. llvm::Value *getExtVectorAddr() const { assert(isExtVectorElt()); return V; } llvm::Constant *getExtVectorElts() const { assert(isExtVectorElt()); return VectorElts; } + // bitfield lvalue - llvm::Value *getBitfieldAddr() const { assert(isBitfield()); return V; } - unsigned short getBitfieldStartBit() const { - assert(isBitfield()); - return BitfieldData.StartBit; - } - unsigned short getBitfieldSize() const { - assert(isBitfield()); - return BitfieldData.Size; + llvm::Value *getBitFieldAddr() const { + assert(isBitField()); + return V; } - bool isBitfieldSigned() const { - assert(isBitfield()); - return BitfieldData.IsSigned; + const CGBitFieldInfo &getBitFieldInfo() const { + assert(isBitField()); + return *BitFieldInfo; } + // property ref lvalue const ObjCPropertyRefExpr *getPropertyRefExpr() const { assert(isPropertyRef()); @@ -272,15 +269,12 @@ public: return R; } - static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit, - unsigned short Size, bool IsSigned, + static LValue MakeBitfield(llvm::Value *V, const CGBitFieldInfo &Info, unsigned CVR) { LValue R; R.LVType = BitField; R.V = V; - R.BitfieldData.StartBit = StartBit; - R.BitfieldData.Size = Size; - R.BitfieldData.IsSigned = IsSigned; + R.BitFieldInfo = &Info; R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index b863aff23612..f38d8a132f02 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -495,12 +495,14 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { const llvm::Type *IntPtr = llvm::IntegerType::get(VMContext, LLVMPointerWidth); - Builder.CreateCall4(CGM.getMemSetFn(), DestPtr, + Builder.CreateCall5(CGM.getMemSetFn(BP, IntPtr), DestPtr, llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)), // TypeInfo.first describes size in bits. llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), - TypeInfo.second/8)); + TypeInfo.second/8), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), + 0)); } llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) { diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 3c872c8560d2..a2ad31e85a80 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -47,8 +47,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M), TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags), Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()), - MangleCtx(C), VTables(*this), Runtime(0), - MemCpyFn(0), MemMoveFn(0), MemSetFn(0), CFConstantStringClassRef(0), + MangleCtx(C), VTables(*this), Runtime(0), CFConstantStringClassRef(0), VMContext(M.getContext()) { if (!Features.ObjC1) @@ -1414,22 +1413,25 @@ llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys, (llvm::Intrinsic::ID)IID, Tys, NumTys); } -llvm::Function *CodeGenModule::getMemCpyFn() { - if (MemCpyFn) return MemCpyFn; - const llvm::Type *IntPtr = TheTargetData.getIntPtrType(VMContext); - return MemCpyFn = getIntrinsic(llvm::Intrinsic::memcpy, &IntPtr, 1); + +llvm::Function *CodeGenModule::getMemCpyFn(const llvm::Type *DestType, + const llvm::Type *SrcType, + const llvm::Type *SizeType) { + const llvm::Type *ArgTypes[3] = {DestType, SrcType, SizeType }; + return getIntrinsic(llvm::Intrinsic::memcpy, ArgTypes, 3); } -llvm::Function *CodeGenModule::getMemMoveFn() { - if (MemMoveFn) return MemMoveFn; - const llvm::Type *IntPtr = TheTargetData.getIntPtrType(VMContext); - return MemMoveFn = getIntrinsic(llvm::Intrinsic::memmove, &IntPtr, 1); +llvm::Function *CodeGenModule::getMemMoveFn(const llvm::Type *DestType, + const llvm::Type *SrcType, + const llvm::Type *SizeType) { + const llvm::Type *ArgTypes[3] = {DestType, SrcType, SizeType }; + return getIntrinsic(llvm::Intrinsic::memmove, ArgTypes, 3); } -llvm::Function *CodeGenModule::getMemSetFn() { - if (MemSetFn) return MemSetFn; - const llvm::Type *IntPtr = TheTargetData.getIntPtrType(VMContext); - return MemSetFn = getIntrinsic(llvm::Intrinsic::memset, &IntPtr, 1); +llvm::Function *CodeGenModule::getMemSetFn(const llvm::Type *DestType, + const llvm::Type *SizeType) { + const llvm::Type *ArgTypes[2] = { DestType, SizeType }; + return getIntrinsic(llvm::Intrinsic::memset, ArgTypes, 2); } static llvm::StringMapEntry<llvm::Constant*> & diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 3c57c0b8cbfc..e9f78bcdb0a5 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -97,10 +97,6 @@ class CodeGenModule : public BlockModule { CGObjCRuntime* Runtime; CGDebugInfo* DebugInfo; - - llvm::Function *MemCpyFn; - llvm::Function *MemMoveFn; - llvm::Function *MemSetFn; // WeakRefReferences - A set of references that have only been seen via // a weakref so far. This is used to remove the weak of the reference if we ever @@ -290,9 +286,17 @@ public: llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD, unsigned BuiltinID); - llvm::Function *getMemCpyFn(); - llvm::Function *getMemMoveFn(); - llvm::Function *getMemSetFn(); + llvm::Function *getMemCpyFn(const llvm::Type *DestType, + const llvm::Type *SrcType, + const llvm::Type *SizeType); + + llvm::Function *getMemMoveFn(const llvm::Type *DestType, + const llvm::Type *SrcType, + const llvm::Type *SizeType); + + llvm::Function *getMemSetFn(const llvm::Type *DestType, + const llvm::Type *SizeType); + llvm::Function *getIntrinsic(unsigned IID, const llvm::Type **Tys = 0, unsigned NumTys = 0); diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index 2228ea45df33..b0faf0ae86b1 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -12,6 +12,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTImporter.h" +#include "clang/Basic/Diagnostic.h" using namespace clang; @@ -36,9 +37,9 @@ void ASTMergeAction::ExecuteAction() { CI.getASTContext().getLangOptions()); CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &CI.getASTContext()); + llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { - ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], CI.getDiagnostics(), - false); + ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], Diags, false); if (!Unit) continue; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 7243f709cc65..427bd6a9b803 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -35,10 +35,9 @@ #include "llvm/System/Path.h" using namespace clang; -ASTUnit::ASTUnit(Diagnostic &Diag, bool _MainFileIsAST) - : SourceMgr(Diag), MainFileIsAST(_MainFileIsAST), - ConcurrencyCheckValue(CheckUnlocked) { -} +ASTUnit::ASTUnit(bool _MainFileIsAST) + : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { } + ASTUnit::~ASTUnit() { ConcurrencyCheckValue = CheckLocked; for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) @@ -142,18 +141,29 @@ const std::string &ASTUnit::getPCHFileName() { } ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, - Diagnostic &Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool CaptureDiagnostics) { - llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags, true)); + llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true)); + + if (!Diags.getPtr()) { + // No diagnostics engine was provided, so create our own diagnostics object + // with the default options. + DiagnosticOptions DiagOpts; + Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); + } + AST->OnlyLocalDecls = OnlyLocalDecls; + AST->Diagnostics = Diags; + AST->FileMgr.reset(new FileManager); + AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics())); AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager())); // If requested, capture diagnostics in the ASTUnit. - CaptureDroppedDiagnostics Capture(CaptureDiagnostics, Diags, - AST->Diagnostics); + CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(), + AST->StoredDiagnostics); for (unsigned I = 0; I != NumRemappedFiles; ++I) { // Create the file entry for the file that we're mapping from. @@ -162,7 +172,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, RemappedFiles[I].second->getBufferSize(), 0); if (!FromFile) { - Diags.Report(diag::err_fe_remap_missing_from_file) + AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file) << RemappedFiles[I].first; delete RemappedFiles[I].second; continue; @@ -186,7 +196,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, llvm::OwningPtr<ExternalASTSource> Source; Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(), - Diags)); + AST->getDiagnostics())); Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple, Predefines, Counter)); @@ -196,7 +206,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, case PCHReader::Failure: case PCHReader::IgnorePCH: - Diags.Report(diag::err_fe_unable_to_load_pch); + AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch); return NULL; } @@ -212,8 +222,10 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, TargetOpts.CPU = ""; TargetOpts.Features.clear(); TargetOpts.Triple = TargetTriple; - AST->Target.reset(TargetInfo::CreateTargetInfo(Diags, TargetOpts)); - AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(), + AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(), + TargetOpts)); + AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo, + *AST->Target.get(), AST->getSourceManager(), HeaderInfo)); Preprocessor &PP = *AST->PP.get(); @@ -276,7 +288,7 @@ public: } ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, - Diagnostic &Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, bool OnlyLocalDecls, bool CaptureDiagnostics) { // Create the compiler instance to use for building the AST. @@ -284,17 +296,23 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, llvm::OwningPtr<ASTUnit> AST; llvm::OwningPtr<TopLevelDeclTrackerAction> Act; + if (!Diags.getPtr()) { + // No diagnostics engine was provided, so create our own diagnostics object + // with the default options. + DiagnosticOptions DiagOpts; + Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); + } + Clang.setInvocation(CI); - Clang.setDiagnostics(&Diags); - Clang.setDiagnosticClient(Diags.getClient()); + Clang.setDiagnostics(Diags.getPtr()); + Clang.setDiagnosticClient(Diags->getClient()); // Create the target instance. Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), Clang.getTargetOpts())); if (!Clang.hasTarget()) { Clang.takeDiagnosticClient(); - Clang.takeDiagnostics(); return 0; } @@ -310,14 +328,17 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, "FIXME: AST inputs not yet supported here!"); // Create the AST unit. - AST.reset(new ASTUnit(Diags, false)); + AST.reset(new ASTUnit(false)); + AST->Diagnostics = Diags; + AST->FileMgr.reset(new FileManager); + AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics())); AST->OnlyLocalDecls = OnlyLocalDecls; AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second; // Capture any diagnostics that would otherwise be dropped. CaptureDroppedDiagnostics Capture(CaptureDiagnostics, Clang.getDiagnostics(), - AST->Diagnostics); + AST->StoredDiagnostics); // Create a file manager object to provide access to and cache the filesystem. Clang.setFileManager(&AST->getFileManager()); @@ -346,7 +367,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, Act->EndSourceFile(); Clang.takeDiagnosticClient(); - Clang.takeDiagnostics(); Clang.takeInvocation(); AST->Invocation.reset(Clang.takeInvocation()); @@ -356,18 +376,24 @@ error: Clang.takeSourceManager(); Clang.takeFileManager(); Clang.takeDiagnosticClient(); - Clang.takeDiagnostics(); return 0; } ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, - Diagnostic &Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags, llvm::StringRef ResourceFilesPath, bool OnlyLocalDecls, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool CaptureDiagnostics) { + if (!Diags.getPtr()) { + // No diagnostics engine was provided, so create our own diagnostics object + // with the default options. + DiagnosticOptions DiagOpts; + Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); + } + llvm::SmallVector<const char *, 16> Args; Args.push_back("<clang>"); // FIXME: Remove dummy argument. Args.insert(Args.end(), ArgBegin, ArgEnd); @@ -378,7 +404,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, // FIXME: We shouldn't have to pass in the path info. driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(), - "a.out", false, false, Diags); + "a.out", false, false, *Diags); // Don't check that inputs exist, they have been remapped. TheDriver.setCheckInputsExist(false); @@ -393,13 +419,13 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, llvm::SmallString<256> Msg; llvm::raw_svector_ostream OS(Msg); C->PrintJob(OS, C->getJobs(), "; ", true); - Diags.Report(diag::err_fe_expected_compiler_job) << OS.str(); + Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); return 0; } const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin()); if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") { - Diags.Report(diag::err_fe_expected_clang_command); + Diags->Report(diag::err_fe_expected_clang_command); return 0; } @@ -407,7 +433,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation); CompilerInvocation::CreateFromArgs(*CI, (const char**) CCArgs.data(), (const char**) CCArgs.data()+CCArgs.size(), - Diags); + *Diags); // Override any files that need remapping for (unsigned I = 0; I != NumRemappedFiles; ++I) diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 879e9f681de9..1f915e3713d3 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -52,7 +52,7 @@ void CompilerInstance::setInvocation(CompilerInvocation *Value) { } void CompilerInstance::setDiagnostics(Diagnostic *Value) { - Diagnostics.reset(Value); + Diagnostics = Value; } void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) { @@ -130,15 +130,16 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, } void CompilerInstance::createDiagnostics(int Argc, char **Argv) { - Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv)); + Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv); if (Diagnostics) DiagClient.reset(Diagnostics->getClient()); } -Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, - int Argc, char **Argv) { - llvm::OwningPtr<Diagnostic> Diags(new Diagnostic()); +llvm::IntrusiveRefCntPtr<Diagnostic> +CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, + int Argc, char **Argv) { + llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic()); // Create the diagnostic client for reporting errors or for // implementing -verify. @@ -152,7 +153,7 @@ Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); Diags->setClient(DiagClient.take()); Diags->Report(diag::err_fe_stderr_binary); - return Diags.take(); + return Diags; } else { DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs())); } @@ -171,7 +172,7 @@ Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // Configure our handling of diagnostics. ProcessWarningOptions(*Diags, Opts); - return Diags.take(); + return Diags; } // File Manager diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 110612d03b58..87fc1227b2f2 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -45,8 +45,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, "Attempt to pass AST file to preprocessor only action!"); assert(hasASTSupport() && "This action does not have AST support!"); + llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics()); std::string Error; - ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, CI.getDiagnostics()); + ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, Diags); if (!AST) goto failure; @@ -135,7 +136,7 @@ void FrontendAction::Execute() { // simplest way to reuse the logic in ParseAST. const char *EmptyStr = ""; llvm::MemoryBuffer *SB = - llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>"); + llvm::MemoryBuffer::getMemBuffer(EmptyStr, "<dummy input>"); CI.getSourceManager().createMainFileIDForMemBuffer(SB); } else { if (!CI.InitializeSourceManager(getCurrentFile())) diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 6d39952e9d27..b96c04d0a8e0 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -950,9 +950,8 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { } llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(BlobStart, - BlobStart + BlobLen - 1, - Name); + = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1), + Name); FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); if (strcmp(Name, "<built-in>") == 0) { diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 8b4b1ddf4149..4598383c1c93 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -258,9 +258,10 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File, // Truncate the buffer. if (Position < Buffer->getBufferEnd()) { + llvm::StringRef Data(Buffer->getBufferStart(), + Position-Buffer->getBufferStart()); MemoryBuffer *TruncatedBuffer - = MemoryBuffer::getMemBufferCopy(Buffer->getBufferStart(), Position, - Buffer->getBufferIdentifier()); + = MemoryBuffer::getMemBufferCopy(Data, Buffer->getBufferIdentifier()); SourceMgr.overrideFileContents(File, TruncatedBuffer); } @@ -508,9 +509,7 @@ bool Preprocessor::EnterMainSourceFile() { // Preprocess Predefines to populate the initial preprocessor state. llvm::MemoryBuffer *SB = - llvm::MemoryBuffer::getMemBufferCopy(Predefines.data(), - Predefines.data() + Predefines.size(), - "<built-in>"); + llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>"); assert(SB && "Cannot fail to create predefined source buffer"); FileID FID = SourceMgr.createFileIDForMemBuffer(SB); assert(!FID.isInvalid() && "Could not create FileID for predefines?"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e87d052141cc..c85b6ee9746c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -334,7 +334,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList); + return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -348,10 +348,11 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, /// [OMP] threadprivate-directive [TODO] /// /// If RequireSemi is false, this does not check for a ';' at the end of the -/// declaration. +/// declaration. If it is true, it checks for and eats it. Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, SourceLocation &DeclEnd, - AttributeList *Attr) { + AttributeList *Attr, + bool RequireSemi) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); if (Attr) @@ -362,15 +363,13 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { - ConsumeToken(); + if (RequireSemi) ConsumeToken(); DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); DS.complete(TheDecl); return Actions.ConvertDeclToDeclGroup(TheDecl); } - DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, - &DeclEnd); - return DG; + return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd); } /// ParseDeclGroup - Having concluded that this is either a function @@ -999,6 +998,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DiagID, Tok.getAnnotationValue()); else DS.SetTypeSpecError(); + + if (isInvalid) + break; + DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeToken(); // The typename diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index b752b48cfd49..b208c50c81bc 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -997,7 +997,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd, - AttrList); + AttrList, false); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (Tok.is(tok::semi)) { // for (int x = 4; diff --git a/lib/Runtime/Makefile b/lib/Runtime/Makefile new file mode 100644 index 000000000000..9a3c34719cfb --- /dev/null +++ b/lib/Runtime/Makefile @@ -0,0 +1,99 @@ +##===- clang/lib/Runtime/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This file defines support for building the Clang runtime libraries (which are +# implemented by compiler-rt) and placing them in the proper locations in the +# Clang resources directory (i.e., where the driver expects them). +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +include $(LEVEL)/Makefile.common + +CLANG_VERSION := $(shell cat $(PROJ_SRC_DIR)/../../VER) +ResourceDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/lib/clang/$(CLANG_VERSION) +PROJ_resources := $(DESTDIR)$(PROJ_prefix)/lib/clang/$(CLANG_VERSION) + +ResourceLibDir := $(ResourceDir)/lib +PROJ_resources_lib := $(PROJ_resources)/lib + +# Expect compiler-rt to be in llvm/projects/compiler-rt +COMPILERRT_SRC_ROOT := $(LLVM_SRC_ROOT)/projects/compiler-rt + +ifeq ($(shell test -d $(COMPILERRT_SRC_ROOT) && echo OK),OK) + +# Select the compiler-rt configuration to use, and install directory. +# +# FIXME: Eventually, we want some kind of configure support for this. We want to +# build/install runtime libraries for as many targets as clang was configured to +# support. +RuntimeDirs := +ifeq ($(OS),Darwin) +RuntimeDirs += darwin +RuntimeLibrary.darwin.Configs = 10.4 armv6 cc_kext +endif + +# Rule to build the compiler-rt libraries we need. +# +# We build all the libraries in a single shot to avoid recursive make as much as +# possible. +BuildRuntimeLibraries: + $(Verb) $(MAKE) -C $(COMPILERRT_SRC_ROOT) \ + ProjSrcRoot=$(COMPILERRT_SRC_ROOT) \ + ProjObjRoot=$(PROJ_OBJ_DIR) \ + $(RuntimeDirs:%=clang_%) +.PHONY: BuildRuntimeLibraries +CleanRuntimeLibraries: + $(Verb) $(MAKE) -C $(COMPILERRT_SRC_ROOT) \ + ProjSrcRoot=$(COMPILERRT_SRC_ROOT) \ + ProjObjRoot=$(PROJ_OBJ_DIR) \ + clean +.PHONY: CleanRuntimeLibraries + +$(PROJ_resources_lib): + $(Verb) $(MKDIR) $@ + +# Expand rules for copying/installing each individual library. We can't use +# implicit rules here because we need to match against multiple things. +define RuntimeLibraryTemplate +$(PROJ_OBJ_DIR)/clang_$1/%/libcompiler_rt.a: BuildRuntimeLibraries + @true +.PRECIOUS: $(PROJ_OBJ_DIR)/clang_$1/%/libcompiler_rt.a + +# Rule to copy the libraries to their resource directory location. +$(ResourceLibDir)/$1/libclang_rt.%.a: \ + $(PROJ_OBJ_DIR)/clang_$1/%/libcompiler_rt.a \ + $(ResourceLibDir)/$1/.dir + $(Echo) Copying runtime library $1/$$* to build dir + $(Verb) cp $(PROJ_OBJ_DIR)/clang_$1/$$*/libcompiler_rt.a $$@ +RuntimeLibrary.$1: \ + $(RuntimeLibrary.$1.Configs:%=$(ResourceLibDir)/$1/libclang_rt.%.a) +.PHONY: RuntimeLibrary.$1 + +$(PROJ_resources_lib)/$1: $(PROJ_resources_lib) + $(Verb) $(MKDIR) $$@ + +$(PROJ_resources_lib)/$1/libclang_rt.%.a: \ + $(ResourceLibDir)/$1/libclang_rt.%.a | $(PROJ_resources_lib)/$1 + $(Echo) Installing compiler runtime library: $1/$$* + $(Verb) $(DataInstall) $$< $(PROJ_resources_lib)/$1 + +# Rule to install runtime libraries. +RuntimeLibraryInstall.$1: \ + $(RuntimeLibrary.$1.Configs:%=$(PROJ_resources_lib)/$1/libclang_rt.%.a) +.PHONY: RuntimeLibraryInstall.$1 +endef +$(foreach lib,$(RuntimeDirs), $(eval $(call RuntimeLibraryTemplate,$(lib)))) + +# Hook into the standard Makefile rules. +all-local:: $(RuntimeDirs:%=RuntimeLibrary.%) +install-local:: $(RuntimeDirs:%=RuntimeLibraryInstall.%) +clean-local:: CleanRuntimeLibraries + +endif diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 299e84e33eff..5483a292e955 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -582,9 +582,12 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, break; } break; - - case Result::RK_Keyword: + case Result::RK_Macro: + Kind = CXCursor_MacroDefinition; + break; + + case Result::RK_Keyword: case Result::RK_Pattern: Kind = CXCursor_NotImplemented; break; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 317eef8d60fc..df14aa7fc5a4 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1338,8 +1338,11 @@ static void AddResultTypeChunk(ASTContext &Context, if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) return; + PrintingPolicy Policy(Context.PrintingPolicy); + Policy.AnonymousTagLocations = false; + std::string TypeStr; - T.getAsStringInternal(TypeStr, Context.PrintingPolicy); + T.getAsStringInternal(TypeStr, Policy); Result->AddResultTypeChunk(TypeStr); } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 52b9bcf86c8d..cda1f0be2023 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -160,7 +160,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, PIDecl->getSetterName(), DeclPtrTy::make(CCPrimary), isOverridingProperty, MethodImplKind); - PIDecl = ProtocolPtrTy.getAs<ObjCPropertyDecl>(); + PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy.getAs<Decl>()); } PIDecl->makeitReadWriteAttribute(); if (Attributes & ObjCDeclSpec::DQ_PR_retain) @@ -281,7 +281,8 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, DeclPtrTy ClassCatImpDecl, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar) { - ObjCContainerDecl *ClassImpDecl = ClassCatImpDecl.getAs<ObjCContainerDecl>(); + ObjCContainerDecl *ClassImpDecl = + cast_or_null<ObjCContainerDecl>(ClassCatImpDecl.getAs<Decl>()); // Make sure we have a context for the property implementation declaration. if (!ClassImpDecl) { Diag(AtLoc, diag::error_missing_property_context); @@ -984,7 +985,10 @@ void Sema::CheckObjCPropertyAttributes(DeclPtrTy PropertyPtrTy, unsigned &Attributes) { // FIXME: Improve the reported location. Decl *PDecl = PropertyPtrTy.getAs<Decl>(); - ObjCPropertyDecl *PropertyDecl = dyn_cast_or_null<ObjCPropertyDecl>(PDecl); + if (!PDecl) + return; + + ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); QualType PropertyTy = PropertyDecl->getType(); // readonly and readwrite/assign/retain/copy conflict. diff --git a/test/Analysis/inline4.c b/test/Analysis/inline4.c new file mode 100644 index 000000000000..dd2379f04381 --- /dev/null +++ b/test/Analysis/inline4.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f -verify %s + +int g(int a) { + return a; +} + +int f(int a) { + // Do not remove block-level expression bindings of caller when analyzing + // in the callee. + if (1 && g(a)) // The binding of '1 && g(a)' which is an UndefinedVal + // carries important information. + return 1; + return 0; +} diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c index bf1c806a2c47..ace0db9af6d4 100644 --- a/test/CodeGen/asm.c +++ b/test/CodeGen/asm.c @@ -135,3 +135,15 @@ int t18(unsigned data) { // CHECK-NEXT: extractvalue // CHECK-NEXT: extractvalue } + + +// PR6780 +int t19(unsigned data) { + int a, b; + + asm("x{abc|def|ghi}z" :"=r"(a): "r"(data)); + return a + b; + // CHECK: t19(i32 + // CHECK: = call {{.*}}asm "x$(abc$|def$|ghi$)z" +} + diff --git a/test/CodeGen/builtin-memfns.c b/test/CodeGen/builtin-memfns.c index a7b716b931c7..e8c407fd6f27 100644 --- a/test/CodeGen/builtin-memfns.c +++ b/test/CodeGen/builtin-memfns.c @@ -1,9 +1,11 @@ -// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o %t %s -// RUN: grep '@llvm.memset.i32' %t -// RUN: grep '@llvm.memcpy.i32' %t -// RUN: grep '@llvm.memmove.i32' %t -// RUN: grep __builtin %t | count 0 +// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm < %s| FileCheck %s +// CHECK: call void @llvm.memset.p0i8.i32 +// CHECK: call void @llvm.memset.p0i8.i32 +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 +// CHECK: call void @llvm.memmove.p0i8.p0i8.i32 +// CHECK-NOT: __builtin +// CHECK: ret int main(int argc, char **argv) { unsigned char a = 0x11223344; unsigned char b = 0x11223344; diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp index d233525f0a48..afd9da698646 100644 --- a/test/CodeGenCXX/eh.cpp +++ b/test/CodeGenCXX/eh.cpp @@ -15,7 +15,7 @@ void test1() { // CHECK-NEXT: store i8* %{{exception|2}}, i8** %{{exception.ptr|1}} // CHECK-NEXT: %{{0|3}} = bitcast i8* %{{exception|2}} to %struct.test1_D* // CHECK-NEXT: %{{tmp|4}} = bitcast %struct.test1_D* %{{0|3}} to i8* -// CHECK-NEXT: call void @llvm.memcpy.i64(i8* %{{tmp|4}}, i8* bitcast (%struct.test1_D* @d1 to i8*), i64 8, i32 8) +// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{tmp|4}}, i8* bitcast (%struct.test1_D* @d1 to i8*), i64 8, i32 8, i1 false) // CHECK-NEXT: call void @__cxa_throw(i8* %{{exception|2}}, i8* bitcast (%0* @_ZTI7test1_D to i8*), i8* null) noreturn // CHECK-NEXT: unreachable diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 6ea12eb5f6ba..ca7c52f2cc0d 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -93,6 +93,6 @@ A* t10() { struct B { }; void t11() { // CHECK: call noalias i8* @_Znwm - // CHECK: call void @llvm.memset.i64( + // CHECK: call void @llvm.memset.p0i8.i64( B* b = new B(); } diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp index 8b6e43fd8ec0..37891bd6af67 100644 --- a/test/CodeGenCXX/value-init.cpp +++ b/test/CodeGenCXX/value-init.cpp @@ -18,7 +18,7 @@ void test_value_init() { // PR5800 // CHECK: store i32 17 - // CHECK: call void @llvm.memset.i64 + // CHECK: call void @llvm.memset.p0i8.i64 // CHECK: call void @_ZN1BC1Ev C c = { 17 } ; // CHECK: call void @_ZN1CD1Ev diff --git a/test/CodeGenObjC/property-dbg.m b/test/CodeGenObjC/property-dbg.m new file mode 100644 index 000000000000..5bbb04644e05 --- /dev/null +++ b/test/CodeGenObjC/property-dbg.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -S -g -masm-verbose -x objective-c < %s | grep setI | grep DW_AT_name +@interface Foo { + int i; +} +@property int i; +@end + +@implementation Foo +@synthesize i; +@end + +int bar(Foo *f) { + int i = 1; + f.i = 2; + i = f.i; + return i; +} diff --git a/test/Index/complete-enums.c b/test/Index/complete-enums.c new file mode 100644 index 000000000000..5e712a11227f --- /dev/null +++ b/test/Index/complete-enums.c @@ -0,0 +1,15 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +enum { + Red = 17, + Green, + Blue +}; + +void f() { + +} + +// RUN: c-index-test -code-completion-at=%s:11:1 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: EnumConstantDecl:{ResultType enum <anonymous>}{TypedText Red} diff --git a/test/Index/complete-macros.c b/test/Index/complete-macros.c new file mode 100644 index 000000000000..c33d8c02e13b --- /dev/null +++ b/test/Index/complete-macros.c @@ -0,0 +1,11 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +#define FOO(Arg1,Arg2) foobar + +void f() { + +} + +// RUN: c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: macro definition:{TypedText FOO}{LeftParen (}{Placeholder Arg1}{Comma , }{Placeholder Arg2}{RightParen )} diff --git a/test/Makefile b/test/Makefile index b7cb38af8af0..e9d89454b898 100644 --- a/test/Makefile +++ b/test/Makefile @@ -18,7 +18,7 @@ ifndef TESTARGS ifdef VERBOSE TESTARGS = -v else -TESTARGS = -s +TESTARGS = -s -v endif endif diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp index c8f2c0b76903..ae004ce81c1d 100644 --- a/test/Parser/cxx-decl.cpp +++ b/test/Parser/cxx-decl.cpp @@ -62,3 +62,13 @@ struct test4 { // PR5825 struct test5 {}; ::new(static_cast<void*>(0)) test5; // expected-error {{expected unqualified-id}} + + +// PR6782 +template<class T> +class Class1; + +class Class2 { +} // no ; + +typedef Class1<Class2> Type1; // expected-error {{cannot combine with previous 'class' declaration specifier}} diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 998fbbba22b6..01130e22773d 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -996,11 +996,8 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); - // Configure the diagnostics. - DiagnosticOptions DiagOpts; - llvm::OwningPtr<Diagnostic> Diags; - Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0)); - return ASTUnit::LoadFromPCHFile(ast_filename, *Diags, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags; + return ASTUnit::LoadFromPCHFile(ast_filename, Diags, CXXIdx->getOnlyLocalDecls(), 0, 0, true); } @@ -1019,15 +1016,14 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, // Configure the diagnostics. DiagnosticOptions DiagOpts; - llvm::OwningPtr<Diagnostic> Diags; - Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0)); + llvm::IntrusiveRefCntPtr<Diagnostic> Diags; + Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles; for (unsigned I = 0; I != num_unsaved_files; ++I) { + llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); const llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBufferCopy(unsaved_files[I].Contents, - unsaved_files[I].Contents + unsaved_files[I].Length, - unsaved_files[I].Filename); + = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename, Buffer)); } @@ -1052,7 +1048,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, llvm::OwningPtr<ASTUnit> Unit( ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(), - *Diags, + Diags, CXXIdx->getClangResourcesPath(), CXXIdx->getOnlyLocalDecls(), RemappedFiles.data(), @@ -1064,8 +1060,8 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, if (NumErrors != Diags->getNumErrors()) { // Make sure to check that 'Unit' is non-NULL. if (CXXIdx->getDisplayDiagnostics() && Unit.get()) { - for (ASTUnit::diag_iterator D = Unit->diag_begin(), - DEnd = Unit->diag_end(); + for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(), + DEnd = Unit->stored_diag_end(); D != DEnd; ++D) { CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions()); CXString Msg = clang_formatDiagnostic(&Diag, @@ -1169,7 +1165,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg; } - ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, *Diags, + ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, Diags, CXXIdx->getOnlyLocalDecls(), RemappedFiles.data(), RemappedFiles.size(), @@ -1179,7 +1175,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, num_unsaved_files, unsaved_files, ATU->getFileManager(), ATU->getSourceManager(), - ATU->getDiagnostics()); + ATU->getStoredDiagnostics()); } else if (CXXIdx->getDisplayDiagnostics()) { // We failed to load the ASTUnit, but we can still deserialize the // diagnostics and emit them. @@ -2333,7 +2329,7 @@ void clang_annotateTokens(CXTranslationUnit TU, RegionOfInterest.setBegin( cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0]))); SourceLocation End - = cxloc::translateSourceLocation(clang_getTokenLocation(TU, + = cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[NumTokens - 1])); RegionOfInterest.setEnd(CXXUnit->getPreprocessor().getLocForEndOfToken(End)); diff --git a/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp index 264e5064ddb4..d11b8dfb50f7 100644 --- a/tools/CIndex/CIndexCodeCompletion.cpp +++ b/tools/CIndex/CIndexCodeCompletion.cpp @@ -231,8 +231,8 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, // Configure the diagnostics. DiagnosticOptions DiagOpts; - llvm::OwningPtr<Diagnostic> Diags; - Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0)); + llvm::IntrusiveRefCntPtr<Diagnostic> Diags; + Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0); // The set of temporary files that we've built. std::vector<llvm::sys::Path> TemporaryFiles; diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp index 0314a67d07d1..bcf066daf217 100644 --- a/tools/CIndex/CIndexDiagnostic.cpp +++ b/tools/CIndex/CIndexDiagnostic.cpp @@ -32,15 +32,15 @@ extern "C" { unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit); - return CXXUnit? CXXUnit->diag_size() : 0; + return CXXUnit? CXXUnit->stored_diag_size() : 0; } CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit); - if (!CXXUnit || Index >= CXXUnit->diag_size()) + if (!CXXUnit || Index >= CXXUnit->stored_diag_size()) return 0; - return new CXStoredDiagnostic(CXXUnit->diag_begin()[Index], + return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index], CXXUnit->getASTContext().getLangOptions()); } diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 35854bea057e..dd440f5227b4 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -211,6 +211,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd, // Initialize targets first, so that --version shows registered targets. llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllAsmParsers(); // Buffer diagnostics from argument parsing so that we can output them using a // well formed diagnostic object. |