aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/APValue.h253
-rw-r--r--include/clang/AST/AST.h28
-rw-r--r--include/clang/AST/ASTConsumer.h81
-rw-r--r--include/clang/AST/ASTContext.h857
-rw-r--r--include/clang/AST/ASTDiagnostic.h27
-rw-r--r--include/clang/AST/Attr.h506
-rw-r--r--include/clang/AST/Builtins.def389
-rw-r--r--include/clang/AST/Builtins.h137
-rw-r--r--include/clang/AST/CFG.h405
-rw-r--r--include/clang/AST/Decl.h1409
-rw-r--r--include/clang/AST/DeclBase.h900
-rw-r--r--include/clang/AST/DeclCXX.h1073
-rw-r--r--include/clang/AST/DeclContextInternals.h220
-rw-r--r--include/clang/AST/DeclGroup.h152
-rw-r--r--include/clang/AST/DeclNodes.def161
-rw-r--r--include/clang/AST/DeclObjC.h1224
-rw-r--r--include/clang/AST/DeclTemplate.h859
-rw-r--r--include/clang/AST/DeclVisitor.h54
-rw-r--r--include/clang/AST/DeclarationName.h357
-rw-r--r--include/clang/AST/Expr.h2500
-rw-r--r--include/clang/AST/ExprCXX.h1234
-rw-r--r--include/clang/AST/ExprObjC.h494
-rw-r--r--include/clang/AST/ExternalASTSource.h184
-rw-r--r--include/clang/AST/NestedNameSpecifier.h183
-rw-r--r--include/clang/AST/PPCBuiltins.def24
-rw-r--r--include/clang/AST/ParentMap.h50
-rw-r--r--include/clang/AST/PrettyPrinter.h86
-rw-r--r--include/clang/AST/RecordLayout.h103
-rw-r--r--include/clang/AST/Stmt.h1223
-rw-r--r--include/clang/AST/StmtCXX.h100
-rw-r--r--include/clang/AST/StmtGraphTraits.h83
-rw-r--r--include/clang/AST/StmtIterator.h145
-rw-r--r--include/clang/AST/StmtNodes.def156
-rw-r--r--include/clang/AST/StmtObjC.h307
-rw-r--r--include/clang/AST/StmtVisitor.h176
-rw-r--r--include/clang/AST/TargetBuiltins.h38
-rw-r--r--include/clang/AST/TemplateName.h258
-rw-r--r--include/clang/AST/Type.h1977
-rw-r--r--include/clang/AST/TypeNodes.def85
-rw-r--r--include/clang/AST/TypeOrdering.h63
-rw-r--r--include/clang/AST/X86Builtins.def427
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h119
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h74
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h27
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h291
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowValues.h172
-rw-r--r--include/clang/Analysis/LocalCheckers.h54
-rw-r--r--include/clang/Analysis/PathDiagnostic.h487
-rw-r--r--include/clang/Analysis/PathSensitive/BasicValueFactory.h163
-rw-r--r--include/clang/Analysis/PathSensitive/BugReporter.h466
-rw-r--r--include/clang/Analysis/PathSensitive/ConstraintManager.h67
-rw-r--r--include/clang/Analysis/PathSensitive/Environment.h151
-rw-r--r--include/clang/Analysis/PathSensitive/ExplodedGraph.h582
-rw-r--r--include/clang/Analysis/PathSensitive/GRAuditor.h39
-rw-r--r--include/clang/Analysis/PathSensitive/GRBlockCounter.h50
-rw-r--r--include/clang/Analysis/PathSensitive/GRCoreEngine.h668
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h738
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h101
-rw-r--r--include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h40
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h820
-rw-r--r--include/clang/Analysis/PathSensitive/GRStateTrait.h148
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h123
-rw-r--r--include/clang/Analysis/PathSensitive/GRWorkList.h76
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h665
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h447
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h204
-rw-r--r--include/clang/Analysis/PathSensitive/SymbolManager.h329
-rw-r--r--include/clang/Analysis/PathSensitive/ValueManager.h103
-rw-r--r--include/clang/Analysis/ProgramPoint.h351
-rw-r--r--include/clang/Analysis/Support/BlkExprDeclBitVector.h307
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h91
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtVisitor.h35
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h156
-rw-r--r--include/clang/Analysis/Visitors/CFGVarDeclVisitor.h64
-rw-r--r--include/clang/Basic/CMakeLists.txt20
-rw-r--r--include/clang/Basic/ConvertUTF.h159
-rw-r--r--include/clang/Basic/Diagnostic.h697
-rw-r--r--include/clang/Basic/Diagnostic.td73
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td29
-rw-r--r--include/clang/Basic/DiagnosticAnalysisKinds.td15
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td58
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td64
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td136
-rw-r--r--include/clang/Basic/DiagnosticGroups.td133
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td277
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td280
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td1822
-rw-r--r--include/clang/Basic/FileManager.h178
-rw-r--r--include/clang/Basic/IdentifierTable.h561
-rw-r--r--include/clang/Basic/LangOptions.h157
-rw-r--r--include/clang/Basic/Makefile22
-rw-r--r--include/clang/Basic/OnDiskHashTable.h362
-rw-r--r--include/clang/Basic/OperatorKinds.def106
-rw-r--r--include/clang/Basic/OperatorKinds.h32
-rw-r--r--include/clang/Basic/PrettyStackTrace.h37
-rw-r--r--include/clang/Basic/SourceLocation.h305
-rw-r--r--include/clang/Basic/SourceManager.h714
-rw-r--r--include/clang/Basic/SourceManagerInternals.h130
-rw-r--r--include/clang/Basic/TargetInfo.h391
-rw-r--r--include/clang/Basic/TemplateKinds.h39
-rw-r--r--include/clang/Basic/TokenKinds.def413
-rw-r--r--include/clang/Basic/TokenKinds.h64
-rw-r--r--include/clang/Basic/TypeTraits.h40
-rw-r--r--include/clang/Basic/Version.h35
-rw-r--r--include/clang/CMakeLists.txt1
-rw-r--r--include/clang/CodeGen/ModuleBuilder.h40
-rw-r--r--include/clang/Driver/Action.h209
-rw-r--r--include/clang/Driver/Arg.h230
-rw-r--r--include/clang/Driver/ArgList.h245
-rw-r--r--include/clang/Driver/Compilation.h127
-rw-r--r--include/clang/Driver/Driver.h271
-rw-r--r--include/clang/Driver/DriverDiagnostic.h27
-rw-r--r--include/clang/Driver/HostInfo.h84
-rw-r--r--include/clang/Driver/Job.h138
-rw-r--r--include/clang/Driver/Option.h308
-rw-r--r--include/clang/Driver/Options.def624
-rw-r--r--include/clang/Driver/Options.h90
-rw-r--r--include/clang/Driver/Phases.h32
-rw-r--r--include/clang/Driver/Tool.h69
-rw-r--r--include/clang/Driver/ToolChain.h105
-rw-r--r--include/clang/Driver/Types.def78
-rw-r--r--include/clang/Driver/Types.h85
-rw-r--r--include/clang/Driver/Util.h30
-rw-r--r--include/clang/Frontend/ASTConsumers.h107
-rw-r--r--include/clang/Frontend/Analyses.def77
-rw-r--r--include/clang/Frontend/AnalysisConsumer.h78
-rw-r--r--include/clang/Frontend/CompileOptions.h62
-rw-r--r--include/clang/Frontend/DocumentXML.h128
-rw-r--r--include/clang/Frontend/FixItRewriter.h95
-rw-r--r--include/clang/Frontend/FrontendDiagnostic.h27
-rw-r--r--include/clang/Frontend/InitHeaderSearch.h74
-rw-r--r--include/clang/Frontend/InitPreprocessor.h70
-rw-r--r--include/clang/Frontend/ManagerRegistry.h53
-rw-r--r--include/clang/Frontend/PCHBitCodes.h660
-rw-r--r--include/clang/Frontend/PCHReader.h567
-rw-r--r--include/clang/Frontend/PCHWriter.h278
-rw-r--r--include/clang/Frontend/PathDiagnosticClients.h34
-rw-r--r--include/clang/Frontend/TextDiagnosticBuffer.h48
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h85
-rw-r--r--include/clang/Frontend/Utils.h79
-rw-r--r--include/clang/Lex/DirectoryLookup.h133
-rw-r--r--include/clang/Lex/HeaderMap.h67
-rw-r--r--include/clang/Lex/HeaderSearch.h237
-rw-r--r--include/clang/Lex/LexDiagnostic.h27
-rw-r--r--include/clang/Lex/Lexer.h376
-rw-r--r--include/clang/Lex/LiteralSupport.h176
-rw-r--r--include/clang/Lex/MacroInfo.h218
-rw-r--r--include/clang/Lex/MultipleIncludeOpt.h130
-rw-r--r--include/clang/Lex/PPCallbacks.h122
-rw-r--r--include/clang/Lex/PTHLexer.h104
-rw-r--r--include/clang/Lex/PTHManager.h141
-rw-r--r--include/clang/Lex/Pragma.h90
-rw-r--r--include/clang/Lex/Preprocessor.h801
-rw-r--r--include/clang/Lex/PreprocessorLexer.h161
-rw-r--r--include/clang/Lex/ScratchBuffer.h45
-rw-r--r--include/clang/Lex/Token.h312
-rw-r--r--include/clang/Lex/TokenConcatenation.h73
-rw-r--r--include/clang/Lex/TokenLexer.h154
-rw-r--r--include/clang/Makefile4
-rw-r--r--include/clang/Parse/AccessSpecifier.h30
-rw-r--r--include/clang/Parse/Action.h1839
-rw-r--r--include/clang/Parse/AttributeList.h173
-rw-r--r--include/clang/Parse/DeclSpec.h1086
-rw-r--r--include/clang/Parse/Designator.h239
-rw-r--r--include/clang/Parse/Ownership.h830
-rw-r--r--include/clang/Parse/ParseDiagnostic.h27
-rw-r--r--include/clang/Parse/Parser.h1208
-rw-r--r--include/clang/Parse/Scope.h310
-rw-r--r--include/clang/Rewrite/DeltaTree.h48
-rw-r--r--include/clang/Rewrite/HTMLRewrite.h82
-rw-r--r--include/clang/Rewrite/RewriteRope.h230
-rw-r--r--include/clang/Rewrite/Rewriter.h238
-rw-r--r--include/clang/Rewrite/TokenRewriter.h79
-rw-r--r--include/clang/Sema/ExternalSemaSource.h56
-rw-r--r--include/clang/Sema/ParseAST.h37
-rw-r--r--include/clang/Sema/SemaConsumer.h45
-rw-r--r--include/clang/Sema/SemaDiagnostic.h27
177 files changed, 49815 insertions, 0 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
new file mode 100644
index 000000000000..5d5abfe011d4
--- /dev/null
+++ b/include/clang/AST/APValue.h
@@ -0,0 +1,253 @@
+//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the APValue class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_APVALUE_H
+#define LLVM_CLANG_AST_APVALUE_H
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/APFloat.h"
+
+namespace clang {
+ class Expr;
+
+/// APValue - This class implements a discriminated union of [uninitialized]
+/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset].
+class APValue {
+ typedef llvm::APSInt APSInt;
+ typedef llvm::APFloat APFloat;
+public:
+ enum ValueKind {
+ Uninitialized,
+ Int,
+ Float,
+ ComplexInt,
+ ComplexFloat,
+ LValue,
+ Vector
+ };
+private:
+ ValueKind Kind;
+
+ struct ComplexAPSInt {
+ APSInt Real, Imag;
+ ComplexAPSInt() : Real(1), Imag(1) {}
+ };
+ struct ComplexAPFloat {
+ APFloat Real, Imag;
+ ComplexAPFloat() : Real(0.0), Imag(0.0) {}
+ };
+
+ struct LV {
+ Expr* Base;
+ uint64_t Offset;
+ };
+ struct Vec {
+ APValue *Elts;
+ unsigned NumElts;
+ Vec() : Elts(0), NumElts(0) {}
+ ~Vec() { delete[] Elts; }
+ };
+
+ enum {
+ MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
+ sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
+ };
+
+ /// Data - space for the largest member in units of void*. This is an effort
+ /// to ensure that the APSInt/APFloat values have proper alignment.
+ void *Data[(MaxSize+sizeof(void*)-1)/sizeof(void*)];
+
+public:
+ APValue() : Kind(Uninitialized) {}
+ explicit APValue(const APSInt &I) : Kind(Uninitialized) {
+ MakeInt(); setInt(I);
+ }
+ explicit APValue(const APFloat &F) : Kind(Uninitialized) {
+ MakeFloat(); setFloat(F);
+ }
+ explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
+ MakeVector(); setVector(E, N);
+ }
+ APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
+ MakeComplexInt(); setComplexInt(R, I);
+ }
+ APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
+ MakeComplexFloat(); setComplexFloat(R, I);
+ }
+ APValue(const APValue &RHS) : Kind(Uninitialized) {
+ *this = RHS;
+ }
+ APValue(Expr* B, uint64_t O) : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, O);
+ }
+ ~APValue() {
+ MakeUninit();
+ }
+
+ ValueKind getKind() const { return Kind; }
+ bool isUninit() const { return Kind == Uninitialized; }
+ bool isInt() const { return Kind == Int; }
+ bool isFloat() const { return Kind == Float; }
+ bool isComplexInt() const { return Kind == ComplexInt; }
+ bool isComplexFloat() const { return Kind == ComplexFloat; }
+ bool isLValue() const { return Kind == LValue; }
+ bool isVector() const { return Kind == Vector; }
+
+ void print(llvm::raw_ostream &OS) const;
+ void dump() const;
+
+ APSInt &getInt() {
+ assert(isInt() && "Invalid accessor");
+ return *(APSInt*)(void*)Data;
+ }
+ const APSInt &getInt() const {
+ return const_cast<APValue*>(this)->getInt();
+ }
+
+ APFloat &getFloat() {
+ assert(isFloat() && "Invalid accessor");
+ return *(APFloat*)(void*)Data;
+ }
+ const APFloat &getFloat() const {
+ return const_cast<APValue*>(this)->getFloat();
+ }
+
+ APValue &getVectorElt(unsigned i) const {
+ assert(isVector() && "Invalid accessor");
+ return ((Vec*)(void*)Data)->Elts[i];
+ }
+ unsigned getVectorLength() const {
+ assert(isVector() && "Invalid accessor");
+ return ((Vec*)(void *)Data)->NumElts;
+ }
+
+ APSInt &getComplexIntReal() {
+ assert(isComplexInt() && "Invalid accessor");
+ return ((ComplexAPSInt*)(void*)Data)->Real;
+ }
+ const APSInt &getComplexIntReal() const {
+ return const_cast<APValue*>(this)->getComplexIntReal();
+ }
+
+ APSInt &getComplexIntImag() {
+ assert(isComplexInt() && "Invalid accessor");
+ return ((ComplexAPSInt*)(void*)Data)->Imag;
+ }
+ const APSInt &getComplexIntImag() const {
+ return const_cast<APValue*>(this)->getComplexIntImag();
+ }
+
+ APFloat &getComplexFloatReal() {
+ assert(isComplexFloat() && "Invalid accessor");
+ return ((ComplexAPFloat*)(void*)Data)->Real;
+ }
+ const APFloat &getComplexFloatReal() const {
+ return const_cast<APValue*>(this)->getComplexFloatReal();
+ }
+
+ APFloat &getComplexFloatImag() {
+ assert(isComplexFloat() && "Invalid accessor");
+ return ((ComplexAPFloat*)(void*)Data)->Imag;
+ }
+ const APFloat &getComplexFloatImag() const {
+ return const_cast<APValue*>(this)->getComplexFloatImag();
+ }
+
+ Expr* getLValueBase() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Base;
+ }
+ uint64_t getLValueOffset() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Offset;
+ }
+
+ void setInt(const APSInt &I) {
+ assert(isInt() && "Invalid accessor");
+ *(APSInt*)(void*)Data = I;
+ }
+ void setFloat(const APFloat &F) {
+ assert(isFloat() && "Invalid accessor");
+ *(APFloat*)(void*)Data = F;
+ }
+ void setVector(const APValue *E, unsigned N) {
+ assert(isVector() && "Invalid accessor");
+ ((Vec*)(void*)Data)->Elts = new APValue[N];
+ ((Vec*)(void*)Data)->NumElts = N;
+ for (unsigned i = 0; i != N; ++i)
+ ((Vec*)(void*)Data)->Elts[i] = E[i];
+ }
+ void setComplexInt(const APSInt &R, const APSInt &I) {
+ assert(R.getBitWidth() == I.getBitWidth() &&
+ "Invalid complex int (type mismatch).");
+ assert(isComplexInt() && "Invalid accessor");
+ ((ComplexAPSInt*)(void*)Data)->Real = R;
+ ((ComplexAPSInt*)(void*)Data)->Imag = I;
+ }
+ void setComplexFloat(const APFloat &R, const APFloat &I) {
+ assert(&R.getSemantics() == &I.getSemantics() &&
+ "Invalid complex float (type mismatch).");
+ assert(isComplexFloat() && "Invalid accessor");
+ ((ComplexAPFloat*)(void*)Data)->Real = R;
+ ((ComplexAPFloat*)(void*)Data)->Imag = I;
+ }
+ void setLValue(Expr *B, uint64_t O) {
+ assert(isLValue() && "Invalid accessor");
+ ((LV*)(void*)Data)->Base = B;
+ ((LV*)(void*)Data)->Offset = O;
+ }
+
+ const APValue &operator=(const APValue &RHS);
+
+private:
+ void MakeUninit();
+ void MakeInt() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)Data) APSInt(1);
+ Kind = Int;
+ }
+ void MakeFloat() {
+ assert(isUninit() && "Bad state change");
+ new ((APFloat*)(void*)Data) APFloat(0.0);
+ Kind = Float;
+ }
+ void MakeVector() {
+ assert(isUninit() && "Bad state change");
+ new ((Vec*)(void*)Data) Vec();
+ Kind = Vector;
+ }
+ void MakeComplexInt() {
+ assert(isUninit() && "Bad state change");
+ new ((ComplexAPSInt*)(void*)Data) ComplexAPSInt();
+ Kind = ComplexInt;
+ }
+ void MakeComplexFloat() {
+ assert(isUninit() && "Bad state change");
+ new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat();
+ Kind = ComplexFloat;
+ }
+ void MakeLValue() {
+ assert(isUninit() && "Bad state change");
+ new ((LV*)(void*)Data) LV();
+ Kind = LValue;
+ }
+};
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
+ V.print(OS);
+ return OS;
+}
+
+} // end namespace clang.
+
+#endif
diff --git a/include/clang/AST/AST.h b/include/clang/AST/AST.h
new file mode 100644
index 000000000000..164c5fbbb6e2
--- /dev/null
+++ b/include/clang/AST/AST.h
@@ -0,0 +1,28 @@
+//===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface to the AST classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_AST_H
+#define LLVM_CLANG_AST_AST_H
+
+// This header exports all AST interfaces.
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/StmtVisitor.h"
+
+#endif
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
new file mode 100644
index 000000000000..6dc7e13d8f70
--- /dev/null
+++ b/include/clang/AST/ASTConsumer.h
@@ -0,0 +1,81 @@
+//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTConsumer class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
+#define LLVM_CLANG_AST_ASTCONSUMER_H
+
+namespace clang {
+ class ASTContext;
+ class DeclGroupRef;
+ class TagDecl;
+ class HandleTagDeclDefinition;
+ class SemaConsumer; // layering violation required for safe SemaConsumer
+ class VarDecl;
+
+/// ASTConsumer - This is an abstract interface that should be implemented by
+/// clients that read ASTs. This abstraction layer allows the client to be
+/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
+class ASTConsumer {
+ /// \brief Whether this AST consumer also requires information about
+ /// semantic analysis.
+ bool SemaConsumer;
+
+ friend class SemaConsumer;
+
+public:
+ ASTConsumer() : SemaConsumer(false) { }
+
+ virtual ~ASTConsumer() {}
+
+ /// Initialize - This is called to initialize the consumer, providing the
+ /// ASTContext and the Action.
+ virtual void Initialize(ASTContext &Context) {}
+
+ /// HandleTopLevelDecl - Handle the specified top-level declaration. This is
+ /// called by the parser to process every top-level Decl*. Note that D can
+ /// be the head of a chain of Decls (e.g. for `int a, b` the chain will have
+ /// two elements). Use Decl::getNextDeclarator() to walk the chain.
+ virtual void HandleTopLevelDecl(DeclGroupRef D);
+
+ /// HandleTranslationUnit - This method is called when the ASTs for entire
+ /// translation unit have been parsed.
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {}
+
+ /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
+ /// (e.g. struct, union, enum, class) is completed. This allows the client to
+ /// hack on the type, which can occur at any point in the file (because these
+ /// can be defined in declspecs).
+ virtual void HandleTagDeclDefinition(TagDecl *D) {}
+
+ /// \brief Callback invoked at the end of a translation unit to
+ /// notify the consumer that the given tentative definition should
+ /// be completed.
+ ///
+ /// The variable declaration itself will be a tentative
+ /// definition. If it had an incomplete array type, its type will
+ /// have already been changed to an array of size 1. However, the
+ /// declaration remains a tentative definition and has not been
+ /// modified by the introduction of an implicit zero initializer.
+ virtual void CompleteTentativeDefinition(VarDecl *D) {}
+
+ /// PrintStats - If desired, print any statistics.
+ virtual void PrintStats() {
+ }
+
+ // Support isa/cast/dyn_cast
+ static bool classof(const ASTConsumer *) { return true; }
+};
+
+} // end namespace clang.
+
+#endif
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
new file mode 100644
index 000000000000..e99e9f2b18f3
--- /dev/null
+++ b/include/clang/AST/ASTContext.h
@@ -0,0 +1,857 @@
+//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ASTContext interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
+#define LLVM_CLANG_AST_ASTCONTEXT_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Builtins.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace llvm {
+ struct fltSemantics;
+}
+
+namespace clang {
+ class FileManager;
+ class ASTRecordLayout;
+ class Expr;
+ class ExternalASTSource;
+ class IdentifierTable;
+ class SelectorTable;
+ class SourceManager;
+ class TargetInfo;
+ // Decls
+ class Decl;
+ class ObjCPropertyDecl;
+ class RecordDecl;
+ class TagDecl;
+ class TranslationUnitDecl;
+ class TypeDecl;
+ class TypedefDecl;
+ class TemplateTypeParmDecl;
+ class FieldDecl;
+ class ObjCIvarRefExpr;
+ class ObjCIvarDecl;
+
+/// ASTContext - This class holds long-lived AST nodes (such as types and
+/// decls) that can be referred to throughout the semantic analysis of a file.
+class ASTContext {
+ std::vector<Type*> Types;
+ llvm::FoldingSet<ExtQualType> ExtQualTypes;
+ llvm::FoldingSet<ComplexType> ComplexTypes;
+ llvm::FoldingSet<PointerType> PointerTypes;
+ llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
+ llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
+ llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
+ llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
+ llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
+ llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
+ std::vector<VariableArrayType*> VariableArrayTypes;
+ std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
+ llvm::FoldingSet<VectorType> VectorTypes;
+ llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
+ llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
+ llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;
+ llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
+ llvm::FoldingSet<TypenameType> TypenameTypes;
+ llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
+ llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
+
+ llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
+ llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
+
+ /// \brief The set of nested name specifiers.
+ ///
+ /// This set is managed by the NestedNameSpecifier class.
+ llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
+ NestedNameSpecifier *GlobalNestedNameSpecifier;
+ friend class NestedNameSpecifier;
+
+ /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
+ /// This is lazily created. This is intentionally not serialized.
+ llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
+ llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts;
+
+ llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes;
+ llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes;
+
+ /// BuiltinVaListType - built-in va list type.
+ /// This is initially null and set by Sema::LazilyCreateBuiltin when
+ /// a builtin that takes a valist is encountered.
+ QualType BuiltinVaListType;
+
+ /// ObjCIdType - a pseudo built-in typedef type (set by Sema).
+ QualType ObjCIdType;
+ const RecordType *IdStructType;
+
+ /// ObjCSelType - another pseudo built-in typedef type (set by Sema).
+ QualType ObjCSelType;
+ const RecordType *SelStructType;
+
+ /// ObjCProtoType - another pseudo built-in typedef type (set by Sema).
+ QualType ObjCProtoType;
+ const RecordType *ProtoStructType;
+
+ /// ObjCClassType - another pseudo built-in typedef type (set by Sema).
+ QualType ObjCClassType;
+ const RecordType *ClassStructType;
+
+ QualType ObjCConstantStringType;
+ RecordDecl *CFConstantStringTypeDecl;
+
+ RecordDecl *ObjCFastEnumerationStateTypeDecl;
+
+ TranslationUnitDecl *TUDecl;
+
+ /// SourceMgr - The associated SourceManager object.
+ SourceManager &SourceMgr;
+
+ /// LangOpts - The language options used to create the AST associated with
+ /// this ASTContext object.
+ LangOptions LangOpts;
+
+ /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
+ bool FreeMemory;
+ llvm::MallocAllocator MallocAlloc;
+ llvm::BumpPtrAllocator BumpAlloc;
+public:
+ TargetInfo &Target;
+ IdentifierTable &Idents;
+ SelectorTable &Selectors;
+ DeclarationNameTable DeclarationNames;
+ llvm::OwningPtr<ExternalASTSource> ExternalSource;
+ clang::PrintingPolicy PrintingPolicy;
+
+ SourceManager& getSourceManager() { return SourceMgr; }
+ const SourceManager& getSourceManager() const { return SourceMgr; }
+ void *Allocate(unsigned Size, unsigned Align = 8) {
+ return FreeMemory ? MallocAlloc.Allocate(Size, Align) :
+ BumpAlloc.Allocate(Size, Align);
+ }
+ void Deallocate(void *Ptr) {
+ if (FreeMemory)
+ MallocAlloc.Deallocate(Ptr);
+ }
+ const LangOptions& getLangOptions() const { return LangOpts; }
+
+ FullSourceLoc getFullLoc(SourceLocation Loc) const {
+ return FullSourceLoc(Loc,SourceMgr);
+ }
+
+ TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
+
+ Builtin::Context BuiltinInfo;
+
+ // Builtin Types.
+ QualType VoidTy;
+ QualType BoolTy;
+ QualType CharTy;
+ QualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
+ QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
+ QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
+ QualType UnsignedLongLongTy, UnsignedInt128Ty;
+ QualType FloatTy, DoubleTy, LongDoubleTy;
+ QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
+ QualType VoidPtrTy, NullPtrTy;
+ QualType OverloadTy;
+ QualType DependentTy;
+
+ ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
+ IdentifierTable &idents, SelectorTable &sels,
+ bool FreeMemory = true, unsigned size_reserve=0,
+ bool InitializeBuiltins = true);
+
+ ~ASTContext();
+
+ /// \brief Initialize builtins.
+ ///
+ /// Typically, this routine will be called automatically by the
+ /// constructor. However, in certain cases (e.g., when there is a
+ /// PCH file to be loaded), the constructor does not perform
+ /// initialization for builtins. This routine can be called to
+ /// perform the initialization.
+ void InitializeBuiltins(IdentifierTable &idents);
+
+ /// \brief Attach an external AST source to the AST context.
+ ///
+ /// The external AST source provides the ability to load parts of
+ /// the abstract syntax tree as needed from some external storage,
+ /// e.g., a precompiled header.
+ void setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source);
+
+ /// \brief Retrieve a pointer to the external AST source associated
+ /// with this AST context, if any.
+ ExternalASTSource *getExternalSource() const { return ExternalSource.get(); }
+
+ void PrintStats() const;
+ const std::vector<Type*>& getTypes() const { return Types; }
+
+ //===--------------------------------------------------------------------===//
+ // Type Constructors
+ //===--------------------------------------------------------------------===//
+
+ /// getAddSpaceQualType - Return the uniqued reference to the type for an
+ /// address space qualified type with the specified type and address space.
+ /// The resulting type has a union of the qualifiers from T and the address
+ /// space. If T already has an address space specifier, it is silently
+ /// replaced.
+ QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace);
+
+ /// getObjCGCQualType - Returns the uniqued reference to the type for an
+ /// objc gc qualified type. The retulting type has a union of the qualifiers
+ /// from T and the gc attribute.
+ QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes gcAttr);
+
+ /// getComplexType - Return the uniqued reference to the type for a complex
+ /// number with the specified element type.
+ QualType getComplexType(QualType T);
+
+ /// getPointerType - Return the uniqued reference to the type for a pointer to
+ /// the specified type.
+ QualType getPointerType(QualType T);
+
+ /// getBlockPointerType - Return the uniqued reference to the type for a block
+ /// of the specified type.
+ QualType getBlockPointerType(QualType T);
+
+ /// getLValueReferenceType - Return the uniqued reference to the type for an
+ /// lvalue reference to the specified type.
+ QualType getLValueReferenceType(QualType T);
+
+ /// getRValueReferenceType - Return the uniqued reference to the type for an
+ /// rvalue reference to the specified type.
+ QualType getRValueReferenceType(QualType T);
+
+ /// getMemberPointerType - Return the uniqued reference to the type for a
+ /// member pointer to the specified type in the specified class. The class
+ /// is a Type because it could be a dependent name.
+ QualType getMemberPointerType(QualType T, const Type *Cls);
+
+ /// getVariableArrayType - Returns a non-unique reference to the type for a
+ /// variable array of the specified element type.
+ QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals);
+
+ /// getDependentSizedArrayType - Returns a non-unique reference to
+ /// the type for a dependently-sized array of the specified element
+ /// type. FIXME: We will need these to be uniqued, or at least
+ /// comparable, at some point.
+ QualType getDependentSizedArrayType(QualType EltTy, Expr *NumElts,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals);
+
+ /// getIncompleteArrayType - Returns a unique reference to the type for a
+ /// incomplete array of the specified element type.
+ QualType getIncompleteArrayType(QualType EltTy,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals);
+
+ /// getConstantArrayType - Return the unique reference to the type for a
+ /// constant array of the specified element type.
+ QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned EltTypeQuals);
+
+ /// getVectorType - Return the unique reference to a vector type of
+ /// the specified element type and size. VectorType must be a built-in type.
+ QualType getVectorType(QualType VectorType, unsigned NumElts);
+
+ /// getExtVectorType - Return the unique reference to an extended vector type
+ /// of the specified element type and size. VectorType must be a built-in
+ /// type.
+ QualType getExtVectorType(QualType VectorType, unsigned NumElts);
+
+ /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
+ ///
+ QualType getFunctionNoProtoType(QualType ResultTy);
+
+ /// getFunctionType - Return a normal function type with a typed argument
+ /// list. isVariadic indicates whether the argument list includes '...'.
+ QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
+ unsigned NumArgs, bool isVariadic,
+ unsigned TypeQuals, bool hasExceptionSpec = false,
+ bool hasAnyExceptionSpec = false,
+ unsigned NumExs = 0, const QualType *ExArray = 0);
+
+ /// getTypeDeclType - Return the unique reference to the type for
+ /// the specified type declaration.
+ QualType getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl=0);
+
+ /// getTypedefType - Return the unique reference to the type for the
+ /// specified typename decl.
+ QualType getTypedefType(TypedefDecl *Decl);
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
+
+ QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ IdentifierInfo *Name = 0);
+
+ QualType getTemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ QualType Canon = QualType());
+
+ QualType getQualifiedNameType(NestedNameSpecifier *NNS,
+ QualType NamedType);
+ QualType getTypenameType(NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name,
+ QualType Canon = QualType());
+ QualType getTypenameType(NestedNameSpecifier *NNS,
+ const TemplateSpecializationType *TemplateId,
+ QualType Canon = QualType());
+
+ /// getObjCQualifiedInterfaceType - Return a
+ /// ObjCQualifiedInterfaceType type for the given interface decl and
+ /// the conforming protocol list.
+ QualType getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **ProtocolList,
+ unsigned NumProtocols);
+
+ /// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a
+ /// given 'id' and conforming protocol list.
+ QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList,
+ unsigned NumProtocols);
+
+
+ /// getTypeOfType - GCC extension.
+ QualType getTypeOfExprType(Expr *e);
+ QualType getTypeOfType(QualType t);
+
+ /// getTagDeclType - Return the unique reference to the type for the
+ /// specified TagDecl (struct/union/class/enum) decl.
+ QualType getTagDeclType(TagDecl *Decl);
+
+ /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
+ /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
+ QualType getSizeType() const;
+
+ /// getWCharType - In C++, this returns the unique wchar_t type. In C99, this
+ /// returns a type compatible with the type defined in <stddef.h> as defined
+ /// by the target.
+ QualType getWCharType() const { return WCharTy; }
+
+ /// getSignedWCharType - Return the type of "signed wchar_t".
+ /// Used when in C++, as a GCC extension.
+ QualType getSignedWCharType() const;
+
+ /// getUnsignedWCharType - Return the type of "unsigned wchar_t".
+ /// Used when in C++, as a GCC extension.
+ QualType getUnsignedWCharType() const;
+
+ /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+ /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
+ QualType getPointerDiffType() const;
+
+ // getCFConstantStringType - Return the C structure type used to represent
+ // constant CFStrings.
+ QualType getCFConstantStringType();
+
+ /// Get the structure type used to representation CFStrings, or NULL
+ /// if it hasn't yet been built.
+ QualType getRawCFConstantStringType() {
+ if (CFConstantStringTypeDecl)
+ return getTagDeclType(CFConstantStringTypeDecl);
+ return QualType();
+ }
+ void setCFConstantStringType(QualType T);
+
+ // This setter/getter represents the ObjC type for an NSConstantString.
+ void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl);
+ QualType getObjCConstantStringInterface() const {
+ return ObjCConstantStringType;
+ }
+
+ //// This gets the struct used to keep track of fast enumerations.
+ QualType getObjCFastEnumerationStateType();
+
+ /// Get the ObjCFastEnumerationState type, or NULL if it hasn't yet
+ /// been built.
+ QualType getRawObjCFastEnumerationStateType() {
+ if (ObjCFastEnumerationStateTypeDecl)
+ return getTagDeclType(ObjCFastEnumerationStateTypeDecl);
+ return QualType();
+ }
+
+ void setObjCFastEnumerationStateType(QualType T);
+
+ /// getObjCEncodingForType - Emit the ObjC type encoding for the
+ /// given type into \arg S. If \arg NameFields is specified then
+ /// record field names are also encoded.
+ void getObjCEncodingForType(QualType t, std::string &S,
+ const FieldDecl *Field=0);
+
+ void getLegacyIntegralTypeEncoding(QualType &t) const;
+
+ // Put the string version of type qualifiers into S.
+ void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
+ std::string &S) const;
+
+ /// getObjCEncodingForMethodDecl - Return the encoded type for this method
+ /// declaration.
+ void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S);
+
+ /// getObjCEncodingForPropertyDecl - Return the encoded type for
+ /// this method declaration. If non-NULL, Container must be either
+ /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
+ /// only be NULL when getting encodings for protocol properties.
+ void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ const Decl *Container,
+ std::string &S);
+
+ /// getObjCEncodingTypeSize returns size of type for objective-c encoding
+ /// purpose.
+ int getObjCEncodingTypeSize(QualType t);
+
+ /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
+ /// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
+ QualType getObjCIdType() const { return ObjCIdType; }
+ void setObjCIdType(QualType T);
+
+ void setObjCSelType(QualType T);
+ QualType getObjCSelType() const { return ObjCSelType; }
+
+ void setObjCProtoType(QualType QT);
+ QualType getObjCProtoType() const { return ObjCProtoType; }
+
+ /// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
+ /// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a
+ /// struct.
+ QualType getObjCClassType() const { return ObjCClassType; }
+ void setObjCClassType(QualType T);
+
+ void setBuiltinVaListType(QualType T);
+ QualType getBuiltinVaListType() const { return BuiltinVaListType; }
+
+ QualType getFixedWidthIntType(unsigned Width, bool Signed);
+
+ TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ bool TemplateKeyword,
+ TemplateDecl *Template);
+
+ TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name);
+
+private:
+ QualType getFromTargetType(unsigned Type) const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Predicates.
+ //===--------------------------------------------------------------------===//
+
+public:
+ /// isObjCObjectPointerType - Returns true if type is an Objective-C pointer
+ /// to an object type. This includes "id" and "Class" (two 'special' pointers
+ /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
+ /// ID type).
+ bool isObjCObjectPointerType(QualType Ty) const;
+
+ /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
+ /// garbage collection attribute.
+ ///
+ QualType::GCAttrTypes getObjCGCAttrKind(const QualType &Ty) const;
+
+ /// isObjCNSObjectType - Return true if this is an NSObject object with
+ /// its NSObject attribute set.
+ bool isObjCNSObjectType(QualType Ty) const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Sizing and Analysis
+ //===--------------------------------------------------------------------===//
+
+ /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
+ /// scalar floating point type.
+ const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
+
+ /// getTypeInfo - Get the size and alignment of the specified complete type in
+ /// bits.
+ std::pair<uint64_t, unsigned> getTypeInfo(const Type *T);
+ std::pair<uint64_t, unsigned> getTypeInfo(QualType T) {
+ return getTypeInfo(T.getTypePtr());
+ }
+
+ /// getTypeSize - Return the size of the specified type, in bits. This method
+ /// does not work on incomplete types.
+ uint64_t getTypeSize(QualType T) {
+ return getTypeInfo(T).first;
+ }
+ uint64_t getTypeSize(const Type *T) {
+ return getTypeInfo(T).first;
+ }
+
+ /// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
+ /// This method does not work on incomplete types.
+ unsigned getTypeAlign(QualType T) {
+ return getTypeInfo(T).second;
+ }
+ unsigned getTypeAlign(const Type *T) {
+ return getTypeInfo(T).second;
+ }
+
+ /// getPreferredTypeAlign - Return the "preferred" alignment of the specified
+ /// type for the current target in bits. This can be different than the ABI
+ /// alignment in cases where it is beneficial for performance to overalign
+ /// a data type.
+ unsigned getPreferredTypeAlign(const Type *T);
+
+ /// getDeclAlignInBytes - Return the alignment of the specified decl
+ /// that should be returned by __alignof(). Note that bitfields do
+ /// not have a valid alignment, so this method will assert on them.
+ unsigned getDeclAlignInBytes(const Decl *D);
+
+ /// getASTRecordLayout - Get or compute information about the layout of the
+ /// specified record (struct/union/class), which indicates its size and field
+ /// position information.
+ const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D);
+
+ /// getASTObjCInterfaceLayout - Get or compute information about the
+ /// layout of the specified Objective-C interface.
+ const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D);
+
+ /// getASTObjCImplementationLayout - Get or compute information about
+ /// the layout of the specified Objective-C implementation. This may
+ /// differ from the interface if synthesized ivars are present.
+ const ASTRecordLayout &
+ getASTObjCImplementationLayout(const ObjCImplementationDecl *D);
+
+ void CollectObjCIvars(const ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<FieldDecl*> &Fields);
+
+ void CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ void CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
+ //===--------------------------------------------------------------------===//
+ // Type Operators
+ //===--------------------------------------------------------------------===//
+
+ /// getCanonicalType - Return the canonical (structural) type corresponding to
+ /// the specified potentially non-canonical type. The non-canonical version
+ /// of a type may have many "decorated" versions of types. Decorators can
+ /// include typedefs, 'typeof' operators, etc. The returned type is guaranteed
+ /// to be free of any of these, allowing two canonical types to be compared
+ /// for exact equality with a simple pointer comparison.
+ QualType getCanonicalType(QualType T);
+ const Type *getCanonicalType(const Type *T) {
+ return T->getCanonicalTypeInternal().getTypePtr();
+ }
+
+ /// \brief Determine whether the given types are equivalent.
+ bool hasSameType(QualType T1, QualType T2) {
+ return getCanonicalType(T1) == getCanonicalType(T2);
+ }
+
+ /// \brief Determine whether the given types are equivalent after
+ /// cvr-qualifiers have been removed.
+ bool hasSameUnqualifiedType(QualType T1, QualType T2) {
+ T1 = getCanonicalType(T1);
+ T2 = getCanonicalType(T2);
+ return T1.getUnqualifiedType() == T2.getUnqualifiedType();
+ }
+
+ /// \brief Retrieves the "canonical" declaration of the given declaration.
+ Decl *getCanonicalDecl(Decl *D);
+
+ /// \brief Retrieves the "canonical" declaration of the given tag
+ /// declaration.
+ ///
+ /// The canonical declaration for the given tag declaration is
+ /// either the definition of the tag (if it is a complete type) or
+ /// the first declaration of that tag.
+ TagDecl *getCanonicalDecl(TagDecl *Tag) {
+ return cast<TagDecl>(getCanonicalDecl((Decl *)Tag));
+ }
+
+ /// \brief Retrieves the "canonical" declaration of
+
+ /// \brief Retrieves the "canonical" nested name specifier for a
+ /// given nested name specifier.
+ ///
+ /// The canonical nested name specifier is a nested name specifier
+ /// that uniquely identifies a type or namespace within the type
+ /// system. For example, given:
+ ///
+ /// \code
+ /// namespace N {
+ /// struct S {
+ /// template<typename T> struct X { typename T* type; };
+ /// };
+ /// }
+ ///
+ /// template<typename T> struct Y {
+ /// typename N::S::X<T>::type member;
+ /// };
+ /// \endcode
+ ///
+ /// Here, the nested-name-specifier for N::S::X<T>:: will be
+ /// S::X<template-param-0-0>, since 'S' and 'X' are uniquely defined
+ /// by declarations in the type system and the canonical type for
+ /// the template type parameter 'T' is template-param-0-0.
+ NestedNameSpecifier *
+ getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+ /// \brief Retrieves the "canonical" template name that refers to a
+ /// given template.
+ ///
+ /// The canonical template name is the simplest expression that can
+ /// be used to refer to a given template. For most templates, this
+ /// expression is just the template declaration itself. For example,
+ /// the template std::vector can be referred to via a variety of
+ /// names---std::vector, ::std::vector, vector (if vector is in
+ /// scope), etc.---but all of these names map down to the same
+ /// TemplateDecl, which is used to form the canonical template name.
+ ///
+ /// Dependent template names are more interesting. Here, the
+ /// template name could be something like T::template apply or
+ /// std::allocator<T>::template rebind, where the nested name
+ /// specifier itself is dependent. In this case, the canonical
+ /// template name uses the shortest form of the dependent
+ /// nested-name-specifier, which itself contains all canonical
+ /// types, values, and templates.
+ TemplateName getCanonicalTemplateName(TemplateName Name);
+
+ /// Type Query functions. If the type is an instance of the specified class,
+ /// return the Type pointer for the underlying maximally pretty type. This
+ /// is a member of ASTContext because this may need to do some amount of
+ /// canonicalization, e.g. to move type qualifiers into the element type.
+ const ArrayType *getAsArrayType(QualType T);
+ const ConstantArrayType *getAsConstantArrayType(QualType T) {
+ return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
+ }
+ const VariableArrayType *getAsVariableArrayType(QualType T) {
+ return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
+ }
+ const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
+ return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
+ }
+
+ /// getBaseElementType - Returns the innermost element type of a variable
+ /// length array type. For example, will return "int" for int[m][n]
+ QualType getBaseElementType(const VariableArrayType *VAT);
+
+ /// getArrayDecayedType - Return the properly qualified result of decaying the
+ /// specified array type to a pointer. This operation is non-trivial when
+ /// handling typedefs etc. The canonical type of "T" must be an array type,
+ /// this returns a pointer to a properly qualified element of the array.
+ ///
+ /// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
+ QualType getArrayDecayedType(QualType T);
+
+ /// getIntegerTypeOrder - Returns the highest ranked integer type:
+ /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
+ /// LHS < RHS, return -1.
+ int getIntegerTypeOrder(QualType LHS, QualType RHS);
+
+ /// getFloatingTypeOrder - Compare the rank of the two specified floating
+ /// point types, ignoring the domain of the type (i.e. 'double' ==
+ /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If
+ /// LHS < RHS, return -1.
+ int getFloatingTypeOrder(QualType LHS, QualType RHS);
+
+ /// getFloatingTypeOfSizeWithinDomain - Returns a real floating
+ /// point or a complex type (based on typeDomain/typeSize).
+ /// 'typeDomain' is a real floating point or complex type.
+ /// 'typeSize' is a real floating point or complex type.
+ QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
+ QualType typeDomain) const;
+
+private:
+ // Helper for integer ordering
+ unsigned getIntegerRank(Type* T);
+
+public:
+
+ //===--------------------------------------------------------------------===//
+ // Type Compatibility Predicates
+ //===--------------------------------------------------------------------===//
+
+ /// Compatibility predicates used to check assignment expressions.
+ bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
+ bool typesAreBlockCompatible(QualType lhs, QualType rhs);
+
+ bool isObjCIdType(QualType T) const {
+ return T == ObjCIdType;
+ }
+ bool isObjCIdStructType(QualType T) const {
+ if (!IdStructType) // ObjC isn't enabled
+ return false;
+ return T->getAsStructureType() == IdStructType;
+ }
+ bool isObjCClassType(QualType T) const {
+ return T == ObjCClassType;
+ }
+ bool isObjCClassStructType(QualType T) const {
+ if (!ClassStructType) // ObjC isn't enabled
+ return false;
+ return T->getAsStructureType() == ClassStructType;
+ }
+ bool isObjCSelType(QualType T) const {
+ assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
+ return T->getAsStructureType() == SelStructType;
+ }
+
+ // Check the safety of assignment from LHS to RHS
+ bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
+ const ObjCInterfaceType *RHS);
+ bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
+
+ // Functions for calculating composite types
+ QualType mergeTypes(QualType, QualType);
+ QualType mergeFunctionTypes(QualType, QualType);
+
+ //===--------------------------------------------------------------------===//
+ // Integer Predicates
+ //===--------------------------------------------------------------------===//
+
+ // The width of an integer, as defined in C99 6.2.6.2. This is the number
+ // of bits in an integer type excluding any padding bits.
+ unsigned getIntWidth(QualType T);
+
+ // Per C99 6.2.5p6, for every signed integer type, there is a corresponding
+ // unsigned integer type. This method takes a signed type, and returns the
+ // corresponding unsigned integer type.
+ QualType getCorrespondingUnsignedType(QualType T);
+
+ //===--------------------------------------------------------------------===//
+ // Type Iterators.
+ //===--------------------------------------------------------------------===//
+
+ typedef std::vector<Type*>::iterator type_iterator;
+ typedef std::vector<Type*>::const_iterator const_type_iterator;
+
+ type_iterator types_begin() { return Types.begin(); }
+ type_iterator types_end() { return Types.end(); }
+ const_type_iterator types_begin() const { return Types.begin(); }
+ const_type_iterator types_end() const { return Types.end(); }
+
+ //===--------------------------------------------------------------------===//
+ // Integer Values
+ //===--------------------------------------------------------------------===//
+
+ /// MakeIntValue - Make an APSInt of the appropriate width and
+ /// signedness for the given \arg Value and integer \arg Type.
+ llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) {
+ llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType());
+ Res = Value;
+ return Res;
+ }
+
+private:
+ ASTContext(const ASTContext&); // DO NOT IMPLEMENT
+ void operator=(const ASTContext&); // DO NOT IMPLEMENT
+
+ void InitBuiltinTypes();
+ void InitBuiltinType(QualType &R, BuiltinType::Kind K);
+
+ // Return the ObjC type encoding for a given type.
+ void getObjCEncodingForTypeImpl(QualType t, std::string &S,
+ bool ExpandPointedToStructures,
+ bool ExpandStructures,
+ const FieldDecl *Field,
+ bool OutermostType = false,
+ bool EncodingProperty = false);
+
+ const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
+ const ObjCImplementationDecl *Impl);
+};
+
+} // end namespace clang
+
+// operator new and delete aren't allowed inside namespaces.
+// The throw specifications are mandated by the standard.
+/// @brief Placement new for using the ASTContext's allocator.
+///
+/// This placement form of operator new uses the ASTContext's allocator for
+/// obtaining memory. It is a non-throwing new, which means that it returns
+/// null on error. (If that is what the allocator does. The current does, so if
+/// this ever changes, this operator will have to be changed, too.)
+/// Usage looks like this (assuming there's an ASTContext 'Context' in scope):
+/// @code
+/// // Default alignment (16)
+/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments);
+/// // Specific alignment
+/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments);
+/// @endcode
+/// Please note that you cannot use delete on the pointer; it must be
+/// deallocated using an explicit destructor call followed by
+/// @c Context.Deallocate(Ptr).
+///
+/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
+/// @param C The ASTContext that provides the allocator.
+/// @param Alignment The alignment of the allocated memory (if the underlying
+/// allocator supports it).
+/// @return The allocated memory. Could be NULL.
+inline void *operator new(size_t Bytes, clang::ASTContext &C,
+ size_t Alignment) throw () {
+ return C.Allocate(Bytes, Alignment);
+}
+/// @brief Placement delete companion to the new above.
+///
+/// This operator is just a companion to the new above. There is no way of
+/// invoking it directly; see the new operator for more details. This operator
+/// is called implicitly by the compiler if a placement new expression using
+/// the ASTContext throws in the object constructor.
+inline void operator delete(void *Ptr, clang::ASTContext &C, size_t)
+ throw () {
+ C.Deallocate(Ptr);
+}
+
+/// This placement form of operator new[] uses the ASTContext's allocator for
+/// obtaining memory. It is a non-throwing new[], which means that it returns
+/// null on error.
+/// Usage looks like this (assuming there's an ASTContext 'Context' in scope):
+/// @code
+/// // Default alignment (16)
+/// char *data = new (Context) char[10];
+/// // Specific alignment
+/// char *data = new (Context, 8) char[10];
+/// @endcode
+/// Please note that you cannot use delete on the pointer; it must be
+/// deallocated using an explicit destructor call followed by
+/// @c Context.Deallocate(Ptr).
+///
+/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
+/// @param C The ASTContext that provides the allocator.
+/// @param Alignment The alignment of the allocated memory (if the underlying
+/// allocator supports it).
+/// @return The allocated memory. Could be NULL.
+inline void *operator new[](size_t Bytes, clang::ASTContext& C,
+ size_t Alignment = 16) throw () {
+ return C.Allocate(Bytes, Alignment);
+}
+
+/// @brief Placement delete[] companion to the new[] above.
+///
+/// This operator is just a companion to the new[] above. There is no way of
+/// invoking it directly; see the new[] operator for more details. This operator
+/// is called implicitly by the compiler if a placement new[] expression using
+/// the ASTContext throws in the object constructor.
+inline void operator delete[](void *Ptr, clang::ASTContext &C) throw () {
+ C.Deallocate(Ptr);
+}
+
+#endif
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
new file mode 100644
index 000000000000..244ca9e10f3a
--- /dev/null
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticAST.h - Diagnostics for the AST library ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICAST_H
+#define LLVM_CLANG_DIAGNOSTICAST_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define ASTSTART
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_AST_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
new file mode 100644
index 000000000000..0427f0003a3a
--- /dev/null
+++ b/include/clang/AST/Attr.h
@@ -0,0 +1,506 @@
+//===--- Attr.h - Classes for representing expressions ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Attr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ATTR_H
+#define LLVM_CLANG_AST_ATTR_H
+
+#include <cassert>
+#include <cstring>
+#include <string>
+#include <algorithm>
+
+namespace clang {
+ class ASTContext;
+}
+
+
+// Defined in ASTContext.cpp
+void *operator new(size_t Bytes, clang::ASTContext &C,
+ size_t Alignment = 16) throw ();
+
+namespace clang {
+
+/// Attr - This represents one attribute.
+class Attr {
+public:
+ enum Kind {
+ Alias,
+ Aligned,
+ AlwaysInline,
+ AnalyzerNoReturn, // Clang-specific.
+ Annotate,
+ AsmLabel, // Represent GCC asm label extension.
+ Blocks,
+ Cleanup,
+ Const,
+ Constructor,
+ DLLExport,
+ DLLImport,
+ Deprecated,
+ Destructor,
+ FastCall,
+ Format,
+ FormatArg,
+ GNUInline,
+ IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with
+ NoReturn,
+ NoThrow,
+ Nodebug,
+ Noinline,
+ NonNull,
+ ObjCException,
+ ObjCNSObject,
+ CFReturnsRetained, // Clang/Checker-specific.
+ NSReturnsRetained, // Clang/Checker-specific.
+ Overloadable, // Clang-specific
+ Packed,
+ Pure,
+ Regparm,
+ Section,
+ Sentinel,
+ StdCall,
+ TransparentUnion,
+ Unavailable,
+ Unused,
+ Used,
+ Visibility,
+ WarnUnusedResult,
+ Weak,
+ WeakImport
+ };
+
+private:
+ Attr *Next;
+ Kind AttrKind;
+ bool Inherited : 1;
+
+protected:
+ void* operator new(size_t bytes) throw() {
+ assert(0 && "Attrs cannot be allocated with regular 'new'.");
+ return 0;
+ }
+ void operator delete(void* data) throw() {
+ assert(0 && "Attrs cannot be released with regular 'delete'.");
+ }
+
+protected:
+ Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
+ virtual ~Attr() {
+ assert(Next == 0 && "Destroy didn't work");
+ }
+public:
+
+ void Destroy(ASTContext &C);
+
+ /// \brief Whether this attribute should be merged to new
+ /// declarations.
+ virtual bool isMerged() const { return true; }
+
+ Kind getKind() const { return AttrKind; }
+
+ Attr *getNext() { return Next; }
+ const Attr *getNext() const { return Next; }
+ void setNext(Attr *next) { Next = next; }
+
+ bool isInherited() const { return Inherited; }
+ void setInherited(bool value) { Inherited = value; }
+
+ void addAttr(Attr *attr) {
+ assert((attr != 0) && "addAttr(): attr is null");
+
+ // FIXME: This doesn't preserve the order in any way.
+ attr->Next = Next;
+ Next = attr;
+ }
+
+ // Clone this attribute.
+ virtual Attr* clone(ASTContext &C) const = 0;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *) { return true; }
+};
+
+#define DEF_SIMPLE_ATTR(ATTR) \
+class ATTR##Attr : public Attr { \
+public: \
+ ATTR##Attr() : Attr(ATTR) {} \
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }\
+ static bool classof(const Attr *A) { return A->getKind() == ATTR; } \
+ static bool classof(const ATTR##Attr *A) { return true; } \
+}
+
+class PackedAttr : public Attr {
+ unsigned Alignment;
+
+public:
+ PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {}
+
+ /// getAlignment - The specified alignment in bits.
+ unsigned getAlignment() const { return Alignment; }
+
+ virtual Attr* clone(ASTContext &C) const {
+ return ::new (C) PackedAttr(Alignment);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == Packed;
+ }
+ static bool classof(const PackedAttr *A) { return true; }
+};
+
+class AlignedAttr : public Attr {
+ unsigned Alignment;
+public:
+ AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
+
+ /// getAlignment - The specified alignment in bits.
+ unsigned getAlignment() const { return Alignment; }
+
+ virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == Aligned;
+ }
+ static bool classof(const AlignedAttr *A) { return true; }
+};
+
+class AnnotateAttr : public Attr {
+ std::string Annotation;
+public:
+ AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {}
+
+ const std::string& getAnnotation() const { return Annotation; }
+
+ virtual Attr* clone(ASTContext &C) const { return ::new (C) AnnotateAttr(Annotation); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == Annotate;
+ }
+ static bool classof(const AnnotateAttr *A) { return true; }
+};
+
+class AsmLabelAttr : public Attr {
+ std::string Label;
+public:
+ AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {}
+
+ const std::string& getLabel() const { return Label; }
+
+ virtual Attr* clone(ASTContext &C) const { return ::new (C) AsmLabelAttr(Label); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == AsmLabel;
+ }
+ static bool classof(const AsmLabelAttr *A) { return true; }
+};
+
+DEF_SIMPLE_ATTR(AlwaysInline);
+
+class AliasAttr : public Attr {
+ std::string Aliasee;
+public:
+ AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {}
+
+ const std::string& getAliasee() const { return Aliasee; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) AliasAttr(Aliasee); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Alias; }
+ static bool classof(const AliasAttr *A) { return true; }
+};
+
+class ConstructorAttr : public Attr {
+ int priority;
+public:
+ ConstructorAttr(int p) : Attr(Constructor), priority(p) {}
+
+ int getPriority() const { return priority; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) ConstructorAttr(priority); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Constructor; }
+ static bool classof(const ConstructorAttr *A) { return true; }
+};
+
+class DestructorAttr : public Attr {
+ int priority;
+public:
+ DestructorAttr(int p) : Attr(Destructor), priority(p) {}
+
+ int getPriority() const { return priority; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) DestructorAttr(priority); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Destructor; }
+ static bool classof(const DestructorAttr *A) { return true; }
+};
+
+class GNUInlineAttr : public Attr {
+public:
+ GNUInlineAttr() : Attr(GNUInline) {}
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) GNUInlineAttr; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == GNUInline;
+ }
+ static bool classof(const GNUInlineAttr *A) { return true; }
+};
+
+class IBOutletAttr : public Attr {
+public:
+ IBOutletAttr() : Attr(IBOutletKind) {}
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) IBOutletAttr; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == IBOutletKind;
+ }
+ static bool classof(const IBOutletAttr *A) { return true; }
+};
+
+DEF_SIMPLE_ATTR(NoReturn);
+DEF_SIMPLE_ATTR(AnalyzerNoReturn);
+DEF_SIMPLE_ATTR(Deprecated);
+
+class SectionAttr : public Attr {
+ std::string Name;
+public:
+ SectionAttr(const std::string &N) : Attr(Section), Name(N) {}
+
+ const std::string& getName() const { return Name; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) SectionAttr(Name); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == Section;
+ }
+ static bool classof(const SectionAttr *A) { return true; }
+};
+
+DEF_SIMPLE_ATTR(Unavailable);
+DEF_SIMPLE_ATTR(Unused);
+DEF_SIMPLE_ATTR(Used);
+DEF_SIMPLE_ATTR(Weak);
+DEF_SIMPLE_ATTR(WeakImport);
+DEF_SIMPLE_ATTR(NoThrow);
+DEF_SIMPLE_ATTR(Const);
+DEF_SIMPLE_ATTR(Pure);
+
+class NonNullAttr : public Attr {
+ unsigned* ArgNums;
+ unsigned Size;
+public:
+ NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull),
+ ArgNums(0), Size(0) {
+
+ if (size == 0) return;
+ assert(arg_nums);
+ ArgNums = new unsigned[size];
+ Size = size;
+ memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
+ }
+
+ virtual ~NonNullAttr() {
+ delete [] ArgNums;
+ }
+
+ typedef const unsigned *iterator;
+ iterator begin() const { return ArgNums; }
+ iterator end() const { return ArgNums + Size; }
+ unsigned size() const { return Size; }
+
+ bool isNonNull(unsigned arg) const {
+ return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
+ }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) NonNullAttr(ArgNums, Size); }
+
+ static bool classof(const Attr *A) { return A->getKind() == NonNull; }
+ static bool classof(const NonNullAttr *A) { return true; }
+};
+
+class FormatAttr : public Attr {
+ std::string Type;
+ int formatIdx, firstArg;
+public:
+ FormatAttr(const std::string &type, int idx, int first) : Attr(Format),
+ Type(type), formatIdx(idx), firstArg(first) {}
+
+ const std::string& getType() const { return Type; }
+ void setType(const std::string &type) { Type = type; }
+ int getFormatIdx() const { return formatIdx; }
+ int getFirstArg() const { return firstArg; }
+
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) FormatAttr(Type, formatIdx, firstArg);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Format; }
+ static bool classof(const FormatAttr *A) { return true; }
+};
+
+class FormatArgAttr : public Attr {
+ int formatIdx;
+public:
+ FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {}
+ int getFormatIdx() const { return formatIdx; }
+
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) FormatArgAttr(formatIdx);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == FormatArg; }
+ static bool classof(const FormatArgAttr *A) { return true; }
+};
+
+class SentinelAttr : public Attr {
+ int sentinel, NullPos;
+public:
+ SentinelAttr(int sentinel_val, int nullPos) : Attr(Sentinel),
+ sentinel(sentinel_val), NullPos(nullPos) {}
+ int getSentinel() const { return sentinel; }
+ int getNullPos() const { return NullPos; }
+
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) SentinelAttr(sentinel, NullPos);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Sentinel; }
+ static bool classof(const SentinelAttr *A) { return true; }
+};
+
+class VisibilityAttr : public Attr {
+public:
+ /// @brief An enumeration for the kinds of visibility of symbols.
+ enum VisibilityTypes {
+ DefaultVisibility = 0,
+ HiddenVisibility,
+ ProtectedVisibility
+ };
+private:
+ VisibilityTypes VisibilityType;
+public:
+ VisibilityAttr(VisibilityTypes v) : Attr(Visibility),
+ VisibilityType(v) {}
+
+ VisibilityTypes getVisibility() const { return VisibilityType; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) VisibilityAttr(VisibilityType); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Visibility; }
+ static bool classof(const VisibilityAttr *A) { return true; }
+};
+
+DEF_SIMPLE_ATTR(DLLImport);
+DEF_SIMPLE_ATTR(DLLExport);
+DEF_SIMPLE_ATTR(FastCall);
+DEF_SIMPLE_ATTR(StdCall);
+DEF_SIMPLE_ATTR(TransparentUnion);
+DEF_SIMPLE_ATTR(ObjCNSObject);
+DEF_SIMPLE_ATTR(ObjCException);
+
+class OverloadableAttr : public Attr {
+public:
+ OverloadableAttr() : Attr(Overloadable) { }
+
+ virtual bool isMerged() const { return false; }
+
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) OverloadableAttr;
+ }
+
+ static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
+ static bool classof(const OverloadableAttr *) { return true; }
+};
+
+class BlocksAttr : public Attr {
+public:
+ enum BlocksAttrTypes {
+ ByRef = 0
+ };
+private:
+ BlocksAttrTypes BlocksAttrType;
+public:
+ BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {}
+
+ BlocksAttrTypes getType() const { return BlocksAttrType; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) BlocksAttr(BlocksAttrType); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Blocks; }
+ static bool classof(const BlocksAttr *A) { return true; }
+};
+
+class FunctionDecl;
+
+class CleanupAttr : public Attr {
+ FunctionDecl *FD;
+
+public:
+ CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {}
+
+ const FunctionDecl *getFunctionDecl() const { return FD; }
+
+ virtual Attr *clone(ASTContext &C) const { return ::new (C) CleanupAttr(FD); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Cleanup; }
+ static bool classof(const CleanupAttr *A) { return true; }
+};
+
+DEF_SIMPLE_ATTR(Nodebug);
+DEF_SIMPLE_ATTR(WarnUnusedResult);
+DEF_SIMPLE_ATTR(Noinline);
+
+class RegparmAttr : public Attr {
+ unsigned NumParams;
+
+public:
+ RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {}
+
+ unsigned getNumParams() const { return NumParams; }
+
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) RegparmAttr(NumParams);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == Regparm; }
+ static bool classof(const RegparmAttr *A) { return true; }
+};
+
+// Checker-specific attributes.
+DEF_SIMPLE_ATTR(CFReturnsRetained);
+DEF_SIMPLE_ATTR(NSReturnsRetained);
+
+#undef DEF_SIMPLE_ATTR
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def
new file mode 100644
index 000000000000..671c4bd6cd4a
--- /dev/null
+++ b/include/clang/AST/Builtins.def
@@ -0,0 +1,389 @@
+//===--- Builtins.def - Builtin function info database ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the standard builtin function database. Users of this file
+// must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
+// adding stuff on demand.
+//
+// FIXME: This should really be a .td file, but that requires modifying tblgen.
+// Perhaps tblgen should have plugins.
+
+// The first value provided to the macro specifies the function name of the
+// builtin, and results in a clang::builtin::BIXX enum value for XX.
+
+// The second value provided to the macro specifies the type of the function
+// (result value, then each argument) as follows:
+// v -> void
+// b -> boolean
+// c -> char
+// s -> short
+// i -> int
+// f -> float
+// d -> double
+// z -> size_t
+// F -> constant CFString
+// a -> __builtin_va_list
+// A -> "reference" to __builtin_va_list
+// V -> Vector, following num elements and a base type.
+// P -> FILE
+// . -> "...". This may only occur at the end of the function list.
+//
+// Types maybe prefixed with the following modifiers:
+// L -> long (e.g. Li for 'long int')
+// LL -> long long
+// LLL -> __int128_t (e.g. LLLi)
+// S -> signed
+// U -> unsigned
+//
+// Types may be postfixed with the following modifiers:
+// * -> pointer
+// & -> reference
+// C -> const
+
+// The third value provided to the macro specifies information about attributes
+// of the function. These must be kept in sync with the predicates in the
+// Builtin::Context class. Currently we have:
+// n -> nothrow
+// c -> const
+// F -> this is a libc/libm function with a '__builtin_' prefix added.
+// f -> this is a libc/libm function without the '__builtin_' prefix. It can
+// be followed by ':headername:' to state which header this function
+// comes from.
+// p:N: -> this is a printf-like function whose Nth argument is the format
+// string.
+// P:N: -> similar to the p:N: attribute, but the function is like vprintf
+// in that it accepts its arguments as a va_list rather than
+// through an ellipsis
+// e -> const, but only when -fmath-errno=0
+// FIXME: gcc has nonnull
+
+#if defined(BUILTIN) && !defined(LIBBUILTIN)
+# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// Standard libc/libm functions:
+BUILTIN(__builtin_huge_val, "d", "nc")
+BUILTIN(__builtin_huge_valf, "f", "nc")
+BUILTIN(__builtin_huge_vall, "Ld", "nc")
+BUILTIN(__builtin_inf , "d" , "nc")
+BUILTIN(__builtin_inff , "f" , "nc")
+BUILTIN(__builtin_infl , "Ld" , "nc")
+BUILTIN(__builtin_nan, "dcC*" , "ncF")
+BUILTIN(__builtin_nanf, "fcC*" , "ncF")
+BUILTIN(__builtin_nanl, "LdcC*", "ncF")
+BUILTIN(__builtin_nans, "dcC*" , "ncF")
+BUILTIN(__builtin_nansf, "fcC*" , "ncF")
+BUILTIN(__builtin_nansl, "LdcC*", "ncF")
+BUILTIN(__builtin_abs , "ii" , "ncF")
+BUILTIN(__builtin_fabs , "dd" , "ncF")
+BUILTIN(__builtin_fabsf, "ff" , "ncF")
+BUILTIN(__builtin_fabsl, "LdLd", "ncF")
+BUILTIN(__builtin_copysign, "ddd", "ncF")
+BUILTIN(__builtin_copysignf, "fff", "ncF")
+BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
+BUILTIN(__builtin_powi , "ddi" , "nc")
+BUILTIN(__builtin_powif, "ffi" , "nc")
+BUILTIN(__builtin_powil, "LdLdi", "nc")
+
+// FP Comparisons.
+BUILTIN(__builtin_isgreater , "i.", "nc")
+BUILTIN(__builtin_isgreaterequal, "i.", "nc")
+BUILTIN(__builtin_isless , "i.", "nc")
+BUILTIN(__builtin_islessequal , "i.", "nc")
+BUILTIN(__builtin_islessgreater , "i.", "nc")
+BUILTIN(__builtin_isunordered , "i.", "nc")
+
+// Builtins for arithmetic.
+BUILTIN(__builtin_clz , "iUi" , "nc")
+BUILTIN(__builtin_clzl , "iULi" , "nc")
+BUILTIN(__builtin_clzll, "iULLi", "nc")
+// TODO: int clzimax(uintmax_t)
+BUILTIN(__builtin_ctz , "iUi" , "nc")
+BUILTIN(__builtin_ctzl , "iULi" , "nc")
+BUILTIN(__builtin_ctzll, "iULLi", "nc")
+// TODO: int ctzimax(uintmax_t)
+BUILTIN(__builtin_ffs , "iUi" , "nc")
+BUILTIN(__builtin_ffsl , "iULi" , "nc")
+BUILTIN(__builtin_ffsll, "iULLi", "nc")
+BUILTIN(__builtin_parity , "iUi" , "nc")
+BUILTIN(__builtin_parityl , "iULi" , "nc")
+BUILTIN(__builtin_parityll, "iULLi", "nc")
+BUILTIN(__builtin_popcount , "iUi" , "nc")
+BUILTIN(__builtin_popcountl , "iULi" , "nc")
+BUILTIN(__builtin_popcountll, "iULLi", "nc")
+
+// FIXME: These type signatures are not correct for targets with int != 32-bits
+// or with ULL != 64-bits.
+BUILTIN(__builtin_bswap32, "UiUi", "nc")
+BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
+
+// Random GCC builtins
+BUILTIN(__builtin_constant_p, "Us.", "nc")
+BUILTIN(__builtin_classify_type, "i.", "nc")
+BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin_va_start, "vA.", "n")
+BUILTIN(__builtin_va_end, "vA", "n")
+BUILTIN(__builtin_va_copy, "vAA", "n")
+BUILTIN(__builtin_stdarg_start, "vA.", "n")
+BUILTIN(__builtin_bcmp, "iv*v*z", "n")
+BUILTIN(__builtin_bcopy, "vv*v*z", "n")
+BUILTIN(__builtin_bzero, "vv*z", "n")
+BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
+BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
+BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
+BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
+BUILTIN(__builtin_memset, "v*v*iz", "nF")
+BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF")
+BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF")
+BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF")
+BUILTIN(__builtin_strcat, "c*c*cC*", "nF")
+BUILTIN(__builtin_strchr, "c*cC*i", "nF")
+BUILTIN(__builtin_strcmp, "icC*cC*", "nF")
+BUILTIN(__builtin_strcpy, "c*c*cC*", "nF")
+BUILTIN(__builtin_strcspn, "zcC*cC*", "nF")
+BUILTIN(__builtin_strdup, "c*cC*", "nF")
+BUILTIN(__builtin_strlen, "zcC*", "nF")
+BUILTIN(__builtin_strncasecmp, "icC*cC*z", "nF")
+BUILTIN(__builtin_strncat, "c*c*cC*z", "nF")
+BUILTIN(__builtin_strncmp, "icC*cC*z", "nF")
+BUILTIN(__builtin_strncpy, "c*c*cC*z", "nF")
+BUILTIN(__builtin_strndup, "c*cC*z", "nF")
+BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF")
+BUILTIN(__builtin_strrchr, "c*cC*i", "nF")
+BUILTIN(__builtin_strspn, "zcC*cC*", "nF")
+BUILTIN(__builtin_strstr, "c*cC*cC*", "nF")
+BUILTIN(__builtin_return_address, "v*Ui", "n")
+BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
+BUILTIN(__builtin_frame_address, "v*Ui", "n")
+BUILTIN(__builtin_flt_rounds, "i", "nc")
+BUILTIN(__builtin_setjmp, "iv**", "")
+BUILTIN(__builtin_longjmp, "vv**i", "")
+BUILTIN(__builtin_unwind_init, "v", "")
+
+// GCC Object size checking builtins
+BUILTIN(__builtin_object_size, "zv*i", "n")
+BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___memset_chk, "v*v*izz", "nF")
+BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF")
+BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF")
+BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF")
+BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF")
+BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF")
+BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "Fp:4:")
+BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "Fp:3:")
+BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "FP:4:")
+BUILTIN(__builtin___vsprintf_chk, "ic*izcC*a", "FP:3:")
+BUILTIN(__builtin___fprintf_chk, "iP*icC*.", "Fp:2:")
+BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
+BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
+BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
+
+BUILTIN(__builtin_expect, "iii" , "nc")
+BUILTIN(__builtin_prefetch, "vvC*.", "nc")
+BUILTIN(__builtin_trap, "v", "n")
+
+BUILTIN(__builtin_shufflevector, "v." , "nc")
+
+BUILTIN(__builtin_alloca, "v*z" , "n")
+
+// "Overloaded" Atomic operator builtins. These are overloaded to support data
+// types of i8, i16, i32, i64, and i128. The front-end sees calls to the
+// non-suffixed version of these (which has a bogus type) and transforms them to
+// the right overloaded version in Sema (plus casts).
+
+// FIXME: These assume that char -> i8, short -> i16, int -> i32,
+// long long -> i64.
+
+BUILTIN(__sync_fetch_and_add, "v.", "")
+BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n")
+BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n")
+BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n")
+BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_sub, "v.", "")
+BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n")
+BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n")
+BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n")
+BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_or, "v.", "")
+BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n")
+BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n")
+BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n")
+BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_and, "v.", "")
+BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n")
+BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n")
+BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n")
+BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_xor, "v.", "")
+BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n")
+BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n")
+BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n")
+BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_fetch_and_nand, "v.", "")
+BUILTIN(__sync_fetch_and_nand_1, "cc*c.", "n")
+BUILTIN(__sync_fetch_and_nand_2, "ss*s.", "n")
+BUILTIN(__sync_fetch_and_nand_4, "ii*i.", "n")
+BUILTIN(__sync_fetch_and_nand_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLi*LLLi.", "n")
+
+
+BUILTIN(__sync_add_and_fetch, "v.", "")
+BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n")
+BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n")
+BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n")
+BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_sub_and_fetch, "v.", "")
+BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n")
+BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n")
+BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n")
+BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_or_and_fetch, "v.", "")
+BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n")
+BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n")
+BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n")
+BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_and_and_fetch, "v.", "")
+BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n")
+BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n")
+BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n")
+BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_xor_and_fetch, "v.", "")
+BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n")
+BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n")
+BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n")
+BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_nand_and_fetch, "v.", "")
+BUILTIN(__sync_nand_and_fetch_1, "cc*c.", "n")
+BUILTIN(__sync_nand_and_fetch_2, "ss*s.", "n")
+BUILTIN(__sync_nand_and_fetch_4, "ii*i.", "n")
+BUILTIN(__sync_nand_and_fetch_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+
+
+BUILTIN(__sync_bool_compare_and_swap, "v.", "")
+BUILTIN(__sync_bool_compare_and_swap_1, "bc*cc.", "n")
+BUILTIN(__sync_bool_compare_and_swap_2, "bs*ss.", "n")
+BUILTIN(__sync_bool_compare_and_swap_4, "bi*ii.", "n")
+BUILTIN(__sync_bool_compare_and_swap_8, "bLLi*LLi.", "n")
+BUILTIN(__sync_bool_compare_and_swap_16, "bLLLi*LLLiLLLi.", "n")
+
+BUILTIN(__sync_val_compare_and_swap, "v.", "")
+BUILTIN(__sync_val_compare_and_swap_1, "cc*cc.", "n")
+BUILTIN(__sync_val_compare_and_swap_2, "ss*ss.", "n")
+BUILTIN(__sync_val_compare_and_swap_4, "ii*ii.", "n")
+BUILTIN(__sync_val_compare_and_swap_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLi*LLLiLLLi.", "n")
+
+BUILTIN(__sync_lock_test_and_set, "v.", "")
+BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n")
+BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n")
+BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n")
+BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n")
+BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n")
+
+BUILTIN(__sync_lock_release, "v.", "")
+BUILTIN(__sync_lock_release_1, "vc*.", "n")
+BUILTIN(__sync_lock_release_2, "vs*.", "n")
+BUILTIN(__sync_lock_release_4, "vi*.", "n")
+BUILTIN(__sync_lock_release_8, "vLLi*.", "n")
+BUILTIN(__sync_lock_release_16, "vLLLi*.", "n")
+
+
+
+// Non-overloaded atomic builtins.
+BUILTIN(__sync_synchronize, "v.", "n")
+// LLVM instruction builtin [Clang extension].
+BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
+// GCC does not support these, they are a Clang extension.
+BUILTIN(__sync_fetch_and_min, "ii*i", "n")
+BUILTIN(__sync_fetch_and_max, "ii*i", "n")
+BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n")
+BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n")
+
+// Builtin library functions
+LIBBUILTIN(alloca, "v*z", "f", "stdlib.h")
+LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h")
+LIBBUILTIN(malloc, "v*z", "f", "stdlib.h")
+LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h")
+LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h")
+LIBBUILTIN(memmove, "v*v*vC*z", "f", "string.h")
+LIBBUILTIN(memset, "v*v*iz", "f", "string.h")
+LIBBUILTIN(strcat, "c*c*cC*", "f", "string.h")
+LIBBUILTIN(strchr, "c*cC*i", "f", "string.h")
+LIBBUILTIN(strcpy, "c*c*cC*", "f", "string.h")
+LIBBUILTIN(strcspn, "zcC*cC*", "f", "string.h")
+LIBBUILTIN(strlen, "zcC*", "f", "string.h")
+LIBBUILTIN(strncat, "c*c*cC*z", "f", "string.h")
+LIBBUILTIN(strncpy, "c*c*cC*z", "f", "string.h")
+LIBBUILTIN(strpbrk, "c*cC*cC*", "f", "string.h")
+LIBBUILTIN(strrchr, "c*cC*i", "f", "string.h")
+LIBBUILTIN(strspn, "zcC*cC*", "f", "string.h")
+LIBBUILTIN(strstr, "c*cC*cC*", "f", "string.h")
+LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h")
+LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h")
+LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h")
+LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h")
+LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h")
+LIBBUILTIN(vfprintf, "iP*cC*a", "fP:1:", "stdio.h")
+LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
+LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
+
+// FIXME: This type isn't very correct, it should be
+// id objc_msgSend(id, SEL)
+// but we need new type letters for that.
+LIBBUILTIN(objc_msgSend, "v*.", "f", "objc/message.h")
+
+// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
+// target-specific builtins, perhaps?
+
+// Builtin math library functions
+LIBBUILTIN(pow, "ddd", "fe", "math.h")
+LIBBUILTIN(powl, "LdLdLd", "fe", "math.h")
+LIBBUILTIN(powf, "fff", "fe", "math.h")
+
+LIBBUILTIN(sqrt, "dd", "fe", "math.h")
+LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h")
+LIBBUILTIN(sqrtf, "ff", "fe", "math.h")
+
+LIBBUILTIN(sin, "dd", "fe", "math.h")
+LIBBUILTIN(sinl, "LdLd", "fe", "math.h")
+LIBBUILTIN(sinf, "ff", "fe", "math.h")
+
+LIBBUILTIN(cos, "dd", "fe", "math.h")
+LIBBUILTIN(cosl, "LdLd", "fe", "math.h")
+LIBBUILTIN(cosf, "ff", "fe", "math.h")
+
+#undef BUILTIN
+#undef LIBBUILTIN
diff --git a/include/clang/AST/Builtins.h b/include/clang/AST/Builtins.h
new file mode 100644
index 000000000000..b16d3bf34139
--- /dev/null
+++ b/include/clang/AST/Builtins.h
@@ -0,0 +1,137 @@
+//===--- Builtins.h - Builtin function header -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines enum values for all the target-independent builtin
+// functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_BUILTINS_H
+#define LLVM_CLANG_AST_BUILTINS_H
+
+#include <cstring>
+#include <string>
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class TargetInfo;
+ class IdentifierTable;
+ class ASTContext;
+ class QualType;
+
+namespace Builtin {
+enum ID {
+ NotBuiltin = 0, // This is not a builtin function.
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/AST/Builtins.def"
+ FirstTSBuiltin
+};
+
+struct Info {
+ const char *Name, *Type, *Attributes, *HeaderName;
+ bool Suppressed;
+
+ bool operator==(const Info &RHS) const {
+ return !strcmp(Name, RHS.Name) &&
+ !strcmp(Type, RHS.Type) &&
+ !strcmp(Attributes, RHS.Attributes);
+ }
+ bool operator!=(const Info &RHS) const { return !(*this == RHS); }
+};
+
+/// Builtin::Context - This holds information about target-independent and
+/// target-specific builtins, allowing easy queries by clients.
+class Context {
+ const Info *TSRecords;
+ unsigned NumTSRecords;
+public:
+ Context() : TSRecords(0), NumTSRecords(0) {}
+
+ /// \brief Load all of the target builtins. This should be called
+ /// prior to initializing the builtin identifiers.
+ void InitializeTargetBuiltins(const TargetInfo &Target);
+
+ /// InitializeBuiltins - Mark the identifiers for all the builtins with their
+ /// appropriate builtin ID # and mark any non-portable builtin identifiers as
+ /// such.
+ void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false);
+
+ /// \brief Popular the vector with the names of all of the builtins.
+ void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
+ bool NoBuiltins);
+
+ /// Builtin::GetName - Return the identifier name for the specified builtin,
+ /// e.g. "__builtin_abs".
+ const char *GetName(unsigned ID) const {
+ return GetRecord(ID).Name;
+ }
+
+ /// isConst - Return true if this function has no side effects and doesn't
+ /// read memory.
+ bool isConst(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'c') != 0;
+ }
+
+ /// isNoThrow - Return true if we know this builtin never throws an exception.
+ bool isNoThrow(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'n') != 0;
+ }
+
+ /// isLibFunction - Return true if this is a builtin for a libc/libm function,
+ /// with a "__builtin_" prefix (e.g. __builtin_abs).
+ bool isLibFunction(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'F') != 0;
+ }
+
+ /// \brief Determines whether this builtin is a predefined libc/libm
+ /// function, such as "malloc", where we know the signature a
+ /// priori.
+ bool isPredefinedLibFunction(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'f') != 0;
+ }
+
+ /// \brief If this is a library function that comes from a specific
+ /// header, retrieve that header name.
+ const char *getHeaderName(unsigned ID) const {
+ return GetRecord(ID).HeaderName;
+ }
+
+ /// \brief Determine whether this builtin is like printf in its
+ /// formatting rules and, if so, set the index to the format string
+ /// argument and whether this function as a va_list argument.
+ bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+
+ /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
+ /// as an operand or return type.
+ bool hasVAListUse(unsigned ID) const {
+ return strpbrk(GetRecord(ID).Type, "Aa") != 0;
+ }
+
+ /// isConstWithoutErrno - Return true if this function has no side
+ /// effects and doesn't read memory, except for possibly errno. Such
+ /// functions can be const when the MathErrno lang option is
+ /// disabled.
+ bool isConstWithoutErrno(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 'e') != 0;
+ }
+
+ /// GetBuiltinType - Return the type for the specified builtin.
+ enum GetBuiltinTypeError {
+ GE_None, //< No error
+ GE_Missing_FILE //< Missing the FILE type from <stdio.h>
+ };
+ QualType GetBuiltinType(unsigned ID, ASTContext &Context,
+ GetBuiltinTypeError &Error) const;
+private:
+ const Info &GetRecord(unsigned ID) const;
+};
+
+}
+} // end namespace clang
+#endif
diff --git a/include/clang/AST/CFG.h b/include/clang/AST/CFG.h
new file mode 100644
index 000000000000..7a9ee01d4f62
--- /dev/null
+++ b/include/clang/AST/CFG.h
@@ -0,0 +1,405 @@
+//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CFG and CFGBuilder classes for representing and
+// building Control-Flow Graphs (CFGs) from ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CFG_H
+#define LLVM_CLANG_CFG_H
+
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
+#include <list>
+#include <vector>
+#include <cassert>
+
+namespace clang {
+ class Stmt;
+ class Expr;
+ class CFG;
+ class PrinterHelper;
+ class BlockEdge;
+
+/// CFGBlock - Represents a single basic block in a source-level CFG.
+/// It consists of:
+///
+/// (1) A set of statements/expressions (which may contain subexpressions).
+/// (2) A "terminator" statement (not in the set of statements).
+/// (3) A list of successors and predecessors.
+///
+/// Terminator: The terminator represents the type of control-flow that occurs
+/// at the end of the basic block. The terminator is a Stmt* referring to an
+/// AST node that has control-flow: if-statements, breaks, loops, etc.
+/// If the control-flow is conditional, the condition expression will appear
+/// within the set of statements in the block (usually the last statement).
+///
+/// Predecessors: the order in the set of predecessors is arbitrary.
+///
+/// Successors: the order in the set of successors is NOT arbitrary. We
+/// currently have the following orderings based on the terminator:
+///
+/// Terminator Successor Ordering
+/// -----------------------------------------------------
+/// if Then Block; Else Block
+/// ? operator LHS expression; RHS expression
+/// &&, || expression that uses result of && or ||, RHS
+///
+class CFGBlock {
+ typedef std::vector<Stmt*> StatementListTy;
+ /// Stmts - The set of statements in the basic block.
+ StatementListTy Stmts;
+
+ /// Label - An (optional) label that prefixes the executable
+ /// statements in the block. When this variable is non-NULL, it is
+ /// either an instance of LabelStmt or SwitchCase.
+ Stmt *Label;
+
+ /// Terminator - The terminator for a basic block that
+ /// indicates the type of control-flow that occurs between a block
+ /// and its successors.
+ Stmt *Terminator;
+
+ /// LoopTarget - Some blocks are used to represent the "loop edge" to
+ /// the start of a loop from within the loop body. This Stmt* will be
+ /// refer to the loop statement for such blocks (and be null otherwise).
+ const Stmt *LoopTarget;
+
+ /// BlockID - A numerical ID assigned to a CFGBlock during construction
+ /// of the CFG.
+ unsigned BlockID;
+
+ /// Predecessors/Successors - Keep track of the predecessor / successor
+ /// CFG blocks.
+ typedef std::vector<CFGBlock*> AdjacentBlocks;
+ AdjacentBlocks Preds;
+ AdjacentBlocks Succs;
+
+public:
+ explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
+ LoopTarget(NULL), BlockID(blockid) {}
+ ~CFGBlock() {};
+
+ // Statement iterators
+ typedef StatementListTy::iterator iterator;
+ typedef StatementListTy::const_iterator const_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+
+ Stmt* front() const { return Stmts.front(); }
+ Stmt* back() const { return Stmts.back(); }
+
+ iterator begin() { return Stmts.begin(); }
+ iterator end() { return Stmts.end(); }
+ const_iterator begin() const { return Stmts.begin(); }
+ const_iterator end() const { return Stmts.end(); }
+
+ reverse_iterator rbegin() { return Stmts.rbegin(); }
+ reverse_iterator rend() { return Stmts.rend(); }
+ const_reverse_iterator rbegin() const { return Stmts.rbegin(); }
+ const_reverse_iterator rend() const { return Stmts.rend(); }
+
+ unsigned size() const { return Stmts.size(); }
+ bool empty() const { return Stmts.empty(); }
+
+ Stmt* operator[](size_t i) const { assert (i < size()); return Stmts[i]; }
+
+ // CFG iterators
+ typedef AdjacentBlocks::iterator pred_iterator;
+ typedef AdjacentBlocks::const_iterator const_pred_iterator;
+ typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator;
+ typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator;
+
+ typedef AdjacentBlocks::iterator succ_iterator;
+ typedef AdjacentBlocks::const_iterator const_succ_iterator;
+ typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator;
+ typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator;
+
+ pred_iterator pred_begin() { return Preds.begin(); }
+ pred_iterator pred_end() { return Preds.end(); }
+ const_pred_iterator pred_begin() const { return Preds.begin(); }
+ const_pred_iterator pred_end() const { return Preds.end(); }
+
+ pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); }
+ pred_reverse_iterator pred_rend() { return Preds.rend(); }
+ const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
+ const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
+
+ succ_iterator succ_begin() { return Succs.begin(); }
+ succ_iterator succ_end() { return Succs.end(); }
+ const_succ_iterator succ_begin() const { return Succs.begin(); }
+ const_succ_iterator succ_end() const { return Succs.end(); }
+
+ succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); }
+ succ_reverse_iterator succ_rend() { return Succs.rend(); }
+ const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
+ const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
+
+ unsigned succ_size() const { return Succs.size(); }
+ bool succ_empty() const { return Succs.empty(); }
+
+ unsigned pred_size() const { return Preds.size(); }
+ bool pred_empty() const { return Preds.empty(); }
+
+ // Manipulation of block contents
+
+ void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
+ void setTerminator(Stmt* Statement) { Terminator = Statement; }
+ void setLabel(Stmt* Statement) { Label = Statement; }
+ void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
+
+ Stmt* getTerminator() { return Terminator; }
+ const Stmt* getTerminator() const { return Terminator; }
+
+ Stmt* getTerminatorCondition();
+
+ const Stmt* getTerminatorCondition() const {
+ return const_cast<CFGBlock*>(this)->getTerminatorCondition();
+ }
+
+ const Stmt *getLoopTarget() const { return LoopTarget; }
+
+ bool hasBinaryBranchTerminator() const;
+
+ Stmt* getLabel() { return Label; }
+ const Stmt* getLabel() const { return Label; }
+
+ void reverseStmts();
+
+ void addSuccessor(CFGBlock* Block) {
+ Block->Preds.push_back(this);
+ Succs.push_back(Block);
+ }
+
+ unsigned getBlockID() const { return BlockID; }
+
+ void dump(const CFG* cfg) const;
+ void print(llvm::raw_ostream& OS, const CFG* cfg) const;
+ void printTerminator(llvm::raw_ostream& OS) const;
+};
+
+
+/// CFG - Represents a source-level, intra-procedural CFG that represents the
+/// control-flow of a Stmt. The Stmt can represent an entire function body,
+/// or a single expression. A CFG will always contain one empty block that
+/// represents the Exit point of the CFG. A CFG will also contain a designated
+/// Entry block. The CFG solely represents control-flow; it consists of
+/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
+/// was constructed from.
+class CFG {
+public:
+ //===--------------------------------------------------------------------===//
+ // CFG Construction & Manipulation.
+ //===--------------------------------------------------------------------===//
+
+ /// buildCFG - Builds a CFG from an AST. The responsibility to free the
+ /// constructed CFG belongs to the caller.
+ static CFG* buildCFG(Stmt* AST);
+
+ /// createBlock - Create a new block in the CFG. The CFG owns the block;
+ /// the caller should not directly free it.
+ CFGBlock* createBlock();
+
+ /// setEntry - Set the entry block of the CFG. This is typically used
+ /// only during CFG construction. Most CFG clients expect that the
+ /// entry block has no predecessors and contains no statements.
+ void setEntry(CFGBlock *B) { Entry = B; }
+
+ /// setExit - Set the exit block of the CFG. This is typically used
+ /// only during CFG construction. Most CFG clients expect that the
+ /// exit block has no successors and contains no statements.
+ void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; }
+
+ //===--------------------------------------------------------------------===//
+ // Block Iterators
+ //===--------------------------------------------------------------------===//
+
+ typedef std::list<CFGBlock> CFGBlockListTy;
+
+ typedef CFGBlockListTy::iterator iterator;
+ typedef CFGBlockListTy::const_iterator const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ CFGBlock& front() { return Blocks.front(); }
+ CFGBlock& back() { return Blocks.back(); }
+
+ iterator begin() { return Blocks.begin(); }
+ iterator end() { return Blocks.end(); }
+ const_iterator begin() const { return Blocks.begin(); }
+ const_iterator end() const { return Blocks.end(); }
+
+ reverse_iterator rbegin() { return Blocks.rbegin(); }
+ reverse_iterator rend() { return Blocks.rend(); }
+ const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
+ const_reverse_iterator rend() const { return Blocks.rend(); }
+
+ CFGBlock& getEntry() { return *Entry; }
+ const CFGBlock& getEntry() const { return *Entry; }
+ CFGBlock& getExit() { return *Exit; }
+ const CFGBlock& getExit() const { return *Exit; }
+
+ CFGBlock* getIndirectGotoBlock() { return IndirectGotoBlock; }
+ const CFGBlock* getIndirectGotoBlock() const { return IndirectGotoBlock; }
+
+ //===--------------------------------------------------------------------===//
+ // Member templates useful for various batch operations over CFGs.
+ //===--------------------------------------------------------------------===//
+
+ template <typename CALLBACK>
+ void VisitBlockStmts(CALLBACK& O) const {
+ for (const_iterator I=begin(), E=end(); I != E; ++I)
+ for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI != BE; ++BI)
+ O(*BI);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // CFG Introspection.
+ //===--------------------------------------------------------------------===//
+
+ struct BlkExprNumTy {
+ const signed Idx;
+ explicit BlkExprNumTy(signed idx) : Idx(idx) {}
+ explicit BlkExprNumTy() : Idx(-1) {}
+ operator bool() const { return Idx >= 0; }
+ operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
+ };
+
+ bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+ BlkExprNumTy getBlkExprNum(const Stmt* S);
+ unsigned getNumBlkExprs();
+
+ unsigned getNumBlockIDs() const { return NumBlockIDs; }
+
+ //===--------------------------------------------------------------------===//
+ // CFG Debugging: Pretty-Printing and Visualization.
+ //===--------------------------------------------------------------------===//
+
+ void viewCFG() const;
+ void print(llvm::raw_ostream& OS) const;
+ void dump() const;
+
+ //===--------------------------------------------------------------------===//
+ // Internal: constructors and data.
+ //===--------------------------------------------------------------------===//
+
+ CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
+ BlkExprMap(NULL) {};
+
+ ~CFG();
+
+ llvm::BumpPtrAllocator& getAllocator() {
+ return Alloc;
+ }
+
+private:
+ CFGBlock* Entry;
+ CFGBlock* Exit;
+ CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
+ // for indirect gotos
+ CFGBlockListTy Blocks;
+ unsigned NumBlockIDs;
+
+ // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
+ // It represents a map from Expr* to integers to record the set of
+ // block-level expressions and their "statement number" in the CFG.
+ void* BlkExprMap;
+
+ /// Alloc - An internal allocator.
+ llvm::BumpPtrAllocator Alloc;
+};
+} // end namespace clang
+
+//===----------------------------------------------------------------------===//
+// GraphTraits specializations for CFG basic block graphs (source-level CFGs)
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+// Traits for: CFGBlock
+
+template <> struct GraphTraits<clang::CFGBlock* > {
+ typedef clang::CFGBlock NodeType;
+ typedef clang::CFGBlock::succ_iterator ChildIteratorType;
+
+ static NodeType* getEntryNode(clang::CFGBlock* BB)
+ { return BB; }
+
+ static inline ChildIteratorType child_begin(NodeType* N)
+ { return N->succ_begin(); }
+
+ static inline ChildIteratorType child_end(NodeType* N)
+ { return N->succ_end(); }
+};
+
+template <> struct GraphTraits<const clang::CFGBlock* > {
+ typedef const clang::CFGBlock NodeType;
+ typedef clang::CFGBlock::const_succ_iterator ChildIteratorType;
+
+ static NodeType* getEntryNode(const clang::CFGBlock* BB)
+ { return BB; }
+
+ static inline ChildIteratorType child_begin(NodeType* N)
+ { return N->succ_begin(); }
+
+ static inline ChildIteratorType child_end(NodeType* N)
+ { return N->succ_end(); }
+};
+
+template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > {
+ typedef const clang::CFGBlock NodeType;
+ typedef clang::CFGBlock::const_pred_iterator ChildIteratorType;
+
+ static NodeType *getEntryNode(Inverse<const clang::CFGBlock*> G)
+ { return G.Graph; }
+
+ static inline ChildIteratorType child_begin(NodeType* N)
+ { return N->pred_begin(); }
+
+ static inline ChildIteratorType child_end(NodeType* N)
+ { return N->pred_end(); }
+};
+
+// Traits for: CFG
+
+template <> struct GraphTraits<clang::CFG* >
+ : public GraphTraits<clang::CFGBlock* > {
+
+ typedef clang::CFG::iterator nodes_iterator;
+
+ static NodeType *getEntryNode(clang::CFG* F) { return &F->getEntry(); }
+ static nodes_iterator nodes_begin(clang::CFG* F) { return F->begin(); }
+ static nodes_iterator nodes_end(clang::CFG* F) { return F->end(); }
+};
+
+template <> struct GraphTraits< const clang::CFG* >
+ : public GraphTraits< const clang::CFGBlock* > {
+
+ typedef clang::CFG::const_iterator nodes_iterator;
+
+ static NodeType *getEntryNode( const clang::CFG* F) { return &F->getEntry(); }
+ static nodes_iterator nodes_begin( const clang::CFG* F) { return F->begin(); }
+ static nodes_iterator nodes_end( const clang::CFG* F) { return F->end(); }
+};
+
+template <> struct GraphTraits<Inverse<const clang::CFG*> >
+ : public GraphTraits<Inverse<const clang::CFGBlock*> > {
+
+ typedef clang::CFG::const_iterator nodes_iterator;
+
+ static NodeType *getEntryNode(const clang::CFG* F) { return &F->getExit(); }
+ static nodes_iterator nodes_begin(const clang::CFG* F) { return F->begin();}
+ static nodes_iterator nodes_end(const clang::CFG* F) { return F->end(); }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
new file mode 100644
index 000000000000..e134aed73d77
--- /dev/null
+++ b/include/clang/AST/Decl.h
@@ -0,0 +1,1409 @@
+//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Decl subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECL_H
+#define LLVM_CLANG_AST_DECL_H
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+
+namespace clang {
+class Expr;
+class FunctionTemplateDecl;
+class Stmt;
+class CompoundStmt;
+class StringLiteral;
+
+/// TranslationUnitDecl - The top declaration context.
+class TranslationUnitDecl : public Decl, public DeclContext {
+ TranslationUnitDecl()
+ : Decl(TranslationUnit, 0, SourceLocation()),
+ DeclContext(TranslationUnit) {}
+public:
+ static TranslationUnitDecl *Create(ASTContext &C);
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
+ static bool classof(const TranslationUnitDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const TranslationUnitDecl *D) {
+ return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D));
+ }
+ static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// NamedDecl - This represents a decl with a name. Many decls have names such
+/// as ObjCMethodDecl, but not @class, etc.
+class NamedDecl : public Decl {
+ /// Name - The name of this declaration, which is typically a normal
+ /// identifier but may also be a special kind of name (C++
+ /// constructor, Objective-C selector, etc.)
+ DeclarationName Name;
+
+protected:
+ NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
+ : Decl(DK, DC, L), Name(N) { }
+
+public:
+ /// getIdentifier - Get the identifier that names this declaration,
+ /// if there is one. This will return NULL if this declaration has
+ /// no name (e.g., for an unnamed class) or if the name is a special
+ /// name (C++ constructor, Objective-C selector, etc.).
+ IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }
+
+ /// getNameAsCString - Get the name of identifier for this declaration as a
+ /// C string (const char*). This requires that the declaration have a name
+ /// and that it be a simple identifier.
+ const char *getNameAsCString() const {
+ assert(getIdentifier() && "Name is not a simple identifier");
+ return getIdentifier()->getName();
+ }
+
+ /// getDeclName - Get the actual, stored name of the declaration,
+ /// which may be a special name.
+ DeclarationName getDeclName() const { return Name; }
+
+ /// \brief Set the name of this declaration.
+ void setDeclName(DeclarationName N) { Name = N; }
+
+ /// getNameAsString - Get a human-readable name for the declaration, even if
+ /// it is one of the special kinds of names (C++ constructor, Objective-C
+ /// selector, etc). Creating this name requires expensive string
+ /// manipulation, so it should be called only when performance doesn't matter.
+ /// For simple declarations, getNameAsCString() should suffice.
+ std::string getNameAsString() const { return Name.getAsString(); }
+
+ /// getQualifiedNameAsString - Returns human-readable qualified name for
+ /// declaration, like A::B::i, for i being member of namespace A::B.
+ /// If declaration is not member of context which can be named (record,
+ /// namespace), it will return same result as getNameAsString().
+ /// Creating this name is expensive, so it should be called only when
+ /// performance doesn't matter.
+ std::string getQualifiedNameAsString() const;
+
+ /// declarationReplaces - Determine whether this declaration, if
+ /// known to be well-formed within its context, will replace the
+ /// declaration OldD if introduced into scope. A declaration will
+ /// replace another declaration if, for example, it is a
+ /// redeclaration of the same variable or function, but not if it is
+ /// a declaration of a different kind (function vs. class) or an
+ /// overloaded function.
+ bool declarationReplaces(NamedDecl *OldD) const;
+
+ /// \brief Determine whether this declaration has linkage.
+ bool hasLinkage() const;
+
+ static bool classof(const Decl *D) {
+ return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
+ }
+ static bool classof(const NamedDecl *D) { return true; }
+};
+
+/// NamespaceDecl - Represent a C++ namespace.
+class NamespaceDecl : public NamedDecl, public DeclContext {
+ SourceLocation LBracLoc, RBracLoc;
+
+ // For extended namespace definitions:
+ //
+ // namespace A { int x; }
+ // namespace A { int y; }
+ //
+ // there will be one NamespaceDecl for each declaration.
+ // NextNamespace points to the next extended declaration.
+ // OrigNamespace points to the original namespace declaration.
+ // OrigNamespace of the first namespace decl points to itself.
+ NamespaceDecl *OrigNamespace, *NextNamespace;
+
+ NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
+ : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) {
+ OrigNamespace = this;
+ NextNamespace = 0;
+ }
+public:
+ static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+
+ virtual void Destroy(ASTContext& C);
+
+ NamespaceDecl *getNextNamespace() { return NextNamespace; }
+ const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
+ void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }
+
+ NamespaceDecl *getOriginalNamespace() const {
+ return OrigNamespace;
+ }
+ void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(LBracLoc, RBracLoc);
+ }
+
+ SourceLocation getLBracLoc() const { return LBracLoc; }
+ SourceLocation getRBracLoc() const { return RBracLoc; }
+ void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
+ void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == Namespace; }
+ static bool classof(const NamespaceDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const NamespaceDecl *D) {
+ return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D));
+ }
+ static NamespaceDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ValueDecl - Represent the declaration of a variable (in which case it is
+/// an lvalue) a function (in which case it is a function designator) or
+/// an enum constant.
+class ValueDecl : public NamedDecl {
+ QualType DeclType;
+
+protected:
+ ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T)
+ : NamedDecl(DK, DC, L, N), DeclType(T) {}
+public:
+ QualType getType() const { return DeclType; }
+ void setType(QualType newType) { DeclType = newType; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= ValueFirst && D->getKind() <= ValueLast;
+ }
+ static bool classof(const ValueDecl *D) { return true; }
+};
+
+/// \brief Structure used to store a statement, the constant value to
+/// which it was evaluated (if any), and whether or not the statement
+/// is an integral constant expression (if known).
+struct EvaluatedStmt {
+ EvaluatedStmt() : WasEvaluated(false), CheckedICE(false), IsICE(false) { }
+
+ /// \brief Whether this statement was already evaluated.
+ bool WasEvaluated : 1;
+
+ /// \brief Whether we already checked whether this statement was an
+ /// integral constant expression.
+ bool CheckedICE : 1;
+
+ /// \brief Whether this statement is an integral constant
+ /// expression. Only valid if CheckedICE is true.
+ bool IsICE : 1;
+
+ Stmt *Value;
+ APValue Evaluated;
+};
+
+/// VarDecl - An instance of this class is created to represent a variable
+/// declaration or definition.
+class VarDecl : public ValueDecl {
+public:
+ enum StorageClass {
+ None, Auto, Register, Extern, Static, PrivateExtern
+ };
+
+ /// getStorageClassSpecifierString - Return the string used to
+ /// specify the storage class \arg SC.
+ ///
+ /// It is illegal to call this function with SC == None.
+ static const char *getStorageClassSpecifierString(StorageClass SC);
+
+private:
+ mutable llvm::PointerUnion<Stmt *, EvaluatedStmt *> Init;
+ // FIXME: This can be packed into the bitfields in Decl.
+ unsigned SClass : 3;
+ bool ThreadSpecified : 1;
+ bool HasCXXDirectInit : 1;
+
+ /// DeclaredInCondition - Whether this variable was declared in a
+ /// condition, e.g., if (int x = foo()) { ... }.
+ bool DeclaredInCondition : 1;
+
+ /// \brief The previous declaration of this variable.
+ VarDecl *PreviousDeclaration;
+
+ // Move to DeclGroup when it is implemented.
+ SourceLocation TypeSpecStartLoc;
+ friend class StmtIteratorBase;
+protected:
+ VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T, StorageClass SC, SourceLocation TSSL = SourceLocation())
+ : ValueDecl(DK, DC, L, Id, T), Init(),
+ ThreadSpecified(false), HasCXXDirectInit(false),
+ DeclaredInCondition(false), PreviousDeclaration(0),
+ TypeSpecStartLoc(TSSL) {
+ SClass = SC;
+ }
+public:
+ static VarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, StorageClass S,
+ SourceLocation TypeSpecStartLoc = SourceLocation());
+
+ virtual ~VarDecl();
+ virtual void Destroy(ASTContext& C);
+
+ StorageClass getStorageClass() const { return (StorageClass)SClass; }
+ void setStorageClass(StorageClass SC) { SClass = SC; }
+
+ SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
+ void setTypeSpecStartLoc(SourceLocation SL) {
+ TypeSpecStartLoc = SL;
+ }
+
+ const Expr *getInit() const {
+ if (Init.isNull())
+ return 0;
+
+ const Stmt *S = Init.dyn_cast<Stmt *>();
+ if (!S)
+ S = Init.get<EvaluatedStmt *>()->Value;
+
+ return (const Expr*) S;
+ }
+ Expr *getInit() {
+ if (Init.isNull())
+ return 0;
+
+ Stmt *S = Init.dyn_cast<Stmt *>();
+ if (!S)
+ S = Init.get<EvaluatedStmt *>()->Value;
+
+ return (Expr*) S;
+ }
+
+ /// \brief Retrieve the address of the initializer expression.
+ Stmt **getInitAddress() {
+ if (Init.is<Stmt *>())
+ return reinterpret_cast<Stmt **>(&Init); // FIXME: ugly hack
+ return &Init.get<EvaluatedStmt *>()->Value;
+ }
+
+ void setInit(ASTContext &C, Expr *I);
+
+ /// \brief Note that constant evaluation has computed the given
+ /// value for this variable's initializer.
+ void setEvaluatedValue(ASTContext &C, const APValue &Value) const {
+ EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
+ if (!Eval) {
+ Stmt *S = Init.get<Stmt *>();
+ Eval = new (C) EvaluatedStmt;
+ Eval->Value = S;
+ Init = Eval;
+ }
+
+ Eval->WasEvaluated = true;
+ Eval->Evaluated = Value;
+ }
+
+ /// \brief Return the already-evaluated value of this variable's
+ /// initializer, or NULL if the value is not yet known.
+ APValue *getEvaluatedValue() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ if (Eval->WasEvaluated)
+ return &Eval->Evaluated;
+
+ return 0;
+ }
+
+ /// \brief Determines whether it is already known whether the
+ /// initializer is an integral constant expression or not.
+ bool isInitKnownICE() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ return Eval->CheckedICE;
+
+ return false;
+ }
+
+ /// \brief Determines whether the initializer is an integral
+ /// constant expression.
+ ///
+ /// \pre isInitKnownICE()
+ bool isInitICE() const {
+ assert(isInitKnownICE() &&
+ "Check whether we already know that the initializer is an ICE");
+ return Init.get<EvaluatedStmt *>()->IsICE;
+ }
+
+ /// \brief Note that we now know whether the initializer is an
+ /// integral constant expression.
+ void setInitKnownICE(ASTContext &C, bool IsICE) const {
+ EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
+ if (!Eval) {
+ Stmt *S = Init.get<Stmt *>();
+ Eval = new (C) EvaluatedStmt;
+ Eval->Value = S;
+ Init = Eval;
+ }
+
+ Eval->CheckedICE = true;
+ Eval->IsICE = IsICE;
+ }
+
+ /// \brief Retrieve the definition of this variable, which may come
+ /// from a previous declaration. Def will be set to the VarDecl that
+ /// contains the initializer, and the result will be that
+ /// initializer.
+ const Expr *getDefinition(const VarDecl *&Def) const;
+
+ void setThreadSpecified(bool T) { ThreadSpecified = T; }
+ bool isThreadSpecified() const {
+ return ThreadSpecified;
+ }
+
+ void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; }
+
+ /// hasCXXDirectInitializer - If true, the initializer was a direct
+ /// initializer, e.g: "int x(1);". The Init expression will be the expression
+ /// inside the parens or a "ClassType(a,b,c)" class constructor expression for
+ /// class types. Clients can distinguish between "int x(1);" and "int x=1;"
+ /// by checking hasCXXDirectInitializer.
+ ///
+ bool hasCXXDirectInitializer() const {
+ return HasCXXDirectInit;
+ }
+
+ /// isDeclaredInCondition - Whether this variable was declared as
+ /// part of a condition in an if/switch/while statement, e.g.,
+ /// @code
+ /// if (int x = foo()) { ... }
+ /// @endcode
+ bool isDeclaredInCondition() const {
+ return DeclaredInCondition;
+ }
+ void setDeclaredInCondition(bool InCondition) {
+ DeclaredInCondition = InCondition;
+ }
+
+ /// getPreviousDeclaration - Return the previous declaration of this
+ /// variable.
+ const VarDecl *getPreviousDeclaration() const { return PreviousDeclaration; }
+
+ void setPreviousDeclaration(VarDecl *PrevDecl) {
+ PreviousDeclaration = PrevDecl;
+ }
+
+ /// hasLocalStorage - Returns true if a variable with function scope
+ /// is a non-static local variable.
+ bool hasLocalStorage() const {
+ if (getStorageClass() == None)
+ return !isFileVarDecl();
+
+ // Return true for: Auto, Register.
+ // Return false for: Extern, Static, PrivateExtern.
+
+ return getStorageClass() <= Register;
+ }
+
+ /// hasExternStorage - Returns true if a variable has extern or
+ /// __private_extern__ storage.
+ bool hasExternalStorage() const {
+ return getStorageClass() == Extern || getStorageClass() == PrivateExtern;
+ }
+
+ /// hasGlobalStorage - Returns true for all variables that do not
+ /// have local storage. This includs all global variables as well
+ /// as static variables declared within a function.
+ bool hasGlobalStorage() const { return !hasLocalStorage(); }
+
+ /// isBlockVarDecl - Returns true for local variable declarations. Note that
+ /// this includes static variables inside of functions.
+ ///
+ /// void foo() { int x; static int y; extern int z; }
+ ///
+ bool isBlockVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+ if (const DeclContext *DC = getDeclContext())
+ return DC->getLookupContext()->isFunctionOrMethod();
+ return false;
+ }
+
+ /// \brief Determines whether this is a static data member.
+ ///
+ /// This will only be true in C++, and applies to, e.g., the
+ /// variable 'x' in:
+ /// \code
+ /// struct S {
+ /// static int x;
+ /// };
+ /// \endcode
+ bool isStaticDataMember() const {
+ return getDeclContext()->isRecord();
+ }
+
+ /// isFileVarDecl - Returns true for file scoped variable declaration.
+ bool isFileVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+ if (const DeclContext *Ctx = getDeclContext()) {
+ Ctx = Ctx->getLookupContext();
+ if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
+ return true;
+ }
+ return false;
+ }
+
+ /// \brief Determine whether this is a tentative definition of a
+ /// variable in C.
+ bool isTentativeDefinition(ASTContext &Context) const;
+
+ /// \brief Determines whether this variable is a variable with
+ /// external, C linkage.
+ bool isExternC(ASTContext &Context) const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= VarFirst && D->getKind() <= VarLast;
+ }
+ static bool classof(const VarDecl *D) { return true; }
+};
+
+class ImplicitParamDecl : public VarDecl {
+protected:
+ ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType Tw)
+ : VarDecl(DK, DC, L, Id, Tw, VarDecl::None) {}
+public:
+ static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T);
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const ImplicitParamDecl *D) { return true; }
+ static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; }
+};
+
+/// ParmVarDecl - Represent a parameter to a function.
+class ParmVarDecl : public VarDecl {
+ // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
+ /// FIXME: Also can be paced into the bitfields in Decl.
+ /// in, inout, etc.
+ unsigned objcDeclQualifier : 6;
+
+ /// Default argument, if any. [C++ Only]
+ Expr *DefaultArg;
+protected:
+ ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, StorageClass S,
+ Expr *DefArg)
+ : VarDecl(DK, DC, L, Id, T, S),
+ objcDeclQualifier(OBJC_TQ_None), DefaultArg(DefArg) {}
+
+public:
+ static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,IdentifierInfo *Id,
+ QualType T, StorageClass S, Expr *DefArg);
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ return ObjCDeclQualifier(objcDeclQualifier);
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier QTVal) {
+ objcDeclQualifier = QTVal;
+ }
+
+ const Expr *getDefaultArg() const { return DefaultArg; }
+ Expr *getDefaultArg() { return DefaultArg; }
+ void setDefaultArg(Expr *defarg) { DefaultArg = defarg; }
+
+ /// hasUnparsedDefaultArg - Determines whether this parameter has a
+ /// default argument that has not yet been parsed. This will occur
+ /// during the processing of a C++ class whose member functions have
+ /// default arguments, e.g.,
+ /// @code
+ /// class X {
+ /// public:
+ /// void f(int x = 17); // x has an unparsed default argument now
+ /// }; // x has a regular default argument now
+ /// @endcode
+ bool hasUnparsedDefaultArg() const {
+ return DefaultArg == reinterpret_cast<Expr *>(-1);
+ }
+
+ /// setUnparsedDefaultArg - Specify that this parameter has an
+ /// unparsed default argument. The argument will be replaced with a
+ /// real default argument via setDefaultArg when the class
+ /// definition enclosing the function declaration that owns this
+ /// default argument is completed.
+ void setUnparsedDefaultArg() { DefaultArg = reinterpret_cast<Expr *>(-1); }
+
+ QualType getOriginalType() const;
+
+ /// setOwningFunction - Sets the function declaration that owns this
+ /// ParmVarDecl. Since ParmVarDecls are often created before the
+ /// FunctionDecls that own them, this routine is required to update
+ /// the DeclContext appropriately.
+ void setOwningFunction(DeclContext *FD) { setDeclContext(FD); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return (D->getKind() == ParmVar ||
+ D->getKind() == OriginalParmVar);
+ }
+ static bool classof(const ParmVarDecl *D) { return true; }
+};
+
+/// OriginalParmVarDecl - Represent a parameter to a function, when
+/// the type of the parameter has been promoted. This node represents the
+/// parameter to the function with its original type.
+///
+class OriginalParmVarDecl : public ParmVarDecl {
+ friend class ParmVarDecl;
+protected:
+ QualType OriginalType;
+private:
+ OriginalParmVarDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ QualType OT, StorageClass S,
+ Expr *DefArg)
+ : ParmVarDecl(OriginalParmVar, DC, L, Id, T, S, DefArg), OriginalType(OT) {}
+public:
+ static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,IdentifierInfo *Id,
+ QualType T, QualType OT,
+ StorageClass S, Expr *DefArg);
+
+ void setOriginalType(QualType T) { OriginalType = T; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; }
+ static bool classof(const OriginalParmVarDecl *D) { return true; }
+};
+
+/// FunctionDecl - An instance of this class is created to represent a
+/// function declaration or definition.
+///
+/// Since a given function can be declared several times in a program,
+/// there may be several FunctionDecls that correspond to that
+/// function. Only one of those FunctionDecls will be found when
+/// traversing the list of declarations in the context of the
+/// FunctionDecl (e.g., the translation unit); this FunctionDecl
+/// contains all of the information known about the function. Other,
+/// previous declarations of the function are available via the
+/// getPreviousDeclaration() chain.
+class FunctionDecl : public ValueDecl, public DeclContext {
+public:
+ enum StorageClass {
+ None, Extern, Static, PrivateExtern
+ };
+private:
+ /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
+ /// parameters of this function. This is null if a prototype or if there are
+ /// no formals. TODO: we could allocate this space immediately after the
+ /// FunctionDecl object to save an allocation like FunctionType does.
+ ParmVarDecl **ParamInfo;
+
+ LazyDeclStmtPtr Body;
+
+ /// PreviousDeclaration - A link to the previous declaration of this
+ /// same function, NULL if this is the first declaration. For
+ /// example, in the following code, the PreviousDeclaration can be
+ /// traversed several times to see all three declarations of the
+ /// function "f", the last of which is also a definition.
+ ///
+ /// int f(int x, int y = 1);
+ /// int f(int x = 0, int y);
+ /// int f(int x, int y) { return x + y; }
+ FunctionDecl *PreviousDeclaration;
+
+ // FIXME: This can be packed into the bitfields in Decl.
+ // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
+ unsigned SClass : 2;
+ bool IsInline : 1;
+ bool C99InlineDefinition : 1;
+ bool IsVirtualAsWritten : 1;
+ bool IsPure : 1;
+ bool HasInheritedPrototype : 1;
+ bool HasWrittenPrototype : 1;
+ bool IsDeleted : 1;
+
+ // Move to DeclGroup when it is implemented.
+ SourceLocation TypeSpecStartLoc;
+
+ /// \brief The template or declaration that this declaration
+ /// describes or was instantiated from, respectively.
+ ///
+ /// For non-templates, this value will be NULL. For function
+ /// declarations that describe a function template, this will be a
+ /// pointer to a FunctionTemplateDecl. For member functions
+ /// of class template specializations, this will be the
+ /// FunctionDecl from which the member function was instantiated.
+ llvm::PointerUnion<FunctionTemplateDecl*, FunctionDecl*>
+ TemplateOrInstantiation;
+
+protected:
+ FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T,
+ StorageClass S, bool isInline,
+ SourceLocation TSSL = SourceLocation())
+ : ValueDecl(DK, DC, L, N, T),
+ DeclContext(DK),
+ ParamInfo(0), Body(), PreviousDeclaration(0),
+ SClass(S), IsInline(isInline), C99InlineDefinition(false),
+ IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
+ HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
+ TemplateOrInstantiation() {}
+
+ virtual ~FunctionDecl() {}
+ virtual void Destroy(ASTContext& C);
+
+public:
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName N, QualType T,
+ StorageClass S = None, bool isInline = false,
+ bool hasWrittenPrototype = true,
+ SourceLocation TSStartLoc = SourceLocation());
+
+ SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
+ void setTypeSpecStartLoc(SourceLocation TS) { TypeSpecStartLoc = TS; }
+
+ /// getBody - Retrieve the body (definition) of the function. The
+ /// function body might be in any of the (re-)declarations of this
+ /// function. The variant that accepts a FunctionDecl pointer will
+ /// set that function declaration to the actual declaration
+ /// containing the body (if there is one).
+ Stmt *getBody(ASTContext &Context, const FunctionDecl *&Definition) const;
+
+ virtual Stmt *getBody(ASTContext &Context) const {
+ const FunctionDecl* Definition;
+ return getBody(Context, Definition);
+ }
+
+ /// \brief If the function has a body that is immediately available,
+ /// return it.
+ Stmt *getBodyIfAvailable() const;
+
+ /// isThisDeclarationADefinition - Returns whether this specific
+ /// declaration of the function is also a definition. This does not
+ /// determine whether the function has been defined (e.g., in a
+ /// previous definition); for that information, use getBody.
+ /// FIXME: Should return true if function is deleted or defaulted. However,
+ /// CodeGenModule.cpp uses it, and I don't know if this would break it.
+ bool isThisDeclarationADefinition() const { return Body; }
+
+ void setBody(Stmt *B) { Body = B; }
+ void setLazyBody(uint64_t Offset) { Body = Offset; }
+
+ /// Whether this function is marked as virtual explicitly.
+ bool isVirtualAsWritten() const { return IsVirtualAsWritten; }
+ void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; }
+
+ /// Whether this virtual function is pure, i.e. makes the containing class
+ /// abstract.
+ bool isPure() const { return IsPure; }
+ void setPure(bool P = true) { IsPure = P; }
+
+ /// \brief Whether this function has a prototype, either because one
+ /// was explicitly written or because it was "inherited" by merging
+ /// a declaration without a prototype with a declaration that has a
+ /// prototype.
+ bool hasPrototype() const {
+ return HasWrittenPrototype || HasInheritedPrototype;
+ }
+
+ bool hasWrittenPrototype() const { return HasWrittenPrototype; }
+ void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; }
+
+ /// \brief Whether this function inherited its prototype from a
+ /// previous declaration.
+ bool hasInheritedPrototype() const { return HasInheritedPrototype; }
+ void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }
+
+ /// \brief Whether this function has been deleted.
+ ///
+ /// A function that is "deleted" (via the C++0x "= delete" syntax)
+ /// acts like a normal function, except that it cannot actually be
+ /// called or have its address taken. Deleted functions are
+ /// typically used in C++ overload resolution to attract arguments
+ /// whose type or lvalue/rvalue-ness would permit the use of a
+ /// different overload that would behave incorrectly. For example,
+ /// one might use deleted functions to ban implicit conversion from
+ /// a floating-point number to an Integer type:
+ ///
+ /// @code
+ /// struct Integer {
+ /// Integer(long); // construct from a long
+ /// Integer(double) = delete; // no construction from float or double
+ /// Integer(long double) = delete; // no construction from long double
+ /// };
+ /// @endcode
+ bool isDeleted() const { return IsDeleted; }
+ void setDeleted(bool D = true) { IsDeleted = D; }
+
+ /// \brief Determines whether this is a function "main", which is
+ /// the entry point into an executable program.
+ bool isMain() const;
+
+ /// \brief Determines whether this function is a function with
+ /// external, C linkage.
+ bool isExternC(ASTContext &Context) const;
+
+ /// \brief Determines whether this is a global function.
+ bool isGlobal() const;
+
+ /// getPreviousDeclaration - Return the previous declaration of this
+ /// function.
+ const FunctionDecl *getPreviousDeclaration() const {
+ return PreviousDeclaration;
+ }
+
+ void setPreviousDeclaration(FunctionDecl * PrevDecl) {
+ PreviousDeclaration = PrevDecl;
+ }
+
+ unsigned getBuiltinID(ASTContext &Context) const;
+
+ unsigned getNumParmVarDeclsFromType() const;
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return getNumParams(); }
+ typedef ParmVarDecl **param_iterator;
+ typedef ParmVarDecl * const *param_const_iterator;
+
+ param_iterator param_begin() { return ParamInfo; }
+ param_iterator param_end() { return ParamInfo+param_size(); }
+
+ param_const_iterator param_begin() const { return ParamInfo; }
+ param_const_iterator param_end() const { return ParamInfo+param_size(); }
+
+ /// getNumParams - Return the number of parameters this function must have
+ /// based on its functiontype. This is the length of the PararmInfo array
+ /// after it has been created.
+ unsigned getNumParams() const;
+
+ const ParmVarDecl *getParamDecl(unsigned i) const {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ ParmVarDecl *getParamDecl(unsigned i) {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams);
+
+ /// getMinRequiredArguments - Returns the minimum number of arguments
+ /// needed to call this function. This may be fewer than the number of
+ /// function parameters, if some of the parameters have default
+ /// arguments (in C++).
+ unsigned getMinRequiredArguments() const;
+
+ QualType getResultType() const {
+ return getType()->getAsFunctionType()->getResultType();
+ }
+ StorageClass getStorageClass() const { return StorageClass(SClass); }
+ void setStorageClass(StorageClass SC) { SClass = SC; }
+
+ bool isInline() const { return IsInline; }
+ void setInline(bool I) { IsInline = I; }
+
+ /// \brief Whether this function is an "inline definition" as
+ /// defined by C99.
+ bool isC99InlineDefinition() const { return C99InlineDefinition; }
+ void setC99InlineDefinition(bool I) { C99InlineDefinition = I; }
+
+ /// \brief Determines whether this function has a gnu_inline
+ /// attribute that affects its semantics.
+ ///
+ /// The gnu_inline attribute only introduces GNU inline semantics
+ /// when all of the inline declarations of the function are marked
+ /// gnu_inline.
+ bool hasActiveGNUInlineAttribute() const;
+
+ /// \brief Determines whether this function is a GNU "extern
+ /// inline", which is roughly the opposite of a C99 "extern inline"
+ /// function.
+ bool isExternGNUInline() const;
+
+ /// isOverloadedOperator - Whether this function declaration
+ /// represents an C++ overloaded operator, e.g., "operator+".
+ bool isOverloadedOperator() const {
+ return getOverloadedOperator() != OO_None;
+ };
+
+ OverloadedOperatorKind getOverloadedOperator() const;
+
+ /// \brief If this function is an instantiation of a member function
+ /// of a class template specialization, retrieves the function from
+ /// which it was instantiated.
+ ///
+ /// This routine will return non-NULL for (non-templated) member
+ /// functions of class templates and for instantiations of function
+ /// templates. For example, given:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// void f(T);
+ /// };
+ /// \endcode
+ ///
+ /// The declaration for X<int>::f is a (non-templated) FunctionDecl
+ /// whose parent is the class template specialization X<int>. For
+ /// this declaration, getInstantiatedFromFunction() will return
+ /// the FunctionDecl X<T>::A. When a complete definition of
+ /// X<int>::A is required, it will be instantiated from the
+ /// declaration returned by getInstantiatedFromMemberFunction().
+ FunctionDecl *getInstantiatedFromMemberFunction() const {
+ return TemplateOrInstantiation.dyn_cast<FunctionDecl*>();
+ }
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member function RD.
+ void setInstantiationOfMemberFunction(FunctionDecl *RD) {
+ TemplateOrInstantiation = RD;
+ }
+
+ /// \brief Retrieves the function template that is described by this
+ /// function declaration.
+ ///
+ /// Every function template is represented as a FunctionTemplateDecl
+ /// and a FunctionDecl (or something derived from FunctionDecl). The
+ /// former contains template properties (such as the template
+ /// parameter lists) while the latter contains the actual
+ /// description of the template's
+ /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the
+ /// FunctionDecl that describes the function template,
+ /// getDescribedFunctionTemplate() retrieves the
+ /// FunctionTemplateDecl from a FunctionDecl.
+ FunctionTemplateDecl *getDescribedFunctionTemplate() const {
+ return TemplateOrInstantiation.dyn_cast<FunctionTemplateDecl*>();
+ }
+
+ void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
+ TemplateOrInstantiation = Template;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
+ }
+ static bool classof(const FunctionDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const FunctionDecl *D) {
+ return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D));
+ }
+ static FunctionDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+
+/// FieldDecl - An instance of this class is created by Sema::ActOnField to
+/// represent a member of a struct/union/class.
+class FieldDecl : public ValueDecl {
+ // FIXME: This can be packed into the bitfields in Decl.
+ bool Mutable : 1;
+ Expr *BitWidth;
+protected:
+ FieldDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *BW, bool Mutable)
+ : ValueDecl(DK, DC, L, Id, T), Mutable(Mutable), BitWidth(BW)
+ { }
+
+public:
+ static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *BW,
+ bool Mutable);
+
+ /// isMutable - Determines whether this field is mutable (C++ only).
+ bool isMutable() const { return Mutable; }
+
+ /// \brief Set whether this field is mutable (C++ only).
+ void setMutable(bool M) { Mutable = M; }
+
+ /// isBitfield - Determines whether this field is a bitfield.
+ bool isBitField() const { return BitWidth != NULL; }
+
+ /// @brief Determines whether this is an unnamed bitfield.
+ bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); }
+
+ /// isAnonymousStructOrUnion - Determines whether this field is a
+ /// representative for an anonymous struct or union. Such fields are
+ /// unnamed and are implicitly generated by the implementation to
+ /// store the data for the anonymous union or struct.
+ bool isAnonymousStructOrUnion() const;
+
+ Expr *getBitWidth() const { return BitWidth; }
+ void setBitWidth(Expr *BW) { BitWidth = BW; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
+ }
+ static bool classof(const FieldDecl *D) { return true; }
+};
+
+/// EnumConstantDecl - An instance of this object exists for each enum constant
+/// that is defined. For example, in "enum X {a,b}", each of a/b are
+/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
+/// TagType for the X EnumDecl.
+class EnumConstantDecl : public ValueDecl {
+ Stmt *Init; // an integer constant expression
+ llvm::APSInt Val; // The value.
+protected:
+ EnumConstantDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T, Expr *E,
+ const llvm::APSInt &V)
+ : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
+
+ virtual ~EnumConstantDecl() {}
+public:
+
+ static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, Expr *E,
+ const llvm::APSInt &V);
+
+ virtual void Destroy(ASTContext& C);
+
+ const Expr *getInitExpr() const { return (const Expr*) Init; }
+ Expr *getInitExpr() { return (Expr*) Init; }
+ const llvm::APSInt &getInitVal() const { return Val; }
+
+ void setInitExpr(Expr *E) { Init = (Stmt*) E; }
+ void setInitVal(const llvm::APSInt &V) { Val = V; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == EnumConstant; }
+ static bool classof(const EnumConstantDecl *D) { return true; }
+
+ friend class StmtIteratorBase;
+};
+
+
+/// TypeDecl - Represents a declaration of a type.
+///
+class TypeDecl : public NamedDecl {
+ /// TypeForDecl - This indicates the Type object that represents
+ /// this TypeDecl. It is a cache maintained by
+ /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
+ /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl.
+ mutable Type *TypeForDecl;
+ friend class ASTContext;
+ friend class DeclContext;
+ friend class TagDecl;
+ friend class TemplateTypeParmDecl;
+ friend class ClassTemplateSpecializationDecl;
+ friend class TagType;
+
+protected:
+ TypeDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id)
+ : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {}
+
+public:
+ // Low-level accessor
+ Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(Type *TD) { TypeForDecl = TD; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= TypeFirst && D->getKind() <= TypeLast;
+ }
+ static bool classof(const TypeDecl *D) { return true; }
+};
+
+
+class TypedefDecl : public TypeDecl {
+ /// UnderlyingType - This is the type the typedef is set to.
+ QualType UnderlyingType;
+ TypedefDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T)
+ : TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {}
+
+ virtual ~TypedefDecl() {}
+public:
+
+ static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,IdentifierInfo *Id,
+ QualType T);
+
+ QualType getUnderlyingType() const { return UnderlyingType; }
+ void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == Typedef; }
+ static bool classof(const TypedefDecl *D) { return true; }
+};
+
+class TypedefDecl;
+
+/// TagDecl - Represents the declaration of a struct/union/class/enum.
+class TagDecl : public TypeDecl, public DeclContext {
+public:
+ enum TagKind {
+ TK_struct,
+ TK_union,
+ TK_class,
+ TK_enum
+ };
+
+private:
+ // FIXME: This can be packed into the bitfields in Decl.
+ /// TagDeclKind - The TagKind enum.
+ unsigned TagDeclKind : 2;
+
+ /// IsDefinition - True if this is a definition ("struct foo {};"), false if
+ /// it is a declaration ("struct foo;").
+ bool IsDefinition : 1;
+
+ /// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef,
+ /// this points to the TypedefDecl. Used for mangling.
+ TypedefDecl *TypedefForAnonDecl;
+
+protected:
+ TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id)
+ : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0) {
+ assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum");
+ TagDeclKind = TK;
+ IsDefinition = false;
+ }
+public:
+
+ /// isDefinition - Return true if this decl has its body specified.
+ bool isDefinition() const {
+ return IsDefinition;
+ }
+
+ /// \brief Whether this declaration declares a type that is
+ /// dependent, i.e., a type that somehow depends on template
+ /// parameters.
+ bool isDependentType() const { return isDependentContext(); }
+
+ /// @brief Starts the definition of this tag declaration.
+ ///
+ /// This method should be invoked at the beginning of the definition
+ /// of this tag declaration. It will set the tag type into a state
+ /// where it is in the process of being defined.
+ void startDefinition();
+
+ /// @brief Completes the definition of this tag declaration.
+ void completeDefinition();
+
+ /// getDefinition - Returns the TagDecl that actually defines this
+ /// struct/union/class/enum. When determining whether or not a
+ /// struct/union/class/enum is completely defined, one should use this method
+ /// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a
+ /// specific TagDecl is defining declaration, not whether or not the
+ /// struct/union/class/enum type is defined. This method returns NULL if
+ /// there is no TagDecl that defines the struct/union/class/enum.
+ TagDecl* getDefinition(ASTContext& C) const;
+
+ const char *getKindName() const {
+ switch (getTagKind()) {
+ default: assert(0 && "Unknown TagKind!");
+ case TK_struct: return "struct";
+ case TK_union: return "union";
+ case TK_class: return "class";
+ case TK_enum: return "enum";
+ }
+ }
+
+ TagKind getTagKind() const {
+ return TagKind(TagDeclKind);
+ }
+
+ void setTagKind(TagKind TK) { TagDeclKind = TK; }
+
+ bool isStruct() const { return getTagKind() == TK_struct; }
+ bool isClass() const { return getTagKind() == TK_class; }
+ bool isUnion() const { return getTagKind() == TK_union; }
+ bool isEnum() const { return getTagKind() == TK_enum; }
+
+ TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; }
+ void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= TagFirst && D->getKind() <= TagLast;
+ }
+ static bool classof(const TagDecl *D) { return true; }
+
+ static DeclContext *castToDeclContext(const TagDecl *D) {
+ return static_cast<DeclContext *>(const_cast<TagDecl*>(D));
+ }
+ static TagDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
+ }
+
+ void setDefinition(bool V) { IsDefinition = V; }
+};
+
+/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
+/// enums.
+class EnumDecl : public TagDecl {
+ /// IntegerType - This represent the integer type that the enum corresponds
+ /// to for code generation purposes. Note that the enumerator constants may
+ /// have a different type than this does.
+ QualType IntegerType;
+
+ /// \brief If the enumeration was instantiated from an enumeration
+ /// within a class or function template, this pointer refers to the
+ /// enumeration declared within the template.
+ EnumDecl *InstantiatedFrom;
+
+ EnumDecl(DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id)
+ : TagDecl(Enum, TK_enum, DC, L, Id), InstantiatedFrom(0) {
+ IntegerType = QualType();
+ }
+public:
+ static EnumDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ EnumDecl *PrevDecl);
+
+ virtual void Destroy(ASTContext& C);
+
+ /// completeDefinition - When created, the EnumDecl corresponds to a
+ /// forward-declared enum. This method is used to mark the
+ /// declaration as being defined; it's enumerators have already been
+ /// added (via DeclContext::addDecl). NewType is the new underlying
+ /// type of the enumeration type.
+ void completeDefinition(ASTContext &C, QualType NewType);
+
+ // enumerator_iterator - Iterates through the enumerators of this
+ // enumeration.
+ typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
+
+ enumerator_iterator enumerator_begin(ASTContext &Context) const {
+ return enumerator_iterator(this->decls_begin(Context));
+ }
+
+ enumerator_iterator enumerator_end(ASTContext &Context) const {
+ return enumerator_iterator(this->decls_end(Context));
+ }
+
+ /// getIntegerType - Return the integer type this enum decl corresponds to.
+ /// This returns a null qualtype for an enum forward definition.
+ QualType getIntegerType() const { return IntegerType; }
+
+ /// \brief Set the underlying integer type.
+ void setIntegerType(QualType T) { IntegerType = T; }
+
+ /// \brief Returns the enumeration (declared within the template)
+ /// from which this enumeration type was instantiated, or NULL if
+ /// this enumeration was not instantiated from any template.
+ EnumDecl *getInstantiatedFromMemberEnum() const {
+ return InstantiatedFrom;
+ }
+
+ void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; }
+
+ static bool classof(const Decl *D) { return D->getKind() == Enum; }
+ static bool classof(const EnumDecl *D) { return true; }
+};
+
+
+/// RecordDecl - Represents a struct/union/class. For example:
+/// struct X; // Forward declaration, no "body".
+/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
+/// This decl will be marked invalid if *any* members are invalid.
+///
+class RecordDecl : public TagDecl {
+ // FIXME: This can be packed into the bitfields in Decl.
+ /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
+ /// array member (e.g. int X[]) or if this union contains a struct that does.
+ /// If so, this cannot be contained in arrays or other structs as a member.
+ bool HasFlexibleArrayMember : 1;
+
+ /// AnonymousStructOrUnion - Whether this is the type of an
+ /// anonymous struct or union.
+ bool AnonymousStructOrUnion : 1;
+
+protected:
+ RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+ virtual ~RecordDecl();
+
+public:
+ static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ RecordDecl* PrevDecl = 0);
+
+ virtual void Destroy(ASTContext& C);
+
+ bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
+ void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
+
+ /// isAnonymousStructOrUnion - Whether this is an anonymous struct
+ /// or union. To be an anonymous struct or union, it must have been
+ /// declared without a name and there must be no objects of this
+ /// type declared, e.g.,
+ /// @code
+ /// union { int i; float f; };
+ /// @endcode
+ /// is an anonymous union but neither of the following are:
+ /// @code
+ /// union X { int i; float f; };
+ /// union { int i; float f; } obj;
+ /// @endcode
+ bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }
+ void setAnonymousStructOrUnion(bool Anon) {
+ AnonymousStructOrUnion = Anon;
+ }
+
+ /// \brief Determines whether this declaration represents the
+ /// injected class name.
+ ///
+ /// The injected class name in C++ is the name of the class that
+ /// appears inside the class itself. For example:
+ ///
+ /// \code
+ /// struct C {
+ /// // C is implicitly declared here as a synonym for the class name.
+ /// };
+ ///
+ /// C::C c; // same as "C c;"
+ /// \endcode
+ bool isInjectedClassName() const;
+
+ /// getDefinition - Returns the RecordDecl that actually defines this
+ /// struct/union/class. When determining whether or not a struct/union/class
+ /// is completely defined, one should use this method as opposed to
+ /// 'isDefinition'. 'isDefinition' indicates whether or not a specific
+ /// RecordDecl is defining declaration, not whether or not the record
+ /// type is defined. This method returns NULL if there is no RecordDecl
+ /// that defines the struct/union/tag.
+ RecordDecl* getDefinition(ASTContext& C) const {
+ return cast_or_null<RecordDecl>(TagDecl::getDefinition(C));
+ }
+
+ // Iterator access to field members. The field iterator only visits
+ // the non-static data members of this class, ignoring any static
+ // data members, functions, constructors, destructors, etc.
+ typedef specific_decl_iterator<FieldDecl> field_iterator;
+
+ field_iterator field_begin(ASTContext &Context) const {
+ return field_iterator(decls_begin(Context));
+ }
+ field_iterator field_end(ASTContext &Context) const {
+ return field_iterator(decls_end(Context));
+ }
+
+ // field_empty - Whether there are any fields (non-static data
+ // members) in this record.
+ bool field_empty(ASTContext &Context) const {
+ return field_begin(Context) == field_end(Context);
+ }
+
+ /// completeDefinition - Notes that the definition of this type is
+ /// now complete.
+ void completeDefinition(ASTContext& C);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() >= RecordFirst && D->getKind() <= RecordLast;
+ }
+ static bool classof(const RecordDecl *D) { return true; }
+};
+
+class FileScopeAsmDecl : public Decl {
+ StringLiteral *AsmString;
+ FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring)
+ : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {}
+public:
+ static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, StringLiteral *Str);
+
+ const StringLiteral *getAsmString() const { return AsmString; }
+ StringLiteral *getAsmString() { return AsmString; }
+ void setAsmString(StringLiteral *Asm) { AsmString = Asm; }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == FileScopeAsm;
+ }
+ static bool classof(const FileScopeAsmDecl *D) { return true; }
+};
+
+/// BlockDecl - This represents a block literal declaration, which is like an
+/// unnamed FunctionDecl. For example:
+/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
+///
+class BlockDecl : public Decl, public DeclContext {
+ // FIXME: This can be packed into the bitfields in Decl.
+ bool isVariadic : 1;
+ /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
+ /// parameters of this function. This is null if a prototype or if there are
+ /// no formals.
+ ParmVarDecl **ParamInfo;
+ unsigned NumParams;
+
+ Stmt *Body;
+
+protected:
+ BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
+ : Decl(Block, DC, CaretLoc), DeclContext(Block),
+ isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {}
+
+ virtual ~BlockDecl();
+ virtual void Destroy(ASTContext& C);
+
+public:
+ static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
+
+ SourceLocation getCaretLocation() const { return getLocation(); }
+
+ bool IsVariadic() const { return isVariadic; }
+ void setIsVariadic(bool value) { isVariadic = value; }
+
+ CompoundStmt *getBody() const { return (CompoundStmt*) Body; }
+ Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; }
+ void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return getNumParams(); }
+ typedef ParmVarDecl **param_iterator;
+ typedef ParmVarDecl * const *param_const_iterator;
+
+ bool param_empty() const { return NumParams == 0; }
+ param_iterator param_begin() { return ParamInfo; }
+ param_iterator param_end() { return ParamInfo+param_size(); }
+
+ param_const_iterator param_begin() const { return ParamInfo; }
+ param_const_iterator param_end() const { return ParamInfo+param_size(); }
+
+ unsigned getNumParams() const;
+ const ParmVarDecl *getParamDecl(unsigned i) const {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ ParmVarDecl *getParamDecl(unsigned i) {
+ assert(i < getNumParams() && "Illegal param #");
+ return ParamInfo[i];
+ }
+ void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == Block; }
+ static bool classof(const BlockDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const BlockDecl *D) {
+ return static_cast<DeclContext *>(const_cast<BlockDecl*>(D));
+ }
+ static BlockDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<BlockDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// Insertion operator for diagnostics. This allows sending NamedDecl's
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ NamedDecl* ND) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), Diagnostic::ak_nameddecl);
+ return DB;
+}
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
new file mode 100644
index 000000000000..c061b857063a
--- /dev/null
+++ b/include/clang/AST/DeclBase.h
@@ -0,0 +1,900 @@
+//===-- DeclBase.h - Base Classes for representing declarations -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Decl and DeclContext interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLBASE_H
+#define LLVM_CLANG_AST_DECLBASE_H
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/Type.h"
+// FIXME: Layering violation
+#include "clang/Parse/AccessSpecifier.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace clang {
+class DeclContext;
+class TranslationUnitDecl;
+class NamespaceDecl;
+class UsingDirectiveDecl;
+class NamedDecl;
+class FunctionDecl;
+class CXXRecordDecl;
+class EnumDecl;
+class ObjCMethodDecl;
+class ObjCContainerDecl;
+class ObjCInterfaceDecl;
+class ObjCCategoryDecl;
+class ObjCProtocolDecl;
+class ObjCImplementationDecl;
+class ObjCCategoryImplDecl;
+class LinkageSpecDecl;
+class BlockDecl;
+class DeclarationName;
+class CompoundStmt;
+}
+
+namespace llvm {
+// DeclContext* is only 4-byte aligned on 32-bit systems.
+template<>
+ class PointerLikeTypeTraits<clang::DeclContext*> {
+ typedef clang::DeclContext* PT;
+public:
+ static inline void *getAsVoidPointer(PT P) { return P; }
+ static inline PT getFromVoidPointer(void *P) {
+ return static_cast<PT>(P);
+ }
+ enum { NumLowBitsAvailable = 2 };
+};
+}
+
+namespace clang {
+
+/// Decl - This represents one declaration (or definition), e.g. a variable,
+/// typedef, function, struct, etc.
+///
+class Decl {
+public:
+ /// \brief Lists the kind of concrete classes of Decl.
+ enum Kind {
+#define DECL(Derived, Base) Derived,
+#define DECL_RANGE(CommonBase, Start, End) \
+ CommonBase##First = Start, CommonBase##Last = End,
+#define LAST_DECL_RANGE(CommonBase, Start, End) \
+ CommonBase##First = Start, CommonBase##Last = End
+#include "clang/AST/DeclNodes.def"
+ };
+
+ /// IdentifierNamespace - According to C99 6.2.3, there are four
+ /// namespaces, labels, tags, members and ordinary
+ /// identifiers. These are meant as bitmasks, so that searches in
+ /// C++ can look into the "tag" namespace during ordinary lookup. We
+ /// use additional namespaces for Objective-C entities.
+ enum IdentifierNamespace {
+ IDNS_Label = 0x1,
+ IDNS_Tag = 0x2,
+ IDNS_Member = 0x4,
+ IDNS_Ordinary = 0x8,
+ IDNS_ObjCProtocol = 0x10,
+ IDNS_ObjCImplementation = 0x20,
+ IDNS_ObjCCategoryImpl = 0x40
+ };
+
+ /// ObjCDeclQualifier - Qualifier used on types in method declarations
+ /// for remote messaging. They are meant for the arguments though and
+ /// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
+ enum ObjCDeclQualifier {
+ OBJC_TQ_None = 0x0,
+ OBJC_TQ_In = 0x1,
+ OBJC_TQ_Inout = 0x2,
+ OBJC_TQ_Out = 0x4,
+ OBJC_TQ_Bycopy = 0x8,
+ OBJC_TQ_Byref = 0x10,
+ OBJC_TQ_Oneway = 0x20
+ };
+
+private:
+ /// NextDeclInContext - The next declaration within the same lexical
+ /// DeclContext. These pointers form the linked list that is
+ /// traversed via DeclContext's decls_begin()/decls_end().
+ Decl *NextDeclInContext;
+
+ friend class DeclContext;
+
+ struct MultipleDC {
+ DeclContext *SemanticDC;
+ DeclContext *LexicalDC;
+ };
+
+
+ /// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
+ /// For declarations that don't contain C++ scope specifiers, it contains
+ /// the DeclContext where the Decl was declared.
+ /// For declarations with C++ scope specifiers, it contains a MultipleDC*
+ /// with the context where it semantically belongs (SemanticDC) and the
+ /// context where it was lexically declared (LexicalDC).
+ /// e.g.:
+ ///
+ /// namespace A {
+ /// void f(); // SemanticDC == LexicalDC == 'namespace A'
+ /// }
+ /// void A::f(); // SemanticDC == namespace 'A'
+ /// // LexicalDC == global namespace
+ llvm::PointerUnion<DeclContext*, MultipleDC*> DeclCtx;
+
+ inline bool isInSemaDC() const { return DeclCtx.is<DeclContext*>(); }
+ inline bool isOutOfSemaDC() const { return DeclCtx.is<MultipleDC*>(); }
+ inline MultipleDC *getMultipleDC() const {
+ return DeclCtx.get<MultipleDC*>();
+ }
+ inline DeclContext *getSemanticDC() const {
+ return DeclCtx.get<DeclContext*>();
+ }
+
+ /// Loc - The location that this decl.
+ SourceLocation Loc;
+
+ /// DeclKind - This indicates which class this is.
+ Kind DeclKind : 8;
+
+ /// InvalidDecl - This indicates a semantic error occurred.
+ unsigned int InvalidDecl : 1;
+
+ /// HasAttrs - This indicates whether the decl has attributes or not.
+ unsigned int HasAttrs : 1;
+
+ /// Implicit - Whether this declaration was implicitly generated by
+ /// the implementation rather than explicitly written by the user.
+ bool Implicit : 1;
+
+ /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
+ unsigned IdentifierNamespace : 8;
+
+#ifndef NDEBUG
+ void CheckAccessDeclContext() const;
+#else
+ void CheckAccessDeclContext() const { }
+#endif
+
+protected:
+ /// Access - Used by C++ decls for the access specifier.
+ // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
+ unsigned Access : 2;
+ friend class CXXClassMemberWrapper;
+
+ Decl(Kind DK, DeclContext *DC, SourceLocation L)
+ : NextDeclInContext(0), DeclCtx(DC),
+ Loc(L), DeclKind(DK), InvalidDecl(0),
+ HasAttrs(false), Implicit(false),
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
+ if (Decl::CollectingStats()) addDeclKind(DK);
+ }
+
+ virtual ~Decl();
+
+public:
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ Kind getKind() const { return DeclKind; }
+ const char *getDeclKindName() const;
+
+ Decl *getNextDeclInContext() { return NextDeclInContext; }
+ const Decl *getNextDeclInContext() const { return NextDeclInContext; }
+
+ DeclContext *getDeclContext() {
+ if (isInSemaDC())
+ return getSemanticDC();
+ return getMultipleDC()->SemanticDC;
+ }
+ const DeclContext *getDeclContext() const {
+ return const_cast<Decl*>(this)->getDeclContext();
+ }
+
+ void setAccess(AccessSpecifier AS) {
+ Access = AS;
+ CheckAccessDeclContext();
+ }
+
+ AccessSpecifier getAccess() const {
+ CheckAccessDeclContext();
+ return AccessSpecifier(Access);
+ }
+
+ bool hasAttrs() const { return HasAttrs; }
+ void addAttr(Attr *attr);
+ const Attr *getAttrs() const {
+ if (!HasAttrs) return 0; // common case, no attributes.
+ return getAttrsImpl(); // Uncommon case, out of line hash lookup.
+ }
+ void swapAttrs(Decl *D);
+ void invalidateAttrs();
+
+ template<typename T> const T *getAttr() const {
+ for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
+ if (const T *V = dyn_cast<T>(attr))
+ return V;
+ return 0;
+ }
+
+ template<typename T> bool hasAttr() const {
+ return getAttr<T>() != 0;
+ }
+
+ /// setInvalidDecl - Indicates the Decl had a semantic error. This
+ /// allows for graceful error recovery.
+ void setInvalidDecl(bool Invalid = true) { InvalidDecl = Invalid; }
+ bool isInvalidDecl() const { return (bool) InvalidDecl; }
+
+ /// isImplicit - Indicates whether the declaration was implicitly
+ /// generated by the implementation. If false, this declaration
+ /// was written explicitly in the source code.
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I = true) { Implicit = I; }
+
+ unsigned getIdentifierNamespace() const {
+ return IdentifierNamespace;
+ }
+ bool isInIdentifierNamespace(unsigned NS) const {
+ return getIdentifierNamespace() & NS;
+ }
+ static unsigned getIdentifierNamespaceForKind(Kind DK);
+
+
+ /// getLexicalDeclContext - The declaration context where this Decl was
+ /// lexically declared (LexicalDC). May be different from
+ /// getDeclContext() (SemanticDC).
+ /// e.g.:
+ ///
+ /// namespace A {
+ /// void f(); // SemanticDC == LexicalDC == 'namespace A'
+ /// }
+ /// void A::f(); // SemanticDC == namespace 'A'
+ /// // LexicalDC == global namespace
+ DeclContext *getLexicalDeclContext() {
+ if (isInSemaDC())
+ return getSemanticDC();
+ return getMultipleDC()->LexicalDC;
+ }
+ const DeclContext *getLexicalDeclContext() const {
+ return const_cast<Decl*>(this)->getLexicalDeclContext();
+ }
+
+ /// setDeclContext - Set both the semantic and lexical DeclContext
+ /// to DC.
+ void setDeclContext(DeclContext *DC);
+
+ void setLexicalDeclContext(DeclContext *DC);
+
+ // isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+ // scoped decl is defined outside the current function or method. This is
+ // roughly global variables and functions, but also handles enums (which could
+ // be defined inside or outside a function etc).
+ bool isDefinedOutsideFunctionOrMethod() const;
+
+ /// getBody - If this Decl represents a declaration for a body of code,
+ /// such as a function or method definition, this method returns the
+ /// top-level Stmt* of that body. Otherwise this method returns null.
+ virtual Stmt* getBody(ASTContext &Context) const { return 0; }
+
+ /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt.
+ CompoundStmt* getCompoundBody(ASTContext &Context) const;
+
+ /// getBodyRBrace - Gets the right brace of the body, if a body exists.
+ /// This works whether the body is a CompoundStmt or a CXXTryStmt.
+ SourceLocation getBodyRBrace(ASTContext &Context) const;
+
+ // global temp stats (until we have a per-module visitor)
+ static void addDeclKind(Kind k);
+ static bool CollectingStats(bool Enable = false);
+ static void PrintStats();
+
+ /// isTemplateParameter - Determines whether this declartion is a
+ /// template parameter.
+ bool isTemplateParameter() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *) { return true; }
+ static DeclContext *castToDeclContext(const Decl *);
+ static Decl *castFromDeclContext(const DeclContext *);
+
+ /// Destroy - Call destructors and release memory.
+ virtual void Destroy(ASTContext& C);
+
+ void print(llvm::raw_ostream &Out, ASTContext &Context,
+ unsigned Indentation = 0);
+ void print(llvm::raw_ostream &Out, ASTContext &Context,
+ const PrintingPolicy &Policy, unsigned Indentation = 0);
+ static void printGroup(Decl** Begin, unsigned NumDecls,
+ llvm::raw_ostream &Out, ASTContext &Context,
+ const PrintingPolicy &Policy,
+ unsigned Indentation = 0);
+ void dump(ASTContext &Context);
+
+private:
+ const Attr *getAttrsImpl() const;
+
+};
+
+/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
+/// doing something to a specific decl.
+class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
+ Decl *TheDecl;
+ SourceLocation Loc;
+ SourceManager &SM;
+ const char *Message;
+public:
+ PrettyStackTraceDecl(Decl *theDecl, SourceLocation L,
+ SourceManager &sm, const char *Msg)
+ : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+
+/// DeclContext - This is used only as base class of specific decl types that
+/// can act as declaration contexts. These decls are (only the top classes
+/// that directly derive from DeclContext are mentioned, not their subclasses):
+///
+/// TranslationUnitDecl
+/// NamespaceDecl
+/// FunctionDecl
+/// TagDecl
+/// ObjCMethodDecl
+/// ObjCContainerDecl
+/// ObjCCategoryImplDecl
+/// ObjCImplementationDecl
+/// LinkageSpecDecl
+/// BlockDecl
+///
+class DeclContext {
+ /// DeclKind - This indicates which class this is.
+ Decl::Kind DeclKind : 8;
+
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are lexically
+ /// part of this context.
+ mutable bool ExternalLexicalStorage : 1;
+
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are visible
+ /// in this context.
+ mutable bool ExternalVisibleStorage : 1;
+
+ /// \brief Pointer to the data structure used to lookup declarations
+ /// within this context, which is a DenseMap<DeclarationName,
+ /// StoredDeclsList>.
+ mutable void* LookupPtr;
+
+ /// FirstDecl - The first declaration stored within this declaration
+ /// context.
+ mutable Decl *FirstDecl;
+
+ /// LastDecl - The last declaration stored within this declaration
+ /// context. FIXME: We could probably cache this value somewhere
+ /// outside of the DeclContext, to reduce the size of DeclContext by
+ /// another pointer.
+ mutable Decl *LastDecl;
+
+protected:
+ DeclContext(Decl::Kind K)
+ : DeclKind(K), ExternalLexicalStorage(false),
+ ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
+ LastDecl(0) { }
+
+ void DestroyDecls(ASTContext &C);
+
+public:
+ ~DeclContext();
+
+ Decl::Kind getDeclKind() const {
+ return DeclKind;
+ }
+ const char *getDeclKindName() const;
+
+ /// getParent - Returns the containing DeclContext.
+ DeclContext *getParent() {
+ return cast<Decl>(this)->getDeclContext();
+ }
+ const DeclContext *getParent() const {
+ return const_cast<DeclContext*>(this)->getParent();
+ }
+
+ /// getLexicalParent - Returns the containing lexical DeclContext. May be
+ /// different from getParent, e.g.:
+ ///
+ /// namespace A {
+ /// struct S;
+ /// }
+ /// struct A::S {}; // getParent() == namespace 'A'
+ /// // getLexicalParent() == translation unit
+ ///
+ DeclContext *getLexicalParent() {
+ return cast<Decl>(this)->getLexicalDeclContext();
+ }
+ const DeclContext *getLexicalParent() const {
+ return const_cast<DeclContext*>(this)->getLexicalParent();
+ }
+
+ bool isFunctionOrMethod() const {
+ switch (DeclKind) {
+ case Decl::Block:
+ case Decl::ObjCMethod:
+ return true;
+ default:
+ return DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast;
+ }
+ }
+
+ bool isFileContext() const {
+ return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
+ }
+
+ bool isTranslationUnit() const {
+ return DeclKind == Decl::TranslationUnit;
+ }
+
+ bool isRecord() const {
+ return DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast;
+ }
+
+ bool isNamespace() const {
+ return DeclKind == Decl::Namespace;
+ }
+
+ /// \brief Determines whether this context is dependent on a
+ /// template parameter.
+ bool isDependentContext() const;
+
+ /// isTransparentContext - Determines whether this context is a
+ /// "transparent" context, meaning that the members declared in this
+ /// context are semantically declared in the nearest enclosing
+ /// non-transparent (opaque) context but are lexically declared in
+ /// this context. For example, consider the enumerators of an
+ /// enumeration type:
+ /// @code
+ /// enum E {
+ /// Val1
+ /// };
+ /// @endcode
+ /// Here, E is a transparent context, so its enumerator (Val1) will
+ /// appear (semantically) that it is in the same context of E.
+ /// Examples of transparent contexts include: enumerations (except for
+ /// C++0x scoped enums), C++ linkage specifications, and C++0x
+ /// inline namespaces.
+ bool isTransparentContext() const;
+
+ bool Encloses(DeclContext *DC) const {
+ for (; DC; DC = DC->getParent())
+ if (DC == this)
+ return true;
+ return false;
+ }
+
+ /// getPrimaryContext - There may be many different
+ /// declarations of the same entity (including forward declarations
+ /// of classes, multiple definitions of namespaces, etc.), each with
+ /// a different set of declarations. This routine returns the
+ /// "primary" DeclContext structure, which will contain the
+ /// information needed to perform name lookup into this context.
+ DeclContext *getPrimaryContext();
+
+ /// getLookupContext - Retrieve the innermost non-transparent
+ /// context of this context, which corresponds to the innermost
+ /// location from which name lookup can find the entities in this
+ /// context.
+ DeclContext *getLookupContext();
+ const DeclContext *getLookupContext() const {
+ return const_cast<DeclContext *>(this)->getLookupContext();
+ }
+
+ /// \brief Retrieve the nearest enclosing namespace context.
+ DeclContext *getEnclosingNamespaceContext();
+ const DeclContext *getEnclosingNamespaceContext() const {
+ return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
+ }
+
+ /// getNextContext - If this is a DeclContext that may have other
+ /// DeclContexts that are semantically connected but syntactically
+ /// different, such as C++ namespaces, this routine retrieves the
+ /// next DeclContext in the link. Iteration through the chain of
+ /// DeclContexts should begin at the primary DeclContext and
+ /// continue until this function returns NULL. For example, given:
+ /// @code
+ /// namespace N {
+ /// int x;
+ /// }
+ /// namespace N {
+ /// int y;
+ /// }
+ /// @endcode
+ /// The first occurrence of namespace N will be the primary
+ /// DeclContext. Its getNextContext will return the second
+ /// occurrence of namespace N.
+ DeclContext *getNextContext();
+
+ /// decl_iterator - Iterates through the declarations stored
+ /// within this context.
+ class decl_iterator {
+ /// Current - The current declaration.
+ Decl *Current;
+
+ public:
+ typedef Decl* value_type;
+ typedef Decl* reference;
+ typedef Decl* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ decl_iterator() : Current(0) { }
+ explicit decl_iterator(Decl *C) : Current(C) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ decl_iterator& operator++() {
+ Current = Current->getNextDeclInContext();
+ return *this;
+ }
+
+ decl_iterator operator++(int) {
+ decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(decl_iterator x, decl_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(decl_iterator x, decl_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// decls_begin/decls_end - Iterate over the declarations stored in
+ /// this context.
+ decl_iterator decls_begin(ASTContext &Context) const;
+ decl_iterator decls_end(ASTContext &Context) const;
+ bool decls_empty(ASTContext &Context) const;
+
+ /// specific_decl_iterator - Iterates over a subrange of
+ /// declarations stored in a DeclContext, providing only those that
+ /// are of type SpecificDecl (or a class derived from it). This
+ /// iterator is used, for example, to provide iteration over just
+ /// the fields within a RecordDecl (with SpecificDecl = FieldDecl).
+ template<typename SpecificDecl>
+ class specific_decl_iterator {
+ /// Current - The current, underlying declaration iterator, which
+ /// will either be NULL or will point to a declaration of
+ /// type SpecificDecl.
+ DeclContext::decl_iterator Current;
+
+ /// SkipToNextDecl - Advances the current position up to the next
+ /// declaration of type SpecificDecl that also meets the criteria
+ /// required by Acceptable.
+ void SkipToNextDecl() {
+ while (*Current && !isa<SpecificDecl>(*Current))
+ ++Current;
+ }
+
+ public:
+ typedef SpecificDecl* value_type;
+ typedef SpecificDecl* reference;
+ typedef SpecificDecl* pointer;
+ typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
+ difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ specific_decl_iterator() : Current() { }
+
+ /// specific_decl_iterator - Construct a new iterator over a
+ /// subset of the declarations the range [C,
+ /// end-of-declarations). If A is non-NULL, it is a pointer to a
+ /// member function of SpecificDecl that should return true for
+ /// all of the SpecificDecl instances that will be in the subset
+ /// of iterators. For example, if you want Objective-C instance
+ /// methods, SpecificDecl will be ObjCMethodDecl and A will be
+ /// &ObjCMethodDecl::isInstanceMethod.
+ explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
+ SkipToNextDecl();
+ }
+
+ reference operator*() const { return cast<SpecificDecl>(*Current); }
+ pointer operator->() const { return cast<SpecificDecl>(*Current); }
+
+ specific_decl_iterator& operator++() {
+ ++Current;
+ SkipToNextDecl();
+ return *this;
+ }
+
+ specific_decl_iterator operator++(int) {
+ specific_decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool
+ operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) {
+ return x.Current == y.Current;
+ }
+
+ friend bool
+ operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// \brief Iterates over a filtered subrange of declarations stored
+ /// in a DeclContext.
+ ///
+ /// This iterator visits only those declarations that are of type
+ /// SpecificDecl (or a class derived from it) and that meet some
+ /// additional run-time criteria. This iterator is used, for
+ /// example, to provide access to the instance methods within an
+ /// Objective-C interface (with SpecificDecl = ObjCMethodDecl and
+ /// Acceptable = ObjCMethodDecl::isInstanceMethod).
+ template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const>
+ class filtered_decl_iterator {
+ /// Current - The current, underlying declaration iterator, which
+ /// will either be NULL or will point to a declaration of
+ /// type SpecificDecl.
+ DeclContext::decl_iterator Current;
+
+ /// SkipToNextDecl - Advances the current position up to the next
+ /// declaration of type SpecificDecl that also meets the criteria
+ /// required by Acceptable.
+ void SkipToNextDecl() {
+ while (*Current &&
+ (!isa<SpecificDecl>(*Current) ||
+ (Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)())))
+ ++Current;
+ }
+
+ public:
+ typedef SpecificDecl* value_type;
+ typedef SpecificDecl* reference;
+ typedef SpecificDecl* pointer;
+ typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
+ difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ filtered_decl_iterator() : Current() { }
+
+ /// specific_decl_iterator - Construct a new iterator over a
+ /// subset of the declarations the range [C,
+ /// end-of-declarations). If A is non-NULL, it is a pointer to a
+ /// member function of SpecificDecl that should return true for
+ /// all of the SpecificDecl instances that will be in the subset
+ /// of iterators. For example, if you want Objective-C instance
+ /// methods, SpecificDecl will be ObjCMethodDecl and A will be
+ /// &ObjCMethodDecl::isInstanceMethod.
+ explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
+ SkipToNextDecl();
+ }
+
+ reference operator*() const { return cast<SpecificDecl>(*Current); }
+ pointer operator->() const { return cast<SpecificDecl>(*Current); }
+
+ filtered_decl_iterator& operator++() {
+ ++Current;
+ SkipToNextDecl();
+ return *this;
+ }
+
+ filtered_decl_iterator operator++(int) {
+ filtered_decl_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool
+ operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
+ return x.Current == y.Current;
+ }
+
+ friend bool
+ operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ /// @brief Add the declaration D into this context.
+ ///
+ /// This routine should be invoked when the declaration D has first
+ /// been declared, to place D into the context where it was
+ /// (lexically) defined. Every declaration must be added to one
+ /// (and only one!) context, where it can be visited via
+ /// [decls_begin(), decls_end()). Once a declaration has been added
+ /// to its lexical context, the corresponding DeclContext owns the
+ /// declaration.
+ ///
+ /// If D is also a NamedDecl, it will be made visible within its
+ /// semantic context via makeDeclVisibleInContext.
+ void addDecl(ASTContext &Context, Decl *D);
+
+ /// lookup_iterator - An iterator that provides access to the results
+ /// of looking up a name within this context.
+ typedef NamedDecl **lookup_iterator;
+
+ /// lookup_const_iterator - An iterator that provides non-mutable
+ /// access to the results of lookup up a name within this context.
+ typedef NamedDecl * const * lookup_const_iterator;
+
+ typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
+ typedef std::pair<lookup_const_iterator, lookup_const_iterator>
+ lookup_const_result;
+
+ /// lookup - Find the declarations (if any) with the given Name in
+ /// this context. Returns a range of iterators that contains all of
+ /// the declarations with this name, with object, function, member,
+ /// and enumerator names preceding any tag name. Note that this
+ /// routine will not look into parent contexts.
+ lookup_result lookup(ASTContext &Context, DeclarationName Name);
+ lookup_const_result lookup(ASTContext &Context, DeclarationName Name) const;
+
+ /// @brief Makes a declaration visible within this context.
+ ///
+ /// This routine makes the declaration D visible to name lookup
+ /// within this context and, if this is a transparent context,
+ /// within its parent contexts up to the first enclosing
+ /// non-transparent context. Making a declaration visible within a
+ /// context does not transfer ownership of a declaration, and a
+ /// declaration can be visible in many contexts that aren't its
+ /// lexical context.
+ ///
+ /// If D is a redeclaration of an existing declaration that is
+ /// visible from this context, as determined by
+ /// NamedDecl::declarationReplaces, the previous declaration will be
+ /// replaced with D.
+ void makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D);
+
+ /// udir_iterator - Iterates through the using-directives stored
+ /// within this context.
+ typedef UsingDirectiveDecl * const * udir_iterator;
+
+ typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range;
+
+ udir_iterator_range getUsingDirectives(ASTContext &Context) const;
+
+ udir_iterator using_directives_begin(ASTContext &Context) const {
+ return getUsingDirectives(Context).first;
+ }
+
+ udir_iterator using_directives_end(ASTContext &Context) const {
+ return getUsingDirectives(Context).second;
+ }
+
+ // Low-level accessors
+
+ /// \brief Retrieve the internal representation of the lookup structure.
+ void* getLookupPtr() const { return LookupPtr; }
+
+ /// \brief Whether this DeclContext has external storage containing
+ /// additional declarations that are lexically in this context.
+ bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
+
+ /// \brief State whether this DeclContext has external storage for
+ /// declarations lexically in this context.
+ void setHasExternalLexicalStorage(bool ES = true) {
+ ExternalLexicalStorage = ES;
+ }
+
+ /// \brief Whether this DeclContext has external storage containing
+ /// additional declarations that are visible in this context.
+ bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
+
+ /// \brief State whether this DeclContext has external storage for
+ /// declarations visible in this context.
+ void setHasExternalVisibleStorage(bool ES = true) {
+ ExternalVisibleStorage = ES;
+ }
+
+ static bool classof(const Decl *D);
+ static bool classof(const DeclContext *D) { return true; }
+#define DECL_CONTEXT(Name) \
+ static bool classof(const Name##Decl *D) { return true; }
+#include "clang/AST/DeclNodes.def"
+
+private:
+ void LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const;
+ void LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const;
+
+ void buildLookup(ASTContext &Context, DeclContext *DCtx);
+ void makeDeclVisibleInContextImpl(ASTContext &Context, NamedDecl *D);
+};
+
+inline bool Decl::isTemplateParameter() const {
+ return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
+}
+
+inline bool Decl::isDefinedOutsideFunctionOrMethod() const {
+ if (getDeclContext())
+ return !getDeclContext()->getLookupContext()->isFunctionOrMethod();
+ return true;
+}
+
+} // end clang.
+
+namespace llvm {
+
+/// Implement a isa_impl_wrap specialization to check whether a DeclContext is
+/// a specific Decl.
+template<class ToTy>
+struct isa_impl_wrap<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {
+ static bool doit(const ::clang::DeclContext &Val) {
+ return ToTy::classof(::clang::Decl::castFromDeclContext(&Val));
+ }
+};
+template<class ToTy>
+struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
+ : public isa_impl_wrap<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {};
+
+/// Implement cast_convert_val for Decl -> DeclContext conversions.
+template<class FromTy>
+struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> {
+ static ::clang::DeclContext &doit(const FromTy &Val) {
+ return *FromTy::castToDeclContext(&Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> {
+ static ::clang::DeclContext *doit(const FromTy *Val) {
+ return FromTy::castToDeclContext(Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> {
+ static const ::clang::DeclContext &doit(const FromTy &Val) {
+ return *FromTy::castToDeclContext(&Val);
+ }
+};
+
+template<class FromTy>
+struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
+ static const ::clang::DeclContext *doit(const FromTy *Val) {
+ return FromTy::castToDeclContext(Val);
+ }
+};
+
+/// Implement cast_convert_val for DeclContext -> Decl conversions.
+template<class ToTy>
+struct cast_convert_val<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {
+ static ToTy &doit(const ::clang::DeclContext &Val) {
+ return *reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(&Val));
+ }
+};
+template<class ToTy>
+struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext>
+ : public cast_convert_val<ToTy,
+ const ::clang::DeclContext,const ::clang::DeclContext> {};
+
+template<class ToTy>
+struct cast_convert_val<ToTy,
+ const ::clang::DeclContext*, const ::clang::DeclContext*> {
+ static ToTy *doit(const ::clang::DeclContext *Val) {
+ return reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(Val));
+ }
+};
+template<class ToTy>
+struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*>
+ : public cast_convert_val<ToTy,
+ const ::clang::DeclContext*,const ::clang::DeclContext*> {};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
new file mode 100644
index 000000000000..4a74a2c2cbc4
--- /dev/null
+++ b/include/clang/AST/DeclCXX.h
@@ -0,0 +1,1073 @@
+//===-- DeclCXX.h - Classes for representing C++ declarations -*- C++ -*-=====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the C++ Decl subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLCXX_H
+#define LLVM_CLANG_AST_DECLCXX_H
+
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class ClassTemplateDecl;
+class CXXRecordDecl;
+class CXXConstructorDecl;
+class CXXDestructorDecl;
+class CXXConversionDecl;
+class CXXMethodDecl;
+class ClassTemplateSpecializationDecl;
+
+/// OverloadedFunctionDecl - An instance of this class represents a
+/// set of overloaded functions. All of the functions have the same
+/// name and occur within the same scope.
+///
+/// An OverloadedFunctionDecl has no ownership over the FunctionDecl
+/// nodes it contains. Rather, the FunctionDecls are owned by the
+/// enclosing scope (which also owns the OverloadedFunctionDecl
+/// node). OverloadedFunctionDecl is used primarily to store a set of
+/// overloaded functions for name lookup.
+class OverloadedFunctionDecl : public NamedDecl {
+protected:
+ OverloadedFunctionDecl(DeclContext *DC, DeclarationName N)
+ : NamedDecl(OverloadedFunction, DC, SourceLocation(), N) { }
+
+ /// Functions - the set of overloaded functions contained in this
+ /// overload set.
+ llvm::SmallVector<FunctionDecl *, 4> Functions;
+
+ // FIXME: This should go away when we stop using
+ // OverloadedFunctionDecl to store conversions in CXXRecordDecl.
+ friend class CXXRecordDecl;
+
+public:
+ typedef llvm::SmallVector<FunctionDecl *, 4>::iterator function_iterator;
+ typedef llvm::SmallVector<FunctionDecl *, 4>::const_iterator
+ function_const_iterator;
+
+ static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ DeclarationName N);
+
+ /// addOverload - Add an overloaded function FD to this set of
+ /// overloaded functions.
+ void addOverload(FunctionDecl *FD) {
+ assert((FD->getDeclName() == getDeclName() ||
+ isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
+ "Overloaded functions must have the same name");
+ Functions.push_back(FD);
+
+ // An overloaded function declaration always has the location of
+ // the most-recently-added function declaration.
+ if (FD->getLocation().isValid())
+ this->setLocation(FD->getLocation());
+ }
+
+ function_iterator function_begin() { return Functions.begin(); }
+ function_iterator function_end() { return Functions.end(); }
+ function_const_iterator function_begin() const { return Functions.begin(); }
+ function_const_iterator function_end() const { return Functions.end(); }
+
+ /// getNumFunctions - the number of overloaded functions stored in
+ /// this set.
+ unsigned getNumFunctions() const { return Functions.size(); }
+
+ /// getFunction - retrieve the ith function in the overload set.
+ const FunctionDecl *getFunction(unsigned i) const {
+ assert(i < getNumFunctions() && "Illegal function #");
+ return Functions[i];
+ }
+ FunctionDecl *getFunction(unsigned i) {
+ assert(i < getNumFunctions() && "Illegal function #");
+ return Functions[i];
+ }
+
+ // getDeclContext - Get the context of these overloaded functions.
+ DeclContext *getDeclContext() {
+ assert(getNumFunctions() > 0 && "Context of an empty overload set");
+ return getFunction(0)->getDeclContext();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == OverloadedFunction;
+ }
+ static bool classof(const OverloadedFunctionDecl *D) { return true; }
+};
+
+/// CXXBaseSpecifier - A base class of a C++ class.
+///
+/// Each CXXBaseSpecifier represents a single, direct base class (or
+/// struct) of a C++ class (or struct). It specifies the type of that
+/// base class, whether it is a virtual or non-virtual base, and what
+/// level of access (public, protected, private) is used for the
+/// derivation. For example:
+///
+/// @code
+/// class A { };
+/// class B { };
+/// class C : public virtual A, protected B { };
+/// @endcode
+///
+/// In this code, C will have two CXXBaseSpecifiers, one for "public
+/// virtual A" and the other for "protected B".
+class CXXBaseSpecifier {
+ /// Range - The source code range that covers the full base
+ /// specifier, including the "virtual" (if present) and access
+ /// specifier (if present).
+ SourceRange Range;
+
+ /// Virtual - Whether this is a virtual base class or not.
+ bool Virtual : 1;
+
+ /// BaseOfClass - Whether this is the base of a class (true) or of a
+ /// struct (false). This determines the mapping from the access
+ /// specifier as written in the source code to the access specifier
+ /// used for semantic analysis.
+ bool BaseOfClass : 1;
+
+ /// Access - Access specifier as written in the source code (which
+ /// may be AS_none). The actual type of data stored here is an
+ /// AccessSpecifier, but we use "unsigned" here to work around a
+ /// VC++ bug.
+ unsigned Access : 2;
+
+ /// BaseType - The type of the base class. This will be a class or
+ /// struct (or a typedef of such).
+ QualType BaseType;
+
+public:
+ CXXBaseSpecifier() { }
+
+ CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
+ : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
+
+ /// getSourceRange - Retrieves the source range that contains the
+ /// entire base specifier.
+ SourceRange getSourceRange() const { return Range; }
+
+ /// isVirtual - Determines whether the base class is a virtual base
+ /// class (or not).
+ bool isVirtual() const { return Virtual; }
+
+ /// getAccessSpecifier - Returns the access specifier for this base
+ /// specifier. This is the actual base specifier as used for
+ /// semantic analysis, so the result can never be AS_none. To
+ /// retrieve the access specifier as written in the source code, use
+ /// getAccessSpecifierAsWritten().
+ AccessSpecifier getAccessSpecifier() const {
+ if ((AccessSpecifier)Access == AS_none)
+ return BaseOfClass? AS_private : AS_public;
+ else
+ return (AccessSpecifier)Access;
+ }
+
+ /// getAccessSpecifierAsWritten - Retrieves the access specifier as
+ /// written in the source code (which may mean that no access
+ /// specifier was explicitly written). Use getAccessSpecifier() to
+ /// retrieve the access specifier for use in semantic analysis.
+ AccessSpecifier getAccessSpecifierAsWritten() const {
+ return (AccessSpecifier)Access;
+ }
+
+ /// getType - Retrieves the type of the base class. This type will
+ /// always be an unqualified class type.
+ QualType getType() const { return BaseType; }
+};
+
+/// CXXRecordDecl - Represents a C++ struct/union/class.
+/// FIXME: This class will disappear once we've properly taught RecordDecl
+/// to deal with C++-specific things.
+class CXXRecordDecl : public RecordDecl {
+ /// UserDeclaredConstructor - True when this class has a
+ /// user-declared constructor.
+ bool UserDeclaredConstructor : 1;
+
+ /// UserDeclaredCopyConstructor - True when this class has a
+ /// user-declared copy constructor.
+ bool UserDeclaredCopyConstructor : 1;
+
+ /// UserDeclaredCopyAssignment - True when this class has a
+ /// user-declared copy assignment operator.
+ bool UserDeclaredCopyAssignment : 1;
+
+ /// UserDeclaredDestructor - True when this class has a
+ /// user-declared destructor.
+ bool UserDeclaredDestructor : 1;
+
+ /// Aggregate - True when this class is an aggregate.
+ bool Aggregate : 1;
+
+ /// PlainOldData - True when this class is a POD-type.
+ bool PlainOldData : 1;
+
+ /// Polymorphic - True when this class is polymorphic, i.e. has at least one
+ /// virtual member or derives from a polymorphic class.
+ bool Polymorphic : 1;
+
+ /// Abstract - True when this class is abstract, i.e. has at least one
+ /// pure virtual function, (that can come from a base class).
+ bool Abstract : 1;
+
+ /// HasTrivialConstructor - True when this class has a trivial constructor
+ bool HasTrivialConstructor : 1;
+
+ /// HasTrivialDestructor - True when this class has a trivial destructor
+ bool HasTrivialDestructor : 1;
+
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ CXXBaseSpecifier *Bases;
+
+ /// NumBases - The number of base class specifiers in Bases.
+ unsigned NumBases;
+
+ /// Conversions - Overload set containing the conversion functions
+ /// of this C++ class (but not its inherited conversion
+ /// functions). Each of the entries in this overload set is a
+ /// CXXConversionDecl.
+ OverloadedFunctionDecl Conversions;
+
+ /// \brief The template or declaration that this declaration
+ /// describes or was instantiated from, respectively.
+ ///
+ /// For non-templates, this value will be NULL. For record
+ /// declarations that describe a class template, this will be a
+ /// pointer to a ClassTemplateDecl. For member
+ /// classes of class template specializations, this will be the
+ /// RecordDecl from which the member class was instantiated.
+ llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>
+ TemplateOrInstantiation;
+
+protected:
+ CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+
+ ~CXXRecordDecl();
+
+public:
+ /// base_class_iterator - Iterator that traverses the base classes
+ /// of a clas.
+ typedef CXXBaseSpecifier* base_class_iterator;
+
+ /// base_class_const_iterator - Iterator that traverses the base
+ /// classes of a clas.
+ typedef const CXXBaseSpecifier* base_class_const_iterator;
+
+ static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ CXXRecordDecl* PrevDecl=0,
+ bool DelayTypeCreation = false);
+
+ /// setBases - Sets the base classes of this struct or class.
+ void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
+
+ /// getNumBases - Retrieves the number of base classes of this
+ /// class.
+ unsigned getNumBases() const { return NumBases; }
+
+ base_class_iterator bases_begin() { return Bases; }
+ base_class_const_iterator bases_begin() const { return Bases; }
+ base_class_iterator bases_end() { return Bases + NumBases; }
+ base_class_const_iterator bases_end() const { return Bases + NumBases; }
+
+ /// hasConstCopyConstructor - Determines whether this class has a
+ /// copy constructor that accepts a const-qualified argument.
+ bool hasConstCopyConstructor(ASTContext &Context) const;
+
+ /// hasConstCopyAssignment - Determines whether this class has a
+ /// copy assignment operator that accepts a const-qualified argument.
+ bool hasConstCopyAssignment(ASTContext &Context) const;
+
+ /// addedConstructor - Notify the class that another constructor has
+ /// been added. This routine helps maintain information about the
+ /// class based on which constructors have been added.
+ void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
+
+ /// hasUserDeclaredConstructor - Whether this class has any
+ /// user-declared constructors. When true, a default constructor
+ /// will not be implicitly declared.
+ bool hasUserDeclaredConstructor() const { return UserDeclaredConstructor; }
+
+ /// hasUserDeclaredCopyConstructor - Whether this class has a
+ /// user-declared copy constructor. When false, a copy constructor
+ /// will be implicitly declared.
+ bool hasUserDeclaredCopyConstructor() const {
+ return UserDeclaredCopyConstructor;
+ }
+
+ /// addedAssignmentOperator - Notify the class that another assignment
+ /// operator has been added. This routine helps maintain information about the
+ /// class based on which operators have been added.
+ void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
+
+ /// hasUserDeclaredCopyAssignment - Whether this class has a
+ /// user-declared copy assignment operator. When false, a copy
+ /// assigment operator will be implicitly declared.
+ bool hasUserDeclaredCopyAssignment() const {
+ return UserDeclaredCopyAssignment;
+ }
+
+ /// hasUserDeclaredDestructor - Whether this class has a
+ /// user-declared destructor. When false, a destructor will be
+ /// implicitly declared.
+ bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; }
+
+ /// setUserDeclaredDestructor - Set whether this class has a
+ /// user-declared destructor. If not set by the time the class is
+ /// fully defined, a destructor will be implicitly declared.
+ void setUserDeclaredDestructor(bool UCD) {
+ UserDeclaredDestructor = UCD;
+ }
+
+ /// getConversions - Retrieve the overload set containing all of the
+ /// conversion functions in this class.
+ OverloadedFunctionDecl *getConversionFunctions() {
+ return &Conversions;
+ }
+ const OverloadedFunctionDecl *getConversionFunctions() const {
+ return &Conversions;
+ }
+
+ /// addConversionFunction - Add a new conversion function to the
+ /// list of conversion functions.
+ void addConversionFunction(ASTContext &Context, CXXConversionDecl *ConvDecl);
+
+ /// isAggregate - Whether this class is an aggregate (C++
+ /// [dcl.init.aggr]), which is a class with no user-declared
+ /// constructors, no private or protected non-static data members,
+ /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
+ bool isAggregate() const { return Aggregate; }
+
+ /// setAggregate - Set whether this class is an aggregate (C++
+ /// [dcl.init.aggr]).
+ void setAggregate(bool Agg) { Aggregate = Agg; }
+
+ /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
+ /// that is an aggregate that has no non-static non-POD data members, no
+ /// reference data members, no user-defined copy assignment operator and no
+ /// user-defined destructor.
+ bool isPOD() const { return PlainOldData; }
+
+ /// setPOD - Set whether this class is a POD-type (C++ [class]p4).
+ void setPOD(bool POD) { PlainOldData = POD; }
+
+ /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
+ /// which means that the class contains or inherits a virtual function.
+ bool isPolymorphic() const { return Polymorphic; }
+
+ /// setPolymorphic - Set whether this class is polymorphic (C++
+ /// [class.virtual]).
+ void setPolymorphic(bool Poly) { Polymorphic = Poly; }
+
+ /// isAbstract - Whether this class is abstract (C++ [class.abstract]),
+ /// which means that the class contains or inherits a pure virtual function.
+ bool isAbstract() const { return Abstract; }
+
+ /// setAbstract - Set whether this class is abstract (C++ [class.abstract])
+ void setAbstract(bool Abs) { Abstract = Abs; }
+
+ // hasTrivialConstructor - Whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ bool hasTrivialConstructor() const { return HasTrivialConstructor; }
+
+ // setHasTrivialConstructor - Set whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; }
+
+ // hasTrivialDestructor - Whether this class has a trivial destructor
+ // (C++ [class.dtor]p3)
+ bool hasTrivialDestructor() const { return HasTrivialDestructor; }
+
+ // setHasTrivialDestructor - Set whether this class has a trivial destructor
+ // (C++ [class.dtor]p3)
+ void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; }
+
+ /// \brief If this record is an instantiation of a member class,
+ /// retrieves the member class from which it was instantiated.
+ ///
+ /// This routine will return non-NULL for (non-templated) member
+ /// classes of class templates. For example, given:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// struct A { };
+ /// };
+ /// \endcode
+ ///
+ /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl
+ /// whose parent is the class template specialization X<int>. For
+ /// this declaration, getInstantiatedFromMemberClass() will return
+ /// the CXXRecordDecl X<T>::A. When a complete definition of
+ /// X<int>::A is required, it will be instantiated from the
+ /// declaration returned by getInstantiatedFromMemberClass().
+ CXXRecordDecl *getInstantiatedFromMemberClass() const {
+ return TemplateOrInstantiation.dyn_cast<CXXRecordDecl*>();
+ }
+
+ /// \brief Specify that this record is an instantiation of the
+ /// member class RD.
+ void setInstantiationOfMemberClass(CXXRecordDecl *RD) {
+ TemplateOrInstantiation = RD;
+ }
+
+ /// \brief Retrieves the class template that is described by this
+ /// class declaration.
+ ///
+ /// Every class template is represented as a ClassTemplateDecl and a
+ /// CXXRecordDecl. The former contains template properties (such as
+ /// the template parameter lists) while the latter contains the
+ /// actual description of the template's
+ /// contents. ClassTemplateDecl::getTemplatedDecl() retrieves the
+ /// CXXRecordDecl that from a ClassTemplateDecl, while
+ /// getDescribedClassTemplate() retrieves the ClassTemplateDecl from
+ /// a CXXRecordDecl.
+ ClassTemplateDecl *getDescribedClassTemplate() const {
+ return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>();
+ }
+
+ void setDescribedClassTemplate(ClassTemplateDecl *Template) {
+ TemplateOrInstantiation = Template;
+ }
+
+ /// getDestructor - Returns the destructor decl for this class.
+ const CXXDestructorDecl *getDestructor(ASTContext &Context);
+
+ /// viewInheritance - Renders and displays an inheritance diagram
+ /// for this C++ class and all of its base classes (transitively) using
+ /// GraphViz.
+ void viewInheritance(ASTContext& Context) const;
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == CXXRecord ||
+ D->getKind() == ClassTemplateSpecialization ||
+ D->getKind() == ClassTemplatePartialSpecialization;
+ }
+ static bool classof(const CXXRecordDecl *D) { return true; }
+ static bool classof(const ClassTemplateSpecializationDecl *D) {
+ return true;
+ }
+};
+
+/// CXXMethodDecl - Represents a static or instance method of a
+/// struct/union/class.
+class CXXMethodDecl : public FunctionDecl {
+protected:
+ CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T,
+ bool isStatic, bool isInline)
+ : FunctionDecl(DK, RD, L, N, T, (isStatic ? Static : None),
+ isInline) {}
+
+public:
+ static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, bool isStatic = false,
+ bool isInline = false);
+
+ bool isStatic() const { return getStorageClass() == Static; }
+ bool isInstance() const { return !isStatic(); }
+
+ bool isOutOfLineDefinition() const {
+ return getLexicalDeclContext() != getDeclContext();
+ }
+
+ bool isVirtual() const {
+ return isVirtualAsWritten() ||
+ (begin_overridden_methods() != end_overridden_methods());
+ }
+
+ ///
+ void addOverriddenMethod(const CXXMethodDecl *MD);
+
+ typedef const CXXMethodDecl ** method_iterator;
+
+ method_iterator begin_overridden_methods() const;
+ method_iterator end_overridden_methods() const;
+
+ /// getParent - Returns the parent of this method declaration, which
+ /// is the class in which this method is defined.
+ const CXXRecordDecl *getParent() const {
+ return cast<CXXRecordDecl>(FunctionDecl::getParent());
+ }
+
+ /// getParent - Returns the parent of this method declaration, which
+ /// is the class in which this method is defined.
+ CXXRecordDecl *getParent() {
+ return const_cast<CXXRecordDecl *>(
+ cast<CXXRecordDecl>(FunctionDecl::getParent()));
+ }
+
+ /// getThisType - Returns the type of 'this' pointer.
+ /// Should only be called for instance methods.
+ QualType getThisType(ASTContext &C) const;
+
+ unsigned getTypeQualifiers() const {
+ return getType()->getAsFunctionProtoType()->getTypeQuals();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion;
+ }
+ static bool classof(const CXXMethodDecl *D) { return true; }
+};
+
+/// CXXBaseOrMemberInitializer - Represents a C++ base or member
+/// initializer, which is part of a constructor initializer that
+/// initializes one non-static member variable or one base class. For
+/// example, in the following, both 'A(a)' and 'f(3.14159)' are member
+/// initializers:
+///
+/// @code
+/// class A { };
+/// class B : public A {
+/// float f;
+/// public:
+/// B(A& a) : A(a), f(3.14159) { }
+/// };
+class CXXBaseOrMemberInitializer {
+ /// BaseOrMember - This points to the entity being initialized,
+ /// which is either a base class (a Type) or a non-static data
+ /// member. When the low bit is 1, it's a base
+ /// class; when the low bit is 0, it's a member.
+ uintptr_t BaseOrMember;
+
+ /// Args - The arguments used to initialize the base or member.
+ Expr **Args;
+ unsigned NumArgs;
+
+public:
+ /// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
+ explicit
+ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs);
+
+ /// CXXBaseOrMemberInitializer - Creates a new member initializer.
+ explicit
+ CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs);
+
+ /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
+ ~CXXBaseOrMemberInitializer();
+
+ /// arg_iterator - Iterates through the member initialization
+ /// arguments.
+ typedef Expr **arg_iterator;
+
+ /// arg_const_iterator - Iterates through the member initialization
+ /// arguments.
+ typedef Expr * const * arg_const_iterator;
+
+ /// isBaseInitializer - Returns true when this initializer is
+ /// initializing a base class.
+ bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; }
+
+ /// isMemberInitializer - Returns true when this initializer is
+ /// initializing a non-static data member.
+ bool isMemberInitializer() const { return (BaseOrMember & 0x1) == 0; }
+
+ /// getBaseClass - If this is a base class initializer, returns the
+ /// type used to specify the initializer. The resulting type will be
+ /// a class type or a typedef of a class type. If this is not a base
+ /// class initializer, returns NULL.
+ Type *getBaseClass() {
+ if (isBaseInitializer())
+ return reinterpret_cast<Type*>(BaseOrMember & ~0x01);
+ else
+ return 0;
+ }
+
+ /// getBaseClass - If this is a base class initializer, returns the
+ /// type used to specify the initializer. The resulting type will be
+ /// a class type or a typedef of a class type. If this is not a base
+ /// class initializer, returns NULL.
+ const Type *getBaseClass() const {
+ if (isBaseInitializer())
+ return reinterpret_cast<const Type*>(BaseOrMember & ~0x01);
+ else
+ return 0;
+ }
+
+ /// getMember - If this is a member initializer, returns the
+ /// declaration of the non-static data member being
+ /// initialized. Otherwise, returns NULL.
+ FieldDecl *getMember() {
+ if (isMemberInitializer())
+ return reinterpret_cast<FieldDecl *>(BaseOrMember);
+ else
+ return 0;
+ }
+
+ /// begin() - Retrieve an iterator to the first initializer argument.
+ arg_iterator begin() { return Args; }
+ /// begin() - Retrieve an iterator to the first initializer argument.
+ arg_const_iterator begin() const { return Args; }
+
+ /// end() - Retrieve an iterator past the last initializer argument.
+ arg_iterator end() { return Args + NumArgs; }
+ /// end() - Retrieve an iterator past the last initializer argument.
+ arg_const_iterator end() const { return Args + NumArgs; }
+
+ /// getNumArgs - Determine the number of arguments used to
+ /// initialize the member or base.
+ unsigned getNumArgs() const { return NumArgs; }
+};
+
+/// CXXConstructorDecl - Represents a C++ constructor within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// explicit X(int); // represented by a CXXConstructorDecl.
+/// };
+/// @endcode
+class CXXConstructorDecl : public CXXMethodDecl {
+ /// Explicit - Whether this constructor is explicit.
+ bool Explicit : 1;
+
+ /// ImplicitlyDefined - Whether this constructor was implicitly
+ /// defined by the compiler. When false, the constructor was defined
+ /// by the user. In C++03, this flag will have the same value as
+ /// Implicit. In C++0x, however, a constructor that is
+ /// explicitly defaulted (i.e., defined with " = default") will have
+ /// @c !Implicit && ImplicitlyDefined.
+ bool ImplicitlyDefined : 1;
+
+ /// FIXME: Add support for base and member initializers.
+
+ CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T,
+ bool isExplicit, bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
+ Explicit(isExplicit), ImplicitlyDefined(false) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, bool isExplicit,
+ bool isInline, bool isImplicitlyDeclared);
+
+ /// isExplicit - Whether this constructor was marked "explicit" or not.
+ bool isExplicit() const { return Explicit; }
+
+ /// isImplicitlyDefined - Whether this constructor was implicitly
+ /// defined. If false, then this constructor was defined by the
+ /// user. This operation can only be invoked if the constructor has
+ /// already been defined.
+ bool isImplicitlyDefined(ASTContext &C) const {
+ assert(isThisDeclarationADefinition() &&
+ "Can only get the implicit-definition flag once the constructor has been defined");
+ return ImplicitlyDefined;
+ }
+
+ /// setImplicitlyDefined - Set whether this constructor was
+ /// implicitly defined or not.
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
+ "Can only set the implicit-definition flag once the constructor has been defined");
+ ImplicitlyDefined = ID;
+ }
+
+ /// isDefaultConstructor - Whether this constructor is a default
+ /// constructor (C++ [class.ctor]p5), which can be used to
+ /// default-initialize a class of this type.
+ bool isDefaultConstructor() const;
+
+ /// isCopyConstructor - Whether this constructor is a copy
+ /// constructor (C++ [class.copy]p2, which can be used to copy the
+ /// class. @p TypeQuals will be set to the qualifiers on the
+ /// argument type. For example, @p TypeQuals would be set to @c
+ /// QualType::Const for the following copy constructor:
+ ///
+ /// @code
+ /// class X {
+ /// public:
+ /// X(const X&);
+ /// };
+ /// @endcode
+ bool isCopyConstructor(ASTContext &Context, unsigned &TypeQuals) const;
+
+ /// isCopyConstructor - Whether this constructor is a copy
+ /// constructor (C++ [class.copy]p2, which can be used to copy the
+ /// class.
+ bool isCopyConstructor(ASTContext &Context) const {
+ unsigned TypeQuals = 0;
+ return isCopyConstructor(Context, TypeQuals);
+ }
+
+ /// isConvertingConstructor - Whether this constructor is a
+ /// converting constructor (C++ [class.conv.ctor]), which can be
+ /// used for user-defined conversions.
+ bool isConvertingConstructor() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == CXXConstructor;
+ }
+ static bool classof(const CXXConstructorDecl *D) { return true; }
+};
+
+/// CXXDestructorDecl - Represents a C++ destructor within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// ~X(); // represented by a CXXDestructorDecl.
+/// };
+/// @endcode
+class CXXDestructorDecl : public CXXMethodDecl {
+ /// ImplicitlyDefined - Whether this destructor was implicitly
+ /// defined by the compiler. When false, the destructor was defined
+ /// by the user. In C++03, this flag will have the same value as
+ /// Implicit. In C++0x, however, a destructor that is
+ /// explicitly defaulted (i.e., defined with " = default") will have
+ /// @c !Implicit && ImplicitlyDefined.
+ bool ImplicitlyDefined : 1;
+
+ CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T,
+ bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, L, N, T, false, isInline),
+ ImplicitlyDefined(false) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, bool isInline,
+ bool isImplicitlyDeclared);
+
+ /// isImplicitlyDefined - Whether this destructor was implicitly
+ /// defined. If false, then this destructor was defined by the
+ /// user. This operation can only be invoked if the destructor has
+ /// already been defined.
+ bool isImplicitlyDefined() const {
+ assert(isThisDeclarationADefinition() &&
+ "Can only get the implicit-definition flag once the destructor has been defined");
+ return ImplicitlyDefined;
+ }
+
+ /// setImplicitlyDefined - Set whether this destructor was
+ /// implicitly defined or not.
+ void setImplicitlyDefined(bool ID) {
+ assert(isThisDeclarationADefinition() &&
+ "Can only set the implicit-definition flag once the destructor has been defined");
+ ImplicitlyDefined = ID;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == CXXDestructor;
+ }
+ static bool classof(const CXXDestructorDecl *D) { return true; }
+};
+
+/// CXXConversionDecl - Represents a C++ conversion function within a
+/// class. For example:
+///
+/// @code
+/// class X {
+/// public:
+/// operator bool();
+/// };
+/// @endcode
+class CXXConversionDecl : public CXXMethodDecl {
+ /// Explicit - Whether this conversion function is marked
+ /// "explicit", meaning that it can only be applied when the user
+ /// explicitly wrote a cast. This is a C++0x feature.
+ bool Explicit : 1;
+
+ CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
+ DeclarationName N, QualType T,
+ bool isInline, bool isExplicit)
+ : CXXMethodDecl(CXXConversion, RD, L, N, T, false, isInline),
+ Explicit(isExplicit) { }
+
+public:
+ static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation L, DeclarationName N,
+ QualType T, bool isInline,
+ bool isExplicit);
+
+ /// isExplicit - Whether this is an explicit conversion operator
+ /// (C++0x only). Explicit conversion operators are only considered
+ /// when the user has explicitly written a cast.
+ bool isExplicit() const { return Explicit; }
+
+ /// getConversionType - Returns the type that this conversion
+ /// function is converting to.
+ QualType getConversionType() const {
+ return getType()->getAsFunctionType()->getResultType();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == CXXConversion;
+ }
+ static bool classof(const CXXConversionDecl *D) { return true; }
+};
+
+/// LinkageSpecDecl - This represents a linkage specification. For example:
+/// extern "C" void foo();
+///
+class LinkageSpecDecl : public Decl, public DeclContext {
+public:
+ /// LanguageIDs - Used to represent the language in a linkage
+ /// specification. The values are part of the serialization abi for
+ /// ASTs and cannot be changed without altering that abi. To help
+ /// ensure a stable abi for this, we choose the DW_LANG_ encodings
+ /// from the dwarf standard.
+ enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002,
+ lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 };
+private:
+ /// Language - The language for this linkage specification.
+ LanguageIDs Language;
+
+ /// HadBraces - Whether this linkage specification had curly braces or not.
+ bool HadBraces : 1;
+
+ LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang,
+ bool Braces)
+ : Decl(LinkageSpec, DC, L),
+ DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { }
+
+public:
+ static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, LanguageIDs Lang,
+ bool Braces);
+
+ LanguageIDs getLanguage() const { return Language; }
+
+ /// hasBraces - Determines whether this linkage specification had
+ /// braces in its syntactic form.
+ bool hasBraces() const { return HadBraces; }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == LinkageSpec;
+ }
+ static bool classof(const LinkageSpecDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const LinkageSpecDecl *D) {
+ return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D));
+ }
+ static LinkageSpecDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<LinkageSpecDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// UsingDirectiveDecl - Represents C++ using-directive. For example:
+///
+/// using namespace std;
+///
+// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide
+// artificial name, for all using-directives in order to store
+// them in DeclContext effectively.
+class UsingDirectiveDecl : public NamedDecl {
+
+ /// SourceLocation - Location of 'namespace' token.
+ SourceLocation NamespaceLoc;
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that precedes the namespace
+ /// name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// IdentLoc - Location of nominated namespace-name identifier.
+ // FIXME: We don't store location of scope specifier.
+ SourceLocation IdentLoc;
+
+ /// NominatedNamespace - Namespace nominated by using-directive.
+ NamespaceDecl *NominatedNamespace;
+
+ /// Enclosing context containing both using-directive and nomintated
+ /// namespace.
+ DeclContext *CommonAncestor;
+
+ /// getUsingDirectiveName - Returns special DeclarationName used by
+ /// using-directives. This is only used by DeclContext for storing
+ /// UsingDirectiveDecls in its lookup structure.
+ static DeclarationName getName() {
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ UsingDirectiveDecl(DeclContext *DC, SourceLocation L,
+ SourceLocation NamespcLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamespaceDecl *Nominated,
+ DeclContext *CommonAncestor)
+ : NamedDecl(Decl::UsingDirective, DC, L, getName()),
+ NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), IdentLoc(IdentLoc),
+ NominatedNamespace(Nominated? Nominated->getOriginalNamespace() : 0),
+ CommonAncestor(CommonAncestor) {
+ }
+
+public:
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifiers the namespace name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// getNominatedNamespace - Returns namespace nominated by using-directive.
+ NamespaceDecl *getNominatedNamespace() { return NominatedNamespace; }
+
+ const NamespaceDecl *getNominatedNamespace() const {
+ return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
+ }
+
+ /// getCommonAncestor - returns common ancestor context of using-directive,
+ /// and nominated by it namespace.
+ DeclContext *getCommonAncestor() { return CommonAncestor; }
+ const DeclContext *getCommonAncestor() const { return CommonAncestor; }
+
+ /// getNamespaceKeyLocation - Returns location of namespace keyword.
+ SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
+
+ /// getIdentLocation - Returns location of identifier.
+ SourceLocation getIdentLocation() const { return IdentLoc; }
+
+ static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ SourceLocation NamespaceLoc,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamespaceDecl *Nominated,
+ DeclContext *CommonAncestor);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::UsingDirective;
+ }
+ static bool classof(const UsingDirectiveDecl *D) { return true; }
+
+ // Friend for getUsingDirectiveName.
+ friend class DeclContext;
+};
+
+/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
+///
+/// @code
+/// namespace Foo = Bar;
+/// @endcode
+class NamespaceAliasDecl : public NamedDecl {
+ SourceLocation AliasLoc;
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that precedes the namespace
+ /// name, if any.
+ NestedNameSpecifier *Qualifier;
+
+ /// IdentLoc - Location of namespace identifier.
+ SourceLocation IdentLoc;
+
+ /// Namespace - The Decl that this alias points to. Can either be a
+ /// NamespaceDecl or a NamespaceAliasDecl.
+ NamedDecl *Namespace;
+
+ NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc, NamedDecl *Namespace)
+ : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
+ QualifierRange(QualifierRange), Qualifier(Qualifier),
+ IdentLoc(IdentLoc), Namespace(Namespace) { }
+
+public:
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifiers the namespace name.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ NamespaceDecl *getNamespace() {
+ if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
+ return AD->getNamespace();
+
+ return cast<NamespaceDecl>(Namespace);
+ }
+
+ const NamespaceDecl *getNamespace() const {
+ return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
+ }
+
+ /// \brief Retrieve the namespace that this alias refers to, which
+ /// may either be a NamespaceDecl or a NamespaceAliasDecl.
+ NamedDecl *getAliasedNamespace() const { return Namespace; }
+
+ static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ SourceRange QualifierRange,
+ NestedNameSpecifier *Qualifier,
+ SourceLocation IdentLoc,
+ NamedDecl *Namespace);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::NamespaceAlias;
+ }
+ static bool classof(const NamespaceAliasDecl *D) { return true; }
+};
+
+/// StaticAssertDecl - Represents a C++0x static_assert declaration.
+class StaticAssertDecl : public Decl {
+ Expr *AssertExpr;
+ StringLiteral *Message;
+
+ StaticAssertDecl(DeclContext *DC, SourceLocation L,
+ Expr *assertexpr, StringLiteral *message)
+ : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { }
+
+public:
+ static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, Expr *AssertExpr,
+ StringLiteral *Message);
+
+ Expr *getAssertExpr() { return AssertExpr; }
+ const Expr *getAssertExpr() const { return AssertExpr; }
+
+ StringLiteral *getMessage() { return Message; }
+ const StringLiteral *getMessage() const { return Message; }
+
+ virtual ~StaticAssertDecl();
+ virtual void Destroy(ASTContext& C);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::StaticAssert;
+ }
+ static bool classof(StaticAssertDecl *D) { return true; }
+};
+
+/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
+/// into a diagnostic with <<.
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ AccessSpecifier AS);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
new file mode 100644
index 000000000000..6c1231c0a73d
--- /dev/null
+++ b/include/clang/AST/DeclContextInternals.h
@@ -0,0 +1,220 @@
+//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the data structures used in the implementation
+// of DeclContext.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
+#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclarationName.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+
+namespace clang {
+
+/// StoredDeclsList - This is an array of decls optimized a common case of only
+/// containing one entry.
+struct StoredDeclsList {
+ /// The kind of data encoded in this list.
+ enum DataKind {
+ /// \brief The data is a NamedDecl*.
+ DK_Decl = 0,
+ /// \brief The data is a declaration ID (an unsigned value),
+ /// shifted left by 2 bits.
+ DK_DeclID = 1,
+ /// \brief The data is a pointer to a vector (of type VectorTy)
+ /// that contains declarations.
+ DK_Decl_Vector = 2,
+ /// \brief The data is a pointer to a vector (of type VectorTy)
+ /// that contains declaration ID.
+ DK_ID_Vector = 3
+ };
+
+ /// VectorTy - When in vector form, this is what the Data pointer points to.
+ typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
+
+ /// \brief The stored data, which will be either a declaration ID, a
+ /// pointer to a NamedDecl, or a pointer to a vector.
+ uintptr_t Data;
+
+public:
+ StoredDeclsList() : Data(0) {}
+
+ StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
+ if (VectorTy *RHSVec = RHS.getAsVector()) {
+ VectorTy *New = new VectorTy(*RHSVec);
+ Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
+ }
+ }
+
+ ~StoredDeclsList() {
+ // If this is a vector-form, free the vector.
+ if (VectorTy *Vector = getAsVector())
+ delete Vector;
+ }
+
+ StoredDeclsList &operator=(const StoredDeclsList &RHS) {
+ if (VectorTy *Vector = getAsVector())
+ delete Vector;
+ Data = RHS.Data;
+ if (VectorTy *RHSVec = RHS.getAsVector()) {
+ VectorTy *New = new VectorTy(*RHSVec);
+ Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
+ }
+ return *this;
+ }
+
+ bool isNull() const { return (Data & ~0x03) == 0; }
+
+ NamedDecl *getAsDecl() const {
+ if ((Data & 0x03) != DK_Decl)
+ return 0;
+
+ return reinterpret_cast<NamedDecl *>(Data & ~0x03);
+ }
+
+ VectorTy *getAsVector() const {
+ if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
+ return 0;
+
+ return reinterpret_cast<VectorTy *>(Data & ~0x03);
+ }
+
+ void setOnlyValue(NamedDecl *ND) {
+ assert(!getAsVector() && "Not inline");
+ Data = reinterpret_cast<uintptr_t>(ND);
+ }
+
+ void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
+ if (Vec.size() > 1) {
+ VectorTy *Vector = getAsVector();
+ if (!Vector) {
+ Vector = new VectorTy;
+ Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector;
+ }
+
+ Vector->resize(Vec.size());
+ std::copy(Vec.begin(), Vec.end(), Vector->begin());
+ return;
+ }
+
+ if (VectorTy *Vector = getAsVector())
+ delete Vector;
+
+ if (Vec.empty())
+ Data = 0;
+ else
+ Data = (Vec[0] << 2) | DK_DeclID;
+ }
+
+ /// \brief Force the stored declarations list to contain actual
+ /// declarations.
+ ///
+ /// This routine will resolve any declaration IDs for declarations
+ /// that may not yet have been loaded from external storage.
+ void materializeDecls(ASTContext &Context);
+
+ bool hasDeclarationIDs() const {
+ DataKind DK = (DataKind)(Data & 0x03);
+ return DK == DK_DeclID || DK == DK_ID_Vector;
+ }
+
+ /// getLookupResult - Return an array of all the decls that this list
+ /// represents.
+ DeclContext::lookup_result getLookupResult(ASTContext &Context) {
+ if (isNull())
+ return DeclContext::lookup_result(0, 0);
+
+ if (hasDeclarationIDs())
+ materializeDecls(Context);
+
+ // If we have a single NamedDecl, return it.
+ if (getAsDecl()) {
+ assert(!isNull() && "Empty list isn't allowed");
+
+ // Data is a raw pointer to a NamedDecl*, return it.
+ void *Ptr = &Data;
+ return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
+ }
+
+ assert(getAsVector() && "Must have a vector at this point");
+ VectorTy &Vector = *getAsVector();
+
+ // Otherwise, we have a range result.
+ return DeclContext::lookup_result((NamedDecl **)&Vector[0],
+ (NamedDecl **)&Vector[0]+Vector.size());
+ }
+
+ /// HandleRedeclaration - If this is a redeclaration of an existing decl,
+ /// replace the old one with D and return true. Otherwise return false.
+ bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
+ if (hasDeclarationIDs())
+ materializeDecls(Context);
+
+ // Most decls only have one entry in their list, special case it.
+ if (NamedDecl *OldD = getAsDecl()) {
+ if (!D->declarationReplaces(OldD))
+ return false;
+ setOnlyValue(D);
+ return true;
+ }
+
+ // Determine if this declaration is actually a redeclaration.
+ VectorTy &Vec = *getAsVector();
+ for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
+ OD != ODEnd; ++OD) {
+ NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
+ if (D->declarationReplaces(OldD)) {
+ *OD = reinterpret_cast<uintptr_t>(D);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// AddSubsequentDecl - This is called on the second and later decl when it is
+ /// not a redeclaration to merge it into the appropriate place in our list.
+ ///
+ void AddSubsequentDecl(NamedDecl *D) {
+ assert(!hasDeclarationIDs() && "Must materialize before adding decls");
+
+ // If this is the second decl added to the list, convert this to vector
+ // form.
+ if (NamedDecl *OldD = getAsDecl()) {
+ VectorTy *VT = new VectorTy();
+ VT->push_back(reinterpret_cast<uintptr_t>(OldD));
+ Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
+ }
+
+ VectorTy &Vec = *getAsVector();
+ if (isa<UsingDirectiveDecl>(D) ||
+ D->getIdentifierNamespace() == Decl::IDNS_Tag)
+ Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ else if (reinterpret_cast<NamedDecl *>(Vec.back())
+ ->getIdentifierNamespace() == Decl::IDNS_Tag) {
+ uintptr_t TagD = Vec.back();
+ Vec.back() = reinterpret_cast<uintptr_t>(D);
+ Vec.push_back(TagD);
+ } else
+ Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ }
+};
+
+typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
new file mode 100644
index 000000000000..15a8adef8e57
--- /dev/null
+++ b/include/clang/AST/DeclGroup.h
@@ -0,0 +1,152 @@
+//===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLGROUP_H
+#define LLVM_CLANG_AST_DECLGROUP_H
+
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclGroup;
+class DeclGroupIterator;
+
+class DeclGroup {
+ // FIXME: Include a TypeSpecifier object.
+ unsigned NumDecls;
+
+private:
+ DeclGroup() : NumDecls(0) {}
+ DeclGroup(unsigned numdecls, Decl** decls);
+
+public:
+ static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
+ void Destroy(ASTContext& C);
+
+ unsigned size() const { return NumDecls; }
+
+ Decl*& operator[](unsigned i) {
+ assert (i < NumDecls && "Out-of-bounds access.");
+ return *((Decl**) (this+1));
+ }
+
+ Decl* const& operator[](unsigned i) const {
+ assert (i < NumDecls && "Out-of-bounds access.");
+ return *((Decl* const*) (this+1));
+ }
+};
+
+class DeclGroupRef {
+ // Note this is not a PointerIntPair because we need the address of the
+ // non-group case to be valid as a Decl** for iteration.
+ enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
+ Decl* D;
+
+ Kind getKind() const {
+ return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
+ }
+
+public:
+ DeclGroupRef() : D(0) {}
+
+ explicit DeclGroupRef(Decl* d) : D(d) {}
+ explicit DeclGroupRef(DeclGroup* dg)
+ : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
+
+ static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
+ if (NumDecls == 0)
+ return DeclGroupRef();
+ if (NumDecls == 1)
+ return DeclGroupRef(Decls[0]);
+ return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
+ }
+
+ typedef Decl** iterator;
+ typedef Decl* const * const_iterator;
+
+ bool isNull() const { return D == 0; }
+ bool isSingleDecl() const { return getKind() == SingleDeclKind; }
+ bool isDeclGroup() const { return getKind() == DeclGroupKind; }
+
+ Decl *getSingleDecl() {
+ assert(isSingleDecl() && "Isn't a declgroup");
+ return D;
+ }
+ const Decl *getSingleDecl() const {
+ return const_cast<DeclGroupRef*>(this)->getSingleDecl();
+ }
+
+ DeclGroup &getDeclGroup() {
+ assert(isDeclGroup() && "Isn't a declgroup");
+ return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
+ }
+ const DeclGroup &getDeclGroup() const {
+ return const_cast<DeclGroupRef*>(this)->getDeclGroup();
+ }
+
+ iterator begin() {
+ if (isSingleDecl())
+ return D ? &D : 0;
+ return &getDeclGroup()[0];
+ }
+
+ iterator end() {
+ if (isSingleDecl())
+ return D ? &D+1 : 0;
+ DeclGroup &G = getDeclGroup();
+ return &G[0] + G.size();
+ }
+
+ const_iterator begin() const {
+ if (isSingleDecl())
+ return D ? &D : 0;
+ return &getDeclGroup()[0];
+ }
+
+ const_iterator end() const {
+ if (isSingleDecl())
+ return D ? &D+1 : 0;
+ const DeclGroup &G = getDeclGroup();
+ return &G[0] + G.size();
+ }
+
+ void *getAsOpaquePtr() const { return D; }
+ static DeclGroupRef getFromOpaquePtr(void *Ptr) {
+ DeclGroupRef X;
+ X.D = static_cast<Decl*>(Ptr);
+ return X;
+ }
+};
+
+} // end clang namespace
+
+namespace llvm {
+ // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
+ template <typename T>
+ class PointerLikeTypeTraits;
+ template <>
+ class PointerLikeTypeTraits<clang::DeclGroupRef> {
+ public:
+ static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
+ return clang::DeclGroupRef::getFromOpaquePtr(P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+}
+#endif
diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def
new file mode 100644
index 000000000000..d1b921a4cb65
--- /dev/null
+++ b/include/clang/AST/DeclNodes.def
@@ -0,0 +1,161 @@
+//===-- DeclNodes.def - Metadata about Decl AST nodes -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the declaration nodes within the AST. The
+// description of the declaration nodes uses six macros:
+//
+// DECL(Derived, Base) describes a normal declaration type Derived
+// and specifies its base class. Note that Derived should not have
+// the Decl suffix on it, while Base should.
+//
+// LAST_DECL(Derived, Base) is like DECL, but is used for the last
+// declaration in the list.
+//
+// ABSTRACT_DECL(Derived, Base) describes an abstract class that is
+// used to specify a classification of declarations. For example,
+// TagDecl is an abstract class used to describe the various kinds of
+// "tag" declarations (unions, structs, classes, enums).
+//
+// DECL_CONTEXT(Decl) specifies that Decl is a kind of declaration
+// that is also a DeclContext.
+//
+// LAST_DECL_CONTEXT(Decl) is like DECL_CONTEXT, but is used for the
+// last declaration context.
+//
+// DECL_RANGE(CommonBase, Start, End) specifies a range of
+// declaration values that have a common (potentially indirect) base
+// class.
+//
+// LAST_DECL_RANGE(CommonBase, Start, End) is like DECL_RANGE, but is
+// used for the last declaration range.
+//
+// Note that, due to the use of ranges, the order of the these
+// declarations is significant. A declaration should be listed under
+// its base class.
+// ===----------------------------------------------------------------------===//
+
+#ifndef DECL
+# define DECL(Derived, Base)
+#endif
+
+#ifndef LAST_DECL
+# define LAST_DECL(Derived, Base) DECL(Derived, Base)
+#endif
+
+#ifndef ABSTRACT_DECL
+# define ABSTRACT_DECL(Derived, Base)
+#endif
+
+#ifndef DECL_CONTEXT
+# define DECL_CONTEXT(Decl)
+#endif
+
+#ifndef DECL_CONTEXT_BASE
+# define DECL_CONTEXT_BASE(Decl) DECL_CONTEXT(Decl)
+#endif
+
+#ifndef LAST_DECL_CONTEXT
+# define LAST_DECL_CONTEXT(Decl) DECL_CONTEXT(Decl)
+#endif
+
+#ifndef DECL_RANGE
+# define DECL_RANGE(CommonBase, Start, End)
+#endif
+
+#ifndef LAST_DECL_RANGE
+# define LAST_DECL_RANGE(CommonBase, Start, End) \
+ DECL_RANGE(CommonBase, Start, End)
+#endif
+
+DECL(TranslationUnit, Decl)
+ABSTRACT_DECL(Named, Decl)
+ DECL(OverloadedFunction, NamedDecl)
+ DECL(Namespace, NamedDecl)
+ DECL(UsingDirective, NamedDecl)
+ DECL(NamespaceAlias, NamedDecl)
+ ABSTRACT_DECL(Type, NamedDecl)
+ DECL(Typedef, TypeDecl)
+ ABSTRACT_DECL(Tag, TypeDecl)
+ DECL(Enum, TagDecl)
+ DECL(Record, TagDecl)
+ DECL(CXXRecord, RecordDecl)
+ DECL(ClassTemplateSpecialization, CXXRecordDecl)
+ DECL(ClassTemplatePartialSpecialization,
+ ClassTemplateSpecializationDecl)
+ DECL(TemplateTypeParm, TypeDecl)
+ ABSTRACT_DECL(Value, NamedDecl)
+ DECL(EnumConstant, ValueDecl)
+ DECL(Function, ValueDecl)
+ DECL(CXXMethod, FunctionDecl)
+ DECL(CXXConstructor, CXXMethodDecl)
+ DECL(CXXDestructor, CXXMethodDecl)
+ DECL(CXXConversion, CXXMethodDecl)
+ DECL(Field, ValueDecl)
+ DECL(ObjCIvar, FieldDecl)
+ DECL(ObjCAtDefsField, FieldDecl)
+ DECL(Var, ValueDecl)
+ DECL(ImplicitParam, VarDecl)
+ DECL(ParmVar, VarDecl)
+ DECL(OriginalParmVar, ParmVarDecl)
+ DECL(NonTypeTemplateParm, VarDecl)
+ DECL(Template, NamedDecl)
+ DECL(FunctionTemplate, TemplateDecl)
+ DECL(ClassTemplate, TemplateDecl)
+ DECL(TemplateTemplateParm, TemplateDecl)
+ DECL(ObjCMethod, NamedDecl)
+ DECL(ObjCContainer, NamedDecl)
+ DECL(ObjCCategory, ObjCContainerDecl)
+ DECL(ObjCProtocol, ObjCContainerDecl)
+ DECL(ObjCInterface, ObjCContainerDecl)
+ DECL(ObjCProperty, NamedDecl)
+ DECL(ObjCCompatibleAlias, NamedDecl)
+ ABSTRACT_DECL(ObjCImpl, NamedDecl)
+ DECL(ObjCCategoryImpl, ObjCImplDecl)
+ DECL(ObjCImplementation, ObjCImplDecl)
+DECL(LinkageSpec, Decl)
+DECL(ObjCPropertyImpl, Decl)
+DECL(ObjCForwardProtocol, Decl)
+DECL(ObjCClass, Decl)
+DECL(FileScopeAsm, Decl)
+DECL(StaticAssert, Decl)
+LAST_DECL(Block, Decl)
+
+// Declaration contexts. DECL_CONTEXT_BASE indicates that it has subclasses.
+DECL_CONTEXT(TranslationUnit)
+DECL_CONTEXT(Namespace)
+DECL_CONTEXT(LinkageSpec)
+DECL_CONTEXT(ObjCMethod)
+DECL_CONTEXT(ObjCCategoryImpl)
+DECL_CONTEXT(ObjCImplementation)
+DECL_CONTEXT_BASE(Tag)
+DECL_CONTEXT_BASE(Function)
+DECL_CONTEXT_BASE(ObjCContainer)
+LAST_DECL_CONTEXT(Block)
+
+// Declaration ranges
+DECL_RANGE(Named, OverloadedFunction, ObjCImplementation)
+DECL_RANGE(ObjCContainer, ObjCContainer, ObjCInterface)
+DECL_RANGE(Field, Field, ObjCAtDefsField)
+DECL_RANGE(Type, Typedef, TemplateTypeParm)
+DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization)
+DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization)
+DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm)
+DECL_RANGE(Function, Function, CXXConversion)
+DECL_RANGE(Template, Template, TemplateTemplateParm)
+DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation)
+LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm)
+
+#undef LAST_DECL_RANGE
+#undef DECL_RANGE
+#undef LAST_DECL_CONTEXT
+#undef DECL_CONTEXT_BASE
+#undef DECL_CONTEXT
+#undef ABSTRACT_DECL
+#undef LAST_DECL
+#undef DECL
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
new file mode 100644
index 000000000000..6e89a7ae7bc9
--- /dev/null
+++ b/include/clang/AST/DeclObjC.h
@@ -0,0 +1,1224 @@
+//===--- DeclObjC.h - Classes for representing declarations -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DeclObjC interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLOBJC_H
+#define LLVM_CLANG_AST_DECLOBJC_H
+
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace clang {
+class Expr;
+class Stmt;
+class FunctionDecl;
+class AttributeList;
+class RecordDecl;
+class ObjCIvarDecl;
+class ObjCMethodDecl;
+class ObjCProtocolDecl;
+class ObjCCategoryDecl;
+class ObjCPropertyDecl;
+class ObjCPropertyImplDecl;
+
+class ObjCListBase {
+ void operator=(const ObjCListBase &); // DO NOT IMPLEMENT
+ ObjCListBase(const ObjCListBase&); // DO NOT IMPLEMENT
+protected:
+ /// List is an array of pointers to objects that are not owned by this object.
+ void **List;
+ unsigned NumElts;
+
+public:
+ ObjCListBase() : List(0), NumElts(0) {}
+ ~ObjCListBase() {
+ assert(List == 0 && "Destroy should have been called before dtor");
+ }
+
+ void Destroy(ASTContext &Ctx);
+
+ unsigned size() const { return NumElts; }
+ bool empty() const { return NumElts == 0; }
+
+protected:
+ void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
+};
+
+
+/// ObjCList - This is a simple template class used to hold various lists of
+/// decls etc, which is heavily used by the ObjC front-end. This only use case
+/// this supports is setting the list all at once and then reading elements out
+/// of it.
+template <typename T>
+class ObjCList : public ObjCListBase {
+public:
+ void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
+ ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
+ }
+
+ typedef T* const * iterator;
+ iterator begin() const { return (iterator)List; }
+ iterator end() const { return (iterator)List+NumElts; }
+
+ T* operator[](unsigned Idx) const {
+ assert(Idx < NumElts && "Invalid access");
+ return (T*)List[Idx];
+ }
+};
+
+
+
+/// ObjCMethodDecl - Represents an instance or class method declaration.
+/// ObjC methods can be declared within 4 contexts: class interfaces,
+/// categories, protocols, and class implementations. While C++ member
+/// functions leverage C syntax, Objective-C method syntax is modeled after
+/// Smalltalk (using colons to specify argument types/expressions).
+/// Here are some brief examples:
+///
+/// Setter/getter instance methods:
+/// - (void)setMenu:(NSMenu *)menu;
+/// - (NSMenu *)menu;
+///
+/// Instance method that takes 2 NSView arguments:
+/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
+///
+/// Getter class method:
+/// + (NSMenu *)defaultMenu;
+///
+/// A selector represents a unique name for a method. The selector names for
+/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
+///
+class ObjCMethodDecl : public NamedDecl, public DeclContext {
+public:
+ enum ImplementationControl { None, Required, Optional };
+private:
+ /// Bitfields must be first fields in this class so they pack with those
+ /// declared in class Decl.
+ /// instance (true) or class (false) method.
+ bool IsInstance : 1;
+ bool IsVariadic : 1;
+
+ // Synthesized declaration method for a property setter/getter
+ bool IsSynthesized : 1;
+
+ // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
+ /// @required/@optional
+ unsigned DeclImplementation : 2;
+
+ // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
+ /// in, inout, etc.
+ unsigned objcDeclQualifier : 6;
+
+ // Type of this method.
+ QualType MethodDeclType;
+ /// ParamInfo - List of pointers to VarDecls for the formal parameters of this
+ /// Method.
+ ObjCList<ParmVarDecl> ParamInfo;
+
+ /// List of attributes for this method declaration.
+ SourceLocation EndLoc; // the location of the ';' or '{'.
+
+ // The following are only used for method definitions, null otherwise.
+ // FIXME: space savings opportunity, consider a sub-class.
+ Stmt *Body;
+
+ /// SelfDecl - Decl for the implicit self parameter. This is lazily
+ /// constructed by createImplicitParams.
+ ImplicitParamDecl *SelfDecl;
+ /// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
+ /// constructed by createImplicitParams.
+ ImplicitParamDecl *CmdDecl;
+
+ ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
+ Selector SelInfo, QualType T,
+ DeclContext *contextDecl,
+ bool isInstance = true,
+ bool isVariadic = false,
+ bool isSynthesized = false,
+ ImplementationControl impControl = None)
+ : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
+ DeclContext(ObjCMethod),
+ IsInstance(isInstance), IsVariadic(isVariadic),
+ IsSynthesized(isSynthesized),
+ DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
+ MethodDeclType(T),
+ EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
+
+ virtual ~ObjCMethodDecl() {}
+
+public:
+
+ /// Destroy - Call destructors and release memory.
+ virtual void Destroy(ASTContext& C);
+
+ static ObjCMethodDecl *Create(ASTContext &C,
+ SourceLocation beginLoc,
+ SourceLocation endLoc, Selector SelInfo,
+ QualType T, DeclContext *contextDecl,
+ bool isInstance = true,
+ bool isVariadic = false,
+ bool isSynthesized = false,
+ ImplementationControl impControl = None);
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ return ObjCDeclQualifier(objcDeclQualifier);
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); }
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setEndLoc(SourceLocation Loc) { EndLoc = Loc; }
+ SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), EndLoc);
+ }
+
+ ObjCInterfaceDecl *getClassInterface();
+ const ObjCInterfaceDecl *getClassInterface() const {
+ return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
+ }
+
+ Selector getSelector() const { return getDeclName().getObjCSelector(); }
+ unsigned getSynthesizedMethodSize() const;
+ QualType getResultType() const { return MethodDeclType; }
+ void setResultType(QualType T) { MethodDeclType = T; }
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return ParamInfo.size(); }
+ typedef ObjCList<ParmVarDecl>::iterator param_iterator;
+ param_iterator param_begin() const { return ParamInfo.begin(); }
+ param_iterator param_end() const { return ParamInfo.end(); }
+
+ void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num) {
+ ParamInfo.set(List, Num, C);
+ }
+
+ // Iterator access to parameter types.
+ typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
+ typedef llvm::mapped_iterator<param_iterator, deref_fun> arg_type_iterator;
+
+ arg_type_iterator arg_type_begin() const {
+ return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
+ }
+ arg_type_iterator arg_type_end() const {
+ return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType));
+ }
+
+ /// createImplicitParams - Used to lazily create the self and cmd
+ /// implict parameters. This must be called prior to using getSelfDecl()
+ /// or getCmdDecl(). The call is ignored if the implicit paramters
+ /// have already been created.
+ void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
+
+ ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
+ void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
+ ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
+ void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
+
+ bool isInstanceMethod() const { return IsInstance; }
+ void setInstanceMethod(bool isInst) { IsInstance = isInst; }
+ bool isVariadic() const { return IsVariadic; }
+ void setVariadic(bool isVar) { IsVariadic = isVar; }
+
+ bool isClassMethod() const { return !IsInstance; }
+
+ bool isSynthesized() const { return IsSynthesized; }
+ void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
+
+ // Related to protocols declared in @protocol
+ void setDeclImplementation(ImplementationControl ic) {
+ DeclImplementation = ic;
+ }
+ ImplementationControl getImplementationControl() const {
+ return ImplementationControl(DeclImplementation);
+ }
+
+ virtual Stmt *getBody(ASTContext &C) const {
+ return (Stmt*) Body;
+ }
+ CompoundStmt *getBody() { return (CompoundStmt*)Body; }
+ void setBody(Stmt *B) { Body = B; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }
+ static bool classof(const ObjCMethodDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
+ }
+ static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ObjCMethodList - a linked list of methods with different signatures.
+struct ObjCMethodList {
+ ObjCMethodDecl *Method;
+ ObjCMethodList *Next;
+
+ ObjCMethodList() {
+ Method = 0;
+ Next = 0;
+ }
+ ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
+ Method = M;
+ Next = C;
+ }
+};
+
+/// ObjCContainerDecl - Represents a container for method declarations.
+/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, and
+/// ObjCProtocolDecl.
+/// FIXME: Use for ObjC implementation decls.
+///
+class ObjCContainerDecl : public NamedDecl, public DeclContext {
+ SourceLocation AtEndLoc; // marks the end of the method container.
+public:
+
+ ObjCContainerDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id)
+ : NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
+
+ virtual ~ObjCContainerDecl() {}
+
+ // Iterator access to properties.
+ typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
+ prop_iterator prop_begin(ASTContext &Context) const {
+ return prop_iterator(decls_begin(Context));
+ }
+ prop_iterator prop_end(ASTContext &Context) const {
+ return prop_iterator(decls_end(Context));
+ }
+
+ // Iterator access to instance/class methods.
+ typedef specific_decl_iterator<ObjCMethodDecl> method_iterator;
+ method_iterator meth_begin(ASTContext &Context) const {
+ return method_iterator(decls_begin(Context));
+ }
+ method_iterator meth_end(ASTContext &Context) const {
+ return method_iterator(decls_end(Context));
+ }
+
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isInstanceMethod>
+ instmeth_iterator;
+ instmeth_iterator instmeth_begin(ASTContext &Context) const {
+ return instmeth_iterator(decls_begin(Context));
+ }
+ instmeth_iterator instmeth_end(ASTContext &Context) const {
+ return instmeth_iterator(decls_end(Context));
+ }
+
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isClassMethod>
+ classmeth_iterator;
+ classmeth_iterator classmeth_begin(ASTContext &Context) const {
+ return classmeth_iterator(decls_begin(Context));
+ }
+ classmeth_iterator classmeth_end(ASTContext &Context) const {
+ return classmeth_iterator(decls_end(Context));
+ }
+
+ // Get the local instance/class method declared in this interface.
+ ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const;
+ ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const;
+
+ ObjCMethodDecl *
+ getMethod(ASTContext &Context, Selector Sel, bool isInstance) const {
+ return isInstance ? getInstanceMethod(Context, Sel)
+ : getClassMethod(Context, Sel);
+ }
+
+ ObjCPropertyDecl *FindPropertyDeclaration(ASTContext &Context,
+ IdentifierInfo *PropertyId) const;
+
+ // Marks the end of the container.
+ SourceLocation getAtEndLoc() const { return AtEndLoc; }
+ void setAtEndLoc(SourceLocation L) { AtEndLoc = L; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= ObjCContainerFirst &&
+ D->getKind() <= ObjCContainerLast;
+ }
+ static bool classof(const ObjCContainerDecl *D) { return true; }
+
+ static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
+ }
+ static ObjCContainerDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ObjCContainerDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example:
+///
+/// // MostPrimitive declares no super class (not particularly useful).
+/// @interface MostPrimitive
+/// // no instance variables or methods.
+/// @end
+///
+/// // NSResponder inherits from NSObject & implements NSCoding (a protocol).
+/// @interface NSResponder : NSObject <NSCoding>
+/// { // instance variables are represented by ObjCIvarDecl.
+/// id nextResponder; // nextResponder instance variable.
+/// }
+/// - (NSResponder *)nextResponder; // return a pointer to NSResponder.
+/// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer
+/// @end // to an NSEvent.
+///
+/// Unlike C/C++, forward class declarations are accomplished with @class.
+/// Unlike C/C++, @class allows for a list of classes to be forward declared.
+/// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes
+/// typically inherit from NSObject (an exception is NSProxy).
+///
+class ObjCInterfaceDecl : public ObjCContainerDecl {
+ /// TypeForDecl - This indicates the Type object that represents this
+ /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
+ mutable Type *TypeForDecl;
+ friend class ASTContext;
+
+ /// Class's super class.
+ ObjCInterfaceDecl *SuperClass;
+
+ /// Protocols referenced in interface header declaration
+ ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+
+ /// Instance variables in the interface.
+ ObjCList<ObjCIvarDecl> IVars;
+
+ /// List of categories defined for this class.
+ /// FIXME: Why is this a linked list??
+ ObjCCategoryDecl *CategoryList;
+
+ bool ForwardDecl:1; // declared with @class.
+ bool InternalInterface:1; // true - no @interface for @implementation
+
+ SourceLocation ClassLoc; // location of the class identifier.
+ SourceLocation SuperClassLoc; // location of the super class identifier.
+ SourceLocation EndLoc; // marks the '>', '}', or identifier.
+
+ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
+ SourceLocation CLoc, bool FD, bool isInternal);
+
+ virtual ~ObjCInterfaceDecl() {}
+
+public:
+
+ /// Destroy - Call destructors and release memory.
+ virtual void Destroy(ASTContext& C);
+
+ static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation atLoc,
+ IdentifierInfo *Id,
+ SourceLocation ClassLoc = SourceLocation(),
+ bool ForwardDecl = false,
+ bool isInternal = false);
+ const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ return ReferencedProtocols;
+ }
+
+ ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ typedef ObjCList<ObjCIvarDecl>::iterator ivar_iterator;
+ ivar_iterator ivar_begin() const { return IVars.begin(); }
+ ivar_iterator ivar_end() const { return IVars.end(); }
+ unsigned ivar_size() const { return IVars.size(); }
+ bool ivar_empty() const { return IVars.empty(); }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
+ ASTContext &C) {
+ ReferencedProtocols.set(List, Num, C);
+ }
+
+ void setIVarList(ObjCIvarDecl * const *List, unsigned Num, ASTContext &C) {
+ IVars.set(List, Num, C);
+ }
+
+ bool isForwardDecl() const { return ForwardDecl; }
+ void setForwardDecl(bool val) { ForwardDecl = val; }
+
+ ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+ void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+
+ ObjCCategoryDecl* getCategoryList() const { return CategoryList; }
+ void setCategoryList(ObjCCategoryDecl *category) {
+ CategoryList = category;
+ }
+
+ /// isSuperClassOf - Return true if this class is the specified class or is a
+ /// super class of the specified interface class.
+ bool isSuperClassOf(const ObjCInterfaceDecl *I) const {
+ // If RHS is derived from LHS it is OK; else it is not OK.
+ while (I != NULL) {
+ if (this == I)
+ return true;
+ I = I->getSuperClass();
+ }
+ return false;
+ }
+
+ ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context,
+ IdentifierInfo *IVarName,
+ ObjCInterfaceDecl *&ClassDeclared);
+ ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context,
+ IdentifierInfo *IVarName) {
+ ObjCInterfaceDecl *ClassDeclared;
+ return lookupInstanceVariable(Context, IVarName, ClassDeclared);
+ }
+
+ // Lookup a method. First, we search locally. If a method isn't
+ // found, we search referenced protocols and class categories.
+ ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel);
+ ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel);
+ ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); } // '@'interface
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setLocEnd(SourceLocation LE) { EndLoc = LE; };
+
+ void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; }
+ SourceLocation getClassLoc() const { return ClassLoc; }
+ void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; }
+ SourceLocation getSuperClassLoc() const { return SuperClassLoc; }
+
+ /// isImplicitInterfaceDecl - check that this is an implicitly declared
+ /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation
+ /// declaration without an @interface declaration.
+ bool isImplicitInterfaceDecl() const { return InternalInterface; }
+ void setImplicitInterfaceDecl(bool val) { InternalInterface = val; }
+
+ // Low-level accessor
+ Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(Type *TD) const { TypeForDecl = TD; }
+
+ static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; }
+ static bool classof(const ObjCInterfaceDecl *D) { return true; }
+};
+
+/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
+/// instance variables are identical to C. The only exception is Objective-C
+/// supports C++ style access control. For example:
+///
+/// @interface IvarExample : NSObject
+/// {
+/// id defaultToProtected;
+/// @public:
+/// id canBePublic; // same as C++.
+/// @protected:
+/// id canBeProtected; // same as C++.
+/// @package:
+/// id canBePackage; // framework visibility (not available in C++).
+/// }
+///
+class ObjCIvarDecl : public FieldDecl {
+public:
+ enum AccessControl {
+ None, Private, Protected, Public, Package
+ };
+
+private:
+ ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T, AccessControl ac, Expr *BW)
+ : FieldDecl(ObjCIvar, DC, L, Id, T, BW, /*Mutable=*/false),
+ DeclAccess(ac) {}
+
+public:
+ static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ AccessControl ac, Expr *BW = NULL);
+
+ void setAccessControl(AccessControl ac) { DeclAccess = ac; }
+
+ AccessControl getAccessControl() const { return AccessControl(DeclAccess); }
+
+ AccessControl getCanonicalAccessControl() const {
+ return DeclAccess == None ? Protected : AccessControl(DeclAccess);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; }
+ static bool classof(const ObjCIvarDecl *D) { return true; }
+private:
+ // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
+ unsigned DeclAccess : 3;
+};
+
+
+/// ObjCAtDefsFieldDecl - Represents a field declaration created by an
+/// @defs(...).
+class ObjCAtDefsFieldDecl : public FieldDecl {
+private:
+ ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T, Expr *BW)
+ : FieldDecl(ObjCAtDefsField, DC, L, Id, T, BW, /*Mutable=*/false) {}
+
+public:
+ static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ Expr *BW);
+
+ virtual void Destroy(ASTContext& C);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return D->getKind() == ObjCAtDefsField; }
+ static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
+};
+
+/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols
+/// declare a pure abstract type (i.e no instance variables are permitted).
+/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++
+/// feature with nice semantics and lousy syntax:-). Here is an example:
+///
+/// @protocol NSDraggingInfo <refproto1, refproto2>
+/// - (NSWindow *)draggingDestinationWindow;
+/// - (NSImage *)draggedImage;
+/// @end
+///
+/// This says that NSDraggingInfo requires two methods and requires everything
+/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
+/// well.
+///
+/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
+/// @end
+///
+/// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and
+/// protocols are in distinct namespaces. For example, Cocoa defines both
+/// an NSObject protocol and class (which isn't allowed in Java). As a result,
+/// protocols are referenced using angle brackets as follows:
+///
+/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo;
+///
+class ObjCProtocolDecl : public ObjCContainerDecl {
+ /// Referenced protocols
+ ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+
+ bool isForwardProtoDecl; // declared with @protocol.
+
+ SourceLocation EndLoc; // marks the '>' or identifier.
+
+ ObjCProtocolDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
+ : ObjCContainerDecl(ObjCProtocol, DC, L, Id),
+ isForwardProtoDecl(true) {
+ }
+
+ virtual ~ObjCProtocolDecl() {}
+
+public:
+ static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+
+ /// Destroy - Call destructors and release memory.
+ virtual void Destroy(ASTContext& C);
+
+ const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ return ReferencedProtocols;
+ }
+ typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ ASTContext &C) {
+ ReferencedProtocols.set(List, Num, C);
+ }
+
+ ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName);
+
+ // Lookup a method. First, we search locally. If a method isn't
+ // found, we search referenced protocols and class categories.
+ ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel);
+ ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel);
+
+ bool isForwardDecl() const { return isForwardProtoDecl; }
+ void setForwardDecl(bool val) { isForwardProtoDecl = val; }
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setLocEnd(SourceLocation LE) { EndLoc = LE; };
+
+ static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; }
+ static bool classof(const ObjCProtocolDecl *D) { return true; }
+};
+
+/// ObjCClassDecl - Specifies a list of forward class declarations. For example:
+///
+/// @class NSCursor, NSImage, NSPasteboard, NSWindow;
+///
+class ObjCClassDecl : public Decl {
+ ObjCList<ObjCInterfaceDecl> ForwardDecls;
+
+ ObjCClassDecl(DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C);
+ virtual ~ObjCClassDecl() {}
+public:
+
+ /// Destroy - Call destructors and release memory.
+ virtual void Destroy(ASTContext& C);
+
+ static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *const *Elts = 0,
+ unsigned nElts = 0);
+
+ typedef ObjCList<ObjCInterfaceDecl>::iterator iterator;
+ iterator begin() const { return ForwardDecls.begin(); }
+ iterator end() const { return ForwardDecls.end(); }
+ unsigned size() const { return ForwardDecls.size(); }
+
+ /// setClassList - Set the list of forward classes.
+ void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) {
+ ForwardDecls.set(List, Num, C);
+ }
+
+ static bool classof(const Decl *D) { return D->getKind() == ObjCClass; }
+ static bool classof(const ObjCClassDecl *D) { return true; }
+};
+
+/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations.
+/// For example:
+///
+/// @protocol NSTextInput, NSChangeSpelling, NSDraggingInfo;
+///
+class ObjCForwardProtocolDecl : public Decl {
+ ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+
+ ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
+ ObjCProtocolDecl *const *Elts, unsigned nElts,
+ ASTContext &C);
+ virtual ~ObjCForwardProtocolDecl() {}
+
+public:
+ static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCProtocolDecl *const *Elts = 0,
+ unsigned Num = 0);
+
+ /// Destroy - Call destructors and release memory.
+ virtual void Destroy(ASTContext& C);
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ /// setProtocolList - Set the list of forward protocols.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ ASTContext &C) {
+ ReferencedProtocols.set(List, Num, C);
+ }
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjCForwardProtocol;
+ }
+ static bool classof(const ObjCForwardProtocolDecl *D) { return true; }
+};
+
+/// ObjCCategoryDecl - Represents a category declaration. A category allows
+/// you to add methods to an existing class (without subclassing or modifying
+/// the original class interface or implementation:-). Categories don't allow
+/// you to add instance data. The following example adds "myMethod" to all
+/// NSView's within a process:
+///
+/// @interface NSView (MyViewMethods)
+/// - myMethod;
+/// @end
+///
+/// Cateogries also allow you to split the implementation of a class across
+/// several files (a feature more naturally supported in C++).
+///
+/// Categories were originally inspired by dynamic languages such as Common
+/// Lisp and Smalltalk. More traditional class-based languages (C++, Java)
+/// don't support this level of dynamism, which is both powerful and dangerous.
+///
+class ObjCCategoryDecl : public ObjCContainerDecl {
+ /// Interface belonging to this category
+ ObjCInterfaceDecl *ClassInterface;
+
+ /// referenced protocols in this category.
+ ObjCList<ObjCProtocolDecl> ReferencedProtocols;
+
+ /// Next category belonging to this class.
+ /// FIXME: this should not be a singly-linked list. Move storage elsewhere.
+ ObjCCategoryDecl *NextClassCategory;
+
+ SourceLocation EndLoc; // marks the '>' or identifier.
+
+ ObjCCategoryDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
+ : ObjCContainerDecl(ObjCCategory, DC, L, Id),
+ ClassInterface(0), NextClassCategory(0){
+ }
+public:
+
+ static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id);
+
+ ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
+ const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ void setClassInterface(ObjCInterfaceDecl *IDecl) { ClassInterface = IDecl; }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ ASTContext &C) {
+ ReferencedProtocols.set(List, Num, C);
+ }
+
+ const ObjCList<ObjCProtocolDecl> &getReferencedProtocols() const {
+ return ReferencedProtocols;
+ }
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
+ protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+ unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; }
+ void setNextClassCategory(ObjCCategoryDecl *Cat) {
+ NextClassCategory = Cat;
+ }
+ void insertNextClassCategory() {
+ NextClassCategory = ClassInterface->getCategoryList();
+ ClassInterface->setCategoryList(this);
+ }
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); } // '@'interface
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setLocEnd(SourceLocation LE) { EndLoc = LE; };
+
+ static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
+ static bool classof(const ObjCCategoryDecl *D) { return true; }
+};
+
+class ObjCImplDecl : public NamedDecl, public DeclContext {
+ /// Class interface for this category implementation
+ ObjCInterfaceDecl *ClassInterface;
+
+ SourceLocation EndLoc;
+
+protected:
+ ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *classInterface)
+ : NamedDecl(DK, DC, L,
+ classInterface? classInterface->getDeclName()
+ : DeclarationName()),
+ DeclContext(DK), ClassInterface(classInterface) {}
+
+public:
+ virtual ~ObjCImplDecl() {}
+
+ const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+ ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
+ void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; }
+
+ void addInstanceMethod(ASTContext &Context, ObjCMethodDecl *method) {
+ // FIXME: Context should be set correctly before we get here.
+ method->setLexicalDeclContext(this);
+ addDecl(Context, method);
+ }
+ void addClassMethod(ASTContext &Context, ObjCMethodDecl *method) {
+ // FIXME: Context should be set correctly before we get here.
+ method->setLexicalDeclContext(this);
+ addDecl(Context, method);
+ }
+
+ // Get the local instance/class method declared in this interface.
+ ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const;
+ ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const;
+ ObjCMethodDecl *getMethod(ASTContext &Context, Selector Sel,
+ bool isInstance) const {
+ return isInstance ? getInstanceMethod(Context, Sel)
+ : getClassMethod(Context, Sel);
+ }
+
+ void addPropertyImplementation(ASTContext &Context,
+ ObjCPropertyImplDecl *property);
+
+ ObjCPropertyImplDecl *FindPropertyImplDecl(ASTContext &Context,
+ IdentifierInfo *propertyId) const;
+ ObjCPropertyImplDecl *FindPropertyImplIvarDecl(ASTContext &Context,
+ IdentifierInfo *ivarId) const;
+
+ // Iterator access to properties.
+ typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator;
+ propimpl_iterator propimpl_begin(ASTContext &Context) const {
+ return propimpl_iterator(decls_begin(Context));
+ }
+ propimpl_iterator propimpl_end(ASTContext &Context) const {
+ return propimpl_iterator(decls_end(Context));
+ }
+
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isInstanceMethod>
+ instmeth_iterator;
+ instmeth_iterator instmeth_begin(ASTContext &Context) const {
+ return instmeth_iterator(decls_begin(Context));
+ }
+ instmeth_iterator instmeth_end(ASTContext &Context) const {
+ return instmeth_iterator(decls_end(Context));
+ }
+
+ typedef filtered_decl_iterator<ObjCMethodDecl,
+ &ObjCMethodDecl::isClassMethod>
+ classmeth_iterator;
+ classmeth_iterator classmeth_begin(ASTContext &Context) const {
+ return classmeth_iterator(decls_begin(Context));
+ }
+ classmeth_iterator classmeth_end(ASTContext &Context) const {
+ return classmeth_iterator(decls_end(Context));
+ }
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const { return getLocation(); }
+ SourceLocation getLocEnd() const { return EndLoc; }
+ void setLocEnd(SourceLocation LE) { EndLoc = LE; };
+};
+
+/// ObjCCategoryImplDecl - An object of this class encapsulates a category
+/// @implementation declaration. If a category class has declaration of a
+/// property, its implementation must be specified in the category's
+/// @implementation declaration. Example:
+/// @interface I @end
+/// @interface I(CATEGORY)
+/// @property int p1, d1;
+/// @end
+/// @implementation I(CATEGORY)
+/// @dynamic p1,d1;
+/// @end
+///
+/// ObjCCategoryImplDecl
+class ObjCCategoryImplDecl : public ObjCImplDecl {
+ // Category name
+ IdentifierInfo *Id;
+
+ ObjCCategoryImplDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl *classInterface)
+ : ObjCImplDecl(ObjCCategoryImpl, DC, L, classInterface), Id(Id) {}
+public:
+ static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl *classInterface);
+
+ /// getIdentifier - Get the identifier that names the class
+ /// interface associated with this implementation.
+ IdentifierInfo *getIdentifier() const {
+ return Id;
+ }
+ void setIdentifier(IdentifierInfo *II) { Id = II; }
+
+ /// getNameAsCString - Get the name of identifier for the class
+ /// interface associated with this implementation as a C string
+ /// (const char*).
+ const char *getNameAsCString() const {
+ return Id ? Id->getName() : "";
+ }
+
+ /// @brief Get the name of the class associated with this interface.
+ std::string getNameAsString() const {
+ return Id ? Id->getName() : "";
+ }
+
+ static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;}
+ static bool classof(const ObjCCategoryImplDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const ObjCCategoryImplDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ObjCCategoryImplDecl*>(D));
+ }
+ static ObjCCategoryImplDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ObjCCategoryImplDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ObjCImplementationDecl - Represents a class definition - this is where
+/// method definitions are specified. For example:
+///
+/// @code
+/// @implementation MyClass
+/// - (void)myMethod { /* do something */ }
+/// @end
+/// @endcode
+///
+/// Typically, instance variables are specified in the class interface,
+/// *not* in the implementation. Nevertheless (for legacy reasons), we
+/// allow instance variables to be specified in the implementation. When
+/// specified, they need to be *identical* to the interface.
+///
+class ObjCImplementationDecl : public ObjCImplDecl {
+ /// Implementation Class's super class.
+ ObjCInterfaceDecl *SuperClass;
+
+ ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
+ ObjCInterfaceDecl *classInterface,
+ ObjCInterfaceDecl *superDecl)
+ : ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
+ SuperClass(superDecl){}
+public:
+ static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ObjCInterfaceDecl *classInterface,
+ ObjCInterfaceDecl *superDecl);
+
+ /// getIdentifier - Get the identifier that names the class
+ /// interface associated with this implementation.
+ IdentifierInfo *getIdentifier() const {
+ return getClassInterface()->getIdentifier();
+ }
+
+ /// getNameAsCString - Get the name of identifier for the class
+ /// interface associated with this implementation as a C string
+ /// (const char*).
+ const char *getNameAsCString() const {
+ assert(getIdentifier() && "Name is not a simple identifier");
+ return getIdentifier()->getName();
+ }
+
+ /// @brief Get the name of the class associated with this interface.
+ std::string getNameAsString() const {
+ return getClassInterface()->getNameAsString();
+ }
+
+ const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+ ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
+
+ void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+ ivar_iterator ivar_begin(ASTContext &Context) const {
+ return ivar_iterator(decls_begin(Context));
+ }
+ ivar_iterator ivar_end(ASTContext &Context) const {
+ return ivar_iterator(decls_end(Context));
+ }
+ unsigned ivar_size(ASTContext &Context) const {
+ return std::distance(ivar_begin(Context), ivar_end(Context));
+ }
+ bool ivar_empty(ASTContext &Context) const {
+ return ivar_begin(Context) == ivar_end(Context);
+ }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjCImplementation;
+ }
+ static bool classof(const ObjCImplementationDecl *D) { return true; }
+ static DeclContext *castToDeclContext(const ObjCImplementationDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ObjCImplementationDecl*>(D));
+ }
+ static ObjCImplementationDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ObjCImplementationDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
+/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
+/// declared as @compatibility_alias alias class.
+class ObjCCompatibleAliasDecl : public NamedDecl {
+ /// Class that this is an alias of.
+ ObjCInterfaceDecl *AliasedClass;
+
+ ObjCCompatibleAliasDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl* aliasedClass)
+ : NamedDecl(ObjCCompatibleAlias, DC, L, Id), AliasedClass(aliasedClass) {}
+public:
+ static ObjCCompatibleAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ ObjCInterfaceDecl* aliasedClass);
+
+ const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
+ ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
+ void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjCCompatibleAlias;
+ }
+ static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
+
+};
+
+/// ObjCPropertyDecl - Represents one property declaration in an interface.
+/// For example:
+/// @property (assign, readwrite) int MyProperty;
+///
+class ObjCPropertyDecl : public NamedDecl {
+public:
+ enum PropertyAttributeKind {
+ OBJC_PR_noattr = 0x00,
+ OBJC_PR_readonly = 0x01,
+ OBJC_PR_getter = 0x02,
+ OBJC_PR_assign = 0x04,
+ OBJC_PR_readwrite = 0x08,
+ OBJC_PR_retain = 0x10,
+ OBJC_PR_copy = 0x20,
+ OBJC_PR_nonatomic = 0x40,
+ OBJC_PR_setter = 0x80
+ };
+
+ enum SetterKind { Assign, Retain, Copy };
+ enum PropertyControl { None, Required, Optional };
+private:
+ QualType DeclType;
+ unsigned PropertyAttributes : 8;
+
+ // @required/@optional
+ unsigned PropertyImplementation : 2;
+
+ Selector GetterName; // getter name of NULL if no getter
+ Selector SetterName; // setter name of NULL if no setter
+
+ ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method
+ ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method
+ ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property
+
+ ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ QualType T)
+ : NamedDecl(ObjCProperty, DC, L, Id), DeclType(T),
+ PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None),
+ GetterName(Selector()),
+ SetterName(Selector()),
+ GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {}
+public:
+ static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id, QualType T,
+ PropertyControl propControl = None);
+ QualType getType() const { return DeclType; }
+ void setType(QualType T) { DeclType = T; }
+
+ PropertyAttributeKind getPropertyAttributes() const {
+ return PropertyAttributeKind(PropertyAttributes);
+ }
+ void setPropertyAttributes(PropertyAttributeKind PRVal) {
+ PropertyAttributes |= PRVal;
+ }
+
+ void makeitReadWriteAttribute(void) {
+ PropertyAttributes &= ~OBJC_PR_readonly;
+ PropertyAttributes |= OBJC_PR_readwrite;
+ }
+
+ // Helper methods for accessing attributes.
+
+ /// isReadOnly - Return true iff the property has a setter.
+ bool isReadOnly() const {
+ return (PropertyAttributes & OBJC_PR_readonly);
+ }
+
+ /// getSetterKind - Return the method used for doing assignment in
+ /// the property setter. This is only valid if the property has been
+ /// defined to have a setter.
+ SetterKind getSetterKind() const {
+ if (PropertyAttributes & OBJC_PR_retain)
+ return Retain;
+ if (PropertyAttributes & OBJC_PR_copy)
+ return Copy;
+ return Assign;
+ }
+
+ Selector getGetterName() const { return GetterName; }
+ void setGetterName(Selector Sel) { GetterName = Sel; }
+
+ Selector getSetterName() const { return SetterName; }
+ void setSetterName(Selector Sel) { SetterName = Sel; }
+
+ ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
+ void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
+
+ ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
+ void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
+
+ // Related to @optional/@required declared in @protocol
+ void setPropertyImplementation(PropertyControl pc) {
+ PropertyImplementation = pc;
+ }
+ PropertyControl getPropertyImplementation() const {
+ return PropertyControl(PropertyImplementation);
+ }
+
+ void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
+ PropertyIvarDecl = Ivar;
+ }
+ ObjCIvarDecl *getPropertyIvarDecl() const {
+ return PropertyIvarDecl;
+ }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjCProperty;
+ }
+ static bool classof(const ObjCPropertyDecl *D) { return true; }
+};
+
+/// ObjCPropertyImplDecl - Represents implementation declaration of a property
+/// in a class or category implementation block. For example:
+/// @synthesize prop1 = ivar1;
+///
+class ObjCPropertyImplDecl : public Decl {
+public:
+ enum Kind {
+ Synthesize,
+ Dynamic
+ };
+private:
+ SourceLocation AtLoc; // location of @synthesize or @dynamic
+ /// Property declaration being implemented
+ ObjCPropertyDecl *PropertyDecl;
+
+ /// Null for @dynamic. Required for @synthesize.
+ ObjCIvarDecl *PropertyIvarDecl;
+
+ ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
+ ObjCIvarDecl *ivarDecl)
+ : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
+ PropertyDecl(property), PropertyIvarDecl(ivarDecl) {
+ assert (PK == Dynamic || PropertyIvarDecl);
+ }
+
+public:
+ static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation atLoc, SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
+ ObjCIvarDecl *ivarDecl);
+
+ SourceLocation getLocStart() const { return AtLoc; }
+ void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
+
+ ObjCPropertyDecl *getPropertyDecl() const {
+ return PropertyDecl;
+ }
+ void setPropertyDecl(ObjCPropertyDecl *Prop) { PropertyDecl = Prop; }
+
+ Kind getPropertyImplementation() const {
+ return PropertyIvarDecl ? Synthesize : Dynamic;
+ }
+
+ ObjCIvarDecl *getPropertyIvarDecl() const {
+ return PropertyIvarDecl;
+ }
+ void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ObjCPropertyImpl;
+ }
+ static bool classof(const ObjCPropertyImplDecl *D) { return true; }
+};
+
+} // end namespace clang
+#endif
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
new file mode 100644
index 000000000000..226af3411d55
--- /dev/null
+++ b/include/clang/AST/DeclTemplate.h
@@ -0,0 +1,859 @@
+//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the C++ template declaration subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
+#define LLVM_CLANG_AST_DECLTEMPLATE_H
+
+#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang {
+
+class TemplateParameterList;
+class TemplateDecl;
+class FunctionTemplateDecl;
+class ClassTemplateDecl;
+class ClassTemplatePartialSpecializationDecl;
+class TemplateTypeParmDecl;
+class NonTypeTemplateParmDecl;
+class TemplateTemplateParmDecl;
+
+/// TemplateParameterList - Stores a list of template parameters for a
+/// TemplateDecl and its derived classes.
+class TemplateParameterList {
+ /// The location of the 'template' keyword.
+ SourceLocation TemplateLoc;
+
+ /// The locations of the '<' and '>' angle brackets.
+ SourceLocation LAngleLoc, RAngleLoc;
+
+ /// The number of template parameters in this template
+ /// parameter list.
+ unsigned NumParams;
+
+ TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ Decl **Params, unsigned NumParams,
+ SourceLocation RAngleLoc);
+
+public:
+ static TemplateParameterList *Create(ASTContext &C,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ Decl **Params,
+ unsigned NumParams,
+ SourceLocation RAngleLoc);
+
+ /// iterator - Iterates through the template parameters in this list.
+ typedef Decl** iterator;
+
+ /// const_iterator - Iterates through the template parameters in this list.
+ typedef Decl* const* const_iterator;
+
+ iterator begin() { return reinterpret_cast<Decl **>(this + 1); }
+ const_iterator begin() const {
+ return reinterpret_cast<Decl * const *>(this + 1);
+ }
+ iterator end() { return begin() + NumParams; }
+ const_iterator end() const { return begin() + NumParams; }
+
+ unsigned size() const { return NumParams; }
+
+ const Decl* getParam(unsigned Idx) const {
+ assert(Idx < size() && "Template parameter index out-of-range");
+ return begin()[Idx];
+ }
+
+ /// \btief Returns the minimum number of arguments needed to form a
+ /// template specialization. This may be fewer than the number of
+ /// template parameters, if some of the parameters have default
+ /// arguments.
+ unsigned getMinRequiredArguments() const;
+
+ SourceLocation getTemplateLoc() const { return TemplateLoc; }
+ SourceLocation getLAngleLoc() const { return LAngleLoc; }
+ SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(TemplateLoc, RAngleLoc);
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Templates
+//===----------------------------------------------------------------------===//
+
+/// TemplateDecl - The base class of all kinds of template declarations (e.g.,
+/// class, function, etc.). The TemplateDecl class stores the list of template
+/// parameters and a reference to the templated scoped declaration: the
+/// underlying AST node.
+class TemplateDecl : public NamedDecl {
+protected:
+ // This is probably never used.
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0)
+ { }
+
+ // Construct a template decl with the given name and parameters.
+ // Used when there is not templated element (tt-params, alias?).
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params)
+ { }
+
+ // Construct a template decl with name, parameters, and templated element.
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
+ TemplateParams(Params) { }
+public:
+ ~TemplateDecl();
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the underlying, templated declaration.
+ NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast;
+ }
+ static bool classof(const TemplateDecl *D) { return true; }
+ static bool classof(const FunctionTemplateDecl *D) { return true; }
+ static bool classof(const ClassTemplateDecl *D) { return true; }
+ static bool classof(const TemplateTemplateParmDecl *D) { return true; }
+
+protected:
+ NamedDecl *TemplatedDecl;
+ TemplateParameterList* TemplateParams;
+};
+
+/// Declaration of a template function.
+class FunctionTemplateDecl : public TemplateDecl {
+protected:
+ FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+public:
+ /// Get the underling function declaration of the template.
+ FunctionDecl *getTemplatedDecl() const {
+ return static_cast<FunctionDecl*>(TemplatedDecl);
+ }
+
+ /// Create a template function node.
+ static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl);
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D)
+ { return D->getKind() == FunctionTemplate; }
+ static bool classof(const FunctionTemplateDecl *D)
+ { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Template Parameters
+//===----------------------------------------------------------------------===//
+
+/// The TemplateParmPosition class defines the position of a template parameter
+/// within a template parameter list. Because template parameter can be listed
+/// sequentially for out-of-line template members, each template parameter is
+/// given a Depth - the nesting of template parameter scopes - and a Position -
+/// the occurrence within the parameter list.
+/// This class is inheritedly privately by different kinds of template
+/// parameters and is not part of the Decl hierarchy. Just a facility.
+class TemplateParmPosition
+{
+protected:
+ // FIXME: This should probably never be called, but it's here as
+ TemplateParmPosition()
+ : Depth(0), Position(0)
+ { /* assert(0 && "Cannot create positionless template parameter"); */ }
+
+ TemplateParmPosition(unsigned D, unsigned P)
+ : Depth(D), Position(P)
+ { }
+
+ // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
+ // position? Maybe?
+ unsigned Depth;
+ unsigned Position;
+
+public:
+ /// Get the nesting depth of the template parameter.
+ unsigned getDepth() const { return Depth; }
+
+ /// Get the position of the template parameter within its parameter list.
+ unsigned getPosition() const { return Position; }
+};
+
+/// TemplateTypeParmDecl - Declaration of a template type parameter,
+/// e.g., "T" in
+/// @code
+/// template<typename T> class vector;
+/// @endcode
+class TemplateTypeParmDecl : public TypeDecl {
+ /// \brief Whether this template type parameter was declaration with
+ /// the 'typename' keyword. If false, it was declared with the
+ /// 'class' keyword.
+ bool Typename : 1;
+
+ /// \brief Whether this template type parameter inherited its
+ /// default argument.
+ bool InheritedDefault : 1;
+
+ /// \brief The location of the default argument, if any.
+ SourceLocation DefaultArgumentLoc;
+
+ /// \brief The default template argument, if any.
+ QualType DefaultArgument;
+
+ TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ bool Typename, QualType Type)
+ : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
+ InheritedDefault(false), DefaultArgument() {
+ TypeForDecl = Type.getTypePtr();
+ }
+
+public:
+ static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id, bool Typename);
+
+ /// \brief Whether this template type parameter was declared with
+ /// the 'typename' keyword. If not, it was declared with the 'class'
+ /// keyword.
+ bool wasDeclaredWithTypename() const { return Typename; }
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
+
+ /// \brief Retrieve the default argument, if any.
+ QualType getDefaultArgument() const { return DefaultArgument; }
+
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
+
+ /// \brief Determines whether the default argument was inherited
+ /// from a previous declaration of this template.
+ bool defaultArgumentWasInherited() const { return InheritedDefault; }
+
+ /// \brief Set the default argument for this template parameter, and
+ /// whether that default argument was inherited from another
+ /// declaration.
+ void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc,
+ bool Inherited) {
+ DefaultArgument = DefArg;
+ DefaultArgumentLoc = DefArgLoc;
+ InheritedDefault = Inherited;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == TemplateTypeParm;
+ }
+ static bool classof(const TemplateTypeParmDecl *D) { return true; }
+};
+
+/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
+/// e.g., "Size" in
+/// @code
+/// template<int Size> class array { };
+/// @endcode
+class NonTypeTemplateParmDecl
+ : public VarDecl, protected TemplateParmPosition {
+ /// \brief The default template argument, if any.
+ Expr *DefaultArgument;
+
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ SourceLocation TSSL = SourceLocation())
+ : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL),
+ TemplateParmPosition(D, P), DefaultArgument(0)
+ { }
+
+public:
+ static NonTypeTemplateParmDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ SourceLocation TypeSpecStartLoc = SourceLocation());
+
+ using TemplateParmPosition::getDepth;
+ using TemplateParmPosition::getPosition;
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument; }
+
+ /// \brief Retrieve the default argument, if any.
+ Expr *getDefaultArgument() const { return DefaultArgument; }
+
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const;
+
+ /// \brief Set the default argument for this template parameter.
+ void setDefaultArgument(Expr *DefArg) {
+ DefaultArgument = DefArg;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == NonTypeTemplateParm;
+ }
+ static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
+};
+
+/// TemplateTemplateParmDecl - Declares a template template parameter,
+/// e.g., "T" in
+/// @code
+/// template <template <typename> class T> class container { };
+/// @endcode
+/// A template template parameter is a TemplateDecl because it defines the
+/// name of a template and the template parameters allowable for substitution.
+class TemplateTemplateParmDecl
+ : public TemplateDecl, protected TemplateParmPosition {
+
+ /// \brief The default template argument, if any.
+ Expr *DefaultArgument;
+
+ TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
+ unsigned D, unsigned P,
+ IdentifierInfo *Id, TemplateParameterList *Params)
+ : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+ TemplateParmPosition(D, P), DefaultArgument(0)
+ { }
+
+public:
+ static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id,
+ TemplateParameterList *Params);
+
+ using TemplateParmPosition::getDepth;
+ using TemplateParmPosition::getPosition;
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument; }
+
+ /// \brief Retrieve the default argument, if any.
+ Expr *getDefaultArgument() const { return DefaultArgument; }
+
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const;
+
+ /// \brief Set the default argument for this template parameter.
+ void setDefaultArgument(Expr *DefArg) {
+ DefaultArgument = DefArg;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == TemplateTemplateParm;
+ }
+ static bool classof(const TemplateTemplateParmDecl *D) { return true; }
+};
+
+/// \brief Represents a template argument within a class template
+/// specialization.
+class TemplateArgument {
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ };
+
+ /// \brief Location of the beginning of this template argument.
+ SourceLocation StartLoc;
+
+public:
+ /// \brief The type of template argument we're storing.
+ enum ArgKind {
+ /// The template argument is a type. It's value is stored in the
+ /// TypeOrValue field.
+ Type = 0,
+ /// The template argument is a declaration
+ Declaration = 1,
+ /// The template argument is an integral value stored in an llvm::APSInt.
+ Integral = 2,
+ /// The template argument is a value- or type-dependent expression
+ /// stored in an Expr*.
+ Expression = 3
+ } Kind;
+
+ /// \brief Construct an empty, invalid template argument.
+ TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Type) { }
+
+ /// \brief Construct a template type argument.
+ TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ StartLoc = Loc;
+ }
+
+ /// \brief Construct a template argument that refers to a
+ /// declaration, which is either an external declaration or a
+ /// template declaration.
+ TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
+ // FIXME: Need to be sure we have the "canonical" declaration!
+ TypeOrValue = reinterpret_cast<uintptr_t>(D);
+ StartLoc = Loc;
+ }
+
+ /// \brief Construct an integral constant template argument.
+ TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
+ QualType Type)
+ : Kind(Integral) {
+ new (Integer.Value) llvm::APSInt(Value);
+ Integer.Type = Type.getAsOpaquePtr();
+ StartLoc = Loc;
+ }
+
+ /// \brief Construct a template argument that is an expression.
+ ///
+ /// This form of template argument only occurs in template argument
+ /// lists used for dependent types and for expression; it will not
+ /// occur in a non-dependent, canonical template argument list.
+ TemplateArgument(Expr *E);
+
+ /// \brief Copy constructor for a template argument.
+ TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
+ if (Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ }
+ else
+ TypeOrValue = Other.TypeOrValue;
+ StartLoc = Other.StartLoc;
+ }
+
+ TemplateArgument& operator=(const TemplateArgument& Other) {
+ // FIXME: Does not provide the strong guarantee for exception
+ // safety.
+ using llvm::APSInt;
+
+ if (Kind == Other.Kind && Kind == Integral) {
+ // Copy integral values.
+ *this->getAsIntegral() = *Other.getAsIntegral();
+ Integer.Type = Other.Integer.Type;
+ } else {
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+
+ Kind = Other.Kind;
+
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else
+ TypeOrValue = Other.TypeOrValue;
+ }
+ StartLoc = Other.StartLoc;
+
+ return *this;
+ }
+
+ ~TemplateArgument() {
+ using llvm::APSInt;
+
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+ }
+
+ /// \brief Return the kind of stored template argument.
+ ArgKind getKind() const { return Kind; }
+
+ /// \brief Retrieve the template argument as a type.
+ QualType getAsType() const {
+ if (Kind != Type)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(
+ reinterpret_cast<void*>(TypeOrValue));
+ }
+
+ /// \brief Retrieve the template argument as a declaration.
+ Decl *getAsDecl() const {
+ if (Kind != Declaration)
+ return 0;
+ return reinterpret_cast<Decl *>(TypeOrValue);
+ }
+
+ /// \brief Retrieve the template argument as an integral value.
+ llvm::APSInt *getAsIntegral() {
+ if (Kind != Integral)
+ return 0;
+ return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
+ }
+
+ const llvm::APSInt *getAsIntegral() const {
+ return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ }
+
+ /// \brief Retrieve the type of the integral value.
+ QualType getIntegralType() const {
+ if (Kind != Integral)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(Integer.Type);
+ }
+
+ /// \brief Retrieve the template argument as an expression.
+ Expr *getAsExpr() const {
+ if (Kind != Expression)
+ return 0;
+
+ return reinterpret_cast<Expr *>(TypeOrValue);
+ }
+
+ /// \brief Retrieve the location where the template argument starts.
+ SourceLocation getLocation() const { return StartLoc; }
+
+ /// \brief Used to insert TemplateArguments into FoldingSets.
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Kind);
+ switch (Kind) {
+ case Type:
+ getAsType().Profile(ID);
+ break;
+
+ case Declaration:
+ ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
+ break;
+
+ case Integral:
+ getAsIntegral()->Profile(ID);
+ getIntegralType().Profile(ID);
+ break;
+
+ case Expression:
+ // FIXME: We need a canonical representation of expressions.
+ ID.AddPointer(getAsExpr());
+ break;
+ }
+ }
+};
+
+/// \brief A template argument list.
+///
+/// FIXME: In the future, this class will be extended to support
+/// variadic templates and member templates, which will make some of
+/// the function names below make more sense.
+class TemplateArgumentList {
+ /// \brief The template argument list.
+ ///
+ /// The integer value will be non-zero to indicate that this
+ /// template argument list does not own the pointer.
+ llvm::PointerIntPair<TemplateArgument *, 1> Arguments;
+
+ /// \brief The number of template arguments in this template
+ /// argument list.
+ unsigned NumArguments;
+
+
+public:
+ TemplateArgumentList(ASTContext &Context,
+ TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ bool CopyArgs);
+
+ ~TemplateArgumentList();
+
+ /// \brief Retrieve the template argument at a given index.
+ const TemplateArgument &get(unsigned Idx) const {
+ assert(Idx < NumArguments && "Invalid template argument index");
+ return getFlatArgumentList()[Idx];
+ }
+
+ /// \brief Retrieve the template argument at a given index.
+ TemplateArgument &get(unsigned Idx) {
+ assert(Idx < NumArguments && "Invalid template argument index");
+ return getFlatArgumentList()[Idx];
+ }
+
+ /// \brief Retrieve the template argument at a given index.
+ TemplateArgument &operator[](unsigned Idx) { return get(Idx); }
+ const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
+
+ /// \brief Retrieve the number of template arguments in this
+ /// template argument list.
+ unsigned size() const { return NumArguments; }
+
+ /// \brief Retrieve the number of template arguments in the
+ /// flattened template argument list.
+ unsigned flat_size() const { return NumArguments; }
+
+ /// \brief Retrieve the flattened template argument list.
+ TemplateArgument *getFlatArgumentList() {
+ return Arguments.getPointer();
+ }
+ const TemplateArgument *getFlatArgumentList() const {
+ return Arguments.getPointer();
+ }
+};
+
+// \brief Describes the kind of template specialization that a
+// particular template specialization declaration represents.
+enum TemplateSpecializationKind {
+ /// This template specialization was formed from a template-id but
+ /// has not yet been declared, defined, or instantiated.
+ TSK_Undeclared = 0,
+ /// This template specialization was declared or defined by an
+ /// explicit specialization (C++ [temp.expl.spec]) or partial
+ /// specialization (C++ [temp.class.spec]).
+ TSK_ExplicitSpecialization,
+ /// This template specialization was implicitly instantiated from a
+ /// template. (C++ [temp.inst]).
+ TSK_ImplicitInstantiation,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation request (C++ [temp.explicit]).
+ TSK_ExplicitInstantiation
+};
+
+/// \brief Represents a class template specialization, which refers to
+/// a class template with a given set of template arguments.
+///
+/// Class template specializations represent both explicit
+/// specialization of class templates, as in the example below, and
+/// implicit instantiations of class templates.
+///
+/// \code
+/// template<typename T> class array;
+///
+/// template<>
+/// class array<bool> { }; // class template specialization array<bool>
+/// \endcode
+class ClassTemplateSpecializationDecl
+ : public CXXRecordDecl, public llvm::FoldingSetNode {
+ /// \brief The template that this specialization specializes
+ ClassTemplateDecl *SpecializedTemplate;
+
+ /// \brief The template arguments used to describe this specialization.
+ TemplateArgumentList TemplateArgs;
+
+ /// \brief The kind of specialization this declaration refers to.
+ /// Really a value of type TemplateSpecializationKind.
+ unsigned SpecializationKind : 2;
+
+protected:
+ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
+ DeclContext *DC, SourceLocation L,
+ ClassTemplateDecl *SpecializedTemplate,
+ TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+
+public:
+ static ClassTemplateSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
+ ClassTemplateDecl *SpecializedTemplate,
+ TemplateArgument *TemplateArgs, unsigned NumTemplateArgs,
+ ClassTemplateSpecializationDecl *PrevDecl);
+
+ /// \brief Retrieve the template that this specialization specializes.
+ ClassTemplateDecl *getSpecializedTemplate() const {
+ return SpecializedTemplate;
+ }
+
+ const TemplateArgumentList &getTemplateArgs() const {
+ return TemplateArgs;
+ }
+
+ /// \brief Determine the kind of specialization that this
+ /// declaration represents.
+ TemplateSpecializationKind getSpecializationKind() const {
+ return static_cast<TemplateSpecializationKind>(SpecializationKind);
+ }
+
+ void setSpecializationKind(TemplateSpecializationKind TSK) {
+ SpecializationKind = TSK;
+ }
+
+ /// \brief Sets the type of this specialization as it was written by
+ /// the user. This will be a class template specialization type.
+ void setTypeAsWritten(QualType T) {
+ TypeForDecl = T.getTypePtr();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size());
+ }
+
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ TemplateArgs[Arg].Profile(ID);
+ }
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ClassTemplateSpecialization ||
+ D->getKind() == ClassTemplatePartialSpecialization;
+ }
+
+ static bool classof(const ClassTemplateSpecializationDecl *) {
+ return true;
+ }
+
+ static bool classof(const ClassTemplatePartialSpecializationDecl *) {
+ return true;
+ }
+};
+
+class ClassTemplatePartialSpecializationDecl
+ : public ClassTemplateSpecializationDecl
+{
+ /// \brief The list of template parameters
+ TemplateParameterList* TemplateParams;
+
+ ClassTemplatePartialSpecializationDecl(ASTContext &Context,
+ DeclContext *DC, SourceLocation L,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs)
+ : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization,
+ DC, L, SpecializedTemplate, TemplateArgs,
+ NumTemplateArgs),
+ TemplateParams(Params) { }
+
+public:
+ static ClassTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ TemplateArgument *TemplateArgs, unsigned NumTemplateArgs,
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ // FIXME: Add Profile support!
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == ClassTemplatePartialSpecialization;
+ }
+
+ static bool classof(const ClassTemplatePartialSpecializationDecl *) {
+ return true;
+ }
+};
+
+/// Declaration of a class template.
+class ClassTemplateDecl : public TemplateDecl {
+protected:
+ /// \brief Data that is common to all of the declarations of a given
+ /// class template.
+ struct Common {
+ /// \brief The class template specializations for this class
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
+
+ /// \brief The class template partial specializations for this class
+ /// template.
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
+ PartialSpecializations;
+
+ /// \brief The injected-class-name type for this class template.
+ QualType InjectedClassNameType;
+ };
+
+ /// \brief Previous declaration of this class template.
+ ClassTemplateDecl *PreviousDeclaration;
+
+ /// \brief Pointer to the data that is common to all of the
+ /// declarations of this class template.
+ ///
+ /// The first declaration of a class template (e.g., the declaration
+ /// with no "previous declaration") owns this pointer.
+ Common *CommonPtr;
+
+ ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl, Common *CommonPtr)
+ : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl),
+ PreviousDeclaration(PrevDecl), CommonPtr(CommonPtr) { }
+
+ ~ClassTemplateDecl();
+
+public:
+ /// Get the underlying class declarations of the template.
+ CXXRecordDecl *getTemplatedDecl() const {
+ return static_cast<CXXRecordDecl *>(TemplatedDecl);
+ }
+
+ /// \brief Retrieve the previous declaration of this template.
+ ClassTemplateDecl *getPreviousDeclaration() const {
+ return PreviousDeclaration;
+ }
+
+ /// Create a class template node.
+ static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl);
+
+ /// \brief Retrieve the set of specializations of this class template.
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
+ return CommonPtr->Specializations;
+ }
+
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ getPartialSpecializations() {
+ return CommonPtr->PartialSpecializations;
+ }
+
+ /// \brief Retrieve the type of the injected-class-name for this
+ /// class template.
+ ///
+ /// The injected-class-name for a class template \c X is \c
+ /// X<template-args>, where \c template-args is formed from the
+ /// template arguments that correspond to the template parameters of
+ /// \c X. For example:
+ ///
+ /// \code
+ /// template<typename T, int N>
+ /// struct array {
+ /// typedef array this_type; // "array" is equivalent to "array<T, N>"
+ /// };
+ /// \endcode
+ QualType getInjectedClassNameType(ASTContext &Context);
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D)
+ { return D->getKind() == ClassTemplate; }
+ static bool classof(const ClassTemplateDecl *D)
+ { return true; }
+
+ virtual void Destroy(ASTContext& C);
+};
+
+} /* end of namespace clang */
+
+#endif
diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h
new file mode 100644
index 000000000000..9423c319c3e3
--- /dev/null
+++ b/include/clang/AST/DeclVisitor.h
@@ -0,0 +1,54 @@
+//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DeclVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLVISITOR_H
+#define LLVM_CLANG_AST_DECLVISITOR_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D))
+
+/// \brief A simple visitor class that helps create declaration visitors.
+template<typename ImplClass, typename RetTy=void>
+class DeclVisitor {
+public:
+ RetTy Visit(Decl *D) {
+ switch (D->getKind()) {
+ default: assert(false && "Decl that isn't part of DeclNodes.def!");
+#define DECL(Derived, Base) \
+ case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl);
+#define ABSTRACT_DECL(Derived, Base)
+#include "clang/AST/DeclNodes.def"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit
+ // method, fall back to the parent.
+#define DECL(Derived, Base) \
+ RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); }
+#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base)
+#include "clang/AST/DeclNodes.def"
+
+ RetTy VisitDecl(Decl *D) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_DECLVISITOR_H
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
new file mode 100644
index 000000000000..db140999b045
--- /dev/null
+++ b/include/clang/AST/DeclarationName.h
@@ -0,0 +1,357 @@
+//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the DeclarationName and DeclarationNameTable classes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
+#define LLVM_CLANG_AST_DECLARATIONNAME_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/Type.h"
+
+namespace llvm {
+ template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+ class CXXSpecialName;
+ class CXXOperatorIdName;
+ class DeclarationNameExtra;
+ class IdentifierInfo;
+ class MultiKeywordSelector;
+ class UsingDirectiveDecl;
+
+/// DeclarationName - The name of a declaration. In the common case,
+/// this just stores an IdentifierInfo pointer to a normal
+/// name. However, it also provides encodings for Objective-C
+/// selectors (optimizing zero- and one-argument selectors, which make
+/// up 78% percent of all selectors in Cocoa.h) and special C++ names
+/// for constructors, destructors, and conversion functions.
+class DeclarationName {
+public:
+ /// NameKind - The kind of name this object contains.
+ enum NameKind {
+ Identifier,
+ ObjCZeroArgSelector,
+ ObjCOneArgSelector,
+ ObjCMultiArgSelector,
+ CXXConstructorName,
+ CXXDestructorName,
+ CXXConversionFunctionName,
+ CXXOperatorName,
+ CXXUsingDirective
+ };
+
+private:
+ /// StoredNameKind - The kind of name that is actually stored in the
+ /// upper bits of the Ptr field. This is only used internally.
+ enum StoredNameKind {
+ StoredIdentifier = 0,
+ StoredObjCZeroArgSelector,
+ StoredObjCOneArgSelector,
+ StoredDeclarationNameExtra,
+ PtrMask = 0x03
+ };
+
+ /// Ptr - The lowest two bits are used to express what kind of name
+ /// we're actually storing, using the values of NameKind. Depending
+ /// on the kind of name this is, the upper bits of Ptr may have one
+ /// of several different meanings:
+ ///
+ /// StoredIdentifier - The name is a normal identifier, and Ptr is
+ /// a normal IdentifierInfo pointer.
+ ///
+ /// StoredObjCZeroArgSelector - The name is an Objective-C
+ /// selector with zero arguments, and Ptr is an IdentifierInfo
+ /// pointer pointing to the selector name.
+ ///
+ /// StoredObjCOneArgSelector - The name is an Objective-C selector
+ /// with one argument, and Ptr is an IdentifierInfo pointer
+ /// pointing to the selector name.
+ ///
+ /// StoredDeclarationNameExtra - Ptr is actually a pointer to a
+ /// DeclarationNameExtra structure, whose first value will tell us
+ /// whether this is an Objective-C selector, C++ operator-id name,
+ /// or special C++ name.
+ uintptr_t Ptr;
+
+ /// getStoredNameKind - Return the kind of object that is stored in
+ /// Ptr.
+ StoredNameKind getStoredNameKind() const {
+ return static_cast<StoredNameKind>(Ptr & PtrMask);
+ }
+
+ /// getExtra - Get the "extra" information associated with this
+ /// multi-argument selector or C++ special name.
+ DeclarationNameExtra *getExtra() const {
+ assert(getStoredNameKind() == StoredDeclarationNameExtra &&
+ "Declaration name does not store an Extra structure");
+ return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
+ }
+
+ /// getAsCXXSpecialName - If the stored pointer is actually a
+ /// CXXSpecialName, returns a pointer to it. Otherwise, returns
+ /// a NULL pointer.
+ CXXSpecialName *getAsCXXSpecialName() const {
+ if (getNameKind() >= CXXConstructorName &&
+ getNameKind() <= CXXConversionFunctionName)
+ return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
+ return 0;
+ }
+
+ /// getAsCXXOperatorIdName
+ CXXOperatorIdName *getAsCXXOperatorIdName() const {
+ if (getNameKind() == CXXOperatorName)
+ return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
+ return 0;
+ }
+
+ // Construct a declaration name from the name of a C++ constructor,
+ // destructor, or conversion function.
+ DeclarationName(CXXSpecialName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ // Construct a declaration name from the name of a C++ overloaded
+ // operator.
+ DeclarationName(CXXOperatorIdName *Name)
+ : Ptr(reinterpret_cast<uintptr_t>(Name)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
+ Ptr |= StoredDeclarationNameExtra;
+ }
+
+ /// Construct a declaration name from a raw pointer.
+ DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
+
+ friend class DeclarationNameTable;
+ friend class NamedDecl;
+
+ /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
+ /// for this name as a void pointer.
+ void *getFETokenInfoAsVoid() const;
+
+public:
+ /// DeclarationName - Used to create an empty selector.
+ DeclarationName() : Ptr(0) { }
+
+ // Construct a declaration name from an IdentifierInfo *.
+ DeclarationName(const IdentifierInfo *II)
+ : Ptr(reinterpret_cast<uintptr_t>(II)) {
+ assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
+ }
+
+ // Construct a declaration name from an Objective-C selector.
+ DeclarationName(Selector Sel);
+
+ /// getUsingDirectiveName - Return name for all using-directives.
+ static DeclarationName getUsingDirectiveName();
+
+ // operator bool() - Evaluates true when this declaration name is
+ // non-empty.
+ operator bool() const {
+ return ((Ptr & PtrMask) != 0) ||
+ (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
+ }
+
+ /// Predicate functions for querying what type of name this is.
+ bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
+ bool isObjCZeroArgSelector() const {
+ return getStoredNameKind() == StoredObjCZeroArgSelector;
+ }
+ bool isObjCOneArgSelector() const {
+ return getStoredNameKind() == StoredObjCOneArgSelector;
+ }
+
+ /// getNameKind - Determine what kind of name this is.
+ NameKind getNameKind() const;
+
+
+ /// getName - Retrieve the human-readable string for this name.
+ std::string getAsString() const;
+
+ /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
+ /// this declaration name, or NULL if this declaration name isn't a
+ /// simple identifier.
+ IdentifierInfo *getAsIdentifierInfo() const {
+ if (isIdentifier())
+ return reinterpret_cast<IdentifierInfo *>(Ptr);
+ return 0;
+ }
+
+ /// getAsOpaqueInteger - Get the representation of this declaration
+ /// name as an opaque integer.
+ uintptr_t getAsOpaqueInteger() const { return Ptr; }
+
+ /// getAsOpaquePtr - Get the representation of this declaration name as
+ /// an opaque pointer.
+ void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
+
+ static DeclarationName getFromOpaqueInteger(uintptr_t P) {
+ DeclarationName N;
+ N.Ptr = P;
+ return N;
+ }
+
+ /// getCXXNameType - If this name is one of the C++ names (of a
+ /// constructor, destructor, or conversion function), return the
+ /// type associated with that name.
+ QualType getCXXNameType() const;
+
+ /// getCXXOverloadedOperator - If this name is the name of an
+ /// overloadable operator in C++ (e.g., @c operator+), retrieve the
+ /// kind of overloaded operator.
+ OverloadedOperatorKind getCXXOverloadedOperator() const;
+
+ /// getObjCSelector - Get the Objective-C selector stored in this
+ /// declaration name.
+ Selector getObjCSelector() const;
+
+ /// getFETokenInfo/setFETokenInfo - The language front-end is
+ /// allowed to associate arbitrary metadata with some kinds of
+ /// declaration names, including normal identifiers and C++
+ /// constructors, destructors, and conversion functions.
+ template<typename T>
+ T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
+
+ void setFETokenInfo(void *T);
+
+ /// operator== - Determine whether the specified names are identical..
+ friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
+ return LHS.Ptr == RHS.Ptr;
+ }
+
+ /// operator!= - Determine whether the specified names are different.
+ friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
+ return LHS.Ptr != RHS.Ptr;
+ }
+
+ static DeclarationName getEmptyMarker() {
+ return DeclarationName(uintptr_t(-1));
+ }
+
+ static DeclarationName getTombstoneMarker() {
+ return DeclarationName(uintptr_t(-2));
+ }
+};
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+bool operator<(DeclarationName LHS, DeclarationName RHS);
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
+ return RHS < LHS;
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
+ return !(RHS < LHS);
+}
+
+/// Ordering on two declaration names. If both names are identifiers,
+/// this provides a lexicographical ordering.
+inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
+ return !(LHS < RHS);
+}
+
+/// DeclarationNameTable - Used to store and retrieve DeclarationName
+/// instances for the various kinds of declaration names, e.g., normal
+/// identifiers, C++ constructor names, etc. This class contains
+/// uniqued versions of each of the C++ special names, which can be
+/// retrieved using its member functions (e.g.,
+/// getCXXConstructorName).
+class DeclarationNameTable {
+ void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
+ CXXOperatorIdName *CXXOperatorNames; // Operator names
+
+ DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
+ DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
+
+public:
+ DeclarationNameTable();
+ ~DeclarationNameTable();
+
+ /// getIdentifier - Create a declaration name that is a simple
+ /// identifier.
+ DeclarationName getIdentifier(IdentifierInfo *ID) {
+ return DeclarationName(ID);
+ }
+
+ /// getCXXConstructorName - Returns the name of a C++ constructor
+ /// for the given Type.
+ DeclarationName getCXXConstructorName(QualType Ty) {
+ return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty);
+ }
+
+ /// getCXXDestructorName - Returns the name of a C++ destructor
+ /// for the given Type.
+ DeclarationName getCXXDestructorName(QualType Ty) {
+ return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty);
+ }
+
+ /// getCXXConversionFunctionName - Returns the name of a C++
+ /// conversion function for the given Type.
+ DeclarationName getCXXConversionFunctionName(QualType Ty) {
+ return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
+ }
+
+ /// getCXXSpecialName - Returns a declaration name for special kind
+ /// of C++ name, e.g., for a constructor, destructor, or conversion
+ /// function.
+ DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
+ QualType Ty);
+
+ /// getCXXOperatorName - Get the name of the overloadable C++
+ /// operator corresponding to Op.
+ DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
+};
+
+/// Insertion operator for diagnostics. This allows sending DeclarationName's
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ DeclarationName N) {
+ DB.AddTaggedVal(N.getAsOpaqueInteger(),
+ Diagnostic::ak_declarationname);
+ return DB;
+}
+
+
+} // end namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that DeclarationNames can be used as keys
+/// in DenseMap and DenseSets.
+template<>
+struct DenseMapInfo<clang::DeclarationName> {
+ static inline clang::DeclarationName getEmptyKey() {
+ return clang::DeclarationName::getEmptyMarker();
+ }
+
+ static inline clang::DeclarationName getTombstoneKey() {
+ return clang::DeclarationName::getTombstoneMarker();
+ }
+
+ static unsigned getHashValue(clang::DeclarationName);
+
+ static inline bool
+ isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
+ return LHS == RHS;
+ }
+
+ static inline bool isPod() { return true; }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
new file mode 100644
index 000000000000..98de5f9d382e
--- /dev/null
+++ b/include/clang/AST/Expr.h
@@ -0,0 +1,2500 @@
+//===--- Expr.h - Classes for representing expressions ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Expr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPR_H
+#define LLVM_CLANG_AST_EXPR_H
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+namespace clang {
+ class ASTContext;
+ class APValue;
+ class Decl;
+ class IdentifierInfo;
+ class ParmVarDecl;
+ class NamedDecl;
+ class ValueDecl;
+ class BlockDecl;
+ class CXXOperatorCallExpr;
+ class CXXMemberCallExpr;
+
+/// Expr - This represents one expression. Note that Expr's are subclasses of
+/// Stmt. This allows an expression to be transparently used any place a Stmt
+/// is required.
+///
+class Expr : public Stmt {
+ QualType TR;
+
+protected:
+ /// TypeDependent - Whether this expression is type-dependent
+ /// (C++ [temp.dep.expr]).
+ bool TypeDependent : 1;
+
+ /// ValueDependent - Whether this expression is value-dependent
+ /// (C++ [temp.dep.constexpr]).
+ bool ValueDependent : 1;
+
+ // FIXME: Eventually, this constructor should go away and we should
+ // require every subclass to provide type/value-dependence
+ // information.
+ Expr(StmtClass SC, QualType T)
+ : Stmt(SC), TypeDependent(false), ValueDependent(false) {
+ setType(T);
+ }
+
+ Expr(StmtClass SC, QualType T, bool TD, bool VD)
+ : Stmt(SC), TypeDependent(TD), ValueDependent(VD) {
+ setType(T);
+ }
+
+ /// \brief Construct an empty expression.
+ explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
+
+public:
+ QualType getType() const { return TR; }
+ void setType(QualType t) {
+ // In C++, the type of an expression is always adjusted so that it
+ // will not have reference type an expression will never have
+ // reference type (C++ [expr]p6). Use
+ // QualType::getNonReferenceType() to retrieve the non-reference
+ // type. Additionally, inspect Expr::isLvalue to determine whether
+ // an expression that is adjusted in this manner should be
+ // considered an lvalue.
+ assert((TR.isNull() || !TR->isReferenceType()) &&
+ "Expressions can't have reference type");
+
+ TR = t;
+ }
+
+ /// isValueDependent - Determines whether this expression is
+ /// value-dependent (C++ [temp.dep.constexpr]). For example, the
+ /// array bound of "Chars" in the following example is
+ /// value-dependent.
+ /// @code
+ /// template<int Size, char (&Chars)[Size]> struct meta_string;
+ /// @endcode
+ bool isValueDependent() const { return ValueDependent; }
+
+ /// \brief Set whether this expression is value-dependent or not.
+ void setValueDependent(bool VD) { ValueDependent = VD; }
+
+ /// isTypeDependent - Determines whether this expression is
+ /// type-dependent (C++ [temp.dep.expr]), which means that its type
+ /// could change from one template instantiation to the next. For
+ /// example, the expressions "x" and "x + y" are type-dependent in
+ /// the following code, but "y" is not type-dependent:
+ /// @code
+ /// template<typename T>
+ /// void add(T x, int y) {
+ /// x + y;
+ /// }
+ /// @endcode
+ bool isTypeDependent() const { return TypeDependent; }
+
+ /// \brief Set whether this expression is type-dependent or not.
+ void setTypeDependent(bool TD) { TypeDependent = TD; }
+
+ /// SourceLocation tokens are not useful in isolation - they are low level
+ /// value objects created/interpreted by SourceManager. We assume AST
+ /// clients will have a pointer to the respective SourceManager.
+ virtual SourceRange getSourceRange() const = 0;
+
+ /// getExprLoc - Return the preferred location for the arrow when diagnosing
+ /// a problem with a generic expression.
+ virtual SourceLocation getExprLoc() const { return getLocStart(); }
+
+ /// isUnusedResultAWarning - Return true if this immediate expression should
+ /// be warned about if the result is unused. If so, fill in Loc and Ranges
+ /// with location to warn on and the source range[s] to report with the
+ /// warning.
+ bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
+ SourceRange &R2) const;
+
+ /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
+ /// incomplete type other than void. Nonarray expressions that can be lvalues:
+ /// - name, where name must be a variable
+ /// - e[i]
+ /// - (e), where e must be an lvalue
+ /// - e.name, where e must be an lvalue
+ /// - e->name
+ /// - *e, the type of e cannot be a function type
+ /// - string-constant
+ /// - reference type [C++ [expr]]
+ /// - b ? x : y, where x and y are lvalues of suitable types [C++]
+ ///
+ enum isLvalueResult {
+ LV_Valid,
+ LV_NotObjectType,
+ LV_IncompleteVoidType,
+ LV_DuplicateVectorComponents,
+ LV_InvalidExpression,
+ LV_MemberFunction
+ };
+ isLvalueResult isLvalue(ASTContext &Ctx) const;
+
+ // Same as above, but excluding checks for non-object and void types in C
+ isLvalueResult isLvalueInternal(ASTContext &Ctx) const;
+
+ /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
+ /// does not have an incomplete type, does not have a const-qualified type,
+ /// and if it is a structure or union, does not have any member (including,
+ /// recursively, any member or element of all contained aggregates or unions)
+ /// with a const-qualified type.
+ ///
+ /// \param Loc [in] [out] - A source location which *may* be filled
+ /// in with the location of the expression making this a
+ /// non-modifiable lvalue, if specified.
+ enum isModifiableLvalueResult {
+ MLV_Valid,
+ MLV_NotObjectType,
+ MLV_IncompleteVoidType,
+ MLV_DuplicateVectorComponents,
+ MLV_InvalidExpression,
+ MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
+ MLV_IncompleteType,
+ MLV_ConstQualified,
+ MLV_ArrayType,
+ MLV_NotBlockQualified,
+ MLV_ReadonlyProperty,
+ MLV_NoSetterProperty,
+ MLV_MemberFunction
+ };
+ isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
+ SourceLocation *Loc = 0) const;
+
+ /// \brief If this expression refers to a bit-field, retrieve the
+ /// declaration of that bit-field.
+ FieldDecl *getBitField();
+
+ const FieldDecl *getBitField() const {
+ return const_cast<Expr*>(this)->getBitField();
+ }
+
+ /// isIntegerConstantExpr - Return true if this expression is a valid integer
+ /// constant expression, and, if so, return its value in Result. If not a
+ /// valid i-c-e, return false and fill in Loc (if specified) with the location
+ /// of the invalid expression.
+ bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
+ SourceLocation *Loc = 0,
+ bool isEvaluated = true) const;
+ bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const {
+ llvm::APSInt X;
+ return isIntegerConstantExpr(X, Ctx, Loc);
+ }
+ /// isConstantInitializer - Returns true if this expression is a constant
+ /// initializer, which can be emitted at compile-time.
+ bool isConstantInitializer(ASTContext &Ctx) const;
+
+ /// EvalResult is a struct with detailed info about an evaluated expression.
+ struct EvalResult {
+ /// Val - This is the value the expression can be folded to.
+ APValue Val;
+
+ /// HasSideEffects - Whether the evaluated expression has side effects.
+ /// For example, (f() && 0) can be folded, but it still has side effects.
+ bool HasSideEffects;
+
+ /// Diag - If the expression is unfoldable, then Diag contains a note
+ /// diagnostic indicating why it's not foldable. DiagLoc indicates a caret
+ /// position for the error, and DiagExpr is the expression that caused
+ /// the error.
+ /// If the expression is foldable, but not an integer constant expression,
+ /// Diag contains a note diagnostic that describes why it isn't an integer
+ /// constant expression. If the expression *is* an integer constant
+ /// expression, then Diag will be zero.
+ unsigned Diag;
+ const Expr *DiagExpr;
+ SourceLocation DiagLoc;
+
+ EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {}
+ };
+
+ /// Evaluate - Return true if this is a constant which we can fold using
+ /// any crazy technique (that has nothing to do with language standards) that
+ /// we want to. If this function returns true, it returns the folded constant
+ /// in Result.
+ bool Evaluate(EvalResult &Result, ASTContext &Ctx) const;
+
+ /// isEvaluatable - Call Evaluate to see if this expression can be constant
+ /// folded, but discard the result.
+ bool isEvaluatable(ASTContext &Ctx) const;
+
+ /// EvaluateAsInt - Call Evaluate and return the folded integer. This
+ /// must be called on an expression that constant folds to an integer.
+ llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const;
+
+ /// EvaluateAsLValue - Evaluate an expression to see if it's a valid LValue.
+ bool EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const;
+
+ /// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an
+ /// integer constant expression with the value zero, or if this is one that is
+ /// cast to void*.
+ bool isNullPointerConstant(ASTContext &Ctx) const;
+
+ /// hasGlobalStorage - Return true if this expression has static storage
+ /// duration. This means that the address of this expression is a link-time
+ /// constant.
+ bool hasGlobalStorage() const;
+
+ /// isOBJCGCCandidate - Return true if this expression may be used in a read/
+ /// write barrier.
+ bool isOBJCGCCandidate(ASTContext &Ctx) const;
+
+ /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return
+ /// its subexpression. If that subexpression is also a ParenExpr,
+ /// then this method recursively returns its subexpression, and so forth.
+ /// Otherwise, the method returns the current Expr.
+ Expr* IgnoreParens();
+
+ /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
+ /// or CastExprs, returning their operand.
+ Expr *IgnoreParenCasts();
+
+ /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
+ /// value (including ptr->int casts of the same size). Strip off any
+ /// ParenExpr or CastExprs, returning their operand.
+ Expr *IgnoreParenNoopCasts(ASTContext &Ctx);
+
+ const Expr* IgnoreParens() const {
+ return const_cast<Expr*>(this)->IgnoreParens();
+ }
+ const Expr *IgnoreParenCasts() const {
+ return const_cast<Expr*>(this)->IgnoreParenCasts();
+ }
+ const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const {
+ return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
+ }
+
+ static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs);
+ static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstExprConstant &&
+ T->getStmtClass() <= lastExprConstant;
+ }
+ static bool classof(const Expr *) { return true; }
+};
+
+
+//===----------------------------------------------------------------------===//
+// Primary Expressions.
+//===----------------------------------------------------------------------===//
+
+/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
+/// enum, etc.
+class DeclRefExpr : public Expr {
+ NamedDecl *D;
+ SourceLocation Loc;
+
+protected:
+ // FIXME: Eventually, this constructor will go away and all subclasses
+ // will have to provide the type- and value-dependent flags.
+ DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
+ Expr(SC, t), D(d), Loc(l) {}
+
+ DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD,
+ bool VD) :
+ Expr(SC, t, TD, VD), D(d), Loc(l) {}
+
+public:
+ // FIXME: Eventually, this constructor will go away and all clients
+ // will have to provide the type- and value-dependent flags.
+ DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
+ Expr(DeclRefExprClass, t), D(d), Loc(l) {}
+
+ DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
+ Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
+
+ /// \brief Construct an empty declaration reference expression.
+ explicit DeclRefExpr(EmptyShell Empty)
+ : Expr(DeclRefExprClass, Empty) { }
+
+ NamedDecl *getDecl() { return D; }
+ const NamedDecl *getDecl() const { return D; }
+ void setDecl(NamedDecl *NewD) { D = NewD; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclRefExprClass ||
+ T->getStmtClass() == CXXConditionDeclExprClass ||
+ T->getStmtClass() == QualifiedDeclRefExprClass;
+ }
+ static bool classof(const DeclRefExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
+class PredefinedExpr : public Expr {
+public:
+ enum IdentType {
+ Func,
+ Function,
+ PrettyFunction
+ };
+
+private:
+ SourceLocation Loc;
+ IdentType Type;
+public:
+ PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
+ : Expr(PredefinedExprClass, type), Loc(l), Type(IT) {}
+
+ /// \brief Construct an empty predefined expression.
+ explicit PredefinedExpr(EmptyShell Empty)
+ : Expr(PredefinedExprClass, Empty) { }
+
+ PredefinedExpr* Clone(ASTContext &C) const;
+
+ IdentType getIdentType() const { return Type; }
+ void setIdentType(IdentType IT) { Type = IT; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ // FIXME: The logic for computing the value of a predefined expr should go
+ // into a method here that takes the inner-most code decl (a block, function
+ // or objc method) that the expr lives in. This would allow sema and codegen
+ // to be consistent for things like sizeof(__func__) etc.
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PredefinedExprClass;
+ }
+ static bool classof(const PredefinedExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+class IntegerLiteral : public Expr {
+ llvm::APInt Value;
+ SourceLocation Loc;
+public:
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // or UnsignedLongLongTy
+ IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l)
+ : Expr(IntegerLiteralClass, type), Value(V), Loc(l) {
+ assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
+ }
+
+ /// \brief Construct an empty integer literal.
+ explicit IntegerLiteral(EmptyShell Empty)
+ : Expr(IntegerLiteralClass, Empty) { }
+
+ IntegerLiteral* Clone(ASTContext &C) const;
+
+ const llvm::APInt &getValue() const { return Value; }
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ /// \brief Retrieve the location of the literal.
+ SourceLocation getLocation() const { return Loc; }
+
+ void setValue(const llvm::APInt &Val) { Value = Val; }
+ void setLocation(SourceLocation Location) { Loc = Location; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IntegerLiteralClass;
+ }
+ static bool classof(const IntegerLiteral *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+class CharacterLiteral : public Expr {
+ unsigned Value;
+ SourceLocation Loc;
+ bool IsWide;
+public:
+ // type should be IntTy
+ CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
+ : Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) {
+ }
+
+ /// \brief Construct an empty character literal.
+ CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
+
+ CharacterLiteral* Clone(ASTContext &C) const;
+
+ SourceLocation getLoc() const { return Loc; }
+ bool isWide() const { return IsWide; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ unsigned getValue() const { return Value; }
+
+ void setLocation(SourceLocation Location) { Loc = Location; }
+ void setWide(bool W) { IsWide = W; }
+ void setValue(unsigned Val) { Value = Val; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CharacterLiteralClass;
+ }
+ static bool classof(const CharacterLiteral *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+class FloatingLiteral : public Expr {
+ llvm::APFloat Value;
+ bool IsExact : 1;
+ SourceLocation Loc;
+public:
+ FloatingLiteral(const llvm::APFloat &V, bool* isexact,
+ QualType Type, SourceLocation L)
+ : Expr(FloatingLiteralClass, Type), Value(V), IsExact(*isexact), Loc(L) {}
+
+ /// \brief Construct an empty floating-point literal.
+ explicit FloatingLiteral(EmptyShell Empty)
+ : Expr(FloatingLiteralClass, Empty), Value(0.0) { }
+
+ FloatingLiteral* Clone(ASTContext &C) const;
+
+ const llvm::APFloat &getValue() const { return Value; }
+ void setValue(const llvm::APFloat &Val) { Value = Val; }
+
+ bool isExact() const { return IsExact; }
+ void setExact(bool E) { IsExact = E; }
+
+ /// getValueAsApproximateDouble - This returns the value as an inaccurate
+ /// double. Note that this may cause loss of precision, but is useful for
+ /// debugging dumps, etc.
+ double getValueAsApproximateDouble() const;
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ // FIXME: The logic for computing the value of a predefined expr should go
+ // into a method here that takes the inner-most code decl (a block, function
+ // or objc method) that the expr lives in. This would allow sema and codegen
+ // to be consistent for things like sizeof(__func__) etc.
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == FloatingLiteralClass;
+ }
+ static bool classof(const FloatingLiteral *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ImaginaryLiteral - We support imaginary integer and floating point literals,
+/// like "1.0i". We represent these as a wrapper around FloatingLiteral and
+/// IntegerLiteral classes. Instances of this class always have a Complex type
+/// whose element type matches the subexpression.
+///
+class ImaginaryLiteral : public Expr {
+ Stmt *Val;
+public:
+ ImaginaryLiteral(Expr *val, QualType Ty)
+ : Expr(ImaginaryLiteralClass, Ty), Val(val) {}
+
+ /// \brief Build an empty imaginary literal.
+ explicit ImaginaryLiteral(EmptyShell Empty)
+ : Expr(ImaginaryLiteralClass, Empty) { }
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ ImaginaryLiteral* Clone(ASTContext &C) const;
+
+ virtual SourceRange getSourceRange() const { return Val->getSourceRange(); }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImaginaryLiteralClass;
+ }
+ static bool classof(const ImaginaryLiteral *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// StringLiteral - This represents a string literal expression, e.g. "foo"
+/// or L"bar" (wide strings). The actual string is returned by getStrData()
+/// is NOT null-terminated, and the length of the string is determined by
+/// calling getByteLength(). The C type for a string is always a
+/// ConstantArrayType. In C++, the char type is const qualified, in C it is
+/// not.
+///
+/// Note that strings in C can be formed by concatenation of multiple string
+/// literal pptokens in translation phase #6. This keeps track of the locations
+/// of each of these pieces.
+///
+/// Strings in C can also be truncated and extended by assigning into arrays,
+/// e.g. with constructs like:
+/// char X[2] = "foobar";
+/// In this case, getByteLength() will return 6, but the string literal will
+/// have type "char[2]".
+class StringLiteral : public Expr {
+ const char *StrData;
+ unsigned ByteLength;
+ bool IsWide;
+ unsigned NumConcatenated;
+ SourceLocation TokLocs[1];
+
+ StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty) {}
+public:
+ /// This is the "fully general" constructor that allows representation of
+ /// strings formed from multiple concatenated tokens.
+ static StringLiteral *Create(ASTContext &C, const char *StrData,
+ unsigned ByteLength, bool Wide, QualType Ty,
+ const SourceLocation *Loc, unsigned NumStrs);
+
+ /// Simple constructor for string literals made from one token.
+ static StringLiteral *Create(ASTContext &C, const char *StrData,
+ unsigned ByteLength,
+ bool Wide, QualType Ty, SourceLocation Loc) {
+ return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1);
+ }
+
+ /// \brief Construct an empty string literal.
+ static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs);
+
+ StringLiteral* Clone(ASTContext &C) const;
+ void Destroy(ASTContext &C);
+
+ const char *getStrData() const { return StrData; }
+ unsigned getByteLength() const { return ByteLength; }
+
+ /// \brief Sets the string data to the given string data.
+ void setStrData(ASTContext &C, const char *Str, unsigned Len);
+
+ bool isWide() const { return IsWide; }
+ void setWide(bool W) { IsWide = W; }
+
+ bool containsNonAsciiOrNull() const {
+ for (unsigned i = 0; i < getByteLength(); ++i)
+ if (!isascii(getStrData()[i]) || !getStrData()[i])
+ return true;
+ return false;
+ }
+ /// getNumConcatenated - Get the number of string literal tokens that were
+ /// concatenated in translation phase #6 to form this string literal.
+ unsigned getNumConcatenated() const { return NumConcatenated; }
+
+ SourceLocation getStrTokenLoc(unsigned TokNum) const {
+ assert(TokNum < NumConcatenated && "Invalid tok number");
+ return TokLocs[TokNum];
+ }
+ void setStrTokenLoc(unsigned TokNum, SourceLocation L) {
+ assert(TokNum < NumConcatenated && "Invalid tok number");
+ TokLocs[TokNum] = L;
+ }
+
+ typedef const SourceLocation *tokloc_iterator;
+ tokloc_iterator tokloc_begin() const { return TokLocs; }
+ tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == StringLiteralClass;
+ }
+ static bool classof(const StringLiteral *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
+/// AST node is only formed if full location information is requested.
+class ParenExpr : public Expr {
+ SourceLocation L, R;
+ Stmt *Val;
+public:
+ ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
+ : Expr(ParenExprClass, val->getType(),
+ val->isTypeDependent(), val->isValueDependent()),
+ L(l), R(r), Val(val) {}
+
+ /// \brief Construct an empty parenthesized expression.
+ explicit ParenExpr(EmptyShell Empty)
+ : Expr(ParenExprClass, Empty) { }
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(L, R); }
+
+ /// \brief Get the location of the left parentheses '('.
+ SourceLocation getLParen() const { return L; }
+ void setLParen(SourceLocation Loc) { L = Loc; }
+
+ /// \brief Get the location of the right parentheses ')'.
+ SourceLocation getRParen() const { return R; }
+ void setRParen(SourceLocation Loc) { R = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ParenExprClass;
+ }
+ static bool classof(const ParenExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// UnaryOperator - This represents the unary-expression's (except sizeof and
+/// alignof), the postinc/postdec operators from postfix-expression, and various
+/// extensions.
+///
+/// Notes on various nodes:
+///
+/// Real/Imag - These return the real/imag part of a complex operand. If
+/// applied to a non-complex value, the former returns its operand and the
+/// later returns zero in the type of the operand.
+///
+/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose
+/// subexpression is a compound literal with the various MemberExpr and
+/// ArraySubscriptExpr's applied to it.
+///
+class UnaryOperator : public Expr {
+public:
+ // Note that additions to this should also update the StmtVisitor class.
+ enum Opcode {
+ PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators
+ PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators.
+ AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators.
+ Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators.
+ Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
+ Real, Imag, // "__real expr"/"__imag expr" Extension.
+ Extension, // __extension__ marker.
+ OffsetOf // __builtin_offsetof
+ };
+private:
+ Stmt *Val;
+ Opcode Opc;
+ SourceLocation Loc;
+public:
+
+ UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
+ : Expr(UnaryOperatorClass, type,
+ input->isTypeDependent() && opc != OffsetOf,
+ input->isValueDependent()),
+ Val(input), Opc(opc), Loc(l) {}
+
+ /// \brief Build an empty unary operator.
+ explicit UnaryOperator(EmptyShell Empty)
+ : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { }
+
+ Opcode getOpcode() const { return Opc; }
+ void setOpcode(Opcode O) { Opc = O; }
+
+ Expr *getSubExpr() const { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ /// getOperatorLoc - Return the location of the operator.
+ SourceLocation getOperatorLoc() const { return Loc; }
+ void setOperatorLoc(SourceLocation L) { Loc = L; }
+
+ /// isPostfix - Return true if this is a postfix operation, like x++.
+ static bool isPostfix(Opcode Op) {
+ return Op == PostInc || Op == PostDec;
+ }
+
+ /// isPostfix - Return true if this is a prefix operation, like --x.
+ static bool isPrefix(Opcode Op) {
+ return Op == PreInc || Op == PreDec;
+ }
+
+ bool isPrefix() const { return isPrefix(Opc); }
+ bool isPostfix() const { return isPostfix(Opc); }
+ bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; }
+ bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
+ bool isOffsetOfOp() const { return Opc == OffsetOf; }
+ static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
+
+ /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+ /// corresponds to, e.g. "sizeof" or "[pre]++"
+ static const char *getOpcodeStr(Opcode Op);
+
+ /// \brief Retrieve the unary opcode that corresponds to the given
+ /// overloaded operator.
+ static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix);
+
+ /// \brief Retrieve the overloaded operator kind that corresponds to
+ /// the given unary opcode.
+ static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
+
+ virtual SourceRange getSourceRange() const {
+ if (isPostfix())
+ return SourceRange(Val->getLocStart(), Loc);
+ else
+ return SourceRange(Loc, Val->getLocEnd());
+ }
+ virtual SourceLocation getExprLoc() const { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryOperatorClass;
+ }
+ static bool classof(const UnaryOperator *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of
+/// types and expressions.
+class SizeOfAlignOfExpr : public Expr {
+ bool isSizeof : 1; // true if sizeof, false if alignof.
+ bool isType : 1; // true if operand is a type, false if an expression
+ union {
+ void *Ty;
+ Stmt *Ex;
+ } Argument;
+ SourceLocation OpLoc, RParenLoc;
+public:
+ SizeOfAlignOfExpr(bool issizeof, QualType T,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp) :
+ Expr(SizeOfAlignOfExprClass, resultType,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ T->isDependentType()),
+ isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
+ Argument.Ty = T.getAsOpaquePtr();
+ }
+
+ SizeOfAlignOfExpr(bool issizeof, Expr *E,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp) :
+ Expr(SizeOfAlignOfExprClass, resultType,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ E->isTypeDependent()),
+ isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
+ Argument.Ex = E;
+ }
+
+ /// \brief Construct an empty sizeof/alignof expression.
+ explicit SizeOfAlignOfExpr(EmptyShell Empty)
+ : Expr(SizeOfAlignOfExprClass, Empty) { }
+
+ virtual void Destroy(ASTContext& C);
+
+ bool isSizeOf() const { return isSizeof; }
+ void setSizeof(bool S) { isSizeof = S; }
+
+ bool isArgumentType() const { return isType; }
+ QualType getArgumentType() const {
+ assert(isArgumentType() && "calling getArgumentType() when arg is expr");
+ return QualType::getFromOpaquePtr(Argument.Ty);
+ }
+ Expr *getArgumentExpr() {
+ assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
+ return static_cast<Expr*>(Argument.Ex);
+ }
+ const Expr *getArgumentExpr() const {
+ return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr();
+ }
+
+ void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
+ void setArgument(QualType T) {
+ Argument.Ty = T.getAsOpaquePtr();
+ isType = true;
+ }
+
+ /// Gets the argument type, or the type of the argument expression, whichever
+ /// is appropriate.
+ QualType getTypeOfArgument() const {
+ return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType();
+ }
+
+ SourceLocation getOperatorLoc() const { return OpLoc; }
+ void setOperatorLoc(SourceLocation L) { OpLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(OpLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfAlignOfExprClass;
+ }
+ static bool classof(const SizeOfAlignOfExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+//===----------------------------------------------------------------------===//
+// Postfix Operators.
+//===----------------------------------------------------------------------===//
+
+/// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
+class ArraySubscriptExpr : public Expr {
+ enum { LHS, RHS, END_EXPR=2 };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation RBracketLoc;
+public:
+ ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
+ SourceLocation rbracketloc)
+ : Expr(ArraySubscriptExprClass, t,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent()),
+ RBracketLoc(rbracketloc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ /// \brief Create an empty array subscript expression.
+ explicit ArraySubscriptExpr(EmptyShell Shell)
+ : Expr(ArraySubscriptExprClass, Shell) { }
+
+ /// An array access can be written A[4] or 4[A] (both are equivalent).
+ /// - getBase() and getIdx() always present the normalized view: A[4].
+ /// In this case getBase() returns "A" and getIdx() returns "4".
+ /// - getLHS() and getRHS() present the syntactic view. e.g. for
+ /// 4[A] getLHS() returns "4".
+ /// Note: Because vector element access is also written A[4] we must
+ /// predicate the format conversion in getBase and getIdx only on the
+ /// the type of the RHS, as it is possible for the LHS to be a vector of
+ /// integer type
+ Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); }
+ const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+
+ Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); }
+ const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ Expr *getBase() {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
+ }
+
+ const Expr *getBase() const {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS());
+ }
+
+ Expr *getIdx() {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
+ }
+
+ const Expr *getIdx() const {
+ return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS());
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLHS()->getLocStart(), RBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ virtual SourceLocation getExprLoc() const { return getBase()->getExprLoc(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArraySubscriptExprClass;
+ }
+ static bool classof(const ArraySubscriptExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
+/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
+/// while its subclasses may represent alternative syntax that (semantically)
+/// results in a function call. For example, CXXOperatorCallExpr is
+/// a subclass for overloaded operator calls that use operator syntax, e.g.,
+/// "str1 + str2" to resolve to a function call.
+class CallExpr : public Expr {
+ enum { FN=0, ARGS_START=1 };
+ Stmt **SubExprs;
+ unsigned NumArgs;
+ SourceLocation RParenLoc;
+
+protected:
+ // This version of the constructor is for derived classes.
+ CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
+ QualType t, SourceLocation rparenloc);
+
+public:
+ CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
+ SourceLocation rparenloc);
+
+ /// \brief Build an empty call expression.
+ CallExpr(ASTContext &C, EmptyShell Empty);
+
+ ~CallExpr() {}
+
+ void Destroy(ASTContext& C);
+
+ const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
+ Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
+ void setCallee(Expr *F) { SubExprs[FN] = F; }
+
+ /// getNumArgs - Return the number of actual arguments to this call.
+ ///
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ }
+
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ SubExprs[Arg+ARGS_START] = ArgExpr;
+ }
+
+ /// setNumArgs - This changes the number of arguments present in this call.
+ /// Any orphaned expressions are deleted by this, and any new operands are set
+ /// to null.
+ void setNumArgs(ASTContext& C, unsigned NumArgs);
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator arg_begin() { return SubExprs+ARGS_START; }
+ arg_iterator arg_end() { return SubExprs+ARGS_START+getNumArgs(); }
+ const_arg_iterator arg_begin() const { return SubExprs+ARGS_START; }
+ const_arg_iterator arg_end() const { return SubExprs+ARGS_START+getNumArgs();}
+
+ /// getNumCommas - Return the number of commas that must have been present in
+ /// this function call.
+ unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
+
+ /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
+ /// not, return 0.
+ unsigned isBuiltinCall(ASTContext &Context) const;
+
+ /// getCallReturnType - Get the return type of the call expr. This is not
+ /// always the type of the expr itself, if the return type is a reference
+ /// type.
+ QualType getCallReturnType() const;
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getCallee()->getLocStart(), RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CallExprClass ||
+ T->getStmtClass() == CXXOperatorCallExprClass ||
+ T->getStmtClass() == CXXMemberCallExprClass;
+ }
+ static bool classof(const CallExpr *) { return true; }
+ static bool classof(const CXXOperatorCallExpr *) { return true; }
+ static bool classof(const CXXMemberCallExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
+///
+class MemberExpr : public Expr {
+ /// Base - the expression for the base pointer or structure references. In
+ /// X.F, this is "X".
+ Stmt *Base;
+
+ /// MemberDecl - This is the decl being referenced by the field/member name.
+ /// In X.F, this is the decl referenced by F.
+ NamedDecl *MemberDecl;
+
+ /// MemberLoc - This is the location of the member name.
+ SourceLocation MemberLoc;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ bool IsArrow;
+public:
+ MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l,
+ QualType ty)
+ : Expr(MemberExprClass, ty,
+ base->isTypeDependent(), base->isValueDependent()),
+ Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {}
+
+ /// \brief Build an empty member reference expression.
+ explicit MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty) { }
+
+ void setBase(Expr *E) { Base = E; }
+ Expr *getBase() const { return cast<Expr>(Base); }
+
+ /// \brief Retrieve the member declaration to which this expression refers.
+ ///
+ /// The returned declaration will either be a FieldDecl or (in C++)
+ /// a CXXMethodDecl.
+ NamedDecl *getMemberDecl() const { return MemberDecl; }
+ void setMemberDecl(NamedDecl *D) { MemberDecl = D; }
+
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// getMemberLoc - Return the location of the "member", in X->F, it is the
+ /// location of 'F'.
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ // If we have an implicit base (like a C++ implicit this),
+ // make sure not to return its location
+ SourceLocation BaseLoc = getBase()->getLocStart();
+ if (BaseLoc.isInvalid())
+ return SourceRange(MemberLoc, MemberLoc);
+ return SourceRange(BaseLoc, MemberLoc);
+ }
+
+ virtual SourceLocation getExprLoc() const { return MemberLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MemberExprClass;
+ }
+ static bool classof(const MemberExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CompoundLiteralExpr - [C99 6.5.2.5]
+///
+class CompoundLiteralExpr : public Expr {
+ /// LParenLoc - If non-null, this is the location of the left paren in a
+ /// compound literal like "(int){4}". This can be null if this is a
+ /// synthesized compound expression.
+ SourceLocation LParenLoc;
+ Stmt *Init;
+ bool FileScope;
+public:
+ CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init,
+ bool fileScope)
+ : Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init),
+ FileScope(fileScope) {}
+
+ /// \brief Construct an empty compound literal.
+ explicit CompoundLiteralExpr(EmptyShell Empty)
+ : Expr(CompoundLiteralExprClass, Empty) { }
+
+ const Expr *getInitializer() const { return cast<Expr>(Init); }
+ Expr *getInitializer() { return cast<Expr>(Init); }
+ void setInitializer(Expr *E) { Init = E; }
+
+ bool isFileScope() const { return FileScope; }
+ void setFileScope(bool FS) { FileScope = FS; }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ // FIXME: Init should never be null.
+ if (!Init)
+ return SourceRange();
+ if (LParenLoc.isInvalid())
+ return Init->getSourceRange();
+ return SourceRange(LParenLoc, Init->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundLiteralExprClass;
+ }
+ static bool classof(const CompoundLiteralExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CastExpr - Base class for type casts, including both implicit
+/// casts (ImplicitCastExpr) and explicit casts that have some
+/// representation in the source code (ExplicitCastExpr's derived
+/// classes).
+class CastExpr : public Expr {
+ Stmt *Op;
+protected:
+ CastExpr(StmtClass SC, QualType ty, Expr *op) :
+ Expr(SC, ty,
+ // Cast expressions are type-dependent if the type is
+ // dependent (C++ [temp.dep.expr]p3).
+ ty->isDependentType(),
+ // Cast expressions are value-dependent if the type is
+ // dependent or if the subexpression is value-dependent.
+ ty->isDependentType() || (op && op->isValueDependent())),
+ Op(op) {}
+
+ /// \brief Construct an empty cast.
+ CastExpr(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) { }
+
+public:
+ Expr *getSubExpr() { return cast<Expr>(Op); }
+ const Expr *getSubExpr() const { return cast<Expr>(Op); }
+ void setSubExpr(Expr *E) { Op = E; }
+
+ static bool classof(const Stmt *T) {
+ StmtClass SC = T->getStmtClass();
+ if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass)
+ return true;
+
+ if (SC >= ImplicitCastExprClass && SC <= CStyleCastExprClass)
+ return true;
+
+ return false;
+ }
+ static bool classof(const CastExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ImplicitCastExpr - Allows us to explicitly represent implicit type
+/// conversions, which have no direct representation in the original
+/// source code. For example: converting T[]->T*, void f()->void
+/// (*f)(), float->double, short->int, etc.
+///
+/// In C, implicit casts always produce rvalues. However, in C++, an
+/// implicit cast whose result is being bound to a reference will be
+/// an lvalue. For example:
+///
+/// @code
+/// class Base { };
+/// class Derived : public Base { };
+/// void f(Derived d) {
+/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base
+/// }
+/// @endcode
+class ImplicitCastExpr : public CastExpr {
+ /// LvalueCast - Whether this cast produces an lvalue.
+ bool LvalueCast;
+
+public:
+ ImplicitCastExpr(QualType ty, Expr *op, bool Lvalue) :
+ CastExpr(ImplicitCastExprClass, ty, op), LvalueCast(Lvalue) { }
+
+ /// \brief Construct an empty implicit cast.
+ explicit ImplicitCastExpr(EmptyShell Shell)
+ : CastExpr(ImplicitCastExprClass, Shell) { }
+
+
+ virtual SourceRange getSourceRange() const {
+ return getSubExpr()->getSourceRange();
+ }
+
+ /// isLvalueCast - Whether this cast produces an lvalue.
+ bool isLvalueCast() const { return LvalueCast; }
+
+ /// setLvalueCast - Set whether this cast produces an lvalue.
+ void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImplicitCastExprClass;
+ }
+ static bool classof(const ImplicitCastExpr *) { return true; }
+};
+
+/// ExplicitCastExpr - An explicit cast written in the source
+/// code.
+///
+/// This class is effectively an abstract class, because it provides
+/// the basic representation of an explicitly-written cast without
+/// specifying which kind of cast (C cast, functional cast, static
+/// cast, etc.) was written; specific derived classes represent the
+/// particular style of cast and its location information.
+///
+/// Unlike implicit casts, explicit cast nodes have two different
+/// types: the type that was written into the source code, and the
+/// actual type of the expression as determined by semantic
+/// analysis. These types may differ slightly. For example, in C++ one
+/// can cast to a reference type, which indicates that the resulting
+/// expression will be an lvalue. The reference type, however, will
+/// not be used as the type of the expression.
+class ExplicitCastExpr : public CastExpr {
+ /// TypeAsWritten - The type that this expression is casting to, as
+ /// written in the source code.
+ QualType TypeAsWritten;
+
+protected:
+ ExplicitCastExpr(StmtClass SC, QualType exprTy, Expr *op, QualType writtenTy)
+ : CastExpr(SC, exprTy, op), TypeAsWritten(writtenTy) {}
+
+ /// \brief Construct an empty explicit cast.
+ ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
+ : CastExpr(SC, Shell) { }
+
+public:
+ /// getTypeAsWritten - Returns the type that this expression is
+ /// casting to, as written in the source code.
+ QualType getTypeAsWritten() const { return TypeAsWritten; }
+ void setTypeAsWritten(QualType T) { TypeAsWritten = T; }
+
+ static bool classof(const Stmt *T) {
+ StmtClass SC = T->getStmtClass();
+ if (SC >= ExplicitCastExprClass && SC <= CStyleCastExprClass)
+ return true;
+ if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass)
+ return true;
+
+ return false;
+ }
+ static bool classof(const ExplicitCastExpr *) { return true; }
+};
+
+/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
+/// cast in C++ (C++ [expr.cast]), which uses the syntax
+/// (Type)expr. For example: @c (int)f.
+class CStyleCastExpr : public ExplicitCastExpr {
+ SourceLocation LPLoc; // the location of the left paren
+ SourceLocation RPLoc; // the location of the right paren
+public:
+ CStyleCastExpr(QualType exprTy, Expr *op, QualType writtenTy,
+ SourceLocation l, SourceLocation r) :
+ ExplicitCastExpr(CStyleCastExprClass, exprTy, op, writtenTy),
+ LPLoc(l), RPLoc(r) {}
+
+ /// \brief Construct an empty C-style explicit cast.
+ explicit CStyleCastExpr(EmptyShell Shell)
+ : ExplicitCastExpr(CStyleCastExprClass, Shell) { }
+
+ SourceLocation getLParenLoc() const { return LPLoc; }
+ void setLParenLoc(SourceLocation L) { LPLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RPLoc; }
+ void setRParenLoc(SourceLocation L) { RPLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CStyleCastExprClass;
+ }
+ static bool classof(const CStyleCastExpr *) { return true; }
+};
+
+/// \brief A builtin binary operation expression such as "x + y" or "x <= y".
+///
+/// This expression node kind describes a builtin binary operation,
+/// such as "x + y" for integer values "x" and "y". The operands will
+/// already have been converted to appropriate types (e.g., by
+/// performing promotions or conversions).
+///
+/// In C++, where operators may be overloaded, a different kind of
+/// expression node (CXXOperatorCallExpr) is used to express the
+/// invocation of an overloaded operator with operator syntax. Within
+/// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is
+/// used to store an expression "x + y" depends on the subexpressions
+/// for x and y. If neither x or y is type-dependent, and the "+"
+/// operator resolves to a built-in operation, BinaryOperator will be
+/// used to express the computation (x and y may still be
+/// value-dependent). If either x or y is type-dependent, or if the
+/// "+" resolves to an overloaded operator, CXXOperatorCallExpr will
+/// be used to express the computation.
+class BinaryOperator : public Expr {
+public:
+ enum Opcode {
+ // Operators listed in order of precedence.
+ // Note that additions to this should also update the StmtVisitor class.
+ PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators.
+ Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators.
+ Add, Sub, // [C99 6.5.6] Additive operators.
+ Shl, Shr, // [C99 6.5.7] Bitwise shift operators.
+ LT, GT, LE, GE, // [C99 6.5.8] Relational operators.
+ EQ, NE, // [C99 6.5.9] Equality operators.
+ And, // [C99 6.5.10] Bitwise AND operator.
+ Xor, // [C99 6.5.11] Bitwise XOR operator.
+ Or, // [C99 6.5.12] Bitwise OR operator.
+ LAnd, // [C99 6.5.13] Logical AND operator.
+ LOr, // [C99 6.5.14] Logical OR operator.
+ Assign, MulAssign,// [C99 6.5.16] Assignment operators.
+ DivAssign, RemAssign,
+ AddAssign, SubAssign,
+ ShlAssign, ShrAssign,
+ AndAssign, XorAssign,
+ OrAssign,
+ Comma // [C99 6.5.17] Comma operator.
+ };
+private:
+ enum { LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ Opcode Opc;
+ SourceLocation OpLoc;
+public:
+
+ BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ SourceLocation opLoc)
+ : Expr(BinaryOperatorClass, ResTy,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent()),
+ Opc(opc), OpLoc(opLoc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ assert(!isCompoundAssignmentOp() &&
+ "Use ArithAssignBinaryOperator for compound assignments");
+ }
+
+ /// \brief Construct an empty binary operator.
+ explicit BinaryOperator(EmptyShell Empty)
+ : Expr(BinaryOperatorClass, Empty), Opc(Comma) { }
+
+ SourceLocation getOperatorLoc() const { return OpLoc; }
+ void setOperatorLoc(SourceLocation L) { OpLoc = L; }
+
+ Opcode getOpcode() const { return Opc; }
+ void setOpcode(Opcode O) { Opc = O; }
+
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+ Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd());
+ }
+
+ /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+ /// corresponds to, e.g. "<<=".
+ static const char *getOpcodeStr(Opcode Op);
+
+ /// \brief Retrieve the binary opcode that corresponds to the given
+ /// overloaded operator.
+ static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);
+
+ /// \brief Retrieve the overloaded operator kind that corresponds to
+ /// the given binary opcode.
+ static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
+
+ /// predicates to categorize the respective opcodes.
+ bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; }
+ bool isAdditiveOp() const { return Opc == Add || Opc == Sub; }
+ bool isShiftOp() const { return Opc == Shl || Opc == Shr; }
+ bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }
+
+ static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
+ bool isRelationalOp() const { return isRelationalOp(Opc); }
+
+ static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
+ bool isEqualityOp() const { return isEqualityOp(Opc); }
+
+ static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
+ bool isLogicalOp() const { return isLogicalOp(Opc); }
+
+ bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; }
+ bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;}
+ bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == BinaryOperatorClass ||
+ S->getStmtClass() == CompoundAssignOperatorClass;
+ }
+ static bool classof(const BinaryOperator *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+protected:
+ BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ SourceLocation oploc, bool dead)
+ : Expr(CompoundAssignOperatorClass, ResTy), Opc(opc), OpLoc(oploc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ BinaryOperator(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty), Opc(MulAssign) { }
+};
+
+/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
+/// track of the type the operation is performed in. Due to the semantics of
+/// these operators, the operands are promoted, the aritmetic performed, an
+/// implicit conversion back to the result type done, then the assignment takes
+/// place. This captures the intermediate type which the computation is done
+/// in.
+class CompoundAssignOperator : public BinaryOperator {
+ QualType ComputationLHSType;
+ QualType ComputationResultType;
+public:
+ CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc,
+ QualType ResType, QualType CompLHSType,
+ QualType CompResultType,
+ SourceLocation OpLoc)
+ : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true),
+ ComputationLHSType(CompLHSType),
+ ComputationResultType(CompResultType) {
+ assert(isCompoundAssignmentOp() &&
+ "Only should be used for compound assignments");
+ }
+
+ /// \brief Build an empty compound assignment operator expression.
+ explicit CompoundAssignOperator(EmptyShell Empty)
+ : BinaryOperator(CompoundAssignOperatorClass, Empty) { }
+
+ // The two computation types are the type the LHS is converted
+ // to for the computation and the type of the result; the two are
+ // distinct in a few cases (specifically, int+=ptr and ptr-=ptr).
+ QualType getComputationLHSType() const { return ComputationLHSType; }
+ void setComputationLHSType(QualType T) { ComputationLHSType = T; }
+
+ QualType getComputationResultType() const { return ComputationResultType; }
+ void setComputationResultType(QualType T) { ComputationResultType = T; }
+
+ static bool classof(const CompoundAssignOperator *) { return true; }
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == CompoundAssignOperatorClass;
+ }
+};
+
+/// ConditionalOperator - The ?: operator. Note that LHS may be null when the
+/// GNU "missing LHS" extension is in use.
+///
+class ConditionalOperator : public Expr {
+ enum { COND, LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+public:
+ ConditionalOperator(Expr *cond, Expr *lhs, Expr *rhs, QualType t)
+ : Expr(ConditionalOperatorClass, t,
+ // FIXME: the type of the conditional operator doesn't
+ // depend on the type of the conditional, but the standard
+ // seems to imply that it could. File a bug!
+ ((lhs && lhs->isTypeDependent()) || (rhs && rhs->isTypeDependent())),
+ (cond->isValueDependent() ||
+ (lhs && lhs->isValueDependent()) ||
+ (rhs && rhs->isValueDependent()))) {
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ /// \brief Build an empty conditional operator.
+ explicit ConditionalOperator(EmptyShell Empty)
+ : Expr(ConditionalOperatorClass, Empty) { }
+
+ // getCond - Return the expression representing the condition for
+ // the ?: operator.
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+ void setCond(Expr *E) { SubExprs[COND] = E; }
+
+ // getTrueExpr - Return the subexpression representing the value of the ?:
+ // expression if the condition evaluates to true. In most cases this value
+ // will be the same as getLHS() except a GCC extension allows the left
+ // subexpression to be omitted, and instead of the condition be returned.
+ // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x"
+ // is only evaluated once.
+ Expr *getTrueExpr() const {
+ return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]);
+ }
+
+ // getTrueExpr - Return the subexpression representing the value of the ?:
+ // expression if the condition evaluates to false. This is the same as getRHS.
+ Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
+
+ Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+
+ Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass;
+ }
+ static bool classof(const ConditionalOperator *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// AddrLabelExpr - The GNU address of label extension, representing &&label.
+class AddrLabelExpr : public Expr {
+ SourceLocation AmpAmpLoc, LabelLoc;
+ LabelStmt *Label;
+public:
+ AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L,
+ QualType t)
+ : Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
+
+ /// \brief Build an empty address of a label expression.
+ explicit AddrLabelExpr(EmptyShell Empty)
+ : Expr(AddrLabelExprClass, Empty) { }
+
+ SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; }
+ void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; }
+ SourceLocation getLabelLoc() const { return LabelLoc; }
+ void setLabelLoc(SourceLocation L) { LabelLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AmpAmpLoc, LabelLoc);
+ }
+
+ LabelStmt *getLabel() const { return Label; }
+ void setLabel(LabelStmt *S) { Label = S; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AddrLabelExprClass;
+ }
+ static bool classof(const AddrLabelExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
+/// The StmtExpr contains a single CompoundStmt node, which it evaluates and
+/// takes the value of the last subexpression.
+class StmtExpr : public Expr {
+ Stmt *SubStmt;
+ SourceLocation LParenLoc, RParenLoc;
+public:
+ StmtExpr(CompoundStmt *substmt, QualType T,
+ SourceLocation lp, SourceLocation rp) :
+ Expr(StmtExprClass, T), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
+
+ /// \brief Build an empty statement expression.
+ explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
+
+ CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); }
+ const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); }
+ void setSubStmt(CompoundStmt *S) { SubStmt = S; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LParenLoc, RParenLoc);
+ }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == StmtExprClass;
+ }
+ static bool classof(const StmtExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// TypesCompatibleExpr - GNU builtin-in function __builtin_types_compatible_p.
+/// This AST node represents a function that returns 1 if two *types* (not
+/// expressions) are compatible. The result of this built-in function can be
+/// used in integer constant expressions.
+class TypesCompatibleExpr : public Expr {
+ QualType Type1;
+ QualType Type2;
+ SourceLocation BuiltinLoc, RParenLoc;
+public:
+ TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
+ QualType t1, QualType t2, SourceLocation RP) :
+ Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2),
+ BuiltinLoc(BLoc), RParenLoc(RP) {}
+
+ /// \brief Build an empty __builtin_type_compatible_p expression.
+ explicit TypesCompatibleExpr(EmptyShell Empty)
+ : Expr(TypesCompatibleExprClass, Empty) { }
+
+ QualType getArgType1() const { return Type1; }
+ void setArgType1(QualType T) { Type1 = T; }
+ QualType getArgType2() const { return Type2; }
+ void setArgType2(QualType T) { Type2 = T; }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TypesCompatibleExprClass;
+ }
+ static bool classof(const TypesCompatibleExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ShuffleVectorExpr - clang-specific builtin-in function
+/// __builtin_shufflevector.
+/// This AST node represents a operator that does a constant
+/// shuffle, similar to LLVM's shufflevector instruction. It takes
+/// two vectors and a variable number of constant indices,
+/// and returns the appropriately shuffled vector.
+class ShuffleVectorExpr : public Expr {
+ SourceLocation BuiltinLoc, RParenLoc;
+
+ // SubExprs - the list of values passed to the __builtin_shufflevector
+ // function. The first two are vectors, and the rest are constant
+ // indices. The number of values in this list is always
+ // 2+the number of indices in the vector type.
+ Stmt **SubExprs;
+ unsigned NumExprs;
+
+public:
+ ShuffleVectorExpr(Expr **args, unsigned nexpr,
+ QualType Type, SourceLocation BLoc,
+ SourceLocation RP) :
+ Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc),
+ RParenLoc(RP), NumExprs(nexpr) {
+
+ SubExprs = new Stmt*[nexpr];
+ for (unsigned i = 0; i < nexpr; i++)
+ SubExprs[i] = args[i];
+ }
+
+ /// \brief Build an empty vector-shuffle expression.
+ explicit ShuffleVectorExpr(EmptyShell Empty)
+ : Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ShuffleVectorExprClass;
+ }
+ static bool classof(const ShuffleVectorExpr *) { return true; }
+
+ ~ShuffleVectorExpr() {
+ delete [] SubExprs;
+ }
+
+ /// getNumSubExprs - Return the size of the SubExprs array. This includes the
+ /// constant expression, the actual arguments passed in, and the function
+ /// pointers.
+ unsigned getNumSubExprs() const { return NumExprs; }
+
+ /// getExpr - Return the Expr at the specified index.
+ Expr *getExpr(unsigned Index) {
+ assert((Index < NumExprs) && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Index]);
+ }
+ const Expr *getExpr(unsigned Index) const {
+ assert((Index < NumExprs) && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Index]);
+ }
+
+ void setExprs(Expr ** Exprs, unsigned NumExprs);
+
+ unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) {
+ assert((N < NumExprs - 2) && "Shuffle idx out of range!");
+ return getExpr(N+2)->EvaluateAsInt(Ctx).getZExtValue();
+ }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
+/// This AST node is similar to the conditional operator (?:) in C, with
+/// the following exceptions:
+/// - the test expression must be a integer constant expression.
+/// - the expression returned acts like the chosen subexpression in every
+/// visible way: the type is the same as that of the chosen subexpression,
+/// and all predicates (whether it's an l-value, whether it's an integer
+/// constant expression, etc.) return the same result as for the chosen
+/// sub-expression.
+class ChooseExpr : public Expr {
+ enum { COND, LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+ SourceLocation BuiltinLoc, RParenLoc;
+public:
+ ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t,
+ SourceLocation RP)
+ : Expr(ChooseExprClass, t),
+ BuiltinLoc(BLoc), RParenLoc(RP) {
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ }
+
+ /// \brief Build an empty __builtin_choose_expr.
+ explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { }
+
+ /// isConditionTrue - Return whether the condition is true (i.e. not
+ /// equal to zero).
+ bool isConditionTrue(ASTContext &C) const;
+
+ /// getChosenSubExpr - Return the subexpression chosen according to the
+ /// condition.
+ Expr *getChosenSubExpr(ASTContext &C) const {
+ return isConditionTrue(C) ? getLHS() : getRHS();
+ }
+
+ Expr *getCond() const { return cast<Expr>(SubExprs[COND]); }
+ void setCond(Expr *E) { SubExprs[COND] = E; }
+ Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
+ void setLHS(Expr *E) { SubExprs[LHS] = E; }
+ Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
+ void setRHS(Expr *E) { SubExprs[RHS] = E; }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ChooseExprClass;
+ }
+ static bool classof(const ChooseExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// GNUNullExpr - Implements the GNU __null extension, which is a name
+/// for a null pointer constant that has integral type (e.g., int or
+/// long) and is the same size and alignment as a pointer. The __null
+/// extension is typically only used by system headers, which define
+/// NULL as __null in C++ rather than using 0 (which is an integer
+/// that may not match the size of a pointer).
+class GNUNullExpr : public Expr {
+ /// TokenLoc - The location of the __null keyword.
+ SourceLocation TokenLoc;
+
+public:
+ GNUNullExpr(QualType Ty, SourceLocation Loc)
+ : Expr(GNUNullExprClass, Ty), TokenLoc(Loc) { }
+
+ /// \brief Build an empty GNU __null expression.
+ explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
+
+ GNUNullExpr* Clone(ASTContext &C) const;
+
+ /// getTokenLocation - The location of the __null token.
+ SourceLocation getTokenLocation() const { return TokenLoc; }
+ void setTokenLocation(SourceLocation L) { TokenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TokenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GNUNullExprClass;
+ }
+ static bool classof(const GNUNullExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// VAArgExpr, used for the builtin function __builtin_va_start.
+class VAArgExpr : public Expr {
+ Stmt *Val;
+ SourceLocation BuiltinLoc, RParenLoc;
+public:
+ VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc)
+ : Expr(VAArgExprClass, t),
+ Val(e),
+ BuiltinLoc(BLoc),
+ RParenLoc(RPLoc) { }
+
+ /// \brief Create an empty __builtin_va_start expression.
+ explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(BuiltinLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == VAArgExprClass;
+ }
+ static bool classof(const VAArgExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// @brief Describes an C or C++ initializer list.
+///
+/// InitListExpr describes an initializer list, which can be used to
+/// initialize objects of different types, including
+/// struct/class/union types, arrays, and vectors. For example:
+///
+/// @code
+/// struct foo x = { 1, { 2, 3 } };
+/// @endcode
+///
+/// Prior to semantic analysis, an initializer list will represent the
+/// initializer list as written by the user, but will have the
+/// placeholder type "void". This initializer list is called the
+/// syntactic form of the initializer, and may contain C99 designated
+/// initializers (represented as DesignatedInitExprs), initializations
+/// of subobject members without explicit braces, and so on. Clients
+/// interested in the original syntax of the initializer list should
+/// use the syntactic form of the initializer list.
+///
+/// After semantic analysis, the initializer list will represent the
+/// semantic form of the initializer, where the initializations of all
+/// subobjects are made explicit with nested InitListExpr nodes and
+/// C99 designators have been eliminated by placing the designated
+/// initializations into the subobject they initialize. Additionally,
+/// any "holes" in the initialization, where no initializer has been
+/// specified for a particular subobject, will be replaced with
+/// implicitly-generated ImplicitValueInitExpr expressions that
+/// value-initialize the subobjects. Note, however, that the
+/// initializer lists may still have fewer initializers than there are
+/// elements to initialize within the object.
+///
+/// Given the semantic form of the initializer list, one can retrieve
+/// the original syntactic form of that initializer list (if it
+/// exists) using getSyntacticForm(). Since many initializer lists
+/// have the same syntactic and semantic forms, getSyntacticForm() may
+/// return NULL, indicating that the current initializer list also
+/// serves as its syntactic form.
+class InitListExpr : public Expr {
+ std::vector<Stmt *> InitExprs;
+ SourceLocation LBraceLoc, RBraceLoc;
+
+ /// Contains the initializer list that describes the syntactic form
+ /// written in the source code.
+ InitListExpr *SyntacticForm;
+
+ /// If this initializer list initializes a union, specifies which
+ /// field within the union will be initialized.
+ FieldDecl *UnionFieldInit;
+
+ /// Whether this initializer list originally had a GNU array-range
+ /// designator in it. This is a temporary marker used by CodeGen.
+ bool HadArrayRangeDesignator;
+
+public:
+ InitListExpr(SourceLocation lbraceloc, Expr **initexprs, unsigned numinits,
+ SourceLocation rbraceloc);
+
+ /// \brief Build an empty initializer list.
+ explicit InitListExpr(EmptyShell Empty) : Expr(InitListExprClass, Empty) { }
+
+ unsigned getNumInits() const { return InitExprs.size(); }
+
+ const Expr* getInit(unsigned Init) const {
+ assert(Init < getNumInits() && "Initializer access out of range!");
+ return cast_or_null<Expr>(InitExprs[Init]);
+ }
+
+ Expr* getInit(unsigned Init) {
+ assert(Init < getNumInits() && "Initializer access out of range!");
+ return cast_or_null<Expr>(InitExprs[Init]);
+ }
+
+ void setInit(unsigned Init, Expr *expr) {
+ assert(Init < getNumInits() && "Initializer access out of range!");
+ InitExprs[Init] = expr;
+ }
+
+ /// \brief Reserve space for some number of initializers.
+ void reserveInits(unsigned NumInits);
+
+ /// @brief Specify the number of initializers
+ ///
+ /// If there are more than @p NumInits initializers, the remaining
+ /// initializers will be destroyed. If there are fewer than @p
+ /// NumInits initializers, NULL expressions will be added for the
+ /// unknown initializers.
+ void resizeInits(ASTContext &Context, unsigned NumInits);
+
+ /// @brief Updates the initializer at index @p Init with the new
+ /// expression @p expr, and returns the old expression at that
+ /// location.
+ ///
+ /// When @p Init is out of range for this initializer list, the
+ /// initializer list will be extended with NULL expressions to
+ /// accomodate the new entry.
+ Expr *updateInit(unsigned Init, Expr *expr);
+
+ /// \brief If this initializes a union, specifies which field in the
+ /// union to initialize.
+ ///
+ /// Typically, this field is the first named field within the
+ /// union. However, a designated initializer can specify the
+ /// initialization of a different field within the union.
+ FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; }
+ void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; }
+
+ // Explicit InitListExpr's originate from source code (and have valid source
+ // locations). Implicit InitListExpr's are created by the semantic analyzer.
+ bool isExplicit() {
+ return LBraceLoc.isValid() && RBraceLoc.isValid();
+ }
+
+ SourceLocation getLBraceLoc() const { return LBraceLoc; }
+ void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }
+
+ /// @brief Retrieve the initializer list that describes the
+ /// syntactic form of the initializer.
+ ///
+ ///
+ InitListExpr *getSyntacticForm() const { return SyntacticForm; }
+ void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; }
+
+ bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; }
+ void sawArrayRangeDesignator(bool ARD = true) {
+ HadArrayRangeDesignator = ARD;
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LBraceLoc, RBraceLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == InitListExprClass;
+ }
+ static bool classof(const InitListExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ typedef std::vector<Stmt *>::iterator iterator;
+ typedef std::vector<Stmt *>::reverse_iterator reverse_iterator;
+
+ iterator begin() { return InitExprs.begin(); }
+ iterator end() { return InitExprs.end(); }
+ reverse_iterator rbegin() { return InitExprs.rbegin(); }
+ reverse_iterator rend() { return InitExprs.rend(); }
+};
+
+/// @brief Represents a C99 designated initializer expression.
+///
+/// A designated initializer expression (C99 6.7.8) contains one or
+/// more designators (which can be field designators, array
+/// designators, or GNU array-range designators) followed by an
+/// expression that initializes the field or element(s) that the
+/// designators refer to. For example, given:
+///
+/// @code
+/// struct point {
+/// double x;
+/// double y;
+/// };
+/// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
+/// @endcode
+///
+/// The InitListExpr contains three DesignatedInitExprs, the first of
+/// which covers @c [2].y=1.0. This DesignatedInitExpr will have two
+/// designators, one array designator for @c [2] followed by one field
+/// designator for @c .y. The initalization expression will be 1.0.
+class DesignatedInitExpr : public Expr {
+public:
+ /// \brief Forward declaration of the Designator class.
+ class Designator;
+
+private:
+ /// The location of the '=' or ':' prior to the actual initializer
+ /// expression.
+ SourceLocation EqualOrColonLoc;
+
+ /// Whether this designated initializer used the GNU deprecated
+ /// syntax rather than the C99 '=' syntax.
+ bool GNUSyntax : 1;
+
+ /// The number of designators in this initializer expression.
+ unsigned NumDesignators : 15;
+
+ /// \brief The designators in this designated initialization
+ /// expression.
+ Designator *Designators;
+
+ /// The number of subexpressions of this initializer expression,
+ /// which contains both the initializer and any additional
+ /// expressions used by array and array-range designators.
+ unsigned NumSubExprs : 16;
+
+
+ DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
+ const Designator *Designators,
+ SourceLocation EqualOrColonLoc, bool GNUSyntax,
+ Expr **IndexExprs, unsigned NumIndexExprs,
+ Expr *Init);
+
+ explicit DesignatedInitExpr(unsigned NumSubExprs)
+ : Expr(DesignatedInitExprClass, EmptyShell()),
+ NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { }
+
+public:
+ /// A field designator, e.g., ".x".
+ struct FieldDesignator {
+ /// Refers to the field that is being initialized. The low bit
+ /// of this field determines whether this is actually a pointer
+ /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When
+ /// initially constructed, a field designator will store an
+ /// IdentifierInfo*. After semantic analysis has resolved that
+ /// name, the field designator will instead store a FieldDecl*.
+ uintptr_t NameOrField;
+
+ /// The location of the '.' in the designated initializer.
+ unsigned DotLoc;
+
+ /// The location of the field name in the designated initializer.
+ unsigned FieldLoc;
+ };
+
+ /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
+ struct ArrayOrRangeDesignator {
+ /// Location of the first index expression within the designated
+ /// initializer expression's list of subexpressions.
+ unsigned Index;
+ /// The location of the '[' starting the array range designator.
+ unsigned LBracketLoc;
+ /// The location of the ellipsis separating the start and end
+ /// indices. Only valid for GNU array-range designators.
+ unsigned EllipsisLoc;
+ /// The location of the ']' terminating the array range designator.
+ unsigned RBracketLoc;
+ };
+
+ /// @brief Represents a single C99 designator.
+ ///
+ /// @todo This class is infuriatingly similar to clang::Designator,
+ /// but minor differences (storing indices vs. storing pointers)
+ /// keep us from reusing it. Try harder, later, to rectify these
+ /// differences.
+ class Designator {
+ /// @brief The kind of designator this describes.
+ enum {
+ FieldDesignator,
+ ArrayDesignator,
+ ArrayRangeDesignator
+ } Kind;
+
+ union {
+ /// A field designator, e.g., ".x".
+ struct FieldDesignator Field;
+ /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]".
+ struct ArrayOrRangeDesignator ArrayOrRange;
+ };
+ friend class DesignatedInitExpr;
+
+ public:
+ Designator() {}
+
+ /// @brief Initializes a field designator.
+ Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
+ SourceLocation FieldLoc)
+ : Kind(FieldDesignator) {
+ Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01;
+ Field.DotLoc = DotLoc.getRawEncoding();
+ Field.FieldLoc = FieldLoc.getRawEncoding();
+ }
+
+ /// @brief Initializes an array designator.
+ Designator(unsigned Index, SourceLocation LBracketLoc,
+ SourceLocation RBracketLoc)
+ : Kind(ArrayDesignator) {
+ ArrayOrRange.Index = Index;
+ ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
+ ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding();
+ ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ /// @brief Initializes a GNU array-range designator.
+ Designator(unsigned Index, SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc, SourceLocation RBracketLoc)
+ : Kind(ArrayRangeDesignator) {
+ ArrayOrRange.Index = Index;
+ ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding();
+ ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ bool isFieldDesignator() const { return Kind == FieldDesignator; }
+ bool isArrayDesignator() const { return Kind == ArrayDesignator; }
+ bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
+
+ IdentifierInfo * getFieldName();
+
+ FieldDecl *getField() {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ if (Field.NameOrField & 0x01)
+ return 0;
+ else
+ return reinterpret_cast<FieldDecl *>(Field.NameOrField);
+ }
+
+ void setField(FieldDecl *FD) {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ Field.NameOrField = reinterpret_cast<uintptr_t>(FD);
+ }
+
+ SourceLocation getDotLoc() const {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ return SourceLocation::getFromRawEncoding(Field.DotLoc);
+ }
+
+ SourceLocation getFieldLoc() const {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ return SourceLocation::getFromRawEncoding(Field.FieldLoc);
+ }
+
+ SourceLocation getLBracketLoc() const {
+ assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ "Only valid on an array or array-range designator");
+ return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const {
+ assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ "Only valid on an array or array-range designator");
+ return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ assert(Kind == ArrayRangeDesignator &&
+ "Only valid on an array-range designator");
+ return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc);
+ }
+
+ unsigned getFirstExprIndex() const {
+ assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) &&
+ "Only valid on an array or array-range designator");
+ return ArrayOrRange.Index;
+ }
+
+ SourceLocation getStartLocation() const {
+ if (Kind == FieldDesignator)
+ return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
+ else
+ return getLBracketLoc();
+ }
+ };
+
+ static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators,
+ unsigned NumDesignators,
+ Expr **IndexExprs, unsigned NumIndexExprs,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax, Expr *Init);
+
+ static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs);
+
+ /// @brief Returns the number of designators in this initializer.
+ unsigned size() const { return NumDesignators; }
+
+ // Iterator access to the designators.
+ typedef Designator* designators_iterator;
+ designators_iterator designators_begin() { return Designators; }
+ designators_iterator designators_end() {
+ return Designators + NumDesignators;
+ }
+
+ Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
+
+ void setDesignators(const Designator *Desigs, unsigned NumDesigs);
+
+ Expr *getArrayIndex(const Designator& D);
+ Expr *getArrayRangeStart(const Designator& D);
+ Expr *getArrayRangeEnd(const Designator& D);
+
+ /// @brief Retrieve the location of the '=' that precedes the
+ /// initializer value itself, if present.
+ SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; }
+ void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; }
+
+ /// @brief Determines whether this designated initializer used the
+ /// deprecated GNU syntax for designated initializers.
+ bool usesGNUSyntax() const { return GNUSyntax; }
+ void setGNUSyntax(bool GNU) { GNUSyntax = GNU; }
+
+ /// @brief Retrieve the initializer value.
+ Expr *getInit() const {
+ return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin());
+ }
+
+ void setInit(Expr *init) {
+ *child_begin() = init;
+ }
+
+ /// \brief Retrieve the total number of subexpressions in this
+ /// designated initializer expression, including the actual
+ /// initialized value and any expressions that occur within array
+ /// and array-range designators.
+ unsigned getNumSubExprs() const { return NumSubExprs; }
+
+ Expr *getSubExpr(unsigned Idx) {
+ assert(Idx < NumSubExprs && "Subscript out of range");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx];
+ }
+
+ void setSubExpr(unsigned Idx, Expr *E) {
+ assert(Idx < NumSubExprs && "Subscript out of range");
+ char* Ptr = static_cast<char*>(static_cast<void *>(this));
+ Ptr += sizeof(DesignatedInitExpr);
+ reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E;
+ }
+
+ /// \brief Replaces the designator at index @p Idx with the series
+ /// of designators in [First, Last).
+ void ExpandDesignator(unsigned Idx, const Designator *First,
+ const Designator *Last);
+
+ virtual SourceRange getSourceRange() const;
+
+ virtual void Destroy(ASTContext &C);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DesignatedInitExprClass;
+ }
+ static bool classof(const DesignatedInitExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// \brief Represents an implicitly-generated value initialization of
+/// an object of a given type.
+///
+/// Implicit value initializations occur within semantic initializer
+/// list expressions (InitListExpr) as placeholders for subobject
+/// initializations not explicitly specified by the user.
+///
+/// \see InitListExpr
+class ImplicitValueInitExpr : public Expr {
+public:
+ explicit ImplicitValueInitExpr(QualType ty)
+ : Expr(ImplicitValueInitExprClass, ty) { }
+
+ /// \brief Construct an empty implicit value initialization.
+ explicit ImplicitValueInitExpr(EmptyShell Empty)
+ : Expr(ImplicitValueInitExprClass, Empty) { }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImplicitValueInitExprClass;
+ }
+ static bool classof(const ImplicitValueInitExpr *) { return true; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange();
+ }
+
+ ImplicitValueInitExpr *Clone(ASTContext &C) const;
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+//===----------------------------------------------------------------------===//
+// Clang Extensions
+//===----------------------------------------------------------------------===//
+
+
+/// ExtVectorElementExpr - This represents access to specific elements of a
+/// vector, and may occur on the left hand side or right hand side. For example
+/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector.
+///
+/// Note that the base may have either vector or pointer to vector type, just
+/// like a struct field reference.
+///
+class ExtVectorElementExpr : public Expr {
+ Stmt *Base;
+ IdentifierInfo *Accessor;
+ SourceLocation AccessorLoc;
+public:
+ ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor,
+ SourceLocation loc)
+ : Expr(ExtVectorElementExprClass, ty),
+ Base(base), Accessor(&accessor), AccessorLoc(loc) {}
+
+ /// \brief Build an empty vector element expression.
+ explicit ExtVectorElementExpr(EmptyShell Empty)
+ : Expr(ExtVectorElementExprClass, Empty) { }
+
+ const Expr *getBase() const { return cast<Expr>(Base); }
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr *E) { Base = E; }
+
+ IdentifierInfo &getAccessor() const { return *Accessor; }
+ void setAccessor(IdentifierInfo *II) { Accessor = II; }
+
+ SourceLocation getAccessorLoc() const { return AccessorLoc; }
+ void setAccessorLoc(SourceLocation L) { AccessorLoc = L; }
+
+ /// getNumElements - Get the number of components being selected.
+ unsigned getNumElements() const;
+
+ /// containsDuplicateElements - Return true if any element access is
+ /// repeated.
+ bool containsDuplicateElements() const;
+
+ /// getEncodedElementAccess - Encode the elements accessed into an llvm
+ /// aggregate Constant of ConstantInt(s).
+ void getEncodedElementAccess(llvm::SmallVectorImpl<unsigned> &Elts) const;
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getBase()->getLocStart(), AccessorLoc);
+ }
+
+ /// isArrow - Return true if the base expression is a pointer to vector,
+ /// return false if the base expression is a vector.
+ bool isArrow() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ExtVectorElementExprClass;
+ }
+ static bool classof(const ExtVectorElementExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
+/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
+class BlockExpr : public Expr {
+protected:
+ BlockDecl *TheBlock;
+ bool HasBlockDeclRefExprs;
+public:
+ BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs)
+ : Expr(BlockExprClass, ty),
+ TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {}
+
+ /// \brief Build an empty block expression.
+ explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { }
+
+ const BlockDecl *getBlockDecl() const { return TheBlock; }
+ BlockDecl *getBlockDecl() { return TheBlock; }
+ void setBlockDecl(BlockDecl *BD) { TheBlock = BD; }
+
+ // Convenience functions for probing the underlying BlockDecl.
+ SourceLocation getCaretLocation() const;
+ const Stmt *getBody() const;
+ Stmt *getBody();
+
+ const Stmt *getBody(ASTContext &C) const { return getBody(); }
+ Stmt *getBody(ASTContext &C) { return getBody(); }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getCaretLocation(), getBody()->getLocEnd());
+ }
+
+ /// getFunctionType - Return the underlying function type for this block.
+ const FunctionType *getFunctionType() const;
+
+ /// hasBlockDeclRefExprs - Return true iff the block has BlockDeclRefExpr
+ /// inside of the block that reference values outside the block.
+ bool hasBlockDeclRefExprs() const { return HasBlockDeclRefExprs; }
+ void setHasBlockDeclRefExprs(bool BDRE) { HasBlockDeclRefExprs = BDRE; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BlockExprClass;
+ }
+ static bool classof(const BlockExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// BlockDeclRefExpr - A reference to a declared variable, function,
+/// enum, etc.
+class BlockDeclRefExpr : public Expr {
+ ValueDecl *D;
+ SourceLocation Loc;
+ bool IsByRef;
+public:
+ BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef) :
+ Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef) {}
+
+ // \brief Build an empty reference to a declared variable in a
+ // block.
+ explicit BlockDeclRefExpr(EmptyShell Empty)
+ : Expr(BlockDeclRefExprClass, Empty) { }
+
+ ValueDecl *getDecl() { return D; }
+ const ValueDecl *getDecl() const { return D; }
+ void setDecl(ValueDecl *VD) { D = VD; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ bool isByRef() const { return IsByRef; }
+ void setByRef(bool BR) { IsByRef = BR; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BlockDeclRefExprClass;
+ }
+ static bool classof(const BlockDeclRefExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
new file mode 100644
index 000000000000..53386231a03f
--- /dev/null
+++ b/include/clang/AST/ExprCXX.h
@@ -0,0 +1,1234 @@
+//===--- ExprCXX.h - Classes for representing expressions -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Expr interface and subclasses for C++ expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPRCXX_H
+#define LLVM_CLANG_AST_EXPRCXX_H
+
+#include "clang/Basic/TypeTraits.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXTemporary;
+
+//===--------------------------------------------------------------------===//
+// C++ Expressions.
+//===--------------------------------------------------------------------===//
+
+/// \brief A call to an overloaded operator written using operator
+/// syntax.
+///
+/// Represents a call to an overloaded operator written using operator
+/// syntax, e.g., "x + y" or "*p". While semantically equivalent to a
+/// normal call, this AST node provides better information about the
+/// syntactic representation of the call.
+///
+/// In a C++ template, this expression node kind will be used whenever
+/// any of the arguments are type-dependent. In this case, the
+/// function itself will be a (possibly empty) set of functions and
+/// function templates that were found by name lookup at template
+/// definition time.
+class CXXOperatorCallExpr : public CallExpr {
+ /// \brief The overloaded operator.
+ OverloadedOperatorKind Operator;
+
+public:
+ CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
+ Expr **args, unsigned numargs, QualType t,
+ SourceLocation operatorloc)
+ : CallExpr(C, CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc),
+ Operator(Op) {}
+
+ /// getOperator - Returns the kind of overloaded operator that this
+ /// expression refers to.
+ OverloadedOperatorKind getOperator() const { return Operator; }
+
+ /// getOperatorLoc - Returns the location of the operator symbol in
+ /// the expression. When @c getOperator()==OO_Call, this is the
+ /// location of the right parentheses; when @c
+ /// getOperator()==OO_Subscript, this is the location of the right
+ /// bracket.
+ SourceLocation getOperatorLoc() const { return getRParenLoc(); }
+
+ virtual SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXOperatorCallExprClass;
+ }
+ static bool classof(const CXXOperatorCallExpr *) { return true; }
+};
+
+/// CXXMemberCallExpr - Represents a call to a member function that
+/// may be written either with member call syntax (e.g., "obj.func()"
+/// or "objptr->func()") or with normal function-call syntax
+/// ("func()") within a member function that ends up calling a member
+/// function. The callee in either case is a MemberExpr that contains
+/// both the object argument and the member function, while the
+/// arguments are the arguments within the parentheses (not including
+/// the object argument).
+class CXXMemberCallExpr : public CallExpr {
+public:
+ CXXMemberCallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs,
+ QualType t, SourceLocation rparenloc)
+ : CallExpr(C, CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) {}
+
+ /// getImplicitObjectArgument - Retrieves the implicit object
+ /// argument for the member call. For example, in "x.f(5)", this
+ /// operation would return "x".
+ Expr *getImplicitObjectArgument();
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXMemberCallExprClass;
+ }
+ static bool classof(const CXXMemberCallExpr *) { return true; }
+};
+
+/// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
+/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
+/// const_cast.
+///
+/// This abstract class is inherited by all of the classes
+/// representing "named" casts, e.g., CXXStaticCastExpr,
+/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr.
+class CXXNamedCastExpr : public ExplicitCastExpr {
+private:
+ SourceLocation Loc; // the location of the casting op
+
+protected:
+ CXXNamedCastExpr(StmtClass SC, QualType ty, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : ExplicitCastExpr(SC, ty, op, writtenTy), Loc(l) {}
+
+public:
+ const char *getCastName() const;
+
+ /// \brief Retrieve the location of the cast operator keyword, e.g.,
+ /// "static_cast".
+ SourceLocation getOperatorLoc() const { return Loc; }
+ void setOperatorLoc(SourceLocation L) { Loc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
+ }
+ static bool classof(const Stmt *T) {
+ switch (T->getStmtClass()) {
+ case CXXNamedCastExprClass:
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const CXXNamedCastExpr *) { return true; }
+};
+
+/// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]).
+///
+/// This expression node represents a C++ static cast, e.g.,
+/// @c static_cast<int>(1.0).
+class CXXStaticCastExpr : public CXXNamedCastExpr {
+public:
+ CXXStaticCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXStaticCastExprClass;
+ }
+ static bool classof(const CXXStaticCastExpr *) { return true; }
+};
+
+/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression
+/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
+/// determine how to perform the type cast.
+///
+/// This expression node represents a dynamic cast, e.g.,
+/// @c dynamic_cast<Derived*>(BasePtr).
+class CXXDynamicCastExpr : public CXXNamedCastExpr {
+public:
+ CXXDynamicCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDynamicCastExprClass;
+ }
+ static bool classof(const CXXDynamicCastExpr *) { return true; }
+};
+
+/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++
+/// [expr.reinterpret.cast]), which provides a differently-typed view
+/// of a value but performs no actual work at run time.
+///
+/// This expression node represents a reinterpret cast, e.g.,
+/// @c reinterpret_cast<int>(VoidPtr).
+class CXXReinterpretCastExpr : public CXXNamedCastExpr {
+public:
+ CXXReinterpretCastExpr(QualType ty, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXReinterpretCastExprClass;
+ }
+ static bool classof(const CXXReinterpretCastExpr *) { return true; }
+};
+
+/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]),
+/// which can remove type qualifiers but does not change the underlying value.
+///
+/// This expression node represents a const cast, e.g.,
+/// @c const_cast<char*>(PtrToConstChar).
+class CXXConstCastExpr : public CXXNamedCastExpr {
+public:
+ CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
+ SourceLocation l)
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, op, writtenTy, l) {}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstCastExprClass;
+ }
+ static bool classof(const CXXConstCastExpr *) { return true; }
+};
+
+/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
+///
+class CXXBoolLiteralExpr : public Expr {
+ bool Value;
+ SourceLocation Loc;
+public:
+ CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
+ Expr(CXXBoolLiteralExprClass, Ty), Value(val), Loc(l) {}
+
+ CXXBoolLiteralExpr* Clone(ASTContext &C) const;
+
+ bool getValue() const { return Value; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXBoolLiteralExprClass;
+ }
+ static bool classof(const CXXBoolLiteralExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal
+class CXXNullPtrLiteralExpr : public Expr {
+ SourceLocation Loc;
+public:
+ CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
+ Expr(CXXNullPtrLiteralExprClass, Ty), Loc(l) {}
+
+ CXXNullPtrLiteralExpr* Clone(ASTContext &C) const;
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNullPtrLiteralExprClass;
+ }
+ static bool classof(const CXXNullPtrLiteralExpr *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
+/// the type_info that corresponds to the supplied type, or the (possibly
+/// dynamic) type of the supplied expression.
+///
+/// This represents code like @c typeid(int) or @c typeid(*objPtr)
+class CXXTypeidExpr : public Expr {
+private:
+ bool isTypeOp : 1;
+ union {
+ void *Ty;
+ Stmt *Ex;
+ } Operand;
+ SourceRange Range;
+
+public:
+ CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) :
+ Expr(CXXTypeidExprClass, Ty,
+ // typeid is never type-dependent (C++ [temp.dep.expr]p4)
+ false,
+ // typeid is value-dependent if the type or expression are dependent
+ (isTypeOp ? QualType::getFromOpaquePtr(op)->isDependentType()
+ : static_cast<Expr*>(op)->isValueDependent())),
+ isTypeOp(isTypeOp), Range(r) {
+ if (isTypeOp)
+ Operand.Ty = op;
+ else
+ // op was an Expr*, so cast it back to that to be safe
+ Operand.Ex = static_cast<Expr*>(op);
+ }
+
+ bool isTypeOperand() const { return isTypeOp; }
+ QualType getTypeOperand() const {
+ assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
+ return QualType::getFromOpaquePtr(Operand.Ty);
+ }
+ Expr* getExprOperand() const {
+ assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
+ return static_cast<Expr*>(Operand.Ex);
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return Range;
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTypeidExprClass;
+ }
+ static bool classof(const CXXTypeidExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXThisExpr - Represents the "this" expression in C++, which is a
+/// pointer to the object on which the current member function is
+/// executing (C++ [expr.prim]p3). Example:
+///
+/// @code
+/// class Foo {
+/// public:
+/// void bar();
+/// void test() { this->bar(); }
+/// };
+/// @endcode
+class CXXThisExpr : public Expr {
+ SourceLocation Loc;
+
+public:
+ CXXThisExpr(SourceLocation L, QualType Type)
+ : Expr(CXXThisExprClass, Type,
+ // 'this' is type-dependent if the class type of the enclosing
+ // member function is dependent (C++ [temp.dep.expr]p2)
+ Type->isDependentType(), Type->isDependentType()),
+ Loc(L) { }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXThisExprClass;
+ }
+ static bool classof(const CXXThisExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles
+/// 'throw' and 'throw' assignment-expression. When
+/// assignment-expression isn't present, Op will be null.
+///
+class CXXThrowExpr : public Expr {
+ Stmt *Op;
+ SourceLocation ThrowLoc;
+public:
+ // Ty is the void type which is used as the result type of the
+ // exepression. The l is the location of the throw keyword. expr
+ // can by null, if the optional expression to throw isn't present.
+ CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) :
+ Expr(CXXThrowExprClass, Ty, false, false), Op(expr), ThrowLoc(l) {}
+ const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
+ Expr *getSubExpr() { return cast_or_null<Expr>(Op); }
+ void setSubExpr(Expr *E) { Op = E; }
+
+ SourceLocation getThrowLoc() const { return ThrowLoc; }
+ void setThrowLoc(SourceLocation L) { ThrowLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ if (getSubExpr() == 0)
+ return SourceRange(ThrowLoc, ThrowLoc);
+ return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXThrowExprClass;
+ }
+ static bool classof(const CXXThrowExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
+/// function call argument that was created from the corresponding
+/// parameter's default argument, when the call did not explicitly
+/// supply arguments for all of the parameters.
+class CXXDefaultArgExpr : public Expr {
+ ParmVarDecl *Param;
+public:
+ // Param is the parameter whose default argument is used by this
+ // expression.
+ explicit CXXDefaultArgExpr(ParmVarDecl *param)
+ : Expr(CXXDefaultArgExprClass,
+ param->hasUnparsedDefaultArg()? param->getType().getNonReferenceType()
+ : param->getDefaultArg()->getType()),
+ Param(param) { }
+
+ // Retrieve the parameter that the argument was created from.
+ const ParmVarDecl *getParam() const { return Param; }
+ ParmVarDecl *getParam() { return Param; }
+
+ // Retrieve the actual argument to the function call.
+ const Expr *getExpr() const { return Param->getDefaultArg(); }
+ Expr *getExpr() { return Param->getDefaultArg(); }
+
+ virtual SourceRange getSourceRange() const {
+ // Default argument expressions have no representation in the
+ // source, so they have an empty source range.
+ return SourceRange();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDefaultArgExprClass;
+ }
+ static bool classof(const CXXDefaultArgExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXTemporary - Represents a C++ temporary.
+class CXXTemporary {
+ /// Destructor - The destructor that needs to be called.
+ const CXXDestructorDecl *Destructor;
+
+ CXXTemporary(const CXXDestructorDecl *destructor)
+ : Destructor(destructor) { }
+ ~CXXTemporary() { }
+
+public:
+ static CXXTemporary *Create(ASTContext &C,
+ const CXXDestructorDecl *Destructor);
+ void Destroy(ASTContext &C);
+
+ const CXXDestructorDecl *getDestructor() const { return Destructor; }
+};
+
+/// CXXBindTemporaryExpr - Represents binding an expression to a temporary,
+/// so its destructor can be called later.
+class CXXBindTemporaryExpr : public Expr {
+ CXXTemporary *Temp;
+
+ Stmt *SubExpr;
+
+ CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
+ : Expr(CXXBindTemporaryExprClass,
+ subexpr->getType()), Temp(temp), SubExpr(subexpr) { }
+ ~CXXBindTemporaryExpr() { }
+
+public:
+ static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp,
+ Expr* SubExpr);
+ void Destroy(ASTContext &C);
+
+ CXXTemporary *getTemporary() { return Temp; }
+ const CXXTemporary *getTemporary() const { return Temp; }
+
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXBindTemporaryExprClass;
+ }
+ static bool classof(const CXXBindTemporaryExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXConstructExpr - Represents a call to a C++ constructor.
+class CXXConstructExpr : public Expr {
+ CXXConstructorDecl *Constructor;
+
+ bool Elidable;
+
+ Stmt **Args;
+ unsigned NumArgs;
+
+
+protected:
+ CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+ CXXConstructorDecl *d, bool elidable,
+ Expr **args, unsigned numargs);
+ ~CXXConstructExpr() { }
+
+public:
+ static CXXConstructExpr *Create(ASTContext &C, QualType T,
+ CXXConstructorDecl *D, bool Elidable,
+ Expr **Args, unsigned NumArgs);
+
+ void Destroy(ASTContext &C);
+
+ CXXConstructorDecl* getConstructor() const { return Constructor; }
+
+ /// \brief Whether this construction is elidable.
+ bool isElidable() const { return Elidable; }
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator arg_begin() { return Args; }
+ arg_iterator arg_end() { return Args + NumArgs; }
+ const_arg_iterator arg_begin() const { return Args; }
+ const_arg_iterator arg_end() const { return Args + NumArgs; }
+
+ unsigned getNumArgs() const { return NumArgs; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstructExprClass ||
+ T->getStmtClass() == CXXTemporaryObjectExprClass;
+ }
+ static bool classof(const CXXConstructExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
+/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c
+/// x = int(0.5);
+class CXXFunctionalCastExpr : public ExplicitCastExpr {
+ SourceLocation TyBeginLoc;
+ SourceLocation RParenLoc;
+public:
+ CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
+ SourceLocation tyBeginLoc, Expr *castExpr,
+ SourceLocation rParenLoc) :
+ ExplicitCastExpr(CXXFunctionalCastExprClass, ty, castExpr, writtenTy),
+ TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+
+ SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TyBeginLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXFunctionalCastExprClass;
+ }
+ static bool classof(const CXXFunctionalCastExpr *) { return true; }
+};
+
+/// @brief Represents a C++ functional cast expression that builds a
+/// temporary object.
+///
+/// This expression type represents a C++ "functional" cast
+/// (C++[expr.type.conv]) with N != 1 arguments that invokes a
+/// constructor to build a temporary object. If N == 0 but no
+/// constructor will be called (because the functional cast is
+/// performing a value-initialized an object whose class type has no
+/// user-declared constructors), CXXZeroInitValueExpr will represent
+/// the functional cast. Finally, with N == 1 arguments the functional
+/// cast expression will be represented by CXXFunctionalCastExpr.
+/// Example:
+/// @code
+/// struct X { X(int, float); }
+///
+/// X create_X() {
+/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
+/// };
+/// @endcode
+class CXXTemporaryObjectExpr : public CXXConstructExpr {
+ SourceLocation TyBeginLoc;
+ SourceLocation RParenLoc;
+
+public:
+ CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons,
+ QualType writtenTy, SourceLocation tyBeginLoc,
+ Expr **Args,unsigned NumArgs,
+ SourceLocation rParenLoc);
+
+ ~CXXTemporaryObjectExpr() { }
+
+ SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TyBeginLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTemporaryObjectExprClass;
+ }
+ static bool classof(const CXXTemporaryObjectExpr *) { return true; }
+};
+
+/// CXXZeroInitValueExpr - [C++ 5.2.3p2]
+/// Expression "T()" which creates a value-initialized rvalue of type
+/// T, which is either a non-class type or a class type without any
+/// user-defined constructors.
+///
+class CXXZeroInitValueExpr : public Expr {
+ SourceLocation TyBeginLoc;
+ SourceLocation RParenLoc;
+
+public:
+ CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc,
+ SourceLocation rParenLoc ) :
+ Expr(CXXZeroInitValueExprClass, ty, false, false),
+ TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
+
+ SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ /// @brief Whether this initialization expression was
+ /// implicitly-generated.
+ bool isImplicit() const {
+ return TyBeginLoc.isInvalid() && RParenLoc.isInvalid();
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TyBeginLoc, RParenLoc);
+ }
+
+ CXXZeroInitValueExpr* Clone(ASTContext &C) const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXZeroInitValueExprClass;
+ }
+ static bool classof(const CXXZeroInitValueExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for
+/// statement, e.g: "if (int x = f()) {...}".
+/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the
+/// decl that it references.
+///
+class CXXConditionDeclExpr : public DeclRefExpr {
+public:
+ CXXConditionDeclExpr(SourceLocation startLoc,
+ SourceLocation eqLoc, VarDecl *var)
+ : DeclRefExpr(CXXConditionDeclExprClass, var,
+ var->getType().getNonReferenceType(), startLoc,
+ var->getType()->isDependentType(),
+ /*FIXME:integral constant?*/
+ var->getType()->isDependentType()) {}
+
+ virtual void Destroy(ASTContext& Ctx);
+
+ SourceLocation getStartLoc() const { return getLocation(); }
+
+ VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); }
+ const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConditionDeclExprClass;
+ }
+ static bool classof(const CXXConditionDeclExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXNewExpr - A new expression for memory allocation and constructor calls,
+/// e.g: "new CXXNewExpr(foo)".
+class CXXNewExpr : public Expr {
+ // Was the usage ::new, i.e. is the global new to be used?
+ bool GlobalNew : 1;
+ // Was the form (type-id) used? Otherwise, it was new-type-id.
+ bool ParenTypeId : 1;
+ // Is there an initializer? If not, built-ins are uninitialized, else they're
+ // value-initialized.
+ bool Initializer : 1;
+ // Do we allocate an array? If so, the first SubExpr is the size expression.
+ bool Array : 1;
+ // The number of placement new arguments.
+ unsigned NumPlacementArgs : 14;
+ // The number of constructor arguments. This may be 1 even for non-class
+ // types; use the pseudo copy constructor.
+ unsigned NumConstructorArgs : 14;
+ // Contains an optional array size expression, any number of optional
+ // placement arguments, and any number of optional constructor arguments,
+ // in that order.
+ Stmt **SubExprs;
+ // Points to the allocation function used.
+ FunctionDecl *OperatorNew;
+ // Points to the deallocation function used in case of error. May be null.
+ FunctionDecl *OperatorDelete;
+ // Points to the constructor used. Cannot be null if AllocType is a record;
+ // it would still point at the default constructor (even an implicit one).
+ // Must be null for all other types.
+ CXXConstructorDecl *Constructor;
+
+ SourceLocation StartLoc;
+ SourceLocation EndLoc;
+
+public:
+ CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs,
+ unsigned numPlaceArgs, bool ParenTypeId, Expr *arraySize,
+ CXXConstructorDecl *constructor, bool initializer,
+ Expr **constructorArgs, unsigned numConsArgs,
+ FunctionDecl *operatorDelete, QualType ty,
+ SourceLocation startLoc, SourceLocation endLoc);
+ ~CXXNewExpr() {
+ delete[] SubExprs;
+ }
+
+ QualType getAllocatedType() const {
+ assert(getType()->isPointerType());
+ return getType()->getAsPointerType()->getPointeeType();
+ }
+
+ FunctionDecl *getOperatorNew() const { return OperatorNew; }
+ FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+ CXXConstructorDecl *getConstructor() const { return Constructor; }
+
+ bool isArray() const { return Array; }
+ Expr *getArraySize() {
+ return Array ? cast<Expr>(SubExprs[0]) : 0;
+ }
+ const Expr *getArraySize() const {
+ return Array ? cast<Expr>(SubExprs[0]) : 0;
+ }
+
+ unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ Expr *getPlacementArg(unsigned i) {
+ assert(i < NumPlacementArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + i]);
+ }
+ const Expr *getPlacementArg(unsigned i) const {
+ assert(i < NumPlacementArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + i]);
+ }
+
+ bool isGlobalNew() const { return GlobalNew; }
+ bool isParenTypeId() const { return ParenTypeId; }
+ bool hasInitializer() const { return Initializer; }
+
+ unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
+ Expr *getConstructorArg(unsigned i) {
+ assert(i < NumConstructorArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
+ }
+ const Expr *getConstructorArg(unsigned i) const {
+ assert(i < NumConstructorArgs && "Index out of range");
+ return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
+ }
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator placement_arg_begin() {
+ return SubExprs + Array;
+ }
+ arg_iterator placement_arg_end() {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+ const_arg_iterator placement_arg_begin() const {
+ return SubExprs + Array;
+ }
+ const_arg_iterator placement_arg_end() const {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+
+ arg_iterator constructor_arg_begin() {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+ arg_iterator constructor_arg_end() {
+ return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
+ }
+ const_arg_iterator constructor_arg_begin() const {
+ return SubExprs + Array + getNumPlacementArgs();
+ }
+ const_arg_iterator constructor_arg_end() const {
+ return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(StartLoc, EndLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNewExprClass;
+ }
+ static bool classof(const CXXNewExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
+/// calls, e.g. "delete[] pArray".
+class CXXDeleteExpr : public Expr {
+ // Is this a forced global delete, i.e. "::delete"?
+ bool GlobalDelete : 1;
+ // Is this the array form of delete, i.e. "delete[]"?
+ bool ArrayForm : 1;
+ // Points to the operator delete overload that is used. Could be a member.
+ FunctionDecl *OperatorDelete;
+ // The pointer expression to be deleted.
+ Stmt *Argument;
+ // Location of the expression.
+ SourceLocation Loc;
+public:
+ CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
+ FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
+ : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete),
+ ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg),
+ Loc(loc) { }
+
+ bool isGlobalDelete() const { return GlobalDelete; }
+ bool isArrayForm() const { return ArrayForm; }
+
+ FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+
+ Expr *getArgument() { return cast<Expr>(Argument); }
+ const Expr *getArgument() const { return cast<Expr>(Argument); }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(Loc, Argument->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDeleteExprClass;
+ }
+ static bool classof(const CXXDeleteExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// \brief Represents the name of a function that has not been
+/// resolved to any declaration.
+///
+/// Unresolved function names occur when a function name is
+/// encountered prior to an open parentheses ('(') in a C++ function
+/// call, and the function name itself did not resolve to a
+/// declaration. These function names can only be resolved when they
+/// form the postfix-expression of a function call, so that
+/// argument-dependent lookup finds declarations corresponding to
+/// these functions.
+
+/// @code
+/// template<typename T> void f(T x) {
+/// g(x); // g is an unresolved function name (that is also a dependent name)
+/// }
+/// @endcode
+class UnresolvedFunctionNameExpr : public Expr {
+ /// The name that was present in the source
+ DeclarationName Name;
+
+ /// The location of this name in the source code
+ SourceLocation Loc;
+
+public:
+ UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L)
+ : Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { }
+
+ /// \brief Retrieves the name that occurred in the source code.
+ DeclarationName getName() const { return Name; }
+
+ /// getLocation - Retrieves the location in the source code where
+ /// the name occurred.
+ SourceLocation getLocation() const { return Loc; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ UnresolvedFunctionNameExpr* Clone(ASTContext &C) const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedFunctionNameExprClass;
+ }
+ static bool classof(const UnresolvedFunctionNameExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_pod(int) == true
+/// __is_enum(std::string) == false
+class UnaryTypeTraitExpr : public Expr {
+ /// UTT - The trait.
+ UnaryTypeTrait UTT;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ /// QueriedType - The type we're testing.
+ QualType QueriedType;
+
+public:
+ UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried,
+ SourceLocation rparen, QualType ty)
+ : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()),
+ UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+
+ UnaryTypeTrait getTrait() const { return UTT; }
+
+ QualType getQueriedType() const { return QueriedType; }
+
+ bool EvaluateTrait() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryTypeTraitExprClass;
+ }
+ static bool classof(const UnaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// QualifiedDeclRefExpr - A reference to a declared variable,
+/// function, enum, etc., that includes a qualification, e.g.,
+/// "N::foo".
+class QualifiedDeclRefExpr : public DeclRefExpr {
+ /// QualifierRange - The source range that covers the
+ /// nested-name-specifier.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that qualifies this declaration
+ /// name.
+ NestedNameSpecifier *NNS;
+
+public:
+ QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
+ bool VD, SourceRange R, NestedNameSpecifier *NNS)
+ : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
+ QualifierRange(R), NNS(NNS) { }
+
+ /// \brief Retrieve the source range of the nested-name-specifier.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies this
+ /// declaration.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(QualifierRange.getBegin(), getLocation());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == QualifiedDeclRefExprClass;
+ }
+ static bool classof(const QualifiedDeclRefExpr *) { return true; }
+};
+
+/// \brief A qualified reference to a name whose declaration cannot
+/// yet be resolved.
+///
+/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that
+/// it expresses a qualified reference to a declaration such as
+/// X<T>::value. The difference, however, is that an
+/// UnresolvedDeclRefExpr node is used only within C++ templates when
+/// the qualification (e.g., X<T>::) refers to a dependent type. In
+/// this case, X<T>::value cannot resolve to a declaration because the
+/// declaration will differ from on instantiation of X<T> to the
+/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
+/// qualifier (X<T>::) and the name of the entity being referenced
+/// ("value"). Such expressions will instantiate to
+/// QualifiedDeclRefExprs.
+class UnresolvedDeclRefExpr : public Expr {
+ /// The name of the entity we will be referencing.
+ DeclarationName Name;
+
+ /// Location of the name of the declaration we're referencing.
+ SourceLocation Loc;
+
+ /// QualifierRange - The source range that covers the
+ /// nested-name-specifier.
+ SourceRange QualifierRange;
+
+ /// \brief The nested-name-specifier that qualifies this unresolved
+ /// declaration name.
+ NestedNameSpecifier *NNS;
+
+public:
+ UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
+ SourceRange R, NestedNameSpecifier *NNS)
+ : Expr(UnresolvedDeclRefExprClass, T, true, true),
+ Name(N), Loc(L), QualifierRange(R), NNS(NNS) { }
+
+ /// \brief Retrieve the name that this expression refers to.
+ DeclarationName getDeclName() const { return Name; }
+
+ /// \brief Retrieve the location of the name within the expression.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Retrieve the source range of the nested-name-specifier.
+ SourceRange getQualifierRange() const { return QualifierRange; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies this
+ /// declaration.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(QualifierRange.getBegin(), getLocation());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedDeclRefExprClass;
+ }
+ static bool classof(const UnresolvedDeclRefExpr *) { return true; }
+
+ virtual StmtIterator child_begin();
+ virtual StmtIterator child_end();
+};
+
+class CXXExprWithTemporaries : public Expr {
+ Stmt *SubExpr;
+
+ CXXTemporary **Temps;
+ unsigned NumTemps;
+
+ CXXExprWithTemporaries(Expr *subexpr, CXXTemporary **temps,
+ unsigned numtemps);
+ ~CXXExprWithTemporaries();
+
+public:
+ static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
+ CXXTemporary **Temps,
+ unsigned NumTemps);
+ void Destroy(ASTContext &C);
+
+ unsigned getNumTemporaries() const { return NumTemps; }
+ CXXTemporary *getTemporary(unsigned i) {
+ assert(i < NumTemps && "Index out of range");
+ return Temps[i];
+ }
+ const CXXTemporary *getTemporary(unsigned i) const {
+ assert(i < NumTemps && "Index out of range");
+ return Temps[i];
+ }
+
+ void removeLastTemporary() { NumTemps--; }
+
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXExprWithTemporariesClass;
+ }
+ static bool classof(const CXXExprWithTemporaries *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// \brief Describes an explicit type conversion that uses functional
+/// notion but could not be resolved because one or more arguments are
+/// type-dependent.
+///
+/// The explicit type conversions expressed by
+/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN),
+/// where \c T is some type and \c a1, a2, ..., aN are values, and
+/// either \C T is a dependent type or one or more of the \c a's is
+/// type-dependent. For example, this would occur in a template such
+/// as:
+///
+/// \code
+/// template<typename T, typename A1>
+/// inline T make_a(const A1& a1) {
+/// return T(a1);
+/// }
+/// \endcode
+///
+/// When the returned expression is instantiated, it may resolve to a
+/// constructor call, conversion function call, or some kind of type
+/// conversion.
+class CXXUnresolvedConstructExpr : public Expr {
+ /// \brief The starting location of the type
+ SourceLocation TyBeginLoc;
+
+ /// \brief The type being constructed.
+ QualType Type;
+
+ /// \brief The location of the left parentheses ('(').
+ SourceLocation LParenLoc;
+
+ /// \brief The location of the right parentheses (')').
+ SourceLocation RParenLoc;
+
+ /// \brief The number of arguments used to construct the type.
+ unsigned NumArgs;
+
+ CXXUnresolvedConstructExpr(SourceLocation TyBegin,
+ QualType T,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+public:
+ static CXXUnresolvedConstructExpr *Create(ASTContext &C,
+ SourceLocation TyBegin,
+ QualType T,
+ SourceLocation LParenLoc,
+ Expr **Args,
+ unsigned NumArgs,
+ SourceLocation RParenLoc);
+
+ /// \brief Retrieve the source location where the type begins.
+ SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+ void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
+
+ /// \brief Retrieve the type that is being constructed, as specified
+ /// in the source code.
+ QualType getTypeAsWritten() const { return Type; }
+ void setTypeAsWritten(QualType T) { Type = T; }
+
+ /// \brief Retrieve the location of the left parentheses ('(') that
+ /// precedes the argument list.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+ /// \brief Retrieve the location of the right parentheses (')') that
+ /// follows the argument list.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ /// \brief Retrieve the number of arguments.
+ unsigned arg_size() const { return NumArgs; }
+
+ typedef Expr** arg_iterator;
+ arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
+ arg_iterator arg_end() { return arg_begin() + NumArgs; }
+
+ Expr *getArg(unsigned I) {
+ assert(I < NumArgs && "Argument index out-of-range");
+ return *(arg_begin() + I);
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TyBeginLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUnresolvedConstructExprClass;
+ }
+ static bool classof(const CXXUnresolvedConstructExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// \brief
+class CXXUnresolvedMemberExpr : public Expr {
+ /// \brief The expression for the base pointer or class reference,
+ /// e.g., the \c x in x.f.
+ Stmt *Base;
+
+ /// \brief Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ bool IsArrow;
+
+ /// \brief The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The member to which this member expression refers, which
+ /// can be name, overloaded operator, or destructor.
+ /// FIXME: could also be a template-id, and we might have a
+ /// nested-name-specifier as well.
+ DeclarationName Member;
+
+ /// \brief The location of the member name.
+ SourceLocation MemberLoc;
+
+public:
+ CXXUnresolvedMemberExpr(ASTContext &C,
+ Expr *Base, bool IsArrow,
+ SourceLocation OperatorLoc,
+ DeclarationName Member,
+ SourceLocation MemberLoc)
+ : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
+ Base(Base), IsArrow(IsArrow), OperatorLoc(OperatorLoc),
+ Member(Member), MemberLoc(MemberLoc) { }
+
+ /// \brief Retrieve the base object of this member expressions,
+ /// e.g., the \c x in \c x.m.
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr *E) { Base = E; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+ void setArrow(bool A) { IsArrow = A; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+ void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMember() const { return Member; }
+ void setMember(DeclarationName N) { Member = N; }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(Base->getSourceRange().getBegin(),
+ MemberLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUnresolvedMemberExprClass;
+ }
+ static bool classof(const CXXUnresolvedMemberExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
new file mode 100644
index 000000000000..51b99610cd9d
--- /dev/null
+++ b/include/clang/AST/ExprObjC.h
@@ -0,0 +1,494 @@
+//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExprObjC interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPROBJC_H
+#define LLVM_CLANG_AST_EXPROBJC_H
+
+#include "clang/AST/Expr.h"
+#include "clang/Basic/IdentifierTable.h"
+
+namespace clang {
+ class IdentifierInfo;
+ class ASTContext;
+ class ObjCMethodDecl;
+ class ObjCPropertyDecl;
+
+/// ObjCStringLiteral, used for Objective-C string literals
+/// i.e. @"foo".
+class ObjCStringLiteral : public Expr {
+ Stmt *String;
+ SourceLocation AtLoc;
+public:
+ ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
+ : Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {}
+ explicit ObjCStringLiteral(EmptyShell Empty)
+ : Expr(ObjCStringLiteralClass, Empty) {}
+
+ StringLiteral *getString() { return cast<StringLiteral>(String); }
+ const StringLiteral *getString() const { return cast<StringLiteral>(String); }
+ void setString(StringLiteral *S) { String = S; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, String->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCStringLiteralClass;
+ }
+ static bool classof(const ObjCStringLiteral *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
+/// and behavior as StringLiteral except that the string initializer is obtained
+/// from ASTContext with the encoding type as an argument.
+class ObjCEncodeExpr : public Expr {
+ QualType EncType;
+ SourceLocation AtLoc, RParenLoc;
+public:
+ ObjCEncodeExpr(QualType T, QualType ET,
+ SourceLocation at, SourceLocation rp)
+ : Expr(ObjCEncodeExprClass, T), EncType(ET), AtLoc(at), RParenLoc(rp) {}
+
+ explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
+
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ QualType getEncodedType() const { return EncType; }
+ void setEncodedType(QualType T) { EncType = T; }
+
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCEncodeExprClass;
+ }
+ static bool classof(const ObjCEncodeExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCSelectorExpr used for @selector in Objective-C.
+class ObjCSelectorExpr : public Expr {
+ Selector SelName;
+ SourceLocation AtLoc, RParenLoc;
+public:
+ ObjCSelectorExpr(QualType T, Selector selInfo,
+ SourceLocation at, SourceLocation rp)
+ : Expr(ObjCSelectorExprClass, T), SelName(selInfo), AtLoc(at), RParenLoc(rp){}
+ explicit ObjCSelectorExpr(EmptyShell Empty)
+ : Expr(ObjCSelectorExprClass, Empty) {}
+
+ Selector getSelector() const { return SelName; }
+ void setSelector(Selector S) { SelName = S; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, RParenLoc);
+ }
+
+ /// getNumArgs - Return the number of actual arguments to this call.
+ unsigned getNumArgs() const { return SelName.getNumArgs(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCSelectorExprClass;
+ }
+ static bool classof(const ObjCSelectorExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used
+/// as: @protocol(foo), as in:
+/// obj conformsToProtocol:@protocol(foo)]
+/// The return type is "Protocol*".
+class ObjCProtocolExpr : public Expr {
+ ObjCProtocolDecl *Protocol;
+ SourceLocation AtLoc, RParenLoc;
+public:
+ ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
+ SourceLocation at, SourceLocation rp)
+ : Expr(ObjCProtocolExprClass, T), Protocol(protocol),
+ AtLoc(at), RParenLoc(rp) {}
+ explicit ObjCProtocolExpr(EmptyShell Empty)
+ : Expr(ObjCProtocolExprClass, Empty) {}
+
+ ObjCProtocolDecl *getProtocol() const { return Protocol; }
+ void setProtocol(ObjCProtocolDecl *P) { Protocol = P; }
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCProtocolExprClass;
+ }
+ static bool classof(const ObjCProtocolExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
+class ObjCIvarRefExpr : public Expr {
+ class ObjCIvarDecl *D;
+ SourceLocation Loc;
+ Stmt *Base;
+ bool IsArrow:1; // True if this is "X->F", false if this is "X.F".
+ bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
+
+public:
+ ObjCIvarRefExpr(ObjCIvarDecl *d,
+ QualType t, SourceLocation l, Expr *base=0,
+ bool arrow = false, bool freeIvar = false) :
+ Expr(ObjCIvarRefExprClass, t), D(d),
+ Loc(l), Base(base), IsArrow(arrow),
+ IsFreeIvar(freeIvar) {}
+
+ explicit ObjCIvarRefExpr(EmptyShell Empty)
+ : Expr(ObjCIvarRefExprClass, Empty) {}
+
+ ObjCIvarDecl *getDecl() { return D; }
+ const ObjCIvarDecl *getDecl() const { return D; }
+ void setDecl(ObjCIvarDecl *d) { D = d; }
+
+ const Expr *getBase() const { return cast<Expr>(Base); }
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr * base) { Base = base; }
+
+ bool isArrow() const { return IsArrow; }
+ bool isFreeIvar() const { return IsFreeIvar; }
+ void setIsArrow(bool A) { IsArrow = A; }
+ void setIsFreeIvar(bool A) { IsFreeIvar = A; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return isFreeIvar() ? SourceRange(Loc)
+ : SourceRange(getBase()->getLocStart(), Loc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIvarRefExprClass;
+ }
+ static bool classof(const ObjCIvarRefExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
+/// property.
+///
+class ObjCPropertyRefExpr : public Expr {
+private:
+ ObjCPropertyDecl *AsProperty;
+ SourceLocation IdLoc;
+ Stmt *Base;
+public:
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ SourceLocation l, Expr *base)
+ : Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) {
+ }
+
+ explicit ObjCPropertyRefExpr(EmptyShell Empty)
+ : Expr(ObjCPropertyRefExprClass, Empty) {}
+
+ ObjCPropertyDecl *getProperty() const { return AsProperty; }
+ void setProperty(ObjCPropertyDecl *D) { AsProperty = D; }
+
+ const Expr *getBase() const { return cast<Expr>(Base); }
+ Expr *getBase() { return cast<Expr>(Base); }
+ void setBase(Expr *base) { Base = base; }
+
+ SourceLocation getLocation() const { return IdLoc; }
+ void setLocation(SourceLocation L) { IdLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getBase()->getLocStart(), IdLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCPropertyRefExprClass;
+ }
+ static bool classof(const ObjCPropertyRefExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCKVCRefExpr - A dot-syntax expression to access "implicit" properties
+/// (i.e. methods following the property naming convention). KVC stands for
+/// Key Value Encoding, a generic concept for accessing or setting a 'Key'
+/// value for an object.
+///
+class ObjCKVCRefExpr : public Expr {
+ ObjCMethodDecl *Setter;
+ ObjCMethodDecl *Getter;
+ SourceLocation Loc;
+ // FIXME: Swizzle these into a single pointer.
+ Stmt *Base;
+ ObjCInterfaceDecl *ClassProp;
+ SourceLocation ClassLoc;
+
+public:
+ ObjCKVCRefExpr(ObjCMethodDecl *getter,
+ QualType t,
+ ObjCMethodDecl *setter,
+ SourceLocation l, Expr *base)
+ : Expr(ObjCKVCRefExprClass, t), Setter(setter),
+ Getter(getter), Loc(l), Base(base), ClassProp(0),
+ ClassLoc(SourceLocation()) {
+ }
+ ObjCKVCRefExpr(ObjCMethodDecl *getter,
+ QualType t,
+ ObjCMethodDecl *setter,
+ SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL)
+ : Expr(ObjCKVCRefExprClass, t), Setter(setter),
+ Getter(getter), Loc(l), Base(0), ClassProp(C), ClassLoc(CL) {
+ }
+ explicit ObjCKVCRefExpr(EmptyShell Empty) : Expr(ObjCKVCRefExprClass, Empty){}
+
+ ObjCMethodDecl *getGetterMethod() const { return Getter; }
+ ObjCMethodDecl *getSetterMethod() const { return Setter; }
+ ObjCInterfaceDecl *getClassProp() const { return ClassProp; }
+ void setGetterMethod(ObjCMethodDecl *D) { Getter = D; }
+ void setSetterMethod(ObjCMethodDecl *D) { Setter = D; }
+ void setClassProp(ObjCInterfaceDecl *D) { ClassProp = D; }
+
+ virtual SourceRange getSourceRange() const {
+ if (Base)
+ return SourceRange(getBase()->getLocStart(), Loc);
+ return SourceRange(ClassLoc, Loc);
+ }
+ const Expr *getBase() const { return cast_or_null<Expr>(Base); }
+ Expr *getBase() { return cast_or_null<Expr>(Base); }
+ void setBase(Expr *base) { Base = base; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getClassLoc() const { return ClassLoc; }
+ void setClassLoc(SourceLocation L) { ClassLoc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCKVCRefExprClass;
+ }
+ static bool classof(const ObjCKVCRefExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+class ObjCMessageExpr : public Expr {
+ // SubExprs - The receiver and arguments of the message expression.
+ Stmt **SubExprs;
+
+ // NumArgs - The number of arguments (not including the receiver) to the
+ // message expression.
+ unsigned NumArgs;
+
+ // A unigue name for this message.
+ Selector SelName;
+
+ // A method prototype for this message (optional).
+ // FIXME: Since method decls contain the selector, and most messages have a
+ // prototype, consider devising a scheme for unifying SelName/MethodProto.
+ ObjCMethodDecl *MethodProto;
+
+ SourceLocation LBracloc, RBracloc;
+
+ // Constants for indexing into SubExprs.
+ enum { RECEIVER=0, ARGS_START=1 };
+
+ // Bit-swizzling flags.
+ enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
+ unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; }
+
+public:
+ /// This constructor is used to represent class messages where the
+ /// ObjCInterfaceDecl* of the receiver is not known.
+ ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
+ QualType retType, ObjCMethodDecl *methDecl,
+ SourceLocation LBrac, SourceLocation RBrac,
+ Expr **ArgExprs, unsigned NumArgs);
+
+ /// This constructor is used to represent class messages where the
+ /// ObjCInterfaceDecl* of the receiver is known.
+ // FIXME: clsName should be typed to ObjCInterfaceType
+ ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
+ QualType retType, ObjCMethodDecl *methDecl,
+ SourceLocation LBrac, SourceLocation RBrac,
+ Expr **ArgExprs, unsigned NumArgs);
+
+ // constructor for instance messages.
+ ObjCMessageExpr(Expr *receiver, Selector selInfo,
+ QualType retType, ObjCMethodDecl *methDecl,
+ SourceLocation LBrac, SourceLocation RBrac,
+ Expr **ArgExprs, unsigned NumArgs);
+
+ explicit ObjCMessageExpr(EmptyShell Empty)
+ : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {}
+
+ ~ObjCMessageExpr() {
+ delete [] SubExprs;
+ }
+
+ /// getReceiver - Returns the receiver of the message expression.
+ /// This can be NULL if the message is for class methods. For
+ /// class methods, use getClassName.
+ /// FIXME: need to handle/detect 'super' usage within a class method.
+ Expr *getReceiver() {
+ uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
+ return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
+ }
+ const Expr *getReceiver() const {
+ return const_cast<ObjCMessageExpr*>(this)->getReceiver();
+ }
+ // FIXME: need setters for different receiver types.
+ void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; }
+ Selector getSelector() const { return SelName; }
+ void setSelector(Selector S) { SelName = S; }
+
+ const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
+ ObjCMethodDecl *getMethodDecl() { return MethodProto; }
+ void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; }
+
+ typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
+
+ /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
+ /// and IdentifierInfo* of the invoked class. Both can be NULL if this
+ /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none
+ /// was available when this ObjCMessageExpr object was constructed.
+ ClassInfo getClassInfo() const;
+ void setClassInfo(const ClassInfo &C);
+
+ /// getClassName - For class methods, this returns the invoked class,
+ /// and returns NULL otherwise. For instance methods, use getReceiver.
+ IdentifierInfo *getClassName() const {
+ return getClassInfo().second;
+ }
+
+ /// getNumArgs - Return the number of actual arguments to this call.
+ unsigned getNumArgs() const { return NumArgs; }
+ void setNumArgs(unsigned nArgs) {
+ NumArgs = nArgs;
+ // FIXME: should always allocate SubExprs via the ASTContext's
+ // allocator.
+ if (!SubExprs)
+ SubExprs = new Stmt* [NumArgs + 1];
+ }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast<Expr>(SubExprs[Arg+ARGS_START]);
+ }
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ SubExprs[Arg+ARGS_START] = ArgExpr;
+ }
+
+ SourceLocation getLeftLoc() const { return LBracloc; }
+ SourceLocation getRightLoc() const { return RBracloc; }
+
+ void setLeftLoc(SourceLocation L) { LBracloc = L; }
+ void setRightLoc(SourceLocation L) { RBracloc = L; }
+
+ void setSourceRange(SourceRange R) {
+ LBracloc = R.getBegin();
+ RBracloc = R.getEnd();
+ }
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LBracloc, RBracloc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCMessageExprClass;
+ }
+ static bool classof(const ObjCMessageExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ arg_iterator arg_begin() { return &SubExprs[ARGS_START]; }
+ arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; }
+ const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; }
+ const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; }
+};
+
+/// ObjCSuperExpr - Represents the "super" expression in Objective-C,
+/// which refers to the object on which the current method is executing.
+class ObjCSuperExpr : public Expr {
+ SourceLocation Loc;
+public:
+ ObjCSuperExpr(SourceLocation L, QualType Type)
+ : Expr(ObjCSuperExprClass, Type), Loc(L) { }
+ explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {}
+
+ SourceLocation getLoc() const { return Loc; }
+ void setLoc(SourceLocation L) { Loc = L; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCSuperExprClass;
+ }
+ static bool classof(const ObjCSuperExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
new file mode 100644
index 000000000000..4219bd507a90
--- /dev/null
+++ b/include/clang/AST/ExternalASTSource.h
@@ -0,0 +1,184 @@
+//===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalASTSource interface, which enables
+// construction of AST nodes from some external source.x
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+namespace clang {
+
+class ASTConsumer;
+class Decl;
+class DeclContext;
+class ExternalSemaSource; // layering violation required for downcasting
+class Stmt;
+
+/// \brief The deserialized representation of a set of declarations
+/// with the same name that are visible in a given context.
+struct VisibleDeclaration {
+ /// \brief The name of the declarations.
+ DeclarationName Name;
+
+ /// \brief The ID numbers of all of the declarations with this name.
+ ///
+ /// These declarations have not necessarily been de-serialized.
+ llvm::SmallVector<unsigned, 4> Declarations;
+};
+
+/// \brief Abstract interface for external sources of AST nodes.
+///
+/// External AST sources provide AST nodes constructed from some
+/// external source, such as a precompiled header. External AST
+/// sources can resolve types and declarations from abstract IDs into
+/// actual type and declaration nodes, and read parts of declaration
+/// contexts.
+class ExternalASTSource {
+ /// \brief Whether this AST source also provides information for
+ /// semantic analysis.
+ bool SemaSource;
+
+ friend class ExternalSemaSource;
+
+public:
+ ExternalASTSource() : SemaSource(false) { }
+
+ virtual ~ExternalASTSource();
+
+ /// \brief Resolve a type ID into a type, potentially building a new
+ /// type.
+ virtual QualType GetType(uint32_t ID) = 0;
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ virtual Decl *GetDecl(uint32_t ID) = 0;
+
+ /// \brief Resolve the offset of a statement in the decl stream into a
+ /// statement.
+ ///
+ /// This operation will read a new statement from the external
+ /// source each time it is called, and is meant to be used via a
+ /// LazyOffsetPtr.
+ virtual Stmt *GetDeclStmt(uint64_t Offset) = 0;
+
+ /// \brief Read all of the declarations lexically stored in a
+ /// declaration context.
+ ///
+ /// \param DC The declaration context whose declarations will be
+ /// read.
+ ///
+ /// \param Decls Vector that will contain the declarations loaded
+ /// from the external source. The caller is responsible for merging
+ /// these declarations with any declarations already stored in the
+ /// declaration context.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ virtual bool ReadDeclsLexicallyInContext(DeclContext *DC,
+ llvm::SmallVectorImpl<uint32_t> &Decls) = 0;
+
+ /// \brief Read all of the declarations visible from a declaration
+ /// context.
+ ///
+ /// \param DC The declaration context whose visible declarations
+ /// will be read.
+ ///
+ /// \param Decls A vector of visible declaration structures,
+ /// providing the mapping from each name visible in the declaration
+ /// context to the declaration IDs of declarations with that name.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ virtual bool ReadDeclsVisibleInContext(DeclContext *DC,
+ llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0;
+
+ /// \brief Function that will be invoked when we begin parsing a new
+ /// translation unit involving this external AST source.
+ virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
+
+ /// \brief Print any statistics that have been gathered regarding
+ /// the external AST source.
+ virtual void PrintStats();
+};
+
+/// \brief A lazy pointer to an AST node (of base type T) that resides
+/// within an external AST source.
+///
+/// The AST node is identified within the external AST source by a
+/// 63-bit offset, and can be retrieved via an operation on the
+/// external AST source itself.
+template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)>
+struct LazyOffsetPtr {
+ /// \brief Either a pointer to an AST node or the offset within the
+ /// external AST source where the AST node can be found.
+ ///
+ /// If the low bit is clear, a pointer to the AST node. If the low
+ /// bit is set, the upper 63 bits are the offset.
+ mutable uint64_t Ptr;
+
+public:
+ LazyOffsetPtr() : Ptr(0) { }
+
+ explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
+ explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
+ assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
+ if (Offset == 0)
+ Ptr = 0;
+ }
+
+ LazyOffsetPtr &operator=(T *Ptr) {
+ this->Ptr = reinterpret_cast<uint64_t>(Ptr);
+ return *this;
+ }
+
+ LazyOffsetPtr &operator=(uint64_t Offset) {
+ assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
+ if (Offset == 0)
+ Ptr = 0;
+ else
+ Ptr = (Offset << 1) | 0x01;
+
+ return *this;
+ }
+
+ /// \brief Whether this pointer is non-NULL.
+ ///
+ /// This operation does not require the AST node to be deserialized.
+ operator bool() const { return Ptr != 0; }
+
+ /// \brief Whether this pointer is currently stored as an offset.
+ bool isOffset() const { return Ptr & 0x01; }
+
+ /// \brief Retrieve the pointer to the AST node that this lazy pointer
+ ///
+ /// \param Source the external AST source.
+ ///
+ /// \returns a pointer to the AST node.
+ T* get(ExternalASTSource *Source) const {
+ if (isOffset()) {
+ assert(Source &&
+ "Cannot deserialize a lazy pointer without an AST source");
+ Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
+ }
+ return reinterpret_cast<T*>(Ptr);
+ }
+};
+
+/// \brief A lazy pointer to a statement.
+typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetDeclStmt> LazyDeclStmtPtr;
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
new file mode 100644
index 000000000000..4eea1031f063
--- /dev/null
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -0,0 +1,183 @@
+//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NestedNameSpecifier class, which represents
+// a C++ nested-name-specifier.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
+#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class ASTContext;
+class NamespaceDecl;
+class IdentifierInfo;
+class PrintingPolicy;
+class Type;
+
+/// \brief Represents a C++ nested name specifier, such as
+/// "::std::vector<int>::".
+///
+/// C++ nested name specifiers are the prefixes to qualified
+/// namespaces. For example, "foo::" in "foo::x" is a nested name
+/// specifier. Nested name specifiers are made up of a sequence of
+/// specifiers, each of which can be a namespace, type, identifier
+/// (for dependent names), or the global specifier ('::', must be the
+/// first specifier).
+class NestedNameSpecifier : public llvm::FoldingSetNode {
+ /// \brief The nested name specifier that precedes this nested name
+ /// specifier.
+ ///
+ /// The pointer is the nested-name-specifier that precedes this
+ /// one. The integer stores one of the first four values of type
+ /// SpecifierKind.
+ llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
+
+ /// \brief The last component in the nested name specifier, which
+ /// can be an identifier, a declaration, or a type.
+ ///
+ /// When the pointer is NULL, this specifier represents the global
+ /// specifier '::'. Otherwise, the pointer is one of
+ /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
+ /// specifier as encoded within the prefix.
+ void* Specifier;
+
+public:
+ /// \brief The kind of specifier that completes this nested name
+ /// specifier.
+ enum SpecifierKind {
+ /// \brief An identifier, stored as an IdentifierInfo*.
+ Identifier = 0,
+ /// \brief A namespace, stored as a Namespace*.
+ Namespace = 1,
+ /// \brief A type, stored as a Type*.
+ TypeSpec = 2,
+ /// \brief A type that was preceded by the 'template' keyword,
+ /// stored as a Type*.
+ TypeSpecWithTemplate = 3,
+ /// \brief The global specifier '::'. There is no stored value.
+ Global = 4
+ };
+
+private:
+ /// \brief Builds the global specifier.
+ NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
+
+ /// \brief Copy constructor used internally to clone nested name
+ /// specifiers.
+ NestedNameSpecifier(const NestedNameSpecifier &Other)
+ : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
+ Specifier(Other.Specifier) {
+ }
+
+ NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement
+
+ /// \brief Either find or insert the given nested name specifier
+ /// mockup in the given context.
+ static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
+ const NestedNameSpecifier &Mockup);
+
+public:
+ /// \brief Builds a specifier combining a prefix and an identifier.
+ ///
+ /// The prefix must be dependent, since nested name specifiers
+ /// referencing an identifier are only permitted when the identifier
+ /// cannot be resolved.
+ static NestedNameSpecifier *Create(ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ IdentifierInfo *II);
+
+ /// \brief Builds a nested name specifier that names a namespace.
+ static NestedNameSpecifier *Create(ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceDecl *NS);
+
+ /// \brief Builds a nested name specifier that names a type.
+ static NestedNameSpecifier *Create(ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ bool Template, Type *T);
+
+ /// \brief Returns the nested name specifier representing the global
+ /// scope.
+ static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
+
+ /// \brief Return the prefix of this nested name specifier.
+ ///
+ /// The prefix contains all of the parts of the nested name
+ /// specifier that preced this current specifier. For example, for a
+ /// nested name specifier that represents "foo::bar::", the current
+ /// specifier will contain "bar::" and the prefix will contain
+ /// "foo::".
+ NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
+
+ /// \brief Determine what kind of nested name specifier is stored.
+ SpecifierKind getKind() const {
+ if (Specifier == 0)
+ return Global;
+ return (SpecifierKind)Prefix.getInt();
+ }
+
+ /// \brief Retrieve the identifier stored in this nested name
+ /// specifier.
+ IdentifierInfo *getAsIdentifier() const {
+ if (Prefix.getInt() == Identifier)
+ return (IdentifierInfo *)Specifier;
+
+ return 0;
+ }
+
+ /// \brief Retrieve the namespace stored in this nested name
+ /// specifier.
+ NamespaceDecl *getAsNamespace() const {
+ if (Prefix.getInt() == Namespace)
+ return (NamespaceDecl *)Specifier;
+
+ return 0;
+ }
+
+ /// \brief Retrieve the type stored in this nested name specifier.
+ Type *getAsType() const {
+ if (Prefix.getInt() == TypeSpec ||
+ Prefix.getInt() == TypeSpecWithTemplate)
+ return (Type *)Specifier;
+
+ return 0;
+ }
+
+ /// \brief Whether this nested name specifier refers to a dependent
+ /// type or not.
+ bool isDependent() const;
+
+ /// \brief Print this nested name specifier to the given output
+ /// stream.
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(Prefix.getOpaqueValue());
+ ID.AddPointer(Specifier);
+ }
+
+ void Destroy(ASTContext &Context);
+
+ /// \brief Dump the nested name specifier to standard output to aid
+ /// in debugging.
+ void dump();
+};
+
+}
+
+#endif
diff --git a/include/clang/AST/PPCBuiltins.def b/include/clang/AST/PPCBuiltins.def
new file mode 100644
index 000000000000..b8c791286e55
--- /dev/null
+++ b/include/clang/AST/PPCBuiltins.def
@@ -0,0 +1,24 @@
+//===--- PPCBuiltins.def - PowerPC Builtin function database ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PowerPC-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
+// adding stuff on demand.
+
+// The format of this database matches clang/AST/Builtins.def.
+
+// This is just a placeholder, the types and attributes are wrong.
+BUILTIN(__builtin_altivec_abs_v4sf , "ii" , "nc")
+// FIXME: Obviously incomplete.
+
+#undef BUILTIN
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
new file mode 100644
index 000000000000..c669991ccc08
--- /dev/null
+++ b/include/clang/AST/ParentMap.h
@@ -0,0 +1,50 @@
+//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ParentMap class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARENTMAP_H
+#define LLVM_CLANG_PARENTMAP_H
+
+namespace clang {
+class Stmt;
+class Expr;
+
+class ParentMap {
+ void* Impl;
+public:
+ ParentMap(Stmt* ASTRoot);
+ ~ParentMap();
+
+ Stmt *getParent(Stmt*) const;
+ Stmt *getParentIgnoreParens(Stmt *) const;
+
+ const Stmt *getParent(const Stmt* S) const {
+ return getParent(const_cast<Stmt*>(S));
+ }
+
+ const Stmt *getParentIgnoreParens(const Stmt *S) const {
+ return getParentIgnoreParens(const_cast<Stmt*>(S));
+ }
+
+ bool hasParent(Stmt* S) const {
+ return getParent(S) != 0;
+ }
+
+ bool isConsumedExpr(Expr *E) const;
+
+ bool isConsumedExpr(const Expr *E) const {
+ return isConsumedExpr(const_cast<Expr*>(E));
+ }
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
new file mode 100644
index 000000000000..385602b1fb9c
--- /dev/null
+++ b/include/clang/AST/PrettyPrinter.h
@@ -0,0 +1,86 @@
+//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PrinterHelper interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
+#define LLVM_CLANG_AST_PRETTY_PRINTER_H
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class Stmt;
+class TagDecl;
+
+class PrinterHelper {
+public:
+ virtual ~PrinterHelper();
+ virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0;
+};
+
+/// \brief Describes how types, statements, expressions, and
+/// declarations should be printed.
+struct PrintingPolicy {
+ /// \brief Create a default printing policy for C.
+ PrintingPolicy()
+ : Indentation(2), CPlusPlus(false), SuppressSpecifiers(false),
+ SuppressTag(false), SuppressTagKind(false), Dump(false) { }
+
+ /// \brief The number of spaces to use to indent each line.
+ unsigned Indentation : 8;
+
+ /// \brief Whether we're printing C++ code (otherwise, we're
+ /// printing C code).
+ bool CPlusPlus : 1;
+
+ /// \brief Whether we should suppress printing of the actual specifiers for
+ /// the given type or declaration.
+ ///
+ /// This flag is only used when we are printing declarators beyond
+ /// the first declarator within a declaration group. For example, given:
+ ///
+ /// \code
+ /// const int *x, *y;
+ /// \endcode
+ ///
+ /// SuppressSpecifiers will be false when printing the
+ /// declaration for "x", so that we will print "int *x"; it will be
+ /// \c true when we print "y", so that we suppress printing the
+ /// "const int" type specifier and instead only print the "*y".
+ bool SuppressSpecifiers : 1;
+
+ /// \brief Whether type printing should skip printing the actual tag type.
+ ///
+ /// This is used when the caller needs to print a tag definition in front
+ /// of the type, as in constructs like the following:
+ ///
+ /// \code
+ /// typedef struct { int x, y; } Point;
+ /// \endcode
+ bool SuppressTag : 1;
+
+ /// \brief If we are printing a tag type, suppresses printing of the
+ /// kind of tag, e.g., "struct", "union", "enum".
+ bool SuppressTagKind : 1;
+
+ /// \brief True when we are "dumping" rather than "pretty-printing",
+ /// where dumping involves printing the internal details of the AST
+ /// and pretty-printing involves printing something similar to
+ /// source code.
+ bool Dump : 1;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
new file mode 100644
index 000000000000..ab184563da23
--- /dev/null
+++ b/include/clang/AST/RecordLayout.h
@@ -0,0 +1,103 @@
+//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the RecordLayout interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
+#define LLVM_CLANG_AST_LAYOUTINFO_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+ class ASTContext;
+ class RecordDecl;
+
+/// ASTRecordLayout -
+/// This class contains layout information for one RecordDecl,
+/// which is a struct/union/class. The decl represented must be a definition,
+/// not a forward declaration.
+/// This class is also used to contain layout information for one
+/// ObjCInterfaceDecl. FIXME - Find appropriate name.
+/// These objects are managed by ASTContext.
+class ASTRecordLayout {
+ uint64_t Size; // Size of record in bits.
+ uint64_t NextOffset; // Next available offset
+ uint64_t *FieldOffsets;
+ unsigned Alignment; // Alignment of record in bits.
+ unsigned FieldCount; // Number of fields
+ friend class ASTContext;
+
+ ASTRecordLayout(uint64_t S = 0, unsigned A = 8)
+ : Size(S), NextOffset(S), Alignment(A), FieldCount(0) {}
+ ~ASTRecordLayout() {
+ delete [] FieldOffsets;
+ }
+
+ /// Initialize record layout. N is the number of fields in this record.
+ void InitializeLayout(unsigned N) {
+ FieldCount = N;
+ FieldOffsets = new uint64_t[N];
+ }
+
+ /// Finalize record layout. Adjust record size based on the alignment.
+ void FinalizeLayout(bool ForceNonEmpty = false) {
+ // In C++, records cannot be of size 0.
+ if (ForceNonEmpty && Size == 0)
+ Size = 8;
+ // Finally, round the size of the record up to the alignment of the
+ // record itself.
+ Size = (Size + (Alignment-1)) & ~(Alignment-1);
+ }
+
+ void SetFieldOffset(unsigned FieldNo, uint64_t Offset) {
+ assert (FieldNo < FieldCount && "Invalid Field No");
+ FieldOffsets[FieldNo] = Offset;
+ }
+
+ void SetAlignment(unsigned A) { Alignment = A; }
+
+ /// LayoutField - Field layout. StructPacking is the specified
+ /// packing alignment (maximum alignment) in bits to use for the
+ /// structure, or 0 if no packing alignment is specified.
+ void LayoutField(const FieldDecl *FD, unsigned FieldNo,
+ bool IsUnion, unsigned StructPacking,
+ ASTContext &Context);
+
+ ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
+ void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
+public:
+
+ /// getAlignment - Get the record alignment in bits.
+ unsigned getAlignment() const { return Alignment; }
+
+ /// getSize - Get the record size in bits.
+ uint64_t getSize() const { return Size; }
+
+ /// getFieldCount - Get the number of fields in the layout.
+ unsigned getFieldCount() const { return FieldCount; }
+
+ /// getFieldOffset - Get the offset of the given field index, in
+ /// bits.
+ uint64_t getFieldOffset(unsigned FieldNo) const {
+ assert (FieldNo < FieldCount && "Invalid Field No");
+ return FieldOffsets[FieldNo];
+ }
+
+ /// getNextOffset - Get the next available (unused) offset in the
+ /// structure, in bits.
+ uint64_t getNextOffset() const {
+ return NextOffset;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
new file mode 100644
index 000000000000..3656333d7423
--- /dev/null
+++ b/include/clang/AST/Stmt.h
@@ -0,0 +1,1223 @@
+//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Stmt interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMT_H
+#define LLVM_CLANG_AST_STMT_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/StmtIterator.h"
+#include "clang/AST/DeclGroup.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "clang/AST/ASTContext.h"
+#include <string>
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+ class ASTContext;
+ class Expr;
+ class Decl;
+ class ParmVarDecl;
+ class QualType;
+ class IdentifierInfo;
+ class SourceManager;
+ class StringLiteral;
+ class SwitchStmt;
+
+ //===----------------------------------------------------------------------===//
+ // ExprIterator - Iterators for iterating over Stmt* arrays that contain
+ // only Expr*. This is needed because AST nodes use Stmt* arrays to store
+ // references to children (to be compatible with StmtIterator).
+ //===----------------------------------------------------------------------===//
+
+ class Stmt;
+ class Expr;
+
+ class ExprIterator {
+ Stmt** I;
+ public:
+ ExprIterator(Stmt** i) : I(i) {}
+ ExprIterator() : I(0) {}
+ ExprIterator& operator++() { ++I; return *this; }
+ ExprIterator operator-(size_t i) { return I-i; }
+ ExprIterator operator+(size_t i) { return I+i; }
+ Expr* operator[](size_t idx);
+ // FIXME: Verify that this will correctly return a signed distance.
+ signed operator-(const ExprIterator& R) const { return I - R.I; }
+ Expr* operator*() const;
+ Expr* operator->() const;
+ bool operator==(const ExprIterator& R) const { return I == R.I; }
+ bool operator!=(const ExprIterator& R) const { return I != R.I; }
+ bool operator>(const ExprIterator& R) const { return I > R.I; }
+ bool operator>=(const ExprIterator& R) const { return I >= R.I; }
+ };
+
+ class ConstExprIterator {
+ Stmt* const * I;
+ public:
+ ConstExprIterator(Stmt* const* i) : I(i) {}
+ ConstExprIterator() : I(0) {}
+ ConstExprIterator& operator++() { ++I; return *this; }
+ ConstExprIterator operator+(size_t i) { return I+i; }
+ ConstExprIterator operator-(size_t i) { return I-i; }
+ const Expr * operator[](size_t idx) const;
+ signed operator-(const ConstExprIterator& R) const { return I - R.I; }
+ const Expr * operator*() const;
+ const Expr * operator->() const;
+ bool operator==(const ConstExprIterator& R) const { return I == R.I; }
+ bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
+ bool operator>(const ConstExprIterator& R) const { return I > R.I; }
+ bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
+ };
+
+//===----------------------------------------------------------------------===//
+// AST classes for statements.
+//===----------------------------------------------------------------------===//
+
+/// Stmt - This represents one statement.
+///
+class Stmt {
+public:
+ enum StmtClass {
+ NoStmtClass = 0,
+#define STMT(CLASS, PARENT) CLASS##Class,
+#define FIRST_STMT(CLASS) firstStmtConstant = CLASS##Class,
+#define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class,
+#define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class,
+#define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class
+#include "clang/AST/StmtNodes.def"
+};
+private:
+ const StmtClass sClass;
+
+ // Make vanilla 'new' and 'delete' illegal for Stmts.
+protected:
+ void* operator new(size_t bytes) throw() {
+ assert(0 && "Stmts cannot be allocated with regular 'new'.");
+ return 0;
+ }
+ void operator delete(void* data) throw() {
+ assert(0 && "Stmts cannot be released with regular 'delete'.");
+ }
+
+public:
+ // Only allow allocation of Stmts using the allocator in ASTContext
+ // or by doing a placement new.
+ void* operator new(size_t bytes, ASTContext& C,
+ unsigned alignment = 16) throw() {
+ return ::operator new(bytes, C, alignment);
+ }
+
+ void* operator new(size_t bytes, ASTContext* C,
+ unsigned alignment = 16) throw() {
+ return ::operator new(bytes, *C, alignment);
+ }
+
+ void* operator new(size_t bytes, void* mem) throw() {
+ return mem;
+ }
+
+ void operator delete(void*, ASTContext&, unsigned) throw() { }
+ void operator delete(void*, ASTContext*, unsigned) throw() { }
+ void operator delete(void*, std::size_t) throw() { }
+ void operator delete(void*, void*) throw() { }
+
+public:
+ /// \brief A placeholder type used to construct an empty shell of a
+ /// type, that will be filled in later (e.g., by some
+ /// de-serialization).
+ struct EmptyShell { };
+
+protected:
+ /// DestroyChildren - Invoked by destructors of subclasses of Stmt to
+ /// recursively release child AST nodes.
+ void DestroyChildren(ASTContext& Ctx);
+
+ /// \brief Construct an empty statement.
+ explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) {
+ if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
+ }
+
+public:
+ Stmt(StmtClass SC) : sClass(SC) {
+ if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
+ }
+ virtual ~Stmt() {}
+
+ virtual void Destroy(ASTContext &Ctx);
+
+ StmtClass getStmtClass() const { return sClass; }
+ const char *getStmtClassName() const;
+
+ /// SourceLocation tokens are not useful in isolation - they are low level
+ /// value objects created/interpreted by SourceManager. We assume AST
+ /// clients will have a pointer to the respective SourceManager.
+ virtual SourceRange getSourceRange() const = 0;
+ SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
+ SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
+
+ // global temp stats (until we have a per-module visitor)
+ static void addStmtClass(const StmtClass s);
+ static bool CollectingStats(bool enable=false);
+ static void PrintStats();
+
+ /// dump - This does a local dump of the specified AST fragment. It dumps the
+ /// specified node and a few nodes underneath it, but not the whole subtree.
+ /// This is useful in a debugger.
+ void dump() const;
+ void dump(SourceManager &SM) const;
+
+ /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+ void dumpAll() const;
+ void dumpAll(SourceManager &SM) const;
+
+ /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
+ /// back to its original source language syntax.
+ void dumpPretty(ASTContext& Context) const;
+ void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper = 0,
+ const PrintingPolicy &Policy = PrintingPolicy(),
+ unsigned Indentation = 0) const {
+ printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation);
+ }
+ void printPretty(llvm::raw_ostream &OS, ASTContext& Context,
+ PrinterHelper *Helper = 0,
+ const PrintingPolicy &Policy = PrintingPolicy(),
+ unsigned Indentation = 0) const;
+
+ /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
+ /// works on systems with GraphViz (Mac OS X) or dot+gv installed.
+ void viewAST() const;
+
+ // Implement isa<T> support.
+ static bool classof(const Stmt *) { return true; }
+
+ /// hasImplicitControlFlow - Some statements (e.g. short circuited operations)
+ /// contain implicit control-flow in the order their subexpressions
+ /// are evaluated. This predicate returns true if this statement has
+ /// such implicit control-flow. Such statements are also specially handled
+ /// within CFGs.
+ bool hasImplicitControlFlow() const;
+
+ /// Child Iterators: All subclasses must implement child_begin and child_end
+ /// to permit easy iteration over the substatements/subexpessions of an
+ /// AST node. This permits easy iteration over all nodes in the AST.
+ typedef StmtIterator child_iterator;
+ typedef ConstStmtIterator const_child_iterator;
+
+ virtual child_iterator child_begin() = 0;
+ virtual child_iterator child_end() = 0;
+
+ const_child_iterator child_begin() const {
+ return const_child_iterator(const_cast<Stmt*>(this)->child_begin());
+ }
+
+ const_child_iterator child_end() const {
+ return const_child_iterator(const_cast<Stmt*>(this)->child_end());
+ }
+};
+
+/// DeclStmt - Adaptor class for mixing declarations with statements and
+/// expressions. For example, CompoundStmt mixes statements, expressions
+/// and declarations (variables, types). Another example is ForStmt, where
+/// the first statement can be an expression or a declaration.
+///
+class DeclStmt : public Stmt {
+ DeclGroupRef DG;
+ SourceLocation StartLoc, EndLoc;
+public:
+ DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
+ SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
+ StartLoc(startLoc), EndLoc(endLoc) {}
+
+ /// \brief Build an empty declaration statement.
+ explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { }
+
+ virtual void Destroy(ASTContext& Ctx);
+
+ /// isSingleDecl - This method returns true if this DeclStmt refers
+ /// to a single Decl.
+ bool isSingleDecl() const {
+ return DG.isSingleDecl();
+ }
+
+ const Decl *getSingleDecl() const { return DG.getSingleDecl(); }
+ Decl *getSingleDecl() { return DG.getSingleDecl(); }
+
+ const DeclGroupRef getDeclGroup() const { return DG; }
+ DeclGroupRef getDeclGroup() { return DG; }
+ void setDeclGroup(DeclGroupRef DGR) { DG = DGR; }
+
+ SourceLocation getStartLoc() const { return StartLoc; }
+ void setStartLoc(SourceLocation L) { StartLoc = L; }
+ SourceLocation getEndLoc() const { return EndLoc; }
+ void setEndLoc(SourceLocation L) { EndLoc = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(StartLoc, EndLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclStmtClass;
+ }
+ static bool classof(const DeclStmt *) { return true; }
+
+ // Iterators over subexpressions.
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ typedef DeclGroupRef::iterator decl_iterator;
+ typedef DeclGroupRef::const_iterator const_decl_iterator;
+
+ decl_iterator decl_begin() { return DG.begin(); }
+ decl_iterator decl_end() { return DG.end(); }
+ const_decl_iterator decl_begin() const { return DG.begin(); }
+ const_decl_iterator decl_end() const { return DG.end(); }
+};
+
+/// NullStmt - This is the null statement ";": C99 6.8.3p3.
+///
+class NullStmt : public Stmt {
+ SourceLocation SemiLoc;
+public:
+ NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
+
+ /// \brief Build an empty null statement.
+ explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
+
+ NullStmt* Clone(ASTContext &C) const;
+
+ SourceLocation getSemiLoc() const { return SemiLoc; }
+ void setSemiLoc(SourceLocation L) { SemiLoc = L; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == NullStmtClass;
+ }
+ static bool classof(const NullStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CompoundStmt - This represents a group of statements like { stmt stmt }.
+///
+class CompoundStmt : public Stmt {
+ Stmt** Body;
+ unsigned NumStmts;
+ SourceLocation LBracLoc, RBracLoc;
+public:
+ CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts,
+ SourceLocation LB, SourceLocation RB)
+ : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) {
+ if (NumStmts == 0) {
+ Body = 0;
+ return;
+ }
+
+ Body = new (C) Stmt*[NumStmts];
+ memcpy(Body, StmtStart, numStmts * sizeof(*Body));
+ }
+
+ // \brief Build an empty compound statement.
+ explicit CompoundStmt(EmptyShell Empty)
+ : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
+
+ void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
+
+ bool body_empty() const { return NumStmts == 0; }
+ unsigned size() const { return NumStmts; }
+
+ typedef Stmt** body_iterator;
+ body_iterator body_begin() { return Body; }
+ body_iterator body_end() { return Body + NumStmts; }
+ Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; }
+
+ typedef Stmt* const * const_body_iterator;
+ const_body_iterator body_begin() const { return Body; }
+ const_body_iterator body_end() const { return Body + NumStmts; }
+ const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; }
+
+ typedef std::reverse_iterator<body_iterator> reverse_body_iterator;
+ reverse_body_iterator body_rbegin() {
+ return reverse_body_iterator(body_end());
+ }
+ reverse_body_iterator body_rend() {
+ return reverse_body_iterator(body_begin());
+ }
+
+ typedef std::reverse_iterator<const_body_iterator>
+ const_reverse_body_iterator;
+
+ const_reverse_body_iterator body_rbegin() const {
+ return const_reverse_body_iterator(body_end());
+ }
+
+ const_reverse_body_iterator body_rend() const {
+ return const_reverse_body_iterator(body_begin());
+ }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(LBracLoc, RBracLoc);
+ }
+
+ SourceLocation getLBracLoc() const { return LBracLoc; }
+ void setLBracLoc(SourceLocation L) { LBracLoc = L; }
+ SourceLocation getRBracLoc() const { return RBracLoc; }
+ void setRBracLoc(SourceLocation L) { RBracLoc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundStmtClass;
+ }
+ static bool classof(const CompoundStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+// SwitchCase is the base class for CaseStmt and DefaultStmt,
+class SwitchCase : public Stmt {
+protected:
+ // A pointer to the following CaseStmt or DefaultStmt class,
+ // used by SwitchStmt.
+ SwitchCase *NextSwitchCase;
+
+ SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {}
+
+public:
+ const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
+
+ SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
+
+ void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
+
+ Stmt *getSubStmt() { return v_getSubStmt(); }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass ||
+ T->getStmtClass() == DefaultStmtClass;
+ }
+ static bool classof(const SwitchCase *) { return true; }
+protected:
+ virtual Stmt* v_getSubStmt() = 0;
+};
+
+class CaseStmt : public SwitchCase {
+ enum { SUBSTMT, LHS, RHS, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
+ // GNU "case 1 ... 4" extension
+ SourceLocation CaseLoc;
+ SourceLocation EllipsisLoc;
+ SourceLocation ColonLoc;
+
+ virtual Stmt* v_getSubStmt() { return getSubStmt(); }
+public:
+ CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
+ SourceLocation ellipsisLoc, SourceLocation colonLoc)
+ : SwitchCase(CaseStmtClass) {
+ SubExprs[SUBSTMT] = 0;
+ SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
+ SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
+ CaseLoc = caseLoc;
+ EllipsisLoc = ellipsisLoc;
+ ColonLoc = colonLoc;
+ }
+
+ /// \brief Build an empty switch case statement.
+ explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { }
+
+ SourceLocation getCaseLoc() const { return CaseLoc; }
+ void setCaseLoc(SourceLocation L) { CaseLoc = L; }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
+ Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
+ Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
+
+ const Expr *getLHS() const {
+ return reinterpret_cast<const Expr*>(SubExprs[LHS]);
+ }
+ const Expr *getRHS() const {
+ return reinterpret_cast<const Expr*>(SubExprs[RHS]);
+ }
+ const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
+
+ void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
+ void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
+ void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
+
+
+ virtual SourceRange getSourceRange() const {
+ // Handle deeply nested case statements with iteration instead of recursion.
+ const CaseStmt *CS = this;
+ while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
+ CS = CS2;
+
+ return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass;
+ }
+ static bool classof(const CaseStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+class DefaultStmt : public SwitchCase {
+ Stmt* SubStmt;
+ SourceLocation DefaultLoc;
+ SourceLocation ColonLoc;
+ virtual Stmt* v_getSubStmt() { return getSubStmt(); }
+public:
+ DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
+ SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
+ ColonLoc(CL) {}
+
+ /// \brief Build an empty default statement.
+ explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { }
+
+ Stmt *getSubStmt() { return SubStmt; }
+ const Stmt *getSubStmt() const { return SubStmt; }
+ void setSubStmt(Stmt *S) { SubStmt = S; }
+
+ SourceLocation getDefaultLoc() const { return DefaultLoc; }
+ void setDefaultLoc(SourceLocation L) { DefaultLoc = L; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(DefaultLoc, SubStmt->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DefaultStmtClass;
+ }
+ static bool classof(const DefaultStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+class LabelStmt : public Stmt {
+ IdentifierInfo *Label;
+ Stmt *SubStmt;
+ SourceLocation IdentLoc;
+public:
+ LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
+ : Stmt(LabelStmtClass), Label(label),
+ SubStmt(substmt), IdentLoc(IL) {}
+
+ // \brief Build an empty label statement.
+ explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
+
+ SourceLocation getIdentLoc() const { return IdentLoc; }
+ IdentifierInfo *getID() const { return Label; }
+ void setID(IdentifierInfo *II) { Label = II; }
+ const char *getName() const;
+ Stmt *getSubStmt() { return SubStmt; }
+ const Stmt *getSubStmt() const { return SubStmt; }
+ void setIdentLoc(SourceLocation L) { IdentLoc = L; }
+ void setSubStmt(Stmt *SS) { SubStmt = SS; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(IdentLoc, SubStmt->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == LabelStmtClass;
+ }
+ static bool classof(const LabelStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// IfStmt - This represents an if/then/else.
+///
+class IfStmt : public Stmt {
+ enum { COND, THEN, ELSE, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation IfLoc;
+ SourceLocation ElseLoc;
+public:
+ IfStmt(SourceLocation IL, Expr *cond, Stmt *then,
+ SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
+ : Stmt(IfStmtClass) {
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[THEN] = then;
+ SubExprs[ELSE] = elsev;
+ IfLoc = IL;
+ ElseLoc = EL;
+ }
+
+ /// \brief Build an empty if/then/else statement
+ explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
+
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
+ const Stmt *getThen() const { return SubExprs[THEN]; }
+ void setThen(Stmt *S) { SubExprs[THEN] = S; }
+ const Stmt *getElse() const { return SubExprs[ELSE]; }
+ void setElse(Stmt *S) { SubExprs[ELSE] = S; }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ Stmt *getThen() { return SubExprs[THEN]; }
+ Stmt *getElse() { return SubExprs[ELSE]; }
+
+ SourceLocation getIfLoc() const { return IfLoc; }
+ void setIfLoc(SourceLocation L) { IfLoc = L; }
+ SourceLocation getElseLoc() const { return ElseLoc; }
+ void setElseLoc(SourceLocation L) { ElseLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ if (SubExprs[ELSE])
+ return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
+ else
+ return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IfStmtClass;
+ }
+ static bool classof(const IfStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// SwitchStmt - This represents a 'switch' stmt.
+///
+class SwitchStmt : public Stmt {
+ enum { COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ // This points to a linked list of case and default statements.
+ SwitchCase *FirstCase;
+ SourceLocation SwitchLoc;
+public:
+ SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) {
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = NULL;
+ }
+
+ /// \brief Build a empty switch statement.
+ explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
+
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ const SwitchCase *getSwitchCaseList() const { return FirstCase; }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+ SwitchCase *getSwitchCaseList() { return FirstCase; }
+ void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
+
+ SourceLocation getSwitchLoc() const { return SwitchLoc; }
+ void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
+
+ void setBody(Stmt *S, SourceLocation SL) {
+ SubExprs[BODY] = S;
+ SwitchLoc = SL;
+ }
+ void addSwitchCase(SwitchCase *SC) {
+ assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
+ SC->setNextSwitchCase(FirstCase);
+ FirstCase = SC;
+ }
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SwitchStmtClass;
+ }
+ static bool classof(const SwitchStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// WhileStmt - This represents a 'while' stmt.
+///
+class WhileStmt : public Stmt {
+ enum { COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation WhileLoc;
+public:
+ WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) {
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = body;
+ WhileLoc = WL;
+ }
+
+ /// \brief Build an empty while statement.
+ explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getWhileLoc() const { return WhileLoc; }
+ void setWhileLoc(SourceLocation L) { WhileLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == WhileStmtClass;
+ }
+ static bool classof(const WhileStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// DoStmt - This represents a 'do/while' stmt.
+///
+class DoStmt : public Stmt {
+ enum { COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ SourceLocation DoLoc;
+ SourceLocation WhileLoc;
+
+public:
+ DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL)
+ : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL) {
+ SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
+ SubExprs[BODY] = body;
+ DoLoc = DL;
+ WhileLoc = WL;
+ }
+
+ /// \brief Build an empty do-while statement.
+ explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { }
+
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getDoLoc() const { return DoLoc; }
+ void setDoLoc(SourceLocation L) { DoLoc = L; }
+ SourceLocation getWhileLoc() const { return WhileLoc; }
+ void setWhileLoc(SourceLocation L) { WhileLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(DoLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DoStmtClass;
+ }
+ static bool classof(const DoStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of
+/// the init/cond/inc parts of the ForStmt will be null if they were not
+/// specified in the source.
+///
+class ForStmt : public Stmt {
+ enum { INIT, COND, INC, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
+ SourceLocation ForLoc;
+ SourceLocation LParenLoc, RParenLoc;
+
+public:
+ ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL,
+ SourceLocation LP, SourceLocation RP)
+ : Stmt(ForStmtClass) {
+ SubExprs[INIT] = Init;
+ SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
+ SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
+ SubExprs[BODY] = Body;
+ ForLoc = FL;
+ LParenLoc = LP;
+ RParenLoc = RP;
+ }
+
+ /// \brief Build an empty for statement.
+ explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
+
+ Stmt *getInit() { return SubExprs[INIT]; }
+ Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
+ Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+
+ const Stmt *getInit() const { return SubExprs[INIT]; }
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ const Expr *getInc() const { return reinterpret_cast<Expr*>(SubExprs[INC]); }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+
+ void setInit(Stmt *S) { SubExprs[INIT] = S; }
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getForLoc() const { return ForLoc; }
+ void setForLoc(SourceLocation L) { ForLoc = L; }
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ForStmtClass;
+ }
+ static bool classof(const ForStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// GotoStmt - This represents a direct goto.
+///
+class GotoStmt : public Stmt {
+ LabelStmt *Label;
+ SourceLocation GotoLoc;
+ SourceLocation LabelLoc;
+public:
+ GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
+ : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
+
+ /// \brief Build an empty goto statement.
+ explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
+
+ LabelStmt *getLabel() const { return Label; }
+ void setLabel(LabelStmt *S) { Label = S; }
+
+ SourceLocation getGotoLoc() const { return GotoLoc; }
+ void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+ SourceLocation getLabelLoc() const { return LabelLoc; }
+ void setLabelLoc(SourceLocation L) { LabelLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(GotoLoc, LabelLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GotoStmtClass;
+ }
+ static bool classof(const GotoStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// IndirectGotoStmt - This represents an indirect goto.
+///
+class IndirectGotoStmt : public Stmt {
+ SourceLocation GotoLoc;
+ SourceLocation StarLoc;
+ Stmt *Target;
+public:
+ IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
+ Expr *target)
+ : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
+ Target((Stmt*)target) {}
+
+ /// \brief Build an empty indirect goto statement.
+ explicit IndirectGotoStmt(EmptyShell Empty)
+ : Stmt(IndirectGotoStmtClass, Empty) { }
+
+ void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+ SourceLocation getGotoLoc() const { return GotoLoc; }
+ void setStarLoc(SourceLocation L) { StarLoc = L; }
+ SourceLocation getStarLoc() const { return StarLoc; }
+
+ Expr *getTarget();
+ const Expr *getTarget() const;
+ void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(GotoLoc, Target->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IndirectGotoStmtClass;
+ }
+ static bool classof(const IndirectGotoStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// ContinueStmt - This represents a continue.
+///
+class ContinueStmt : public Stmt {
+ SourceLocation ContinueLoc;
+public:
+ ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
+
+ /// \brief Build an empty continue statement.
+ explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { }
+
+ SourceLocation getContinueLoc() const { return ContinueLoc; }
+ void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(ContinueLoc);
+ }
+
+ ContinueStmt* Clone(ASTContext &C) const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ContinueStmtClass;
+ }
+ static bool classof(const ContinueStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// BreakStmt - This represents a break.
+///
+class BreakStmt : public Stmt {
+ SourceLocation BreakLoc;
+public:
+ BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
+
+ /// \brief Build an empty break statement.
+ explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
+
+ SourceLocation getBreakLoc() const { return BreakLoc; }
+ void setBreakLoc(SourceLocation L) { BreakLoc = L; }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
+
+ BreakStmt* Clone(ASTContext &C) const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BreakStmtClass;
+ }
+ static bool classof(const BreakStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+/// ReturnStmt - This represents a return, optionally of an expression:
+/// return;
+/// return 4;
+///
+/// Note that GCC allows return with no argument in a function declared to
+/// return a value, and it allows returning a value in functions declared to
+/// return void. We explicitly model this in the AST, which means you can't
+/// depend on the return type of the function and the presence of an argument.
+///
+class ReturnStmt : public Stmt {
+ Stmt *RetExpr;
+ SourceLocation RetLoc;
+public:
+ ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass),
+ RetExpr((Stmt*) E), RetLoc(RL) {}
+
+ /// \brief Build an empty return expression.
+ explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }
+
+ const Expr *getRetValue() const;
+ Expr *getRetValue();
+ void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); }
+
+ SourceLocation getReturnLoc() const { return RetLoc; }
+ void setReturnLoc(SourceLocation L) { RetLoc = L; }
+
+ virtual SourceRange getSourceRange() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ReturnStmtClass;
+ }
+ static bool classof(const ReturnStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// AsmStmt - This represents a GNU inline-assembly statement extension.
+///
+class AsmStmt : public Stmt {
+ SourceLocation AsmLoc, RParenLoc;
+ StringLiteral *AsmStr;
+
+ bool IsSimple;
+ bool IsVolatile;
+
+ unsigned NumOutputs;
+ unsigned NumInputs;
+
+ llvm::SmallVector<std::string, 4> Names;
+ llvm::SmallVector<StringLiteral*, 4> Constraints;
+ llvm::SmallVector<Stmt*, 4> Exprs;
+
+ llvm::SmallVector<StringLiteral*, 4> Clobbers;
+public:
+ AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
+ unsigned numoutputs, unsigned numinputs,
+ std::string *names, StringLiteral **constraints,
+ Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
+ StringLiteral **clobbers, SourceLocation rparenloc);
+
+ /// \brief Build an empty inline-assembly statement.
+ explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { }
+
+ SourceLocation getAsmLoc() const { return AsmLoc; }
+ void setAsmLoc(SourceLocation L) { AsmLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ bool isVolatile() const { return IsVolatile; }
+ void setVolatile(bool V) { IsVolatile = V; }
+ bool isSimple() const { return IsSimple; }
+ void setSimple(bool V) { IsSimple = false; }
+
+ //===--- Asm String Analysis ---===//
+
+ const StringLiteral *getAsmString() const { return AsmStr; }
+ StringLiteral *getAsmString() { return AsmStr; }
+ void setAsmString(StringLiteral *E) { AsmStr = E; }
+
+ /// AsmStringPiece - this is part of a decomposed asm string specification
+ /// (for use with the AnalyzeAsmString function below). An asm string is
+ /// considered to be a concatenation of these parts.
+ class AsmStringPiece {
+ public:
+ enum Kind {
+ String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%".
+ Operand // Operand reference, with optional modifier %c4.
+ };
+ private:
+ Kind MyKind;
+ std::string Str;
+ unsigned OperandNo;
+ public:
+ AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
+ AsmStringPiece(unsigned OpNo, char Modifier)
+ : MyKind(Operand), Str(), OperandNo(OpNo) {
+ Str += Modifier;
+ }
+
+ bool isString() const { return MyKind == String; }
+ bool isOperand() const { return MyKind == Operand; }
+
+ const std::string &getString() const {
+ assert(isString());
+ return Str;
+ }
+
+ unsigned getOperandNo() const {
+ assert(isOperand());
+ return OperandNo;
+ }
+
+ /// getModifier - Get the modifier for this operand, if present. This
+ /// returns '\0' if there was no modifier.
+ char getModifier() const {
+ assert(isOperand());
+ return Str[0];
+ }
+ };
+
+ /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
+ /// it into pieces. If the asm string is erroneous, emit errors and return
+ /// true, otherwise return false. This handles canonicalization and
+ /// translation of strings from GCC syntax to LLVM IR syntax, and handles
+ //// flattening of named references like %[foo] to Operand AsmStringPiece's.
+ unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
+ ASTContext &C, unsigned &DiagOffs) const;
+
+
+ //===--- Output operands ---===//
+
+ unsigned getNumOutputs() const { return NumOutputs; }
+
+ const std::string &getOutputName(unsigned i) const {
+ return Names[i];
+ }
+
+ /// getOutputConstraint - Return the constraint string for the specified
+ /// output operand. All output constraints are known to be non-empty (either
+ /// '=' or '+').
+ std::string getOutputConstraint(unsigned i) const;
+
+ const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
+ return Constraints[i];
+ }
+ StringLiteral *getOutputConstraintLiteral(unsigned i) {
+ return Constraints[i];
+ }
+
+
+ Expr *getOutputExpr(unsigned i);
+
+ const Expr *getOutputExpr(unsigned i) const {
+ return const_cast<AsmStmt*>(this)->getOutputExpr(i);
+ }
+
+ /// isOutputPlusConstraint - Return true if the specified output constraint
+ /// is a "+" constraint (which is both an input and an output) or false if it
+ /// is an "=" constraint (just an output).
+ bool isOutputPlusConstraint(unsigned i) const {
+ return getOutputConstraint(i)[0] == '+';
+ }
+
+ /// getNumPlusOperands - Return the number of output operands that have a "+"
+ /// constraint.
+ unsigned getNumPlusOperands() const;
+
+ //===--- Input operands ---===//
+
+ unsigned getNumInputs() const { return NumInputs; }
+
+ const std::string &getInputName(unsigned i) const {
+ return Names[i + NumOutputs];
+ }
+
+ /// getInputConstraint - Return the specified input constraint. Unlike output
+ /// constraints, these can be empty.
+ std::string getInputConstraint(unsigned i) const;
+
+ const StringLiteral *getInputConstraintLiteral(unsigned i) const {
+ return Constraints[i + NumOutputs];
+ }
+ StringLiteral *getInputConstraintLiteral(unsigned i) {
+ return Constraints[i + NumOutputs];
+ }
+
+
+ Expr *getInputExpr(unsigned i);
+
+ const Expr *getInputExpr(unsigned i) const {
+ return const_cast<AsmStmt*>(this)->getInputExpr(i);
+ }
+
+ void setOutputsAndInputs(unsigned NumOutputs,
+ unsigned NumInputs,
+ const std::string *Names,
+ StringLiteral **Constraints,
+ Stmt **Exprs);
+
+ //===--- Other ---===//
+
+ /// getNamedOperand - Given a symbolic operand reference like %[foo],
+ /// translate this into a numeric value needed to reference the same operand.
+ /// This returns -1 if the operand name is invalid.
+ int getNamedOperand(const std::string &SymbolicName) const;
+
+
+
+ unsigned getNumClobbers() const { return Clobbers.size(); }
+ StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
+ const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
+ void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers);
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AsmLoc, RParenLoc);
+ }
+
+ static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;}
+ static bool classof(const AsmStmt *) { return true; }
+
+ // Input expr iterators.
+
+ typedef ExprIterator inputs_iterator;
+ typedef ConstExprIterator const_inputs_iterator;
+
+ inputs_iterator begin_inputs() {
+ return Exprs.data() + NumOutputs;
+ }
+
+ inputs_iterator end_inputs() {
+ return Exprs.data() + NumOutputs + NumInputs;
+ }
+
+ const_inputs_iterator begin_inputs() const {
+ return Exprs.data() + NumOutputs;
+ }
+
+ const_inputs_iterator end_inputs() const {
+ return Exprs.data() + NumOutputs + NumInputs;
+ }
+
+ // Output expr iterators.
+
+ typedef ExprIterator outputs_iterator;
+ typedef ConstExprIterator const_outputs_iterator;
+
+ outputs_iterator begin_outputs() {
+ return Exprs.data();
+ }
+ outputs_iterator end_outputs() {
+ return Exprs.data() + NumOutputs;
+ }
+
+ const_outputs_iterator begin_outputs() const {
+ return Exprs.data();
+ }
+ const_outputs_iterator end_outputs() const {
+ return Exprs.data() + NumOutputs;
+ }
+
+ // Input name iterator.
+
+ const std::string *begin_output_names() const {
+ return &Names[0];
+ }
+
+ const std::string *end_output_names() const {
+ return &Names[0] + NumOutputs;
+ }
+
+ // Child iterators
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
new file mode 100644
index 000000000000..2338f1457a84
--- /dev/null
+++ b/include/clang/AST/StmtCXX.h
@@ -0,0 +1,100 @@
+//===--- StmtCXX.h - Classes for representing C++ statements ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the C++ statement AST node classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTCXX_H
+#define LLVM_CLANG_AST_STMTCXX_H
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+class VarDecl;
+
+/// CXXCatchStmt - This represents a C++ catch block.
+///
+class CXXCatchStmt : public Stmt {
+ SourceLocation CatchLoc;
+ /// The exception-declaration of the type.
+ VarDecl *ExceptionDecl;
+ /// The handler block.
+ Stmt *HandlerBlock;
+
+public:
+ CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
+ : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
+ HandlerBlock(handlerBlock) {}
+
+ virtual void Destroy(ASTContext& Ctx);
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
+ }
+
+ SourceLocation getCatchLoc() const { return CatchLoc; }
+ VarDecl *getExceptionDecl() { return ExceptionDecl; }
+ QualType getCaughtType();
+ Stmt *getHandlerBlock() { return HandlerBlock; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXCatchStmtClass;
+ }
+ static bool classof(const CXXCatchStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// CXXTryStmt - A C++ try block, including all handlers.
+///
+class CXXTryStmt : public Stmt {
+ SourceLocation TryLoc;
+ // First place is the guarded CompoundStatement. Subsequent are the handlers.
+ // More than three handlers should be rare.
+ llvm::SmallVector<Stmt*, 4> Stmts;
+
+public:
+ CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
+ Stmt **handlers, unsigned numHandlers);
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(TryLoc, Stmts.back()->getLocEnd());
+ }
+
+ SourceLocation getTryLoc() const { return TryLoc; }
+
+ CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); }
+ const CompoundStmt *getTryBlock() const {
+ return llvm::cast<CompoundStmt>(Stmts[0]);
+ }
+
+ unsigned getNumHandlers() const { return Stmts.size() - 1; }
+ CXXCatchStmt *getHandler(unsigned i) {
+ return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+ }
+ const CXXCatchStmt *getHandler(unsigned i) const {
+ return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTryStmtClass;
+ }
+ static bool classof(const CXXTryStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h
new file mode 100644
index 000000000000..1bfac6a9587e
--- /dev/null
+++ b/include/clang/AST/StmtGraphTraits.h
@@ -0,0 +1,83 @@
+//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a template specialization of llvm::GraphTraits to
+// treat ASTs (Stmt*) as graphs
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
+#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
+
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+
+namespace llvm {
+
+//template <typename T> struct GraphTraits;
+
+
+template <> struct GraphTraits<clang::Stmt*> {
+ typedef clang::Stmt NodeType;
+ typedef clang::Stmt::child_iterator ChildIteratorType;
+ typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
+
+ static NodeType* getEntryNode(clang::Stmt* S) { return S; }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ if (N) return N->child_begin();
+ else return ChildIteratorType();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ if (N) return N->child_end();
+ else return ChildIteratorType();
+ }
+
+ static nodes_iterator nodes_begin(clang::Stmt* S) {
+ return df_begin(S);
+ }
+
+ static nodes_iterator nodes_end(clang::Stmt* S) {
+ return df_end(S);
+ }
+};
+
+
+template <> struct GraphTraits<const clang::Stmt*> {
+ typedef const clang::Stmt NodeType;
+ typedef clang::Stmt::const_child_iterator ChildIteratorType;
+ typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
+
+ static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ if (N) return N->child_begin();
+ else return ChildIteratorType();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ if (N) return N->child_end();
+ else return ChildIteratorType();
+ }
+
+ static nodes_iterator nodes_begin(const clang::Stmt* S) {
+ return df_begin(S);
+ }
+
+ static nodes_iterator nodes_end(const clang::Stmt* S) {
+ return df_end(S);
+ }
+};
+
+
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
new file mode 100644
index 000000000000..35bd5ada0256
--- /dev/null
+++ b/include/clang/AST/StmtIterator.h
@@ -0,0 +1,145 @@
+//===--- StmtIterator.h - Iterators for Statements ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the StmtIterator and ConstStmtIterator classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMT_ITR_H
+#define LLVM_CLANG_AST_STMT_ITR_H
+
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+
+namespace clang {
+
+class Stmt;
+class Decl;
+class VariableArrayType;
+
+class StmtIteratorBase {
+protected:
+ enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
+ Flags = 0x3 };
+
+ union { Stmt** stmt; Decl* decl; Decl** DGI; };
+ uintptr_t RawVAPtr;
+ Decl** DGE;
+
+ bool inDecl() const {
+ return (RawVAPtr & Flags) == DeclMode;
+ }
+
+ bool inDeclGroup() const {
+ return (RawVAPtr & Flags) == DeclGroupMode;
+ }
+
+ bool inSizeOfTypeVA() const {
+ return (RawVAPtr & Flags) == SizeOfTypeVAMode;
+ }
+
+ bool inStmt() const {
+ return (RawVAPtr & Flags) == 0;
+ }
+
+ VariableArrayType* getVAPtr() const {
+ return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
+ }
+
+ void setVAPtr(VariableArrayType* P) {
+ assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
+ RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
+ }
+
+ void NextDecl(bool ImmediateAdvance = true);
+ bool HandleDecl(Decl* D);
+ void NextVA();
+
+ Stmt*& GetDeclExpr() const;
+
+ StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {}
+ StmtIteratorBase(Decl* d);
+ StmtIteratorBase(VariableArrayType* t);
+ StmtIteratorBase(Decl** dgi, Decl** dge);
+ StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {}
+};
+
+
+template <typename DERIVED, typename REFERENCE>
+class StmtIteratorImpl : public StmtIteratorBase,
+ public std::iterator<std::forward_iterator_tag,
+ REFERENCE, ptrdiff_t,
+ REFERENCE, REFERENCE> {
+protected:
+ StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
+public:
+ StmtIteratorImpl() {}
+ StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {}
+ StmtIteratorImpl(Decl** dgi, Decl** dge) : StmtIteratorBase(dgi, dge) {}
+ StmtIteratorImpl(Decl* d) : StmtIteratorBase(d) {}
+ StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
+
+ DERIVED& operator++() {
+ if (inDecl() || inDeclGroup()) {
+ if (getVAPtr()) NextVA();
+ else NextDecl();
+ }
+ else if (inSizeOfTypeVA())
+ NextVA();
+ else
+ ++stmt;
+
+ return static_cast<DERIVED&>(*this);
+ }
+
+ DERIVED operator++(int) {
+ DERIVED tmp = static_cast<DERIVED&>(*this);
+ operator++();
+ return tmp;
+ }
+
+ bool operator==(const DERIVED& RHS) const {
+ return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr;
+ }
+
+ bool operator!=(const DERIVED& RHS) const {
+ return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr;
+ }
+
+ REFERENCE operator*() const {
+ return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
+ }
+
+ REFERENCE operator->() const { return operator*(); }
+};
+
+struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
+ explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
+
+ StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
+ StmtIterator(Decl** dgi, Decl** dge)
+ : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
+
+ StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
+ StmtIterator(Decl* D) : StmtIteratorImpl<StmtIterator,Stmt*&>(D) {}
+};
+
+struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
+ const Stmt*> {
+ explicit ConstStmtIterator() :
+ StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
+
+ ConstStmtIterator(const StmtIterator& RHS) :
+ StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
new file mode 100644
index 000000000000..ab6524663d63
--- /dev/null
+++ b/include/clang/AST/StmtNodes.def
@@ -0,0 +1,156 @@
+//===-- StmtNodes.def - Metadata about Stmt AST nodes -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AST Node info database.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FIRST_STMT
+#define FIRST_STMT(CLASS)
+#define LAST_STMT(CLASS)
+#endif
+
+#ifndef FIRST_EXPR
+#define FIRST_EXPR(CLASS)
+#define LAST_EXPR(CLASS)
+#endif
+
+#ifndef EXPR
+# define EXPR(Type, Base) STMT(Type, Base)
+#endif
+
+// Normal Statements.
+STMT(NullStmt , Stmt)
+FIRST_STMT(NullStmt)
+STMT(CompoundStmt , Stmt)
+STMT(CaseStmt , SwitchCase)
+STMT(DefaultStmt , SwitchCase)
+STMT(LabelStmt , Stmt)
+STMT(IfStmt , Stmt)
+STMT(SwitchStmt , Stmt)
+STMT(WhileStmt , Stmt)
+STMT(DoStmt , Stmt)
+STMT(ForStmt , Stmt)
+STMT(GotoStmt , Stmt)
+STMT(IndirectGotoStmt, Stmt)
+STMT(ContinueStmt , Stmt)
+STMT(BreakStmt , Stmt)
+STMT(ReturnStmt , Stmt)
+STMT(DeclStmt , Stmt)
+STMT(SwitchCase , Stmt)
+
+// GNU Stmt Extensions
+STMT(AsmStmt , Stmt)
+
+// Obj-C statements
+STMT(ObjCAtTryStmt , Stmt)
+STMT(ObjCAtCatchStmt , Stmt)
+STMT(ObjCAtFinallyStmt , Stmt)
+STMT(ObjCAtThrowStmt , Stmt)
+STMT(ObjCAtSynchronizedStmt , Stmt)
+// Obj-C2 statements
+STMT(ObjCForCollectionStmt, Stmt)
+
+// C++ statements
+STMT(CXXCatchStmt, Stmt)
+STMT(CXXTryStmt , Stmt)
+
+LAST_STMT(CXXTryStmt)
+
+// Expressions.
+EXPR(Expr , Stmt)
+FIRST_EXPR(Expr)
+EXPR(PredefinedExpr , Expr)
+EXPR(DeclRefExpr , Expr)
+EXPR(IntegerLiteral , Expr)
+EXPR(FloatingLiteral , Expr)
+EXPR(ImaginaryLiteral , Expr)
+EXPR(StringLiteral , Expr)
+EXPR(CharacterLiteral , Expr)
+EXPR(ParenExpr , Expr)
+EXPR(UnaryOperator , Expr)
+EXPR(SizeOfAlignOfExpr , Expr)
+EXPR(ArraySubscriptExpr , Expr)
+EXPR(CallExpr , Expr)
+EXPR(MemberExpr , Expr)
+EXPR(CastExpr , Expr)
+EXPR(BinaryOperator , Expr)
+EXPR(CompoundAssignOperator, BinaryOperator)
+EXPR(ConditionalOperator , Expr)
+EXPR(ImplicitCastExpr , CastExpr)
+EXPR(ExplicitCastExpr , CastExpr)
+EXPR(CStyleCastExpr , ExplicitCastExpr)
+EXPR(CompoundLiteralExpr , Expr)
+EXPR(ExtVectorElementExpr , Expr)
+EXPR(InitListExpr , Expr)
+EXPR(DesignatedInitExpr , Expr)
+EXPR(ImplicitValueInitExpr , Expr)
+EXPR(VAArgExpr , Expr)
+
+// GNU Extensions.
+EXPR(AddrLabelExpr , Expr)
+EXPR(StmtExpr , Expr)
+EXPR(TypesCompatibleExpr , Expr)
+EXPR(ChooseExpr , Expr)
+EXPR(GNUNullExpr , Expr)
+
+// C++ Expressions.
+EXPR(CXXOperatorCallExpr , CallExpr)
+EXPR(CXXMemberCallExpr , CallExpr)
+EXPR(CXXNamedCastExpr , ExplicitCastExpr)
+EXPR(CXXStaticCastExpr , CXXNamedCastExpr)
+EXPR(CXXDynamicCastExpr , CXXNamedCastExpr)
+EXPR(CXXReinterpretCastExpr , CXXNamedCastExpr)
+EXPR(CXXConstCastExpr , CXXNamedCastExpr)
+EXPR(CXXFunctionalCastExpr , ExplicitCastExpr)
+EXPR(CXXTypeidExpr , Expr)
+EXPR(CXXBoolLiteralExpr , Expr)
+EXPR(CXXNullPtrLiteralExpr , Expr)
+EXPR(CXXThisExpr , Expr)
+EXPR(CXXThrowExpr , Expr)
+EXPR(CXXDefaultArgExpr , Expr)
+EXPR(CXXZeroInitValueExpr , Expr)
+EXPR(CXXConditionDeclExpr , DeclRefExpr)
+EXPR(CXXNewExpr , Expr)
+EXPR(CXXDeleteExpr , Expr)
+EXPR(UnresolvedFunctionNameExpr , Expr)
+EXPR(UnaryTypeTraitExpr , Expr)
+EXPR(QualifiedDeclRefExpr , DeclRefExpr)
+EXPR(UnresolvedDeclRefExpr , Expr)
+EXPR(CXXConstructExpr , Expr)
+EXPR(CXXBindTemporaryExpr , Expr)
+EXPR(CXXExprWithTemporaries , Expr)
+EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
+EXPR(CXXUnresolvedConstructExpr, Expr)
+EXPR(CXXUnresolvedMemberExpr, Expr)
+
+// Obj-C Expressions.
+EXPR(ObjCStringLiteral , Expr)
+EXPR(ObjCEncodeExpr , Expr)
+EXPR(ObjCMessageExpr , Expr)
+EXPR(ObjCSelectorExpr , Expr)
+EXPR(ObjCProtocolExpr , Expr)
+EXPR(ObjCIvarRefExpr , Expr)
+EXPR(ObjCPropertyRefExpr , Expr)
+EXPR(ObjCKVCRefExpr , Expr)
+EXPR(ObjCSuperExpr , Expr)
+
+// Clang Extensions.
+EXPR(ShuffleVectorExpr , Expr)
+EXPR(BlockExpr , Expr)
+EXPR(BlockDeclRefExpr , Expr)
+
+LAST_EXPR(BlockDeclRefExpr)
+
+#undef STMT
+#undef EXPR
+#undef FIRST_STMT
+#undef LAST_STMT
+#undef FIRST_EXPR
+#undef LAST_EXPR
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
new file mode 100644
index 000000000000..8ae707174403
--- /dev/null
+++ b/include/clang/AST/StmtObjC.h
@@ -0,0 +1,307 @@
+//===--- StmtObjC.h - Classes for representing ObjC statements --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Objective-C statement AST node classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTOBJC_H
+#define LLVM_CLANG_AST_STMTOBJC_H
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+/// ObjCForCollectionStmt - This represents Objective-c's collection statement;
+/// represented as 'for (element 'in' collection-expression)' stmt.
+///
+class ObjCForCollectionStmt : public Stmt {
+ enum { ELEM, COLLECTION, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
+ SourceLocation ForLoc;
+ SourceLocation RParenLoc;
+public:
+ ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
+ SourceLocation FCL, SourceLocation RPL);
+ explicit ObjCForCollectionStmt(EmptyShell Empty) :
+ Stmt(ObjCForCollectionStmtClass, Empty) { }
+
+ Stmt *getElement() { return SubExprs[ELEM]; }
+ Expr *getCollection() {
+ return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
+ }
+ Stmt *getBody() { return SubExprs[BODY]; }
+
+ const Stmt *getElement() const { return SubExprs[ELEM]; }
+ const Expr *getCollection() const {
+ return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
+ }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+
+ void setElement(Stmt *S) { SubExprs[ELEM] = S; }
+ void setCollection(Expr *E) {
+ SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E);
+ }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getForLoc() const { return ForLoc; }
+ void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCForCollectionStmtClass;
+ }
+ static bool classof(const ObjCForCollectionStmt *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
+class ObjCAtCatchStmt : public Stmt {
+private:
+ enum { BODY, NEXT_CATCH, END_EXPR };
+ ParmVarDecl *ExceptionDecl;
+ Stmt *SubExprs[END_EXPR];
+ SourceLocation AtCatchLoc, RParenLoc;
+
+public:
+ ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
+ ParmVarDecl *catchVarDecl,
+ Stmt *atCatchStmt, Stmt *atCatchList);
+
+ explicit ObjCAtCatchStmt(EmptyShell Empty) :
+ Stmt(ObjCAtCatchStmtClass, Empty) { }
+
+ const Stmt *getCatchBody() const { return SubExprs[BODY]; }
+ Stmt *getCatchBody() { return SubExprs[BODY]; }
+ void setCatchBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ const ObjCAtCatchStmt *getNextCatchStmt() const {
+ return static_cast<const ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]);
+ }
+ ObjCAtCatchStmt *getNextCatchStmt() {
+ return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]);
+ }
+ void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; }
+
+ const ParmVarDecl *getCatchParamDecl() const {
+ return ExceptionDecl;
+ }
+ ParmVarDecl *getCatchParamDecl() {
+ return ExceptionDecl;
+ }
+ void setCatchParamDecl(ParmVarDecl *D) { ExceptionDecl = D; }
+
+ SourceLocation getAtCatchLoc() const { return AtCatchLoc; }
+ void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd());
+ }
+
+ bool hasEllipsis() const { return getCatchParamDecl() == 0; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtCatchStmtClass;
+ }
+ static bool classof(const ObjCAtCatchStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement
+class ObjCAtFinallyStmt : public Stmt {
+ Stmt *AtFinallyStmt;
+ SourceLocation AtFinallyLoc;
+public:
+ ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
+ : Stmt(ObjCAtFinallyStmtClass),
+ AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
+
+ explicit ObjCAtFinallyStmt(EmptyShell Empty) :
+ Stmt(ObjCAtFinallyStmtClass, Empty) { }
+
+ const Stmt *getFinallyBody() const { return AtFinallyStmt; }
+ Stmt *getFinallyBody() { return AtFinallyStmt; }
+ void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd());
+ }
+
+ SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
+ void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtFinallyStmtClass;
+ }
+ static bool classof(const ObjCAtFinallyStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCAtTryStmt - This represent objective-c's over-all
+/// @try ... @catch ... @finally statement.
+class ObjCAtTryStmt : public Stmt {
+private:
+ enum { TRY, CATCH, FINALLY, END_EXPR };
+ Stmt* SubStmts[END_EXPR];
+
+ SourceLocation AtTryLoc;
+public:
+ ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt *atCatchStmt,
+ Stmt *atFinallyStmt)
+ : Stmt(ObjCAtTryStmtClass) {
+ SubStmts[TRY] = atTryStmt;
+ SubStmts[CATCH] = atCatchStmt;
+ SubStmts[FINALLY] = atFinallyStmt;
+ AtTryLoc = atTryLoc;
+ }
+ explicit ObjCAtTryStmt(EmptyShell Empty) :
+ Stmt(ObjCAtTryStmtClass, Empty) { }
+
+ SourceLocation getAtTryLoc() const { return AtTryLoc; }
+ void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
+
+ const Stmt *getTryBody() const { return SubStmts[TRY]; }
+ Stmt *getTryBody() { return SubStmts[TRY]; }
+ void setTryBody(Stmt *S) { SubStmts[TRY] = S; }
+
+ const ObjCAtCatchStmt *getCatchStmts() const {
+ return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]);
+ }
+ ObjCAtCatchStmt *getCatchStmts() {
+ return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]);
+ }
+ void setCatchStmts(Stmt *S) { SubStmts[CATCH] = S; }
+
+ const ObjCAtFinallyStmt *getFinallyStmt() const {
+ return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]);
+ }
+ ObjCAtFinallyStmt *getFinallyStmt() {
+ return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]);
+ }
+ void setFinallyStmt(Stmt *S) { SubStmts[FINALLY] = S; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtTryStmtClass;
+ }
+ static bool classof(const ObjCAtTryStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement.
+/// Example: @synchronized (sem) {
+/// do-something;
+/// }
+///
+class ObjCAtSynchronizedStmt : public Stmt {
+private:
+ enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
+ Stmt* SubStmts[END_EXPR];
+ SourceLocation AtSynchronizedLoc;
+
+public:
+ ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
+ Stmt *synchBody)
+ : Stmt(ObjCAtSynchronizedStmtClass) {
+ SubStmts[SYNC_EXPR] = synchExpr;
+ SubStmts[SYNC_BODY] = synchBody;
+ AtSynchronizedLoc = atSynchronizedLoc;
+ }
+ explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
+ Stmt(ObjCAtSynchronizedStmtClass, Empty) { }
+
+ SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; }
+ void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; }
+
+ const CompoundStmt *getSynchBody() const {
+ return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
+ }
+ CompoundStmt *getSynchBody() {
+ return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
+ }
+ void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; }
+
+ const Expr *getSynchExpr() const {
+ return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
+ }
+ Expr *getSynchExpr() {
+ return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
+ }
+ void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
+ }
+ static bool classof(const ObjCAtSynchronizedStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+/// ObjCAtThrowStmt - This represents objective-c's @throw statement.
+class ObjCAtThrowStmt : public Stmt {
+ Stmt *Throw;
+ SourceLocation AtThrowLoc;
+public:
+ ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
+ : Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
+ AtThrowLoc = atThrowLoc;
+ }
+ explicit ObjCAtThrowStmt(EmptyShell Empty) :
+ Stmt(ObjCAtThrowStmtClass, Empty) { }
+
+ const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); }
+ Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
+ void setThrowExpr(Stmt *S) { Throw = S; }
+
+ SourceLocation getThrowLoc() { return AtThrowLoc; }
+ void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
+
+ virtual SourceRange getSourceRange() const {
+ if (Throw)
+ return SourceRange(AtThrowLoc, Throw->getLocEnd());
+ else
+ return SourceRange(AtThrowLoc);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtThrowStmtClass;
+ }
+ static bool classof(const ObjCAtThrowStmt *) { return true; }
+
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
new file mode 100644
index 000000000000..4f4066ab8602
--- /dev/null
+++ b/include/clang/AST/StmtVisitor.h
@@ -0,0 +1,176 @@
+//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the StmtVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTVISITOR_H
+#define LLVM_CLANG_AST_STMTVISITOR_H
+
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+
+namespace clang {
+
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S))
+
+/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
+/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
+template<typename ImplClass, typename RetTy=void>
+class StmtVisitor {
+public:
+ RetTy Visit(Stmt *S) {
+
+ // If we have a binary expr, dispatch to the subcode of the binop. A smart
+ // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
+ // below.
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
+ switch (BinOp->getOpcode()) {
+ default: assert(0 && "Unknown binary operator!");
+ case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
+ case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
+ case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator);
+ case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator);
+ case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator);
+ case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator);
+ case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator);
+ case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator);
+ case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator);
+
+ case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator);
+ case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator);
+ case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator);
+ case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator);
+ case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator);
+ case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator);
+
+ case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator);
+ case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator);
+ case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator);
+ case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator);
+ case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator);
+ case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator);
+ case BinaryOperator::MulAssign:
+ DISPATCH(BinMulAssign, CompoundAssignOperator);
+ case BinaryOperator::DivAssign:
+ DISPATCH(BinDivAssign, CompoundAssignOperator);
+ case BinaryOperator::RemAssign:
+ DISPATCH(BinRemAssign, CompoundAssignOperator);
+ case BinaryOperator::AddAssign:
+ DISPATCH(BinAddAssign, CompoundAssignOperator);
+ case BinaryOperator::SubAssign:
+ DISPATCH(BinSubAssign, CompoundAssignOperator);
+ case BinaryOperator::ShlAssign:
+ DISPATCH(BinShlAssign, CompoundAssignOperator);
+ case BinaryOperator::ShrAssign:
+ DISPATCH(BinShrAssign, CompoundAssignOperator);
+ case BinaryOperator::AndAssign:
+ DISPATCH(BinAndAssign, CompoundAssignOperator);
+ case BinaryOperator::OrAssign:
+ DISPATCH(BinOrAssign, CompoundAssignOperator);
+ case BinaryOperator::XorAssign:
+ DISPATCH(BinXorAssign, CompoundAssignOperator);
+ case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator);
+ }
+ } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
+ switch (UnOp->getOpcode()) {
+ default: assert(0 && "Unknown unary operator!");
+ case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
+ case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
+ case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
+ case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
+ case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
+ case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator);
+ case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator);
+ case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator);
+ case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator);
+ case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator);
+ case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator);
+ case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator);
+ case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator);
+ case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator);
+ }
+ }
+
+ // Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
+ switch (S->getStmtClass()) {
+ default: assert(0 && "Unknown stmt kind!");
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);
+#include "clang/AST/StmtNodes.def"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit method, fall
+ // back on VisitExpr or whatever else is the superclass.
+#define STMT(CLASS, PARENT) \
+ RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); }
+#include "clang/AST/StmtNodes.def"
+
+ // If the implementation doesn't implement binary operator methods, fall back
+ // on VisitBinaryOperator.
+#define BINOP_FALLBACK(NAME) \
+ RetTy VisitBin ## NAME(BinaryOperator *S) { \
+ DISPATCH(BinaryOperator, BinaryOperator); \
+ }
+ BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI)
+ BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem)
+ BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl)
+ BINOP_FALLBACK(Shr)
+
+ BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE)
+ BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE)
+ BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or)
+ BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr)
+
+ BINOP_FALLBACK(Assign)
+ BINOP_FALLBACK(Comma)
+#undef BINOP_FALLBACK
+
+ // If the implementation doesn't implement compound assignment operator
+ // methods, fall back on VisitCompoundAssignOperator.
+#define CAO_FALLBACK(NAME) \
+ RetTy VisitBin ## NAME(CompoundAssignOperator *S) { \
+ DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \
+ }
+ CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign)
+ CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign)
+ CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign)
+ CAO_FALLBACK(XorAssign)
+#undef CAO_FALLBACK
+
+ // If the implementation doesn't implement unary operator methods, fall back
+ // on VisitUnaryOperator.
+#define UNARYOP_FALLBACK(NAME) \
+ RetTy VisitUnary ## NAME(UnaryOperator *S) { \
+ DISPATCH(UnaryOperator, UnaryOperator); \
+ }
+ UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
+ UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec)
+ UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref)
+
+ UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
+ UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
+ UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
+ UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
+#undef UNARYOP_FALLBACK
+
+ // Base case, ignore it. :)
+ RetTy VisitStmt(Stmt *Node) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/TargetBuiltins.h b/include/clang/AST/TargetBuiltins.h
new file mode 100644
index 000000000000..d425a9b8ecad
--- /dev/null
+++ b/include/clang/AST/TargetBuiltins.h
@@ -0,0 +1,38 @@
+//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TARGET_BUILTINS_H
+#define LLVM_CLANG_AST_TARGET_BUILTINS_H
+
+#include "clang/AST/Builtins.h"
+#undef PPC
+
+namespace clang {
+ /// X86 builtins
+ namespace X86 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "X86Builtins.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// PPC builtins
+ namespace PPC {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "PPCBuiltins.def"
+ LastTSBuiltin
+ };
+ }
+} // end namespace clang.
+
+#endif
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
new file mode 100644
index 000000000000..511934c1dbf5
--- /dev/null
+++ b/include/clang/AST/TemplateName.h
@@ -0,0 +1,258 @@
+//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TemplateName interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
+#define LLVM_CLANG_AST_TEMPLATENAME_H
+
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class DependentTemplateName;
+class IdentifierInfo;
+class NestedNameSpecifier;
+class PrintingPolicy;
+class QualifiedTemplateName;
+class TemplateDecl;
+
+/// \brief Represents a C++ template name within the type system.
+///
+/// A C++ template name refers to a template within the C++ type
+/// system. In most cases, a template name is simply a reference to a
+/// class template, e.g.
+///
+/// \code
+/// template<typename T> class X { };
+///
+/// X<int> xi;
+/// \endcode
+///
+/// Here, the 'X' in \c X<int> is a template name that refers to the
+/// declaration of the class template X, above. Template names can
+/// also refer to function templates, C++0x template aliases, etc.
+///
+/// Some template names are dependent. For example, consider:
+///
+/// \code
+/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
+/// typedef typename MetaFun::template apply<T1, T2>::type type;
+/// };
+/// \endcode
+///
+/// Here, "apply" is treated as a template name within the typename
+/// specifier in the typedef. "apply" is a nested template, and can
+/// only be understood in the context of
+class TemplateName {
+ typedef llvm::PointerUnion3<TemplateDecl *, QualifiedTemplateName *,
+ DependentTemplateName *> StorageType;
+
+ StorageType Storage;
+
+ explicit TemplateName(void *Ptr) {
+ Storage = StorageType::getFromOpaqueValue(Ptr);
+ }
+
+public:
+ TemplateName() : Storage() { }
+ explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
+ explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
+ explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
+
+ /// \brief Retrieve the the underlying template declaration that
+ /// this template name refers to, if known.
+ ///
+ /// \returns The template declaration that this template name refers
+ /// to, if any. If the template name does not refer to a specific
+ /// declaration because it is a dependent name, returns NULL.
+ TemplateDecl *getAsTemplateDecl() const;
+
+ /// \brief Retrieve the underlying qualified template name
+ /// structure, if any.
+ QualifiedTemplateName *getAsQualifiedTemplateName() const {
+ return Storage.dyn_cast<QualifiedTemplateName *>();
+ }
+
+ /// \brief Retrieve the underlying dependent template name
+ /// structure, if any.
+ DependentTemplateName *getAsDependentTemplateName() const {
+ return Storage.dyn_cast<DependentTemplateName *>();
+ }
+
+ /// \brief Determines whether this is a dependent template name.
+ bool isDependent() const;
+
+ /// \brief Print the template name.
+ ///
+ /// \param OS the output stream to which the template name will be
+ /// printed.
+ ///
+ /// \param SuppressNNS if true, don't print the
+ /// nested-name-specifier that precedes the template name (if it has
+ /// one).
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
+ bool SuppressNNS = false) const;
+
+ /// \brief Debugging aid that dumps the template name to standard
+ /// error.
+ void dump() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddPointer(Storage.getOpaqueValue());
+ }
+
+ /// \brief Retrieve the template name as a void pointer.
+ void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
+
+ /// \brief Build a template name from a void pointer.
+ static TemplateName getFromVoidPointer(void *Ptr) {
+ return TemplateName(Ptr);
+ }
+};
+
+/// \brief Represents a template name that was expressed as a
+/// qualified name.
+///
+/// This kind of template name refers to a template name that was
+/// preceded by a nested name specifier, e.g., \c std::vector. Here,
+/// the nested name specifier is "std::" and the template name is the
+/// declaration for "vector". The QualifiedTemplateName class is only
+/// used to provide "sugar" for template names that were expressed
+/// with a qualified name, and has no semantic meaning. In this
+/// manner, it is to TemplateName what QualifiedNameType is to Type,
+/// providing extra syntactic sugar for downstream clients.
+class QualifiedTemplateName : public llvm::FoldingSetNode {
+ /// \brief The nested name specifier that qualifies the template name.
+ ///
+ /// The bit is used to indicate whether the "template" keyword was
+ /// present before the template name itself. Note that the
+ /// "template" keyword is always redundant in this case (otherwise,
+ /// the template name would be a dependent name and we would express
+ /// this name with DependentTemplateName).
+ llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
+
+ /// \brief The template declaration that this qualified name refers
+ /// to.
+ TemplateDecl *Template;
+
+ friend class ASTContext;
+
+ QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
+ TemplateDecl *Template)
+ : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) { }
+
+public:
+ /// \brief Return the nested name specifier that qualifies this name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
+
+ /// \brief Whether the template name was prefixed by the "template"
+ /// keyword.
+ bool hasTemplateKeyword() const { return Qualifier.getInt(); }
+
+ /// \brief The template declaration to which this qualified name
+ /// refers.
+ TemplateDecl *getTemplateDecl() const { return Template; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ bool TemplateKeyword, TemplateDecl *Template) {
+ ID.AddPointer(NNS);
+ ID.AddBoolean(TemplateKeyword);
+ ID.AddPointer(Template);
+ }
+};
+
+/// \brief Represents a dependent template name that cannot be
+/// resolved prior to template instantiation.
+///
+/// This kind of template name refers to a dependent template name,
+/// including its nested name specifier. For example,
+/// DependentTemplateName can refer to "MetaFun::template apply",
+/// where "MetaFun::" is the nested name specifier and "apply" is the
+/// template name referenced. The "template" keyword is implied.
+class DependentTemplateName : public llvm::FoldingSetNode {
+ /// \brief The nested name specifier that qualifies the template
+ /// name.
+ NestedNameSpecifier *Qualifier;
+
+ /// \brief The dependent template name.
+ const IdentifierInfo *Name;
+
+ /// \brief The canonical template name to which this dependent
+ /// template name refers.
+ ///
+ /// The canonical template name for a dependent template name is
+ /// another dependent template name whose nested name specifier is
+ /// canonical.
+ TemplateName CanonicalTemplateName;
+
+ friend class ASTContext;
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Name)
+ : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { }
+
+ DependentTemplateName(NestedNameSpecifier *Qualifier,
+ const IdentifierInfo *Name,
+ TemplateName Canon)
+ : Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { }
+
+public:
+ /// \brief Return the nested name specifier that qualifies this name.
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
+
+ /// \brief Return the name to which this dependent template name
+ /// refers.
+ const IdentifierInfo *getName() const { return Name; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getQualifier(), getName());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name) {
+ ID.AddPointer(NNS);
+ ID.AddPointer(Name);
+ }
+};
+
+} // end namespace clang.
+
+namespace llvm {
+
+/// \brief The clang::TemplateName class is effectively a pointer.
+template<>
+class PointerLikeTypeTraits<clang::TemplateName> {
+public:
+ static inline void *getAsVoidPointer(clang::TemplateName TN) {
+ return TN.getAsVoidPointer();
+ }
+
+ static inline clang::TemplateName getFromVoidPointer(void *Ptr) {
+ return clang::TemplateName::getFromVoidPointer(Ptr);
+ }
+
+ // No bits are available!
+ enum { NumLowBitsAvailable = 0 };
+};
+
+} // end namespace llvm.
+
+#endif
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
new file mode 100644
index 000000000000..1b012385c9f2
--- /dev/null
+++ b/include/clang/AST/Type.h
@@ -0,0 +1,1977 @@
+//===--- Type.h - C Language Family Type Representation ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Type interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPE_H
+#define LLVM_CLANG_AST_TYPE_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateName.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+namespace clang { class Type; }
+
+namespace llvm {
+ template <typename T>
+ class PointerLikeTypeTraits;
+ template<>
+ class PointerLikeTypeTraits< ::clang::Type*> {
+ public:
+ static inline void *getAsVoidPointer(::clang::Type *P) { return P; }
+ static inline ::clang::Type *getFromVoidPointer(void *P) {
+ return static_cast< ::clang::Type*>(P);
+ }
+ enum { NumLowBitsAvailable = 3 };
+ };
+}
+
+namespace clang {
+ class ASTContext;
+ class TypedefDecl;
+ class TemplateDecl;
+ class TemplateTypeParmDecl;
+ class NonTypeTemplateParmDecl;
+ class TemplateTemplateParmDecl;
+ class TagDecl;
+ class RecordDecl;
+ class CXXRecordDecl;
+ class EnumDecl;
+ class FieldDecl;
+ class ObjCInterfaceDecl;
+ class ObjCProtocolDecl;
+ class ObjCMethodDecl;
+ class Expr;
+ class Stmt;
+ class SourceLocation;
+ class StmtIteratorBase;
+ class TemplateArgument;
+ class QualifiedNameType;
+ class PrintingPolicy;
+
+ // Provide forward declarations for all of the *Type classes
+#define TYPE(Class, Base) class Class##Type;
+#include "clang/AST/TypeNodes.def"
+
+/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
+/// their own: instead each reference to a type stores the qualifiers. This
+/// greatly reduces the number of nodes we need to allocate for types (for
+/// example we only need one for 'int', 'const int', 'volatile int',
+/// 'const volatile int', etc).
+///
+/// As an added efficiency bonus, instead of making this a pair, we just store
+/// the three bits we care about in the low bits of the pointer. To handle the
+/// packing/unpacking, we make QualType be a simple wrapper class that acts like
+/// a smart pointer.
+class QualType {
+ llvm::PointerIntPair<Type*, 3> Value;
+public:
+ enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+ Const = 0x1,
+ Restrict = 0x2,
+ Volatile = 0x4,
+ CVRFlags = Const|Restrict|Volatile
+ };
+
+ enum GCAttrTypes {
+ GCNone = 0,
+ Weak,
+ Strong
+ };
+
+ QualType() {}
+
+ QualType(const Type *Ptr, unsigned Quals)
+ : Value(const_cast<Type*>(Ptr), Quals) {}
+
+ unsigned getCVRQualifiers() const { return Value.getInt(); }
+ void setCVRQualifiers(unsigned Quals) { Value.setInt(Quals); }
+ Type *getTypePtr() const { return Value.getPointer(); }
+
+ void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
+ static QualType getFromOpaquePtr(void *Ptr) {
+ QualType T;
+ T.Value.setFromOpaqueValue(Ptr);
+ return T;
+ }
+
+ Type &operator*() const {
+ return *getTypePtr();
+ }
+
+ Type *operator->() const {
+ return getTypePtr();
+ }
+
+ /// isNull - Return true if this QualType doesn't point to a type yet.
+ bool isNull() const {
+ return getTypePtr() == 0;
+ }
+
+ bool isConstQualified() const {
+ return (getCVRQualifiers() & Const) ? true : false;
+ }
+ bool isVolatileQualified() const {
+ return (getCVRQualifiers() & Volatile) ? true : false;
+ }
+ bool isRestrictQualified() const {
+ return (getCVRQualifiers() & Restrict) ? true : false;
+ }
+
+ bool isConstant(ASTContext& Ctx) const;
+
+ /// addConst/addVolatile/addRestrict - add the specified type qual to this
+ /// QualType.
+ void addConst() { Value.setInt(Value.getInt() | Const); }
+ void addVolatile() { Value.setInt(Value.getInt() | Volatile); }
+ void addRestrict() { Value.setInt(Value.getInt() | Restrict); }
+
+ void removeConst() { Value.setInt(Value.getInt() & ~Const); }
+ void removeVolatile() { Value.setInt(Value.getInt() & ~Volatile); }
+ void removeRestrict() { Value.setInt(Value.getInt() & ~Restrict); }
+
+ QualType getQualifiedType(unsigned TQs) const {
+ return QualType(getTypePtr(), TQs);
+ }
+ QualType getWithAdditionalQualifiers(unsigned TQs) const {
+ return QualType(getTypePtr(), TQs|getCVRQualifiers());
+ }
+
+ QualType withConst() const { return getWithAdditionalQualifiers(Const); }
+ QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);}
+ QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);}
+
+ QualType getUnqualifiedType() const;
+ bool isMoreQualifiedThan(QualType Other) const;
+ bool isAtLeastAsQualifiedAs(QualType Other) const;
+ QualType getNonReferenceType() const;
+
+ /// getDesugaredType - Return the specified type with any "sugar" removed from
+ /// the type. This takes off typedefs, typeof's etc. If the outer level of
+ /// the type is already concrete, it returns it unmodified. This is similar
+ /// to getting the canonical type, but it doesn't remove *all* typedefs. For
+ /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
+ /// concrete.
+ QualType getDesugaredType(bool ForDisplay = false) const;
+
+ /// operator==/!= - Indicate whether the specified types and qualifiers are
+ /// identical.
+ bool operator==(const QualType &RHS) const {
+ return Value == RHS.Value;
+ }
+ bool operator!=(const QualType &RHS) const {
+ return Value != RHS.Value;
+ }
+ std::string getAsString() const;
+
+ std::string getAsString(const PrintingPolicy &Policy) const {
+ std::string S;
+ getAsStringInternal(S, Policy);
+ return S;
+ }
+ void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const;
+
+ void dump(const char *s) const;
+ void dump() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(getAsOpaquePtr());
+ }
+
+public:
+
+ /// getAddressSpace - Return the address space of this type.
+ inline unsigned getAddressSpace() const;
+
+ /// GCAttrTypesAttr - Returns gc attribute of this type.
+ inline QualType::GCAttrTypes getObjCGCAttr() const;
+
+ /// isObjCGCWeak true when Type is objc's weak.
+ bool isObjCGCWeak() const {
+ return getObjCGCAttr() == Weak;
+ }
+
+ /// isObjCGCStrong true when Type is objc's strong.
+ bool isObjCGCStrong() const {
+ return getObjCGCAttr() == Strong;
+ }
+};
+
+} // end clang.
+
+namespace llvm {
+/// Implement simplify_type for QualType, so that we can dyn_cast from QualType
+/// to a specific Type class.
+template<> struct simplify_type<const ::clang::QualType> {
+ typedef ::clang::Type* SimpleType;
+ static SimpleType getSimplifiedValue(const ::clang::QualType &Val) {
+ return Val.getTypePtr();
+ }
+};
+template<> struct simplify_type< ::clang::QualType>
+ : public simplify_type<const ::clang::QualType> {};
+
+// Teach SmallPtrSet that QualType is "basically a pointer".
+template<>
+class PointerLikeTypeTraits<clang::QualType> {
+public:
+ static inline void *getAsVoidPointer(clang::QualType P) {
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::QualType getFromVoidPointer(void *P) {
+ return clang::QualType::getFromOpaquePtr(P);
+ }
+ // CVR qualifiers go in low bits.
+ enum { NumLowBitsAvailable = 0 };
+};
+} // end namespace llvm
+
+namespace clang {
+
+/// Type - This is the base class of the type hierarchy. A central concept
+/// with types is that each type always has a canonical type. A canonical type
+/// is the type with any typedef names stripped out of it or the types it
+/// references. For example, consider:
+///
+/// typedef int foo;
+/// typedef foo* bar;
+/// 'int *' 'foo *' 'bar'
+///
+/// There will be a Type object created for 'int'. Since int is canonical, its
+/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a
+/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next
+/// there is a PointerType that represents 'int*', which, like 'int', is
+/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical
+/// type is 'int*', and there is a TypedefType for 'bar', whose canonical type
+/// is also 'int*'.
+///
+/// Non-canonical types are useful for emitting diagnostics, without losing
+/// information about typedefs being used. Canonical types are useful for type
+/// comparisons (they allow by-pointer equality tests) and useful for reasoning
+/// about whether something has a particular form (e.g. is a function type),
+/// because they implicitly, recursively, strip all typedefs out of a type.
+///
+/// Types, once created, are immutable.
+///
+class Type {
+public:
+ enum TypeClass {
+#define TYPE(Class, Base) Class,
+#define ABSTRACT_TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+ TagFirst = Record, TagLast = Enum
+ };
+
+private:
+ QualType CanonicalType;
+
+ /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
+ bool Dependent : 1;
+
+ /// TypeClass bitfield - Enum that specifies what subclass this belongs to.
+ /// Note that this should stay at the end of the ivars for Type so that
+ /// subclasses can pack their bitfields into the same word.
+ unsigned TC : 5;
+
+ Type(const Type&); // DO NOT IMPLEMENT.
+ void operator=(const Type&); // DO NOT IMPLEMENT.
+protected:
+ // silence VC++ warning C4355: 'this' : used in base member initializer list
+ Type *this_() { return this; }
+ Type(TypeClass tc, QualType Canonical, bool dependent)
+ : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
+ Dependent(dependent), TC(tc) {}
+ virtual ~Type() {}
+ virtual void Destroy(ASTContext& C);
+ friend class ASTContext;
+
+public:
+ TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
+
+ bool isCanonical() const { return CanonicalType.getTypePtr() == this; }
+
+ /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
+ /// object types, function types, and incomplete types.
+
+ /// \brief Determines whether the type describes an object in memory.
+ ///
+ /// Note that this definition of object type corresponds to the C++
+ /// definition of object type, which includes incomplete types, as
+ /// opposed to the C definition (which does not include incomplete
+ /// types).
+ bool isObjectType() const;
+
+ /// isIncompleteType - Return true if this is an incomplete type.
+ /// A type that can describe objects, but which lacks information needed to
+ /// determine its size (e.g. void, or a fwd declared struct). Clients of this
+ /// routine will need to determine if the size is actually required.
+ bool isIncompleteType() const;
+
+ /// isIncompleteOrObjectType - Return true if this is an incomplete or object
+ /// type, in other words, not a function type.
+ bool isIncompleteOrObjectType() const {
+ return !isFunctionType();
+ }
+
+ /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
+ bool isPODType() const;
+
+ /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
+ /// types that have a non-constant expression. This does not include "[]".
+ bool isVariablyModifiedType() const;
+
+ /// Helper methods to distinguish type categories. All type predicates
+ /// operate on the canonical type, ignoring typedefs and qualifiers.
+
+ /// isSpecificBuiltinType - Test for a particular builtin type.
+ bool isSpecificBuiltinType(unsigned K) const;
+
+ /// isIntegerType() does *not* include complex integers (a GCC extension).
+ /// isComplexIntegerType() can be used to test for complex integers.
+ bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
+ bool isEnumeralType() const;
+ bool isBooleanType() const;
+ bool isCharType() const;
+ bool isWideCharType() const;
+ bool isIntegralType() const;
+
+ /// Floating point categories.
+ bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
+ /// isComplexType() does *not* include complex integers (a GCC extension).
+ /// isComplexIntegerType() can be used to test for complex integers.
+ bool isComplexType() const; // C99 6.2.5p11 (complex)
+ bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int.
+ bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex)
+ bool isRealType() const; // C99 6.2.5p17 (real floating + integer)
+ bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating)
+ bool isVoidType() const; // C99 6.2.5p19
+ bool isDerivedType() const; // C99 6.2.5p20
+ bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
+ bool isAggregateType() const;
+
+ // Type Predicates: Check to see if this type is structurally the specified
+ // type, ignoring typedefs and qualifiers.
+ bool isFunctionType() const;
+ bool isFunctionNoProtoType() const { return getAsFunctionNoProtoType() != 0; }
+ bool isFunctionProtoType() const { return getAsFunctionProtoType() != 0; }
+ bool isPointerType() const;
+ bool isBlockPointerType() const;
+ bool isReferenceType() const;
+ bool isLValueReferenceType() const;
+ bool isRValueReferenceType() const;
+ bool isFunctionPointerType() const;
+ bool isMemberPointerType() const;
+ bool isMemberFunctionPointerType() const;
+ bool isArrayType() const;
+ bool isConstantArrayType() const;
+ bool isIncompleteArrayType() const;
+ bool isVariableArrayType() const;
+ bool isDependentSizedArrayType() const;
+ bool isRecordType() const;
+ bool isClassType() const;
+ bool isStructureType() const;
+ bool isUnionType() const;
+ bool isComplexIntegerType() const; // GCC _Complex integer type.
+ bool isVectorType() const; // GCC vector type.
+ bool isExtVectorType() const; // Extended vector type.
+ bool isObjCInterfaceType() const; // NSString or NSString<foo>
+ bool isObjCQualifiedInterfaceType() const; // NSString<foo>
+ bool isObjCQualifiedIdType() const; // id<foo>
+ bool isTemplateTypeParmType() const; // C++ template type parameter
+ bool isNullPtrType() const; // C++0x nullptr_t
+
+ /// isDependentType - Whether this type is a dependent type, meaning
+ /// that its definition somehow depends on a template parameter
+ /// (C++ [temp.dep.type]).
+ bool isDependentType() const { return Dependent; }
+ bool isOverloadableType() const;
+
+ /// hasPointerRepresentation - Whether this type is represented
+ /// natively as a pointer; this includes pointers, references, block
+ /// pointers, and Objective-C interface, qualified id, and qualified
+ /// interface types, as well as nullptr_t.
+ bool hasPointerRepresentation() const;
+
+ /// hasObjCPointerRepresentation - Whether this type can represent
+ /// an objective pointer type for the purpose of GC'ability
+ bool hasObjCPointerRepresentation() const;
+
+ // Type Checking Functions: Check to see if this type is structurally the
+ // specified type, ignoring typedefs and qualifiers, and return a pointer to
+ // the best type we can.
+ const BuiltinType *getAsBuiltinType() const;
+ const FunctionType *getAsFunctionType() const;
+ const FunctionNoProtoType *getAsFunctionNoProtoType() const;
+ const FunctionProtoType *getAsFunctionProtoType() const;
+ const PointerType *getAsPointerType() const;
+ const BlockPointerType *getAsBlockPointerType() const;
+ const ReferenceType *getAsReferenceType() const;
+ const LValueReferenceType *getAsLValueReferenceType() const;
+ const RValueReferenceType *getAsRValueReferenceType() const;
+ const MemberPointerType *getAsMemberPointerType() const;
+ const TagType *getAsTagType() const;
+ const RecordType *getAsRecordType() const;
+ const RecordType *getAsStructureType() const;
+ /// NOTE: getAs*ArrayType are methods on ASTContext.
+ const TypedefType *getAsTypedefType() const;
+ const RecordType *getAsUnionType() const;
+ const EnumType *getAsEnumType() const;
+ const VectorType *getAsVectorType() const; // GCC vector type.
+ const ComplexType *getAsComplexType() const;
+ const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
+ const ExtVectorType *getAsExtVectorType() const; // Extended vector type.
+ const ObjCInterfaceType *getAsObjCInterfaceType() const;
+ const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
+ const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
+ const TemplateTypeParmType *getAsTemplateTypeParmType() const;
+
+ const TemplateSpecializationType *
+ getAsTemplateSpecializationType() const;
+
+ /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
+ /// interface, return the interface type, otherwise return null.
+ const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
+
+ /// getArrayElementTypeNoTypeQual - If this is an array type, return the
+ /// element type of the array, potentially with type qualifiers missing.
+ /// This method should never be used when type qualifiers are meaningful.
+ const Type *getArrayElementTypeNoTypeQual() const;
+
+ /// getDesugaredType - Return the specified type with any "sugar" removed from
+ /// the type. This takes off typedefs, typeof's etc. If the outer level of
+ /// the type is already concrete, it returns it unmodified. This is similar
+ /// to getting the canonical type, but it doesn't remove *all* typedefs. For
+ /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
+ /// concrete.
+ QualType getDesugaredType(bool ForDisplay = false) const;
+
+ /// More type predicates useful for type checking/promotion
+ bool isPromotableIntegerType() const; // C99 6.3.1.1p2
+
+ /// isSignedIntegerType - Return true if this is an integer type that is
+ /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
+ /// an enum decl which has a signed representation, or a vector of signed
+ /// integer element type.
+ bool isSignedIntegerType() const;
+
+ /// isUnsignedIntegerType - Return true if this is an integer type that is
+ /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
+ /// decl which has an unsigned representation, or a vector of unsigned integer
+ /// element type.
+ bool isUnsignedIntegerType() const;
+
+ /// isConstantSizeType - Return true if this is not a variable sized type,
+ /// according to the rules of C99 6.7.5p3. It is not legal to call this on
+ /// incomplete types.
+ bool isConstantSizeType() const;
+
+ /// isSpecifierType - Returns true if this type can be represented by some
+ /// set of type specifiers.
+ bool isSpecifierType() const;
+
+ QualType getCanonicalTypeInternal() const { return CanonicalType; }
+ void dump() const;
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const = 0;
+ static bool classof(const Type *) { return true; }
+};
+
+/// ExtQualType - TR18037 (C embedded extensions) 6.2.5p26
+/// This supports all kinds of type attributes; including,
+/// address space qualified types, objective-c's __weak and
+/// __strong attributes.
+///
+class ExtQualType : public Type, public llvm::FoldingSetNode {
+ /// BaseType - This is the underlying type that this qualifies. All CVR
+ /// qualifiers are stored on the QualType that references this type, so we
+ /// can't have any here.
+ Type *BaseType;
+
+ /// Address Space ID - The address space ID this type is qualified with.
+ unsigned AddressSpace;
+ /// GC __weak/__strong attributes
+ QualType::GCAttrTypes GCAttrType;
+
+ ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace,
+ QualType::GCAttrTypes gcAttr) :
+ Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base),
+ AddressSpace(AddrSpace), GCAttrType(gcAttr) {
+ assert(!isa<ExtQualType>(BaseType) &&
+ "Cannot have ExtQualType of ExtQualType");
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+ Type *getBaseType() const { return BaseType; }
+ QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; }
+ unsigned getAddressSpace() const { return AddressSpace; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getBaseType(), AddressSpace, GCAttrType);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, Type *Base,
+ unsigned AddrSpace, QualType::GCAttrTypes gcAttr) {
+ ID.AddPointer(Base);
+ ID.AddInteger(AddrSpace);
+ ID.AddInteger(gcAttr);
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == ExtQual; }
+ static bool classof(const ExtQualType *) { return true; }
+};
+
+
+/// BuiltinType - This class is used for builtin types like 'int'. Builtin
+/// types are always canonical and have a literal name field.
+class BuiltinType : public Type {
+public:
+ enum Kind {
+ Void,
+
+ Bool, // This is bool and/or _Bool.
+ Char_U, // This is 'char' for targets where char is unsigned.
+ UChar, // This is explicitly qualified unsigned char.
+ UShort,
+ UInt,
+ ULong,
+ ULongLong,
+ UInt128, // __uint128_t
+
+ Char_S, // This is 'char' for targets where char is signed.
+ SChar, // This is explicitly qualified signed char.
+ WChar, // This is 'wchar_t' for C++.
+ Short,
+ Int,
+ Long,
+ LongLong,
+ Int128, // __int128_t
+
+ Float, Double, LongDouble,
+
+ NullPtr, // This is the type of C++0x 'nullptr'.
+
+ Overload, // This represents the type of an overloaded function declaration.
+ Dependent // This represents the type of a type-dependent expression.
+ };
+private:
+ Kind TypeKind;
+public:
+ BuiltinType(Kind K)
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent)),
+ TypeKind(K) {}
+
+ Kind getKind() const { return TypeKind; }
+ const char *getName(bool CPlusPlus) const;
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
+ static bool classof(const BuiltinType *) { return true; }
+};
+
+/// FixedWidthIntType - Used for arbitrary width types that we either don't
+/// want to or can't map to named integer types. These always have a lower
+/// integer rank than builtin types of the same width.
+class FixedWidthIntType : public Type {
+private:
+ unsigned Width;
+ bool Signed;
+public:
+ FixedWidthIntType(unsigned W, bool S) : Type(FixedWidthInt, QualType(), false),
+ Width(W), Signed(S) {}
+
+ unsigned getWidth() const { return Width; }
+ bool isSigned() const { return Signed; }
+ const char *getName() const;
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; }
+ static bool classof(const FixedWidthIntType *) { return true; }
+};
+
+/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex
+/// types (_Complex float etc) as well as the GCC integer complex extensions.
+///
+class ComplexType : public Type, public llvm::FoldingSetNode {
+ QualType ElementType;
+ ComplexType(QualType Element, QualType CanonicalPtr) :
+ Type(Complex, CanonicalPtr, Element->isDependentType()),
+ ElementType(Element) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+ QualType getElementType() const { return ElementType; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Element) {
+ ID.AddPointer(Element.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
+ static bool classof(const ComplexType *) { return true; }
+};
+
+/// PointerType - C99 6.7.5.1 - Pointer Declarators.
+///
+class PointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+
+ PointerType(QualType Pointee, QualType CanonicalPtr) :
+ Type(Pointer, CanonicalPtr, Pointee->isDependentType()), PointeeType(Pointee) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ QualType getPointeeType() const { return PointeeType; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
+ static bool classof(const PointerType *) { return true; }
+};
+
+/// BlockPointerType - pointer to a block type.
+/// This type is to represent types syntactically represented as
+/// "void (^)(int)", etc. Pointee is required to always be a function type.
+///
+class BlockPointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType; // Block is some kind of pointer type
+ BlockPointerType(QualType Pointee, QualType CanonicalCls) :
+ Type(BlockPointer, CanonicalCls, Pointee->isDependentType()),
+ PointeeType(Pointee) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ // Get the pointee type. Pointee is required to always be a function type.
+ QualType getPointeeType() const { return PointeeType; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == BlockPointer;
+ }
+ static bool classof(const BlockPointerType *) { return true; }
+};
+
+/// ReferenceType - Base for LValueReferenceType and RValueReferenceType
+///
+class ReferenceType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+
+protected:
+ ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) :
+ Type(tc, CanonicalRef, Referencee->isDependentType()),
+ PointeeType(Referencee) {
+ }
+public:
+ QualType getPointeeType() const { return PointeeType; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) {
+ ID.AddPointer(Referencee.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LValueReference ||
+ T->getTypeClass() == RValueReference;
+ }
+ static bool classof(const ReferenceType *) { return true; }
+};
+
+/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
+///
+class LValueReferenceType : public ReferenceType {
+ LValueReferenceType(QualType Referencee, QualType CanonicalRef) :
+ ReferenceType(LValueReference, Referencee, CanonicalRef) {
+ }
+ friend class ASTContext; // ASTContext creates these
+public:
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LValueReference;
+ }
+ static bool classof(const LValueReferenceType *) { return true; }
+};
+
+/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference
+///
+class RValueReferenceType : public ReferenceType {
+ RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
+ ReferenceType(RValueReference, Referencee, CanonicalRef) {
+ }
+ friend class ASTContext; // ASTContext creates these
+public:
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == RValueReference;
+ }
+ static bool classof(const RValueReferenceType *) { return true; }
+};
+
+/// MemberPointerType - C++ 8.3.3 - Pointers to members
+///
+class MemberPointerType : public Type, public llvm::FoldingSetNode {
+ QualType PointeeType;
+ /// The class of which the pointee is a member. Must ultimately be a
+ /// RecordType, but could be a typedef or a template parameter too.
+ const Type *Class;
+
+ MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr) :
+ Type(MemberPointer, CanonicalPtr,
+ Cls->isDependentType() || Pointee->isDependentType()),
+ PointeeType(Pointee), Class(Cls) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ QualType getPointeeType() const { return PointeeType; }
+
+ const Type *getClass() const { return Class; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPointeeType(), getClass());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
+ const Type *Class) {
+ ID.AddPointer(Pointee.getAsOpaquePtr());
+ ID.AddPointer(Class);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == MemberPointer;
+ }
+ static bool classof(const MemberPointerType *) { return true; }
+};
+
+/// ArrayType - C99 6.7.5.2 - Array Declarators.
+///
+class ArrayType : public Type, public llvm::FoldingSetNode {
+public:
+ /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4])
+ /// an array with a static size (e.g. int X[static 4]), or an array
+ /// with a star size (e.g. int X[*]).
+ /// 'static' is only allowed on function parameters.
+ enum ArraySizeModifier {
+ Normal, Static, Star
+ };
+private:
+ /// ElementType - The element type of the array.
+ QualType ElementType;
+
+ // NOTE: VC++ treats enums as signed, avoid using the ArraySizeModifier enum
+ /// NOTE: These fields are packed into the bitfields space in the Type class.
+ unsigned SizeModifier : 2;
+
+ /// IndexTypeQuals - Capture qualifiers in declarations like:
+ /// 'int X[static restrict 4]'. For function parameters only.
+ unsigned IndexTypeQuals : 3;
+
+protected:
+ // C++ [temp.dep.type]p1:
+ // A type is dependent if it is...
+ // - an array type constructed from any dependent type or whose
+ // size is specified by a constant expression that is
+ // value-dependent,
+ ArrayType(TypeClass tc, QualType et, QualType can,
+ ArraySizeModifier sm, unsigned tq)
+ : Type(tc, can, et->isDependentType() || tc == DependentSizedArray),
+ ElementType(et), SizeModifier(sm), IndexTypeQuals(tq) {}
+
+ friend class ASTContext; // ASTContext creates these.
+public:
+ QualType getElementType() const { return ElementType; }
+ ArraySizeModifier getSizeModifier() const {
+ return ArraySizeModifier(SizeModifier);
+ }
+ unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ConstantArray ||
+ T->getTypeClass() == VariableArray ||
+ T->getTypeClass() == IncompleteArray ||
+ T->getTypeClass() == DependentSizedArray;
+ }
+ static bool classof(const ArrayType *) { return true; }
+};
+
+/// ConstantArrayType - This class represents C arrays with a specified constant
+/// size. For example 'int A[100]' has ConstantArrayType where the element type
+/// is 'int' and the size is 100.
+class ConstantArrayType : public ArrayType {
+ llvm::APInt Size; // Allows us to unique the type.
+
+ ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
+ ArraySizeModifier sm, unsigned tq)
+ : ArrayType(ConstantArray, et, can, sm, tq), Size(size) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+ const llvm::APInt &getSize() const { return Size; }
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType(), getSize(),
+ getSizeModifier(), getIndexTypeQualifier());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
+ const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
+ unsigned TypeQuals) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(ArraySize.getZExtValue());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ConstantArray;
+ }
+ static bool classof(const ConstantArrayType *) { return true; }
+};
+
+/// IncompleteArrayType - This class represents C arrays with an unspecified
+/// size. For example 'int A[]' has an IncompleteArrayType where the element
+/// type is 'int' and the size is unspecified.
+class IncompleteArrayType : public ArrayType {
+ IncompleteArrayType(QualType et, QualType can,
+ ArraySizeModifier sm, unsigned tq)
+ : ArrayType(IncompleteArray, et, can, sm, tq) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == IncompleteArray;
+ }
+ static bool classof(const IncompleteArrayType *) { return true; }
+
+ friend class StmtIteratorBase;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType(), getSizeModifier(), getIndexTypeQualifier());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
+ ArraySizeModifier SizeMod, unsigned TypeQuals) {
+ ID.AddPointer(ET.getAsOpaquePtr());
+ ID.AddInteger(SizeMod);
+ ID.AddInteger(TypeQuals);
+ }
+};
+
+/// VariableArrayType - This class represents C arrays with a specified size
+/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'.
+/// Since the size expression is an arbitrary expression, we store it as such.
+///
+/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and
+/// should not be: two lexically equivalent variable array types could mean
+/// different things, for example, these variables do not have the same type
+/// dynamically:
+///
+/// void foo(int x) {
+/// int Y[x];
+/// ++x;
+/// int Z[x];
+/// }
+///
+class VariableArrayType : public ArrayType {
+ /// SizeExpr - An assignment expression. VLA's are only permitted within
+ /// a function block.
+ Stmt *SizeExpr;
+
+ VariableArrayType(QualType et, QualType can, Expr *e,
+ ArraySizeModifier sm, unsigned tq)
+ : ArrayType(VariableArray, et, can, sm, tq), SizeExpr((Stmt*) e) {}
+ friend class ASTContext; // ASTContext creates these.
+ virtual void Destroy(ASTContext& C);
+
+public:
+ Expr *getSizeExpr() const {
+ // We use C-style casts instead of cast<> here because we do not wish
+ // to have a dependency of Type.h on Stmt.h/Expr.h.
+ return (Expr*) SizeExpr;
+ }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == VariableArray;
+ }
+ static bool classof(const VariableArrayType *) { return true; }
+
+ friend class StmtIteratorBase;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ assert(0 && "Cannnot unique VariableArrayTypes.");
+ }
+};
+
+/// DependentSizedArrayType - This type represents an array type in
+/// C++ whose size is a value-dependent expression. For example:
+/// @code
+/// template<typename T, int Size>
+/// class array {
+/// T data[Size];
+/// };
+/// @endcode
+/// For these types, we won't actually know what the array bound is
+/// until template instantiation occurs, at which point this will
+/// become either a ConstantArrayType or a VariableArrayType.
+class DependentSizedArrayType : public ArrayType {
+ /// SizeExpr - An assignment expression that will instantiate to the
+ /// size of the array.
+ Stmt *SizeExpr;
+
+ DependentSizedArrayType(QualType et, QualType can, Expr *e,
+ ArraySizeModifier sm, unsigned tq)
+ : ArrayType(DependentSizedArray, et, can, sm, tq), SizeExpr((Stmt*) e) {}
+ friend class ASTContext; // ASTContext creates these.
+ virtual void Destroy(ASTContext& C);
+
+public:
+ Expr *getSizeExpr() const {
+ // We use C-style casts instead of cast<> here because we do not wish
+ // to have a dependency of Type.h on Stmt.h/Expr.h.
+ return (Expr*) SizeExpr;
+ }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentSizedArray;
+ }
+ static bool classof(const DependentSizedArrayType *) { return true; }
+
+ friend class StmtIteratorBase;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ assert(0 && "Cannnot unique DependentSizedArrayTypes.");
+ }
+};
+
+/// VectorType - GCC generic vector type. This type is created using
+/// __attribute__((vector_size(n)), where "n" specifies the vector size in
+/// bytes. Since the constructor takes the number of vector elements, the
+/// client is responsible for converting the size into the number of elements.
+class VectorType : public Type, public llvm::FoldingSetNode {
+protected:
+ /// ElementType - The element type of the vector.
+ QualType ElementType;
+
+ /// NumElements - The number of elements in the vector.
+ unsigned NumElements;
+
+ VectorType(QualType vecType, unsigned nElements, QualType canonType) :
+ Type(Vector, canonType, vecType->isDependentType()),
+ ElementType(vecType), NumElements(nElements) {}
+ VectorType(TypeClass tc, QualType vecType, unsigned nElements,
+ QualType canonType)
+ : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType),
+ NumElements(nElements) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ QualType getElementType() const { return ElementType; }
+ unsigned getNumElements() const { return NumElements; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getElementType(), getNumElements(), getTypeClass());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType,
+ unsigned NumElements, TypeClass TypeClass) {
+ ID.AddPointer(ElementType.getAsOpaquePtr());
+ ID.AddInteger(NumElements);
+ ID.AddInteger(TypeClass);
+ }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector;
+ }
+ static bool classof(const VectorType *) { return true; }
+};
+
+/// ExtVectorType - Extended vector type. This type is created using
+/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
+/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This
+/// class enables syntactic extensions, like Vector Components for accessing
+/// points, colors, and textures (modeled after OpenGL Shading Language).
+class ExtVectorType : public VectorType {
+ ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
+ VectorType(ExtVector, vecType, nElements, canonType) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+ static int getPointAccessorIdx(char c) {
+ switch (c) {
+ default: return -1;
+ case 'x': return 0;
+ case 'y': return 1;
+ case 'z': return 2;
+ case 'w': return 3;
+ }
+ }
+ static int getNumericAccessorIdx(char c) {
+ switch (c) {
+ default: return -1;
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'a': return 10;
+ case 'b': return 11;
+ case 'c': return 12;
+ case 'd': return 13;
+ case 'e': return 14;
+ case 'f': return 15;
+ }
+ }
+
+ static int getAccessorIdx(char c) {
+ if (int idx = getPointAccessorIdx(c)+1) return idx-1;
+ return getNumericAccessorIdx(c);
+ }
+
+ bool isAccessorWithinNumElements(char c) const {
+ if (int idx = getAccessorIdx(c)+1)
+ return unsigned(idx-1) < NumElements;
+ return false;
+ }
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ExtVector;
+ }
+ static bool classof(const ExtVectorType *) { return true; }
+};
+
+/// FunctionType - C99 6.7.5.3 - Function Declarators. This is the common base
+/// class of FunctionNoProtoType and FunctionProtoType.
+///
+class FunctionType : public Type {
+ /// SubClassData - This field is owned by the subclass, put here to pack
+ /// tightly with the ivars in Type.
+ bool SubClassData : 1;
+
+ /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
+ /// other bitfields.
+ /// The qualifiers are part of FunctionProtoType because...
+ ///
+ /// C++ 8.3.5p4: The return type, the parameter type list and the
+ /// cv-qualifier-seq, [...], are part of the function type.
+ ///
+ unsigned TypeQuals : 3;
+
+ // The type returned by the function.
+ QualType ResultType;
+protected:
+ FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
+ unsigned typeQuals, QualType Canonical, bool Dependent)
+ : Type(tc, Canonical, Dependent),
+ SubClassData(SubclassInfo), TypeQuals(typeQuals), ResultType(res) {}
+ bool getSubClassData() const { return SubClassData; }
+ unsigned getTypeQuals() const { return TypeQuals; }
+public:
+
+ QualType getResultType() const { return ResultType; }
+
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionNoProto ||
+ T->getTypeClass() == FunctionProto;
+ }
+ static bool classof(const FunctionType *) { return true; }
+};
+
+/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has
+/// no information available about its arguments.
+class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
+ FunctionNoProtoType(QualType Result, QualType Canonical)
+ : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
+ /*Dependent=*/false) {}
+ friend class ASTContext; // ASTContext creates these.
+public:
+ // No additional state past what FunctionType provides.
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getResultType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType) {
+ ID.AddPointer(ResultType.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionNoProto;
+ }
+ static bool classof(const FunctionNoProtoType *) { return true; }
+};
+
+/// FunctionProtoType - Represents a prototype with argument type info, e.g.
+/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
+/// arguments, not as having a single void argument. Such a type can have an
+/// exception specification, but this specification is not part of the canonical
+/// type.
+class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
+ /// hasAnyDependentType - Determine whether there are any dependent
+ /// types within the arguments passed in.
+ static bool hasAnyDependentType(const QualType *ArgArray, unsigned numArgs) {
+ for (unsigned Idx = 0; Idx < numArgs; ++Idx)
+ if (ArgArray[Idx]->isDependentType())
+ return true;
+
+ return false;
+ }
+
+ FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,
+ bool isVariadic, unsigned typeQuals, bool hasExs,
+ bool hasAnyExs, const QualType *ExArray,
+ unsigned numExs, QualType Canonical)
+ : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,
+ (Result->isDependentType() ||
+ hasAnyDependentType(ArgArray, numArgs))),
+ NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
+ AnyExceptionSpec(hasAnyExs) {
+ // Fill in the trailing argument array.
+ QualType *ArgInfo = reinterpret_cast<QualType*>(this+1);
+ for (unsigned i = 0; i != numArgs; ++i)
+ ArgInfo[i] = ArgArray[i];
+ // Fill in the exception array.
+ QualType *Ex = ArgInfo + numArgs;
+ for (unsigned i = 0; i != numExs; ++i)
+ Ex[i] = ExArray[i];
+ }
+
+ /// NumArgs - The number of arguments this function has, not counting '...'.
+ unsigned NumArgs : 20;
+
+ /// NumExceptions - The number of types in the exception spec, if any.
+ unsigned NumExceptions : 10;
+
+ /// HasExceptionSpec - Whether this function has an exception spec at all.
+ bool HasExceptionSpec : 1;
+
+ /// AnyExceptionSpec - Whether this function has a throw(...) spec.
+ bool AnyExceptionSpec : 1;
+
+ /// ArgInfo - There is an variable size array after the class in memory that
+ /// holds the argument types.
+
+ /// Exceptions - There is another variable size array after ArgInfo that
+ /// holds the exception types.
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ unsigned getNumArgs() const { return NumArgs; }
+ QualType getArgType(unsigned i) const {
+ assert(i < NumArgs && "Invalid argument number!");
+ return arg_type_begin()[i];
+ }
+
+ bool hasExceptionSpec() const { return HasExceptionSpec; }
+ bool hasAnyExceptionSpec() const { return AnyExceptionSpec; }
+ unsigned getNumExceptions() const { return NumExceptions; }
+ QualType getExceptionType(unsigned i) const {
+ assert(i < NumExceptions && "Invalid exception number!");
+ return exception_begin()[i];
+ }
+ bool hasEmptyExceptionSpec() const {
+ return hasExceptionSpec() && !hasAnyExceptionSpec() &&
+ getNumExceptions() == 0;
+ }
+
+ bool isVariadic() const { return getSubClassData(); }
+ unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
+
+ typedef const QualType *arg_type_iterator;
+ arg_type_iterator arg_type_begin() const {
+ return reinterpret_cast<const QualType *>(this+1);
+ }
+ arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; }
+
+ typedef const QualType *exception_iterator;
+ exception_iterator exception_begin() const {
+ // exceptions begin where arguments end
+ return arg_type_end();
+ }
+ exception_iterator exception_end() const {
+ return exception_begin() + NumExceptions;
+ }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionProto;
+ }
+ static bool classof(const FunctionProtoType *) { return true; }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
+ arg_type_iterator ArgTys, unsigned NumArgs,
+ bool isVariadic, unsigned TypeQuals,
+ bool hasExceptionSpec, bool anyExceptionSpec,
+ unsigned NumExceptions, exception_iterator Exs);
+};
+
+
+class TypedefType : public Type {
+ TypedefDecl *Decl;
+protected:
+ TypedefType(TypeClass tc, TypedefDecl *D, QualType can)
+ : Type(tc, can, can->isDependentType()), Decl(D) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ TypedefDecl *getDecl() const { return Decl; }
+
+ /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
+ /// potentially looking through *all* consecutive typedefs. This returns the
+ /// sum of the type qualifiers, so if you have:
+ /// typedef const int A;
+ /// typedef volatile A B;
+ /// looking through the typedefs for B will give you "const volatile A".
+ QualType LookThroughTypedefs() const;
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
+ static bool classof(const TypedefType *) { return true; }
+};
+
+/// TypeOfExprType (GCC extension).
+class TypeOfExprType : public Type {
+ Expr *TOExpr;
+ TypeOfExprType(Expr *E, QualType can);
+ friend class ASTContext; // ASTContext creates these.
+public:
+ Expr *getUnderlyingExpr() const { return TOExpr; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; }
+ static bool classof(const TypeOfExprType *) { return true; }
+};
+
+/// TypeOfType (GCC extension).
+class TypeOfType : public Type {
+ QualType TOType;
+ TypeOfType(QualType T, QualType can)
+ : Type(TypeOf, can, T->isDependentType()), TOType(T) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+ QualType getUnderlyingType() const { return TOType; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
+ static bool classof(const TypeOfType *) { return true; }
+};
+
+class TagType : public Type {
+ /// Stores the TagDecl associated with this type. The decl will
+ /// point to the TagDecl that actually defines the entity (or is a
+ /// definition in progress), if there is such a definition. The
+ /// single-bit value will be non-zero when this tag is in the
+ /// process of being defined.
+ mutable llvm::PointerIntPair<TagDecl *, 1> decl;
+ friend class ASTContext;
+ friend class TagDecl;
+
+protected:
+ TagType(TypeClass TC, TagDecl *D, QualType can);
+
+public:
+ TagDecl *getDecl() const { return decl.getPointer(); }
+
+ /// @brief Determines whether this type is in the process of being
+ /// defined.
+ bool isBeingDefined() const { return decl.getInt(); }
+ void setBeingDefined(bool Def) { decl.setInt(Def? 1 : 0); }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
+ }
+ static bool classof(const TagType *) { return true; }
+ static bool classof(const RecordType *) { return true; }
+ static bool classof(const EnumType *) { return true; }
+};
+
+/// RecordType - This is a helper class that allows the use of isa/cast/dyncast
+/// to detect TagType objects of structs/unions/classes.
+class RecordType : public TagType {
+protected:
+ explicit RecordType(RecordDecl *D)
+ : TagType(Record, reinterpret_cast<TagDecl*>(D), QualType()) { }
+ explicit RecordType(TypeClass TC, RecordDecl *D)
+ : TagType(TC, reinterpret_cast<TagDecl*>(D), QualType()) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ RecordDecl *getDecl() const {
+ return reinterpret_cast<RecordDecl*>(TagType::getDecl());
+ }
+
+ // FIXME: This predicate is a helper to QualType/Type. It needs to
+ // recursively check all fields for const-ness. If any field is declared
+ // const, it needs to return false.
+ bool hasConstFields() const { return false; }
+
+ // FIXME: RecordType needs to check when it is created that all fields are in
+ // the same address space, and return that.
+ unsigned getAddressSpace() const { return 0; }
+
+ static bool classof(const TagType *T);
+ static bool classof(const Type *T) {
+ return isa<TagType>(T) && classof(cast<TagType>(T));
+ }
+ static bool classof(const RecordType *) { return true; }
+};
+
+/// EnumType - This is a helper class that allows the use of isa/cast/dyncast
+/// to detect TagType objects of enums.
+class EnumType : public TagType {
+ explicit EnumType(EnumDecl *D)
+ : TagType(Enum, reinterpret_cast<TagDecl*>(D), QualType()) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ EnumDecl *getDecl() const {
+ return reinterpret_cast<EnumDecl*>(TagType::getDecl());
+ }
+
+ static bool classof(const TagType *T);
+ static bool classof(const Type *T) {
+ return isa<TagType>(T) && classof(cast<TagType>(T));
+ }
+ static bool classof(const EnumType *) { return true; }
+};
+
+class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ unsigned Depth : 16;
+ unsigned Index : 16;
+ IdentifierInfo *Name;
+
+ TemplateTypeParmType(unsigned D, unsigned I, IdentifierInfo *N,
+ QualType Canon)
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true),
+ Depth(D), Index(I), Name(N) { }
+
+ TemplateTypeParmType(unsigned D, unsigned I)
+ : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true),
+ Depth(D), Index(I), Name(0) { }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ unsigned getDepth() const { return Depth; }
+ unsigned getIndex() const { return Index; }
+ IdentifierInfo *getName() const { return Name; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Depth, Index, Name);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth,
+ unsigned Index, IdentifierInfo *Name) {
+ ID.AddInteger(Depth);
+ ID.AddInteger(Index);
+ ID.AddPointer(Name);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == TemplateTypeParm;
+ }
+ static bool classof(const TemplateTypeParmType *T) { return true; }
+};
+
+/// \brief Represents the type of a template specialization as written
+/// in the source code.
+///
+/// Template specialization types represent the syntactic form of a
+/// template-id that refers to a type, e.g., @c vector<int>. Some
+/// template specialization types are syntactic sugar, whose canonical
+/// type will point to some other type node that represents the
+/// instantiation or class template specialization. For example, a
+/// class template specialization type of @c vector<int> will refer to
+/// a tag type for the instantiation
+/// @c std::vector<int, std::allocator<int>>.
+///
+/// Other template specialization types, for which the template name
+/// is dependent, may be canonical types. These types are always
+/// dependent.
+class TemplateSpecializationType
+ : public Type, public llvm::FoldingSetNode {
+
+ /// \brief The name of the template being specialized.
+ TemplateName Template;
+
+ /// \brief - The number of template arguments named in this class
+ /// template specialization.
+ unsigned NumArgs;
+
+ TemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs, QualType Canon);
+
+ virtual void Destroy(ASTContext& C);
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Determine whether any of the given template arguments are
+ /// dependent.
+ static bool anyDependentTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Print a template argument list, including the '<' and '>'
+ /// enclosing the template arguments.
+ static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy);
+
+ typedef const TemplateArgument * iterator;
+
+ iterator begin() const { return getArgs(); }
+ iterator end() const;
+
+ /// \brief Retrieve the name of the template that we are specializing.
+ TemplateName getTemplateName() const { return Template; }
+
+ /// \brief Retrieve the template arguments.
+ const TemplateArgument *getArgs() const {
+ return reinterpret_cast<const TemplateArgument *>(this + 1);
+ }
+
+ /// \brief Retrieve the number of template arguments.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// \brief Retrieve a specific template argument as a type.
+ /// \precondition @c isArgType(Arg)
+ const TemplateArgument &getArg(unsigned Idx) const;
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Template, getArgs(), NumArgs);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
+ const TemplateArgument *Args, unsigned NumArgs);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == TemplateSpecialization;
+ }
+ static bool classof(const TemplateSpecializationType *T) { return true; }
+};
+
+/// \brief Represents a type that was referred to via a qualified
+/// name, e.g., N::M::type.
+///
+/// This type is used to keep track of a type name as written in the
+/// source code, including any nested-name-specifiers. The type itself
+/// is always "sugar", used to express what was written in the source
+/// code but containing no additional semantic information.
+class QualifiedNameType : public Type, public llvm::FoldingSetNode {
+ /// \brief The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ /// \brief The type that this qualified name refers to.
+ QualType NamedType;
+
+ QualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType,
+ QualType CanonType)
+ : Type(QualifiedName, CanonType, NamedType->isDependentType()),
+ NNS(NNS), NamedType(NamedType) { }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the qualification on this type.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ /// \brief Retrieve the type named by the qualified-id.
+ QualType getNamedType() const { return NamedType; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, NNS, NamedType);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ QualType NamedType) {
+ ID.AddPointer(NNS);
+ NamedType.Profile(ID);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == QualifiedName;
+ }
+ static bool classof(const QualifiedNameType *T) { return true; }
+};
+
+/// \brief Represents a 'typename' specifier that names a type within
+/// a dependent type, e.g., "typename T::type".
+///
+/// TypenameType has a very similar structure to QualifiedNameType,
+/// which also involves a nested-name-specifier following by a type,
+/// and (FIXME!) both can even be prefixed by the 'typename'
+/// keyword. However, the two types serve very different roles:
+/// QualifiedNameType is a non-semantic type that serves only as sugar
+/// to show how a particular type was written in the source
+/// code. TypenameType, on the other hand, only occurs when the
+/// nested-name-specifier is dependent, such that we cannot resolve
+/// the actual type until after instantiation.
+class TypenameType : public Type, public llvm::FoldingSetNode {
+ /// \brief The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ typedef llvm::PointerUnion<const IdentifierInfo *,
+ const TemplateSpecializationType *> NameType;
+
+ /// \brief The type that this typename specifier refers to.
+ NameType Name;
+
+ TypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name,
+ QualType CanonType)
+ : Type(Typename, CanonType, true), NNS(NNS), Name(Name) {
+ assert(NNS->isDependent() &&
+ "TypenameType requires a dependent nested-name-specifier");
+ }
+
+ TypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty,
+ QualType CanonType)
+ : Type(Typename, CanonType, true), NNS(NNS), Name(Ty) {
+ assert(NNS->isDependent() &&
+ "TypenameType requires a dependent nested-name-specifier");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// \brief Retrieve the qualification on this type.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ /// \brief Retrieve the type named by the typename specifier as an
+ /// identifier.
+ ///
+ /// This routine will return a non-NULL identifier pointer when the
+ /// form of the original typename was terminated by an identifier,
+ /// e.g., "typename T::type".
+ const IdentifierInfo *getIdentifier() const {
+ return Name.dyn_cast<const IdentifierInfo *>();
+ }
+
+ /// \brief Retrieve the type named by the typename specifier as a
+ /// type specialization.
+ const TemplateSpecializationType *getTemplateId() const {
+ return Name.dyn_cast<const TemplateSpecializationType *>();
+ }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, NNS, Name);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+ NameType Name) {
+ ID.AddPointer(NNS);
+ ID.AddPointer(Name.getOpaqueValue());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Typename;
+ }
+ static bool classof(const TypenameType *T) { return true; }
+};
+
+/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
+/// object oriented design. They basically correspond to C++ classes. There
+/// are two kinds of interface types, normal interfaces like "NSString" and
+/// qualified interfaces, which are qualified with a protocol list like
+/// "NSString<NSCopyable, NSAmazing>". Qualified interface types are instances
+/// of ObjCQualifiedInterfaceType, which is a subclass of ObjCInterfaceType.
+class ObjCInterfaceType : public Type {
+ ObjCInterfaceDecl *Decl;
+protected:
+ ObjCInterfaceType(TypeClass tc, ObjCInterfaceDecl *D) :
+ Type(tc, QualType(), /*Dependent=*/false), Decl(D) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ ObjCInterfaceDecl *getDecl() const { return Decl; }
+
+ /// qual_iterator and friends: this provides access to the (potentially empty)
+ /// list of protocols qualifying this interface. If this is an instance of
+ /// ObjCQualifiedInterfaceType it returns the list, otherwise it returns an
+ /// empty list if there are no qualifying protocols.
+ typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
+ inline qual_iterator qual_begin() const;
+ inline qual_iterator qual_end() const;
+ bool qual_empty() const { return getTypeClass() != ObjCQualifiedInterface; }
+
+ /// getNumProtocols - Return the number of qualifying protocols in this
+ /// interface type, or 0 if there are none.
+ inline unsigned getNumProtocols() const;
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCInterface ||
+ T->getTypeClass() == ObjCQualifiedInterface;
+ }
+ static bool classof(const ObjCInterfaceType *) { return true; }
+};
+
+/// ObjCQualifiedInterfaceType - This class represents interface types
+/// conforming to a list of protocols, such as INTF<Proto1, Proto2, Proto1>.
+///
+/// Duplicate protocols are removed and protocol list is canonicalized to be in
+/// alphabetical order.
+class ObjCQualifiedInterfaceType : public ObjCInterfaceType,
+ public llvm::FoldingSetNode {
+
+ // List of protocols for this protocol conforming object type
+ // List is sorted on protocol name. No protocol is enterred more than once.
+ llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols;
+
+ ObjCQualifiedInterfaceType(ObjCInterfaceDecl *D,
+ ObjCProtocolDecl **Protos, unsigned NumP) :
+ ObjCInterfaceType(ObjCQualifiedInterface, D),
+ Protocols(Protos, Protos+NumP) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ unsigned getNumProtocols() const {
+ return Protocols.size();
+ }
+
+ qual_iterator qual_begin() const { return Protocols.begin(); }
+ qual_iterator qual_end() const { return Protocols.end(); }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **protocols, unsigned NumProtocols);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCQualifiedInterface;
+ }
+ static bool classof(const ObjCQualifiedInterfaceType *) { return true; }
+};
+
+inline ObjCInterfaceType::qual_iterator ObjCInterfaceType::qual_begin() const {
+ if (const ObjCQualifiedInterfaceType *QIT =
+ dyn_cast<ObjCQualifiedInterfaceType>(this))
+ return QIT->qual_begin();
+ return 0;
+}
+inline ObjCInterfaceType::qual_iterator ObjCInterfaceType::qual_end() const {
+ if (const ObjCQualifiedInterfaceType *QIT =
+ dyn_cast<ObjCQualifiedInterfaceType>(this))
+ return QIT->qual_end();
+ return 0;
+}
+
+/// getNumProtocols - Return the number of qualifying protocols in this
+/// interface type, or 0 if there are none.
+inline unsigned ObjCInterfaceType::getNumProtocols() const {
+ if (const ObjCQualifiedInterfaceType *QIT =
+ dyn_cast<ObjCQualifiedInterfaceType>(this))
+ return QIT->getNumProtocols();
+ return 0;
+}
+
+/// ObjCQualifiedIdType - to represent id<protocol-list>.
+///
+/// Duplicate protocols are removed and protocol list is canonicalized to be in
+/// alphabetical order.
+class ObjCQualifiedIdType : public Type,
+ public llvm::FoldingSetNode {
+ // List of protocols for this protocol conforming 'id' type
+ // List is sorted on protocol name. No protocol is enterred more than once.
+ llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
+
+ ObjCQualifiedIdType(ObjCProtocolDecl **Protos, unsigned NumP)
+ : Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
+ /*Dependent=*/false),
+ Protocols(Protos, Protos+NumP) { }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ unsigned getNumProtocols() const {
+ return Protocols.size();
+ }
+
+ typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
+ qual_iterator qual_begin() const { return Protocols.begin(); }
+ qual_iterator qual_end() const { return Protocols.end(); }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ ObjCProtocolDecl **protocols, unsigned NumProtocols);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCQualifiedId;
+ }
+ static bool classof(const ObjCQualifiedIdType *) { return true; }
+
+};
+
+// Inline function definitions.
+
+/// getUnqualifiedType - Return the type without any qualifiers.
+inline QualType QualType::getUnqualifiedType() const {
+ Type *TP = getTypePtr();
+ if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(TP))
+ TP = EXTQT->getBaseType();
+ return QualType(TP, 0);
+}
+
+/// getAddressSpace - Return the address space of this type.
+inline unsigned QualType::getAddressSpace() const {
+ QualType CT = getTypePtr()->getCanonicalTypeInternal();
+ if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
+ return AT->getElementType().getAddressSpace();
+ if (const RecordType *RT = dyn_cast<RecordType>(CT))
+ return RT->getAddressSpace();
+ if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
+ return EXTQT->getAddressSpace();
+ return 0;
+}
+
+/// getObjCGCAttr - Return the gc attribute of this type.
+inline QualType::GCAttrTypes QualType::getObjCGCAttr() const {
+ QualType CT = getTypePtr()->getCanonicalTypeInternal();
+ if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
+ return AT->getElementType().getObjCGCAttr();
+ if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT))
+ return EXTQT->getObjCGCAttr();
+ if (const PointerType *PT = CT->getAsPointerType())
+ return PT->getPointeeType().getObjCGCAttr();
+ return GCNone;
+}
+
+/// isMoreQualifiedThan - Determine whether this type is more
+/// qualified than the Other type. For example, "const volatile int"
+/// is more qualified than "const int", "volatile int", and
+/// "int". However, it is not more qualified than "const volatile
+/// int".
+inline bool QualType::isMoreQualifiedThan(QualType Other) const {
+ unsigned MyQuals = this->getCVRQualifiers();
+ unsigned OtherQuals = Other.getCVRQualifiers();
+ if (getAddressSpace() != Other.getAddressSpace())
+ return false;
+ return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals;
+}
+
+/// isAtLeastAsQualifiedAs - Determine whether this type is at last
+/// as qualified as the Other type. For example, "const volatile
+/// int" is at least as qualified as "const int", "volatile int",
+/// "int", and "const volatile int".
+inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const {
+ unsigned MyQuals = this->getCVRQualifiers();
+ unsigned OtherQuals = Other.getCVRQualifiers();
+ if (getAddressSpace() != Other.getAddressSpace())
+ return false;
+ return (MyQuals | OtherQuals) == MyQuals;
+}
+
+/// getNonReferenceType - If Type is a reference type (e.g., const
+/// int&), returns the type that the reference refers to ("const
+/// int"). Otherwise, returns the type itself. This routine is used
+/// throughout Sema to implement C++ 5p6:
+///
+/// If an expression initially has the type "reference to T" (8.3.2,
+/// 8.5.3), the type is adjusted to "T" prior to any further
+/// analysis, the expression designates the object or function
+/// denoted by the reference, and the expression is an lvalue.
+inline QualType QualType::getNonReferenceType() const {
+ if (const ReferenceType *RefType = (*this)->getAsReferenceType())
+ return RefType->getPointeeType();
+ else
+ return *this;
+}
+
+inline const TypedefType* Type::getAsTypedefType() const {
+ return dyn_cast<TypedefType>(this);
+}
+inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const {
+ if (const PointerType *PT = getAsPointerType())
+ return PT->getPointeeType()->getAsObjCInterfaceType();
+ return 0;
+}
+
+// NOTE: All of these methods use "getUnqualifiedType" to strip off address
+// space qualifiers if present.
+inline bool Type::isFunctionType() const {
+ return isa<FunctionType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isPointerType() const {
+ return isa<PointerType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isBlockPointerType() const {
+ return isa<BlockPointerType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isReferenceType() const {
+ return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isLValueReferenceType() const {
+ return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isRValueReferenceType() const {
+ return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isFunctionPointerType() const {
+ if (const PointerType* T = getAsPointerType())
+ return T->getPointeeType()->isFunctionType();
+ else
+ return false;
+}
+inline bool Type::isMemberPointerType() const {
+ return isa<MemberPointerType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isMemberFunctionPointerType() const {
+ if (const MemberPointerType* T = getAsMemberPointerType())
+ return T->getPointeeType()->isFunctionType();
+ else
+ return false;
+}
+inline bool Type::isArrayType() const {
+ return isa<ArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isConstantArrayType() const {
+ return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isIncompleteArrayType() const {
+ return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isVariableArrayType() const {
+ return isa<VariableArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isDependentSizedArrayType() const {
+ return isa<DependentSizedArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isRecordType() const {
+ return isa<RecordType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isAnyComplexType() const {
+ return isa<ComplexType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isVectorType() const {
+ return isa<VectorType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isExtVectorType() const {
+ return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isObjCInterfaceType() const {
+ return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isObjCQualifiedInterfaceType() const {
+ return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isObjCQualifiedIdType() const {
+ return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isTemplateTypeParmType() const {
+ return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
+}
+
+inline bool Type::isSpecificBuiltinType(unsigned K) const {
+ if (const BuiltinType *BT = getAsBuiltinType())
+ if (BT->getKind() == (BuiltinType::Kind) K)
+ return true;
+ return false;
+}
+
+/// \brief Determines whether this is a type for which one can define
+/// an overloaded operator.
+inline bool Type::isOverloadableType() const {
+ return isDependentType() || isRecordType() || isEnumeralType();
+}
+
+inline bool Type::hasPointerRepresentation() const {
+ return (isPointerType() || isReferenceType() || isBlockPointerType() ||
+ isObjCInterfaceType() || isObjCQualifiedIdType() ||
+ isObjCQualifiedInterfaceType() || isNullPtrType());
+}
+
+inline bool Type::hasObjCPointerRepresentation() const {
+ return (isObjCInterfaceType() || isObjCQualifiedIdType() ||
+ isObjCQualifiedInterfaceType());
+}
+
+/// Insertion operator for diagnostics. This allows sending QualType's into a
+/// diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ QualType T) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
+ Diagnostic::ak_qualtype);
+ return DB;
+}
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
new file mode 100644
index 000000000000..76cbed311d79
--- /dev/null
+++ b/include/clang/AST/TypeNodes.def
@@ -0,0 +1,85 @@
+//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AST type info database. Each type node is
+// enumerated by providing its name (e.g., "Builtin" or "Enum") and
+// base class (e.g., "Type" or "TagType"). Depending on where in the
+// abstract syntax tree the type will show up, the enumeration uses
+// one of four different macros:
+//
+// TYPE(Class, Base) - A type that can show up anywhere in the AST,
+// and might be dependent, canonical, or non-canonical. All clients
+// will need to understand these types.
+//
+// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
+// the type hierarchy but has no concrete instances.
+//
+// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
+// anywhere in the AST but will never be a part of a canonical
+// type. Clients that only need to deal with canonical types
+// (ignoring, e.g., typedefs and other type alises used for
+// pretty-printing) can ignore these types.
+//
+// DEPENDENT_TYPE(Class, Base) - A type that will only show up
+// within a C++ template that has not been instantiated, e.g., a
+// type that is always dependent. Clients that do not need to deal
+// with uninstantiated C++ templates can ignore these types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ABSTRACT_TYPE
+# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+#ifndef NON_CANONICAL_TYPE
+# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+#ifndef DEPENDENT_TYPE
+# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
+TYPE(ExtQual, Type)
+TYPE(Builtin, Type)
+TYPE(FixedWidthInt, Type)
+TYPE(Complex, Type)
+TYPE(Pointer, Type)
+TYPE(BlockPointer, Type)
+ABSTRACT_TYPE(Reference, Type)
+TYPE(LValueReference, ReferenceType)
+TYPE(RValueReference, ReferenceType)
+TYPE(MemberPointer, Type)
+ABSTRACT_TYPE(Array, Type)
+TYPE(ConstantArray, ArrayType)
+TYPE(IncompleteArray, ArrayType)
+TYPE(VariableArray, ArrayType)
+DEPENDENT_TYPE(DependentSizedArray, ArrayType)
+TYPE(Vector, Type)
+TYPE(ExtVector, VectorType)
+ABSTRACT_TYPE(Function, Type)
+TYPE(FunctionProto, FunctionType)
+TYPE(FunctionNoProto, FunctionType)
+NON_CANONICAL_TYPE(Typedef, Type)
+NON_CANONICAL_TYPE(TypeOfExpr, Type)
+NON_CANONICAL_TYPE(TypeOf, Type)
+ABSTRACT_TYPE(Tag, Type)
+TYPE(Record, TagType)
+TYPE(Enum, TagType)
+DEPENDENT_TYPE(TemplateTypeParm, Type)
+TYPE(TemplateSpecialization, Type)
+NON_CANONICAL_TYPE(QualifiedName, Type)
+DEPENDENT_TYPE(Typename, Type)
+TYPE(ObjCInterface, Type)
+TYPE(ObjCQualifiedInterface, ObjCInterfaceType)
+TYPE(ObjCQualifiedId, Type)
+
+#undef DEPENDENT_TYPE
+#undef NON_CANONICAL_TYPE
+#undef ABSTRACT_TYPE
+#undef TYPE
diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
new file mode 100644
index 000000000000..4f60273d6809
--- /dev/null
+++ b/include/clang/AST/TypeOrdering.h
@@ -0,0 +1,63 @@
+//===-------------- TypeOrdering.h - Total ordering for types -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a function objects and specializations that
+// allow QualType values to be sorted, used in std::maps, std::sets,
+// llvm::DenseMaps, and llvm::DenseSets.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TYPE_ORDERING_H
+#define LLVM_CLANG_TYPE_ORDERING_H
+
+#include "clang/AST/Type.h"
+#include <functional>
+
+namespace clang {
+
+/// QualTypeOrdering - Function object that provides a total ordering
+/// on QualType values.
+struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
+ bool operator()(QualType T1, QualType T2) const {
+ return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
+ }
+};
+
+}
+
+namespace llvm {
+ template<class> struct DenseMapInfo;
+
+ template<> struct DenseMapInfo<clang::QualType> {
+ static inline clang::QualType getEmptyKey() { return clang::QualType(); }
+
+ static inline clang::QualType getTombstoneKey() {
+ using clang::QualType;
+ return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
+ }
+
+ static unsigned getHashValue(clang::QualType Val) {
+ return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+ ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+ }
+
+ static bool isEqual(clang::QualType LHS, clang::QualType RHS) {
+ return LHS == RHS;
+ }
+
+ static bool isPod() {
+ // QualType isn't *technically* a POD type. However, we can get
+ // away with calling it a POD type since its copy constructor,
+ // copy assignment operator, and destructor are all trivial.
+ return true;
+ }
+ };
+}
+
+#endif
diff --git a/include/clang/AST/X86Builtins.def b/include/clang/AST/X86Builtins.def
new file mode 100644
index 000000000000..710efa8cee4b
--- /dev/null
+++ b/include/clang/AST/X86Builtins.def
@@ -0,0 +1,427 @@
+//===--- X86Builtins.def - X86 Builtin function database --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the X86-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
+// adding stuff on demand.
+
+// The format of this database matches clang/AST/Builtins.def.
+
+// FIXME: In GCC, these builtins are defined depending on whether support for
+// MMX/SSE/etc is turned on. We should do this too.
+
+// FIXME: Ideally we would be able to pull this information from what
+// LLVM already knows about X86 builtins. We need to match the LLVM
+// definition anyway, since code generation will lower to the
+// intrinsic if one exists.
+
+BUILTIN(__builtin_ia32_emms , "v", "")
+
+// FIXME: Are these nothrow/const?
+
+// SSE intrinsics.
+BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comile, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comige, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_addps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_subps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_mulps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_divps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_addss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_subss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_mulss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_divss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fc", "")
+BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fc", "")
+BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_andps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_andnps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_orps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_xorps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_movss, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_movhlps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_movlhps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_unpckhps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_unpcklps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_addpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_subpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_mulpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_divpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_addsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_subsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_mulsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_divsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
+BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
+BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_andpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_andnpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_orpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_xorpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_movsd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_unpckhpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_unpcklpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_paddb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_paddw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_paddd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_paddq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_psubb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psubw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psubd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psubq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmullw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pand128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_pandn128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_por128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_pxor128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pcmpeqb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pcmpeqw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pcmpeqd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pcmpgtb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pcmpgtw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pcmpgtd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_punpckhbw128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_punpckhwd128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_punpckhdq128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_punpckhqdq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_punpcklbw128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_punpcklwd128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_punpckldq128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_punpcklqdq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_packsswb128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_packssdw128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_packuswb128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "")
+BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "")
+BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "")
+BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "")
+BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
+BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
+BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
+BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
+BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_pshufw, "V4sV4si", "")
+BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
+BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
+BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
+BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
+BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
+BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
+BUILTIN(__builtin_ia32_cvtsi2ss, "V4fV4fi", "")
+BUILTIN(__builtin_ia32_cvtsi642ss, "V4fV4fLLi", "")
+BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
+BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
+BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
+BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "")
+BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "")
+BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
+BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
+BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
+BUILTIN(__builtin_ia32_loadhps, "V4fV4fV2i*", "")
+BUILTIN(__builtin_ia32_loadlps, "V4fV4fV2i*", "")
+BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
+BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
+BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
+BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
+BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
+BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
+BUILTIN(__builtin_ia32_sfence, "v", "")
+BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
+BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "")
+BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "")
+BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fi", "")
+BUILTIN(__builtin_ia32_femms, "v", "")
+BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "")
+BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "")
+BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "")
+BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "")
+BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "")
+BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "")
+BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "")
+BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "")
+BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "")
+BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "")
+BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "")
+BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "")
+BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "")
+BUILTIN(__builtin_ia32_loadupd, "V2ddC*", "")
+BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "")
+BUILTIN(__builtin_ia32_loadhpd, "V2dV2ddC*", "")
+BUILTIN(__builtin_ia32_loadlpd, "V2dV2ddC*", "")
+BUILTIN(__builtin_ia32_movmskpd, "iV2d", "")
+BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "")
+BUILTIN(__builtin_ia32_movnti, "vi*i", "")
+BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "")
+BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "")
+BUILTIN(__builtin_ia32_pshufd, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_pshuflw, "V8sV8si", "")
+BUILTIN(__builtin_ia32_pshufhw, "V8sV8si", "")
+BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "")
+BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "")
+BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "")
+BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2di", "")
+BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "")
+BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "")
+BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "")
+BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "")
+BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "")
+BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "")
+BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "")
+BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "")
+BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "")
+BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "")
+BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "")
+BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "")
+BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "")
+BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "")
+BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "")
+BUILTIN(__builtin_ia32_cvtsi2sd, "V2dV2di", "")
+BUILTIN(__builtin_ia32_cvtsi642sd, "V2dV2dLLi", "")
+BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "")
+BUILTIN(__builtin_ia32_cvtss2sd, "V2dV2dV4f", "")
+BUILTIN(__builtin_ia32_clflush, "vvC*", "")
+BUILTIN(__builtin_ia32_lfence, "v", "")
+BUILTIN(__builtin_ia32_mfence, "v", "")
+BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
+BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
+BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
+BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
+BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "")
+BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "")
+BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "")
+BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "")
+BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
+BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
+BUILTIN(__builtin_ia32_movshdup, "V4fV4f", "")
+BUILTIN(__builtin_ia32_movsldup, "V4fV4f", "")
+BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
+BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLis", "")
+BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
+BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
+BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
+BUILTIN(__builtin_ia32_vec_ext_v2df, "dV2di", "")
+BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLii", "")
+BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fi", "")
+BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4ii", "")
+BUILTIN(__builtin_ia32_vec_ext_v8hi, "UsV8si", "")
+BUILTIN(__builtin_ia32_vec_ext_v4hi, "sV4si", "")
+BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
+BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssi", "")
+BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4ssi", "")
+BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16cii", "")
+BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iii", "")
+BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLii", "")
+BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
+
+BUILTIN(__builtin_ia32_loadlv4si, "V4iV2i*", "")
+BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
+
+BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8si", "")
+BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2di", "")
+BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fi", "")
+BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "")
+BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "")
+BUILTIN(__builtin_ia32_pmovsxbd128, "V4iV16c", "")
+BUILTIN(__builtin_ia32_pmovsxbq128, "V2LLiV16c", "")
+BUILTIN(__builtin_ia32_pmovsxbw128, "V8sV16c", "")
+BUILTIN(__builtin_ia32_pmovsxdq128, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_pmovsxwd128, "V4iV8s", "")
+BUILTIN(__builtin_ia32_pmovsxwq128, "V2LLiV8s", "")
+BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "")
+BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "")
+BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "")
+BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "")
+BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "")
+BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "")
+BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "")
+BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "")
+BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "")
+BUILTIN(__builtin_ia32_roundss, "V4fV4fi", "")
+BUILTIN(__builtin_ia32_roundsd, "V2dV2di", "")
+BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "")
+
+
+#undef BUILTIN
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
new file mode 100644
index 000000000000..b41cd684e951
--- /dev/null
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -0,0 +1,119 @@
+//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Live Variables analysis for source-level CFGs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIVEVARIABLES_H
+#define LLVM_CLANG_LIVEVARIABLES_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
+#include "clang/Analysis/FlowSensitive/DataflowValues.h"
+
+namespace clang {
+
+class Stmt;
+class DeclRefExpr;
+class SourceManager;
+
+struct LiveVariables_ValueTypes {
+
+ struct ObserverTy;
+
+ // We keep dataflow state for declarations and block-level expressions;
+ typedef StmtDeclBitVector_Types::ValTy ValTy;
+
+ // We need to keep track of both declarations and CFGBlock-level expressions,
+ // (so that we don't explore such expressions twice). We also want
+ // to compute liveness information for block-level expressions, since these
+ // act as "temporary" values.
+
+ struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
+ ObserverTy* Observer;
+ ValTy AlwaysLive;
+
+ AnalysisDataTy() : Observer(NULL) {}
+ };
+
+ //===-----------------------------------------------------===//
+ // ObserverTy - Observer for uninitialized values queries.
+ //===-----------------------------------------------------===//
+
+ struct ObserverTy {
+ virtual ~ObserverTy() {}
+
+ /// ObserveStmt - A callback invoked right before invoking the
+ /// liveness transfer function on the given statement.
+ virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD,
+ const ValTy& V) {}
+
+ virtual void ObserverKill(DeclRefExpr* DR) {}
+ };
+};
+
+class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
+ dataflow::backward_analysis_tag> {
+
+
+public:
+ typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
+
+ LiveVariables(ASTContext& Ctx, CFG& cfg);
+
+ /// IsLive - Return true if a variable is live at beginning of a
+ /// specified block.
+ bool isLive(const CFGBlock* B, const VarDecl* D) const;
+
+ /// IsLive - Returns true if a variable is live at the beginning of the
+ /// the statement. This query only works if liveness information
+ /// has been recorded at the statement level (see runOnAllBlocks), and
+ /// only returns liveness information for block-level expressions.
+ bool isLive(const Stmt* S, const VarDecl* D) const;
+
+ /// IsLive - Returns true the block-level expression "value" is live
+ /// before the given block-level expression (see runOnAllBlocks).
+ bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;
+
+ /// IsLive - Return true if a variable is live according to the
+ /// provided livness bitvector.
+ bool isLive(const ValTy& V, const VarDecl* D) const;
+
+ /// dumpLiveness - Print to stderr the liveness information encoded
+ /// by a specified bitvector.
+ void dumpLiveness(const ValTy& V, SourceManager& M) const;
+
+ /// dumpBlockLiveness - Print to stderr the liveness information
+ /// associated with each basic block.
+ void dumpBlockLiveness(SourceManager& M) const;
+
+ /// getNumDecls - Return the number of variables (declarations) that
+ /// whose liveness status is being tracked by the dataflow
+ /// analysis.
+ unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }
+
+ /// IntializeValues - This routine can perform extra initialization, but
+ /// for LiveVariables this does nothing since all that logic is in
+ /// the constructor.
+ void InitializeValues(const CFG& cfg) {}
+
+ void runOnCFG(CFG& cfg);
+
+ /// runOnAllBlocks - Propagate the dataflow values once for each block,
+ /// starting from the current dataflow values. 'recordStmtValues' indicates
+ /// whether the method should store dataflow values per each individual
+ /// block-level expression.
+ void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs,
+ bool recordStmtValues=false);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
new file mode 100644
index 000000000000..7a9da03e4bd2
--- /dev/null
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -0,0 +1,74 @@
+//===- UninitializedValues.h - unintialized values analysis ----*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Unintialized Values analysis,
+// a flow-sensitive analysis that detects when variable values are unintialized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITVALS_H
+#define LLVM_CLANG_UNITVALS_H
+
+#include "clang/Analysis/Support/BlkExprDeclBitVector.h"
+#include "clang/Analysis/FlowSensitive/DataflowValues.h"
+
+namespace clang {
+
+ class BlockVarDecl;
+ class Expr;
+ class DeclRefExpr;
+ class VarDecl;
+
+/// UninitializedValues_ValueTypes - Utility class to wrap type declarations
+/// for dataflow values and dataflow analysis state for the
+/// Unitialized Values analysis.
+class UninitializedValues_ValueTypes {
+public:
+
+ struct ObserverTy;
+
+ struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
+ AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
+ virtual ~AnalysisDataTy() {};
+
+ ObserverTy* Observer;
+ bool FullUninitTaint;
+ };
+
+ typedef StmtDeclBitVector_Types::ValTy ValTy;
+
+ //===--------------------------------------------------------------------===//
+ // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized
+ // value.
+ //===--------------------------------------------------------------------===//
+
+ struct ObserverTy {
+ virtual ~ObserverTy();
+ virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD,
+ DeclRefExpr* DR, VarDecl* VD) = 0;
+ };
+};
+
+/// UninitializedValues - Objects of this class encapsulate dataflow analysis
+/// information regarding what variable declarations in a function are
+/// potentially unintialized.
+class UninitializedValues :
+ public DataflowValues<UninitializedValues_ValueTypes> {
+public:
+ typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy;
+
+ UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(cfg); }
+
+ /// IntializeValues - Create initial dataflow values and meta data for
+ /// a given CFG. This is intended to be called by the dataflow solver.
+ void InitializeValues(const CFG& cfg);
+};
+
+} // end namespace clang
+#endif
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
new file mode 100644
index 000000000000..e82dc9ed9f3f
--- /dev/null
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticAnalysis.h - Diagnostics for libanalysis -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICANALYSIS_H
+#define LLVM_CLANG_DIAGNOSTICANALYSIS_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define ANALYSISSTART
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_ANALYSIS_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
new file mode 100644
index 000000000000..38612593368b
--- /dev/null
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -0,0 +1,291 @@
+//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines skeleton code for implementing dataflow analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
+#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
+
+#include "clang/AST/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "functional" // STL
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+/// DataflowWorkListTy - Data structure representing the worklist used for
+/// dataflow algorithms.
+//===----------------------------------------------------------------------===//
+
+class DataflowWorkListTy {
+ typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
+ BlockSet wlist;
+public:
+ /// enqueue - Add a block to the worklist. Blocks already on the
+ /// worklist are not added a second time.
+ void enqueue(const CFGBlock* B) { wlist.insert(B); }
+
+ /// dequeue - Remove a block from the worklist.
+ const CFGBlock* dequeue() {
+ assert (!wlist.empty());
+ const CFGBlock* B = *wlist.begin();
+ wlist.erase(B);
+ return B;
+ }
+
+ /// isEmpty - Return true if the worklist is empty.
+ bool isEmpty() const { return wlist.empty(); }
+};
+
+//===----------------------------------------------------------------------===//
+// BlockItrTraits - Traits classes that allow transparent iteration
+// over successors/predecessors of a block depending on the direction
+// of our dataflow analysis.
+//===----------------------------------------------------------------------===//
+
+namespace dataflow {
+template<typename Tag> struct ItrTraits {};
+
+template <> struct ItrTraits<forward_analysis_tag> {
+ typedef CFGBlock::const_pred_iterator PrevBItr;
+ typedef CFGBlock::const_succ_iterator NextBItr;
+ typedef CFGBlock::const_iterator StmtItr;
+
+ static PrevBItr PrevBegin(const CFGBlock* B) { return B->pred_begin(); }
+ static PrevBItr PrevEnd(const CFGBlock* B) { return B->pred_end(); }
+
+ static NextBItr NextBegin(const CFGBlock* B) { return B->succ_begin(); }
+ static NextBItr NextEnd(const CFGBlock* B) { return B->succ_end(); }
+
+ static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); }
+ static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); }
+
+ static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) {
+ return BlockEdge(Prev, B);
+ }
+
+ static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
+ return BlockEdge(B, Next);
+ }
+};
+
+template <> struct ItrTraits<backward_analysis_tag> {
+ typedef CFGBlock::const_succ_iterator PrevBItr;
+ typedef CFGBlock::const_pred_iterator NextBItr;
+ typedef CFGBlock::const_reverse_iterator StmtItr;
+
+ static PrevBItr PrevBegin(const CFGBlock* B) { return B->succ_begin(); }
+ static PrevBItr PrevEnd(const CFGBlock* B) { return B->succ_end(); }
+
+ static NextBItr NextBegin(const CFGBlock* B) { return B->pred_begin(); }
+ static NextBItr NextEnd(const CFGBlock* B) { return B->pred_end(); }
+
+ static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); }
+ static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); }
+
+ static BlockEdge PrevEdge(const CFGBlock* B, const CFGBlock* Prev) {
+ return BlockEdge(B, Prev);
+ }
+
+ static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
+ return BlockEdge(Next, B);
+ }
+};
+} // end namespace dataflow
+
+//===----------------------------------------------------------------------===//
+/// DataflowSolverTy - Generic dataflow solver.
+//===----------------------------------------------------------------------===//
+
+template <typename _DFValuesTy, // Usually a subclass of DataflowValues
+ typename _TransferFuncsTy,
+ typename _MergeOperatorTy,
+ typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> >
+class DataflowSolver {
+
+ //===----------------------------------------------------===//
+ // Type declarations.
+ //===----------------------------------------------------===//
+
+public:
+ typedef _DFValuesTy DFValuesTy;
+ typedef _TransferFuncsTy TransferFuncsTy;
+ typedef _MergeOperatorTy MergeOperatorTy;
+
+ typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
+ typedef typename _DFValuesTy::ValTy ValTy;
+ typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
+ typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
+
+ typedef dataflow::ItrTraits<AnalysisDirTag> ItrTraits;
+ typedef typename ItrTraits::NextBItr NextBItr;
+ typedef typename ItrTraits::PrevBItr PrevBItr;
+ typedef typename ItrTraits::StmtItr StmtItr;
+
+ //===----------------------------------------------------===//
+ // External interface: constructing and running the solver.
+ //===----------------------------------------------------===//
+
+public:
+ DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {}
+ ~DataflowSolver() {}
+
+ /// runOnCFG - Computes dataflow values for all blocks in a CFG.
+ void runOnCFG(CFG& cfg, bool recordStmtValues = false) {
+ // Set initial dataflow values and boundary conditions.
+ D.InitializeValues(cfg);
+ // Solve the dataflow equations. This will populate D.EdgeDataMap
+ // with dataflow values.
+ SolveDataflowEquations(cfg, recordStmtValues);
+ }
+
+ /// runOnBlock - Computes dataflow values for a given block. This
+ /// should usually be invoked only after previously computing
+ /// dataflow values using runOnCFG, as runOnBlock is intended to
+ /// only be used for querying the dataflow values within a block
+ /// with and Observer object.
+ void runOnBlock(const CFGBlock* B, bool recordStmtValues) {
+ BlockDataMapTy& M = D.getBlockDataMap();
+ typename BlockDataMapTy::iterator I = M.find(B);
+
+ if (I != M.end()) {
+ TF.getVal().copyValues(I->second);
+ ProcessBlock(B, recordStmtValues, AnalysisDirTag());
+ }
+ }
+
+ void runOnBlock(const CFGBlock& B, bool recordStmtValues) {
+ runOnBlock(&B, recordStmtValues);
+ }
+ void runOnBlock(CFG::iterator& I, bool recordStmtValues) {
+ runOnBlock(*I, recordStmtValues);
+ }
+ void runOnBlock(CFG::const_iterator& I, bool recordStmtValues) {
+ runOnBlock(*I, recordStmtValues);
+ }
+
+ void runOnAllBlocks(const CFG& cfg, bool recordStmtValues = false) {
+ for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
+ runOnBlock(I, recordStmtValues);
+ }
+
+ //===----------------------------------------------------===//
+ // Internal solver logic.
+ //===----------------------------------------------------===//
+
+private:
+
+ /// SolveDataflowEquations - Perform the actual worklist algorithm
+ /// to compute dataflow values.
+ void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) {
+ // Enqueue all blocks to ensure the dataflow values are computed
+ // for every block. Not all blocks are guaranteed to reach the exit block.
+ for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
+ WorkList.enqueue(&*I);
+
+ while (!WorkList.isEmpty()) {
+ const CFGBlock* B = WorkList.dequeue();
+ ProcessMerge(cfg,B);
+ ProcessBlock(B, recordStmtValues, AnalysisDirTag());
+ UpdateEdges(cfg,B,TF.getVal());
+ }
+ }
+
+ void ProcessMerge(CFG& cfg, const CFGBlock* B) {
+ ValTy& V = TF.getVal();
+ TF.SetTopValue(V);
+
+ // Merge dataflow values from all predecessors of this block.
+ MergeOperatorTy Merge;
+
+ EdgeDataMapTy& M = D.getEdgeDataMap();
+ bool firstMerge = true;
+
+ for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
+
+ typename EdgeDataMapTy::iterator EI =
+ M.find(ItrTraits::PrevEdge(B, *I));
+
+ if (EI != M.end()) {
+ if (firstMerge) {
+ firstMerge = false;
+ V.copyValues(EI->second);
+ }
+ else Merge(V,EI->second);
+ }
+ }
+
+ // Set the data for the block.
+ D.getBlockDataMap()[B].copyValues(V);
+ }
+
+ /// ProcessBlock - Process the transfer functions for a given block.
+ void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
+ dataflow::forward_analysis_tag) {
+
+ for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
+ ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
+
+ TF.VisitTerminator(const_cast<CFGBlock*>(B));
+ }
+
+ void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
+ dataflow::backward_analysis_tag) {
+
+ TF.VisitTerminator(const_cast<CFGBlock*>(B));
+
+ for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
+ ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
+ }
+
+ void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) {
+ if (record) D.getStmtDataMap()[S] = TF.getVal();
+ TF.BlockStmt_Visit(const_cast<Stmt*>(S));
+ }
+
+ void ProcessStmt(const Stmt* S, bool record, dataflow::backward_analysis_tag){
+ TF.BlockStmt_Visit(const_cast<Stmt*>(S));
+ if (record) D.getStmtDataMap()[S] = TF.getVal();
+ }
+
+ /// UpdateEdges - After processing the transfer functions for a
+ /// block, update the dataflow value associated with the block's
+ /// outgoing/incoming edges (depending on whether we do a
+ // forward/backward analysis respectively)
+ void UpdateEdges(CFG& cfg, const CFGBlock* B, ValTy& V) {
+ for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I)
+ UpdateEdgeValue(ItrTraits::NextEdge(B, *I),V,*I);
+ }
+
+ /// UpdateEdgeValue - Update the value associated with a given edge.
+ void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) {
+ EdgeDataMapTy& M = D.getEdgeDataMap();
+ typename EdgeDataMapTy::iterator I = M.find(E);
+
+ if (I == M.end()) { // First computed value for this edge?
+ M[E].copyValues(V);
+ WorkList.enqueue(TargetBlock);
+ }
+ else if (!_Equal()(V,I->second)) {
+ I->second.copyValues(V);
+ WorkList.enqueue(TargetBlock);
+ }
+ }
+
+private:
+ DFValuesTy& D;
+ DataflowWorkListTy WorkList;
+ TransferFuncsTy TF;
+};
+
+} // end namespace clang
+#endif
diff --git a/include/clang/Analysis/FlowSensitive/DataflowValues.h b/include/clang/Analysis/FlowSensitive/DataflowValues.h
new file mode 100644
index 000000000000..d6427a5cab47
--- /dev/null
+++ b/include/clang/Analysis/FlowSensitive/DataflowValues.h
@@ -0,0 +1,172 @@
+//===--- DataflowValues.h - Data structure for dataflow values --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a skeleton data structure for encapsulating the dataflow
+// values for a CFG. Typically this is subclassed to provide methods for
+// computing these values from a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
+#define LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
+
+#include "clang/AST/CFG.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "llvm/ADT/DenseMap.h"
+
+//===----------------------------------------------------------------------===//
+/// Dataflow Directional Tag Classes. These are used for tag dispatching
+/// within the dataflow solver/transfer functions to determine what direction
+/// a dataflow analysis flows.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace dataflow {
+ struct forward_analysis_tag {};
+ struct backward_analysis_tag {};
+} // end namespace dataflow
+
+//===----------------------------------------------------------------------===//
+/// DataflowValues. Container class to store dataflow values for a CFG.
+//===----------------------------------------------------------------------===//
+
+template <typename ValueTypes,
+ typename _AnalysisDirTag = dataflow::forward_analysis_tag >
+class DataflowValues {
+
+ //===--------------------------------------------------------------------===//
+ // Type declarations.
+ //===--------------------------------------------------------------------===//
+
+public:
+ typedef typename ValueTypes::ValTy ValTy;
+ typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
+ typedef _AnalysisDirTag AnalysisDirTag;
+ typedef llvm::DenseMap<ProgramPoint, ValTy> EdgeDataMapTy;
+ typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
+ typedef llvm::DenseMap<const Stmt*, ValTy> StmtDataMapTy;
+
+ //===--------------------------------------------------------------------===//
+ // Predicates.
+ //===--------------------------------------------------------------------===//
+
+public:
+ /// isForwardAnalysis - Returns true if the dataflow values are computed
+ /// from a forward analysis.
+ bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); }
+
+ /// isBackwardAnalysis - Returns true if the dataflow values are computed
+ /// from a backward analysis.
+ bool isBackwardAnalysis() { return !isForwardAnalysis(); }
+
+private:
+ bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; }
+ bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; }
+
+ //===--------------------------------------------------------------------===//
+ // Initialization and accessors methods.
+ //===--------------------------------------------------------------------===//
+
+public:
+ DataflowValues() : StmtDataMap(NULL) {}
+ ~DataflowValues() { delete StmtDataMap; }
+
+ /// InitializeValues - Invoked by the solver to initialize state needed for
+ /// dataflow analysis. This method is usually specialized by subclasses.
+ void InitializeValues(const CFG& cfg) {};
+
+
+ /// getEdgeData - Retrieves the dataflow values associated with a
+ /// CFG edge.
+ ValTy& getEdgeData(const BlockEdge& E) {
+ typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
+ assert (I != EdgeDataMap.end() && "No data associated with Edge.");
+ return I->second;
+ }
+
+ const ValTy& getEdgeData(const BlockEdge& E) const {
+ return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
+ }
+
+ /// getBlockData - Retrieves the dataflow values associated with a
+ /// specified CFGBlock. If the dataflow analysis is a forward analysis,
+ /// this data is associated with the END of the block. If the analysis
+ /// is a backwards analysis, it is associated with the ENTRY of the block.
+ ValTy& getBlockData(const CFGBlock* B) {
+ typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
+ assert (I != BlockDataMap.end() && "No data associated with block.");
+ return I->second;
+ }
+
+ const ValTy& getBlockData(const CFGBlock* B) const {
+ return const_cast<DataflowValues*>(this)->getBlockData(B);
+ }
+
+ /// getStmtData - Retrieves the dataflow values associated with a
+ /// specified Stmt. If the dataflow analysis is a forward analysis,
+ /// this data corresponds to the point immediately before a Stmt.
+ /// If the analysis is a backwards analysis, it is associated with
+ /// the point after a Stmt. This data is only computed for block-level
+ /// expressions, and only when requested when the analysis is executed.
+ ValTy& getStmtData(const Stmt* S) {
+ assert (StmtDataMap && "Dataflow values were not computed for statements.");
+ typename StmtDataMapTy::iterator I = StmtDataMap->find(S);
+ assert (I != StmtDataMap->end() && "No data associated with statement.");
+ return I->second;
+ }
+
+ const ValTy& getStmtData(const Stmt* S) const {
+ return const_cast<DataflowValues*>(this)->getStmtData(S);
+ }
+
+ /// getEdgeDataMap - Retrieves the internal map between CFG edges and
+ /// dataflow values. Usually used by a dataflow solver to compute
+ /// values for blocks.
+ EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; }
+ const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; }
+
+ /// getBlockDataMap - Retrieves the internal map between CFGBlocks and
+ /// dataflow values. If the dataflow analysis operates in the forward
+ /// direction, the values correspond to the dataflow values at the start
+ /// of the block. Otherwise, for a backward analysis, the values correpsond
+ /// to the dataflow values at the end of the block.
+ BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
+ const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
+
+ /// getStmtDataMap - Retrieves the internal map between Stmts and
+ /// dataflow values.
+ StmtDataMapTy& getStmtDataMap() {
+ if (!StmtDataMap) StmtDataMap = new StmtDataMapTy();
+ return *StmtDataMap;
+ }
+
+ const StmtDataMapTy& getStmtDataMap() const {
+ return const_cast<DataflowValues*>(this)->getStmtDataMap();
+ }
+
+ /// getAnalysisData - Retrieves the meta data associated with a
+ /// dataflow analysis for analyzing a particular CFG.
+ /// This is typically consumed by transfer function code (via the solver).
+ /// This can also be used by subclasses to interpret the dataflow values.
+ AnalysisDataTy& getAnalysisData() { return AnalysisData; }
+ const AnalysisDataTy& getAnalysisData() const { return AnalysisData; }
+
+ //===--------------------------------------------------------------------===//
+ // Internal data.
+ //===--------------------------------------------------------------------===//
+
+protected:
+ EdgeDataMapTy EdgeDataMap;
+ BlockDataMapTy BlockDataMap;
+ StmtDataMapTy* StmtDataMap;
+ AnalysisDataTy AnalysisData;
+};
+
+} // end namespace clang
+#endif
diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h
new file mode 100644
index 000000000000..23610f9a2d97
--- /dev/null
+++ b/include/clang/Analysis/LocalCheckers.h
@@ -0,0 +1,54 @@
+//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface to call a set of intra-procedural (local)
+// checkers that use flow/path-sensitive analyses to find bugs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H
+#define LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H
+
+namespace clang {
+
+class CFG;
+class Decl;
+class Diagnostic;
+class ASTContext;
+class PathDiagnosticClient;
+class GRTransferFuncs;
+class BugType;
+class LangOptions;
+class ParentMap;
+class LiveVariables;
+class BugReporter;
+class ObjCImplementationDecl;
+class LangOptions;
+class GRExprEngine;
+
+void CheckDeadStores(LiveVariables& L, BugReporter& BR);
+
+void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
+ bool FullUninitTaint=false);
+
+GRTransferFuncs* MakeGRSimpleValsTF();
+GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+ const LangOptions& lopts);
+
+void CheckObjCDealloc(ObjCImplementationDecl* D, const LangOptions& L,
+ BugReporter& BR);
+
+void CheckObjCInstMethSignature(ObjCImplementationDecl* ID, BugReporter& BR);
+void CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR);
+
+void RegisterAppleChecks(GRExprEngine& Eng);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h
new file mode 100644
index 000000000000..994b35e5efda
--- /dev/null
+++ b/include/clang/Analysis/PathDiagnostic.h
@@ -0,0 +1,487 @@
+//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PathDiagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H
+#define LLVM_CLANG_PATH_DIAGNOSTIC_H
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/OwningPtr.h"
+
+#include <vector>
+#include <deque>
+#include <string>
+#include <algorithm>
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// High-level interface for handlers of path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnostic;
+class Stmt;
+class Decl;
+class Preprocessor;
+
+class PathDiagnosticClient : public DiagnosticClient {
+public:
+ PathDiagnosticClient() {}
+ virtual ~PathDiagnosticClient() {}
+
+ virtual void SetPreprocessor(Preprocessor *PP) {}
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+
+ virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
+
+ enum PathGenerationScheme { Minimal, Extensive };
+ virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
+ virtual bool supportsLogicalOpControlFlow() const { return false; }
+ virtual bool supportsAllBlockEdges() const { return false; }
+ virtual bool useVerboseDescription() const { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnosticRange : public SourceRange {
+public:
+ const bool isPoint;
+
+ PathDiagnosticRange(const SourceRange &R, bool isP = false)
+ : SourceRange(R), isPoint(isP) {}
+};
+
+class PathDiagnosticLocation {
+private:
+ enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
+ SourceRange R;
+ const Stmt *S;
+ const Decl *D;
+ const SourceManager *SM;
+public:
+ PathDiagnosticLocation()
+ : K(SingleLocK), S(0), D(0), SM(0) {}
+
+ PathDiagnosticLocation(FullSourceLoc L)
+ : K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()) {}
+
+ PathDiagnosticLocation(const Stmt *s, const SourceManager &sm)
+ : K(StmtK), S(s), D(0), SM(&sm) {}
+
+ PathDiagnosticLocation(SourceRange r, const SourceManager &sm)
+ : K(RangeK), R(r), S(0), D(0), SM(&sm) {}
+
+ PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
+ : K(DeclK), S(0), D(d), SM(&sm) {}
+
+ bool operator==(const PathDiagnosticLocation &X) const {
+ return K == X.K && R == X.R && S == X.S && D == X.D;
+ }
+
+ bool operator!=(const PathDiagnosticLocation &X) const {
+ return K != X.K || R != X.R || S != X.S || D != X.D;;
+ }
+
+ PathDiagnosticLocation& operator=(const PathDiagnosticLocation &X) {
+ K = X.K;
+ R = X.R;
+ S = X.S;
+ D = X.D;
+ SM = X.SM;
+ return *this;
+ }
+
+ bool isValid() const {
+ return SM != 0;
+ }
+
+ const SourceManager& getSourceManager() const { assert(isValid());return *SM;}
+
+ FullSourceLoc asLocation() const;
+ PathDiagnosticRange asRange() const;
+ const Stmt *asStmt() const { assert(isValid()); return S; }
+ const Decl *asDecl() const { assert(isValid()); return D; }
+
+ bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
+
+ void invalidate() {
+ *this = PathDiagnosticLocation();
+ }
+
+ void flatten();
+
+ const SourceManager& getManager() const { assert(isValid()); return *SM; }
+};
+
+class PathDiagnosticLocationPair {
+private:
+ PathDiagnosticLocation Start, End;
+public:
+ PathDiagnosticLocationPair(const PathDiagnosticLocation &start,
+ const PathDiagnosticLocation &end)
+ : Start(start), End(end) {}
+
+ const PathDiagnosticLocation &getStart() const { return Start; }
+ const PathDiagnosticLocation &getEnd() const { return End; }
+
+ void flatten() {
+ Start.flatten();
+ End.flatten();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Path "pieces" for path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnosticPiece {
+public:
+ enum Kind { ControlFlow, Event, Macro };
+ enum DisplayHint { Above, Below };
+
+private:
+ const std::string str;
+ std::vector<CodeModificationHint> CodeModificationHints;
+ const Kind kind;
+ const DisplayHint Hint;
+ std::vector<SourceRange> ranges;
+
+ // Do not implement:
+ PathDiagnosticPiece();
+ PathDiagnosticPiece(const PathDiagnosticPiece &P);
+ PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P);
+
+protected:
+ PathDiagnosticPiece(const std::string& s, Kind k, DisplayHint hint = Below);
+
+ PathDiagnosticPiece(const char* s, Kind k, DisplayHint hint = Below);
+
+ PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
+
+public:
+ virtual ~PathDiagnosticPiece();
+
+ const std::string& getString() const { return str; }
+
+ /// getDisplayHint - Return a hint indicating where the diagnostic should
+ /// be displayed by the PathDiagnosticClient.
+ DisplayHint getDisplayHint() const { return Hint; }
+
+ virtual PathDiagnosticLocation getLocation() const = 0;
+ virtual void flattenLocations() = 0;
+
+ Kind getKind() const { return kind; }
+
+ void addRange(SourceRange R) { ranges.push_back(R); }
+
+ void addRange(SourceLocation B, SourceLocation E) {
+ ranges.push_back(SourceRange(B,E));
+ }
+
+ void addCodeModificationHint(const CodeModificationHint& Hint) {
+ CodeModificationHints.push_back(Hint);
+ }
+
+ typedef const SourceRange* range_iterator;
+
+ range_iterator ranges_begin() const {
+ return ranges.empty() ? NULL : &ranges[0];
+ }
+
+ range_iterator ranges_end() const {
+ return ranges_begin() + ranges.size();
+ }
+
+ typedef const CodeModificationHint *code_modifications_iterator;
+
+ code_modifications_iterator code_modifications_begin() const {
+ return CodeModificationHints.empty()? 0 : &CodeModificationHints[0];
+ }
+
+ code_modifications_iterator code_modifications_end() const {
+ return CodeModificationHints.empty()? 0
+ : &CodeModificationHints[0] + CodeModificationHints.size();
+ }
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return true;
+ }
+};
+
+class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
+private:
+ PathDiagnosticLocation Pos;
+public:
+ PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
+ const std::string& s,
+ PathDiagnosticPiece::Kind k,
+ bool addPosRange = true)
+ : PathDiagnosticPiece(s, k), Pos(pos) {
+ assert(Pos.asLocation().isValid() &&
+ "PathDiagnosticSpotPiece's must have a valid location.");
+ if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
+ }
+
+ PathDiagnosticLocation getLocation() const { return Pos; }
+ virtual void flattenLocations() { Pos.flatten(); }
+};
+
+class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
+
+public:
+ PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
+ const std::string& s, bool addPosRange = true)
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
+
+ PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, const char* s,
+ bool addPosRange = true)
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
+
+ ~PathDiagnosticEventPiece();
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return P->getKind() == Event;
+ }
+};
+
+class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
+ std::vector<PathDiagnosticLocationPair> LPairs;
+public:
+ PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
+ const PathDiagnosticLocation &endPos,
+ const std::string& s)
+ : PathDiagnosticPiece(s, ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
+
+ PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
+ const PathDiagnosticLocation &endPos,
+ const char* s)
+ : PathDiagnosticPiece(s, ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
+
+ PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
+ const PathDiagnosticLocation &endPos)
+ : PathDiagnosticPiece(ControlFlow) {
+ LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
+ }
+
+ ~PathDiagnosticControlFlowPiece();
+
+ PathDiagnosticLocation getStartLocation() const {
+ assert(!LPairs.empty() &&
+ "PathDiagnosticControlFlowPiece needs at least one location.");
+ return LPairs[0].getStart();
+ }
+
+ PathDiagnosticLocation getEndLocation() const {
+ assert(!LPairs.empty() &&
+ "PathDiagnosticControlFlowPiece needs at least one location.");
+ return LPairs[0].getEnd();
+ }
+
+ void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
+
+ virtual PathDiagnosticLocation getLocation() const {
+ return getStartLocation();
+ }
+
+ typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
+ iterator begin() { return LPairs.begin(); }
+ iterator end() { return LPairs.end(); }
+
+ virtual void flattenLocations() {
+ for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
+ }
+
+ typedef std::vector<PathDiagnosticLocationPair>::const_iterator
+ const_iterator;
+ const_iterator begin() const { return LPairs.begin(); }
+ const_iterator end() const { return LPairs.end(); }
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return P->getKind() == ControlFlow;
+ }
+};
+
+class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
+ std::vector<PathDiagnosticPiece*> SubPieces;
+public:
+ PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
+ : PathDiagnosticSpotPiece(pos, "", Macro) {}
+
+ ~PathDiagnosticMacroPiece();
+
+ bool containsEvent() const;
+
+ void push_back(PathDiagnosticPiece* P) { SubPieces.push_back(P); }
+
+ typedef std::vector<PathDiagnosticPiece*>::iterator iterator;
+ iterator begin() { return SubPieces.begin(); }
+ iterator end() { return SubPieces.end(); }
+
+ virtual void flattenLocations() {
+ PathDiagnosticSpotPiece::flattenLocations();
+ for (iterator I=begin(), E=end(); I!=E; ++I) (*I)->flattenLocations();
+ }
+
+ typedef std::vector<PathDiagnosticPiece*>::const_iterator const_iterator;
+ const_iterator begin() const { return SubPieces.begin(); }
+ const_iterator end() const { return SubPieces.end(); }
+
+ static inline bool classof(const PathDiagnosticPiece* P) {
+ return P->getKind() == Macro;
+ }
+};
+
+/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
+/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
+/// each which represent the pieces of the path.
+class PathDiagnostic {
+ std::deque<PathDiagnosticPiece*> path;
+ unsigned Size;
+ std::string BugType;
+ std::string Desc;
+ std::string Category;
+ std::deque<std::string> OtherDesc;
+
+public:
+ PathDiagnostic();
+
+ PathDiagnostic(const char* bugtype, const char* desc, const char* category);
+
+ PathDiagnostic(const std::string& bugtype, const std::string& desc,
+ const std::string& category);
+
+ ~PathDiagnostic();
+
+ const std::string& getDescription() const { return Desc; }
+ const std::string& getBugType() const { return BugType; }
+ const std::string& getCategory() const { return Category; }
+
+ typedef std::deque<std::string>::const_iterator meta_iterator;
+ meta_iterator meta_begin() const { return OtherDesc.begin(); }
+ meta_iterator meta_end() const { return OtherDesc.end(); }
+ void addMeta(const std::string& s) { OtherDesc.push_back(s); }
+ void addMeta(const char* s) { OtherDesc.push_back(s); }
+
+ PathDiagnosticLocation getLocation() const {
+ assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic.");
+ return rbegin()->getLocation();
+ }
+
+ void push_front(PathDiagnosticPiece* piece) {
+ path.push_front(piece);
+ ++Size;
+ }
+
+ void push_back(PathDiagnosticPiece* piece) {
+ path.push_back(piece);
+ ++Size;
+ }
+
+ PathDiagnosticPiece* back() {
+ return path.back();
+ }
+
+ const PathDiagnosticPiece* back() const {
+ return path.back();
+ }
+
+ unsigned size() const { return Size; }
+ bool empty() const { return Size == 0; }
+
+ void resetPath(bool deletePieces = true);
+
+ class iterator {
+ public:
+ typedef std::deque<PathDiagnosticPiece*>::iterator ImplTy;
+
+ typedef PathDiagnosticPiece value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ private:
+ ImplTy I;
+
+ public:
+ iterator(const ImplTy& i) : I(i) {}
+
+ bool operator==(const iterator& X) const { return I == X.I; }
+ bool operator!=(const iterator& X) const { return I != X.I; }
+
+ PathDiagnosticPiece& operator*() const { return **I; }
+ PathDiagnosticPiece* operator->() const { return *I; }
+
+ iterator& operator++() { ++I; return *this; }
+ iterator& operator--() { --I; return *this; }
+ };
+
+ class const_iterator {
+ public:
+ typedef std::deque<PathDiagnosticPiece*>::const_iterator ImplTy;
+
+ typedef const PathDiagnosticPiece value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ private:
+ ImplTy I;
+
+ public:
+ const_iterator(const ImplTy& i) : I(i) {}
+
+ bool operator==(const const_iterator& X) const { return I == X.I; }
+ bool operator!=(const const_iterator& X) const { return I != X.I; }
+
+ reference operator*() const { return **I; }
+ pointer operator->() const { return *I; }
+
+ const_iterator& operator++() { ++I; return *this; }
+ const_iterator& operator--() { --I; return *this; }
+ };
+
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // forward iterator creation methods.
+
+ iterator begin() { return path.begin(); }
+ iterator end() { return path.end(); }
+
+ const_iterator begin() const { return path.begin(); }
+ const_iterator end() const { return path.end(); }
+
+ // reverse iterator creation methods.
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+ void flattenLocations() {
+ for (iterator I = begin(), E = end(); I != E; ++I) I->flattenLocations();
+ }
+};
+
+
+} //end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Analysis/PathSensitive/BasicValueFactory.h
new file mode 100644
index 000000000000..b694e9b29940
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/BasicValueFactory.h
@@ -0,0 +1,163 @@
+//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*---//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BasicValueFactory, a class that manages the lifetime
+// of APSInt objects and symbolic constraints used by GRExprEngine
+// and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
+#define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
+
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+#include "clang/Analysis/PathSensitive/SVals.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ImmutableList.h"
+
+namespace clang {
+
+class CompoundValData : public llvm::FoldingSetNode {
+ QualType T;
+ llvm::ImmutableList<SVal> L;
+
+public:
+ CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
+ : T(t), L(l) {}
+
+ typedef llvm::ImmutableList<SVal>::iterator iterator;
+ iterator begin() const { return L.begin(); }
+ iterator end() const { return L.end(); }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
+ llvm::ImmutableList<SVal> L);
+
+ void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
+};
+
+class BasicValueFactory {
+ typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
+ APSIntSetTy;
+
+ ASTContext& Ctx;
+ llvm::BumpPtrAllocator& BPAlloc;
+
+ APSIntSetTy APSIntSet;
+ void* PersistentSVals;
+ void* PersistentSValPairs;
+
+ llvm::ImmutableList<SVal>::Factory SValListFactory;
+ llvm::FoldingSet<CompoundValData> CompoundValDataSet;
+
+public:
+ BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
+ : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
+ SValListFactory(Alloc) {}
+
+ ~BasicValueFactory();
+
+ ASTContext& getContext() const { return Ctx; }
+
+ const llvm::APSInt& getValue(const llvm::APSInt& X);
+ const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
+ const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
+ const llvm::APSInt& getValue(uint64_t X, QualType T);
+
+ /// Convert - Create a new persistent APSInt with the same value as 'From'
+ /// but with the bitwidth and signedness of 'To'.
+ const llvm::APSInt& Convert(const llvm::APSInt& To,
+ const llvm::APSInt& From) {
+
+ if (To.isUnsigned() == From.isUnsigned() &&
+ To.getBitWidth() == From.getBitWidth())
+ return From;
+
+ return getValue(From.getSExtValue(),
+ To.getBitWidth(),
+ To.isUnsigned());
+ }
+
+ const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
+ QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
+ return getValue(X, T);
+ }
+
+ inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
+ return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned()));
+ }
+
+ inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
+ return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned()));
+ }
+
+ inline const llvm::APSInt& getMaxValue(QualType T) {
+ assert(T->isIntegerType() || Loc::IsLocType(T));
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
+ return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
+ }
+
+ inline const llvm::APSInt& getMinValue(QualType T) {
+ assert(T->isIntegerType() || Loc::IsLocType(T));
+ bool isUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
+ return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
+ }
+
+ inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
+ llvm::APSInt X = V;
+ ++X;
+ return getValue(X);
+ }
+
+ inline const llvm::APSInt& Sub1(const llvm::APSInt& V) {
+ llvm::APSInt X = V;
+ --X;
+ return getValue(X);
+ }
+
+ inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
+ return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
+ }
+
+ inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
+ return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
+ }
+
+ inline const llvm::APSInt& getTruthValue(bool b) {
+ return getTruthValue(b, Ctx.IntTy);
+ }
+
+ const CompoundValData* getCompoundValData(QualType T,
+ llvm::ImmutableList<SVal> Vals);
+
+ llvm::ImmutableList<SVal> getEmptySValList() {
+ return SValListFactory.GetEmptyList();
+ }
+
+ llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
+ return SValListFactory.Add(X, L);
+ }
+
+ const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
+ const llvm::APSInt& V1,
+ const llvm::APSInt& V2);
+
+ const std::pair<SVal, uintptr_t>&
+ getPersistentSValWithData(const SVal& V, uintptr_t Data);
+
+ const std::pair<SVal, SVal>&
+ getPersistentSValPair(const SVal& V1, const SVal& V2);
+
+ const SVal* getPersistentSVal(SVal X);
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h
new file mode 100644
index 000000000000..90fd9d8ebf45
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -0,0 +1,466 @@
+//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BugReporter, a utility class for generating
+// PathDiagnostics for analyses based on GRState.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
+#define LLVM_CLANG_ANALYSIS_BUGREPORTER
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include <list>
+
+namespace clang {
+
+class PathDiagnostic;
+class PathDiagnosticPiece;
+class PathDiagnosticClient;
+class ASTContext;
+class Diagnostic;
+class BugReporter;
+class BugReporterContext;
+class GRExprEngine;
+class GRState;
+class Stmt;
+class BugType;
+class ParentMap;
+
+//===----------------------------------------------------------------------===//
+// Interface for individual bug reports.
+//===----------------------------------------------------------------------===//
+
+class BugReporterVisitor {
+public:
+ virtual ~BugReporterVisitor();
+ virtual PathDiagnosticPiece* VisitNode(const ExplodedNode<GRState>* N,
+ const ExplodedNode<GRState>* PrevN,
+ BugReporterContext& BRC) = 0;
+
+ virtual bool isOwnedByReporterContext() { return true; }
+};
+
+// FIXME: Combine this with RangedBugReport and remove RangedBugReport.
+class BugReport : public BugReporterVisitor {
+protected:
+ BugType& BT;
+ std::string ShortDescription;
+ std::string Description;
+ const ExplodedNode<GRState> *EndNode;
+ SourceRange R;
+
+protected:
+ friend class BugReporter;
+ friend class BugReportEquivClass;
+
+ virtual void Profile(llvm::FoldingSetNodeID& hash) const {
+ hash.AddInteger(getLocation().getRawEncoding());
+ }
+
+public:
+ class NodeResolver {
+ public:
+ virtual ~NodeResolver() {}
+ virtual const ExplodedNode<GRState>*
+ getOriginalNode(const ExplodedNode<GRState>* N) = 0;
+ };
+
+ BugReport(BugType& bt, const char* desc, const ExplodedNode<GRState> *n)
+ : BT(bt), Description(desc), EndNode(n) {}
+
+ BugReport(BugType& bt, const char* shortDesc, const char* desc,
+ const ExplodedNode<GRState> *n)
+ : BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {}
+
+ virtual ~BugReport();
+
+ virtual bool isOwnedByReporterContext() { return false; }
+
+ const BugType& getBugType() const { return BT; }
+ BugType& getBugType() { return BT; }
+
+ // FIXME: Perhaps this should be moved into a subclass?
+ const ExplodedNode<GRState>* getEndNode() const { return EndNode; }
+
+ // FIXME: Do we need this? Maybe getLocation() should return a ProgramPoint
+ // object.
+ // FIXME: If we do need it, we can probably just make it private to
+ // BugReporter.
+ Stmt* getStmt(BugReporter& BR) const;
+
+ const std::string& getDescription() const { return Description; }
+
+ const std::string& getShortDescription() const {
+ return ShortDescription.empty() ? Description : ShortDescription;
+ }
+
+ // FIXME: Is this needed?
+ virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
+ return std::make_pair((const char**)0,(const char**)0);
+ }
+
+ // FIXME: Perhaps move this into a subclass.
+ virtual PathDiagnosticPiece* getEndPath(BugReporterContext& BRC,
+ const ExplodedNode<GRState>* N);
+
+ /// getLocation - Return the "definitive" location of the reported bug.
+ /// While a bug can span an entire path, usually there is a specific
+ /// location that can be used to identify where the key issue occured.
+ /// This location is used by clients rendering diagnostics.
+ virtual SourceLocation getLocation() const;
+
+ /// getRanges - Returns the source ranges associated with this bug.
+ virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
+ const SourceRange*& end);
+
+ virtual PathDiagnosticPiece* VisitNode(const ExplodedNode<GRState>* N,
+ const ExplodedNode<GRState>* PrevN,
+ BugReporterContext& BR);
+
+ virtual void registerInitialVisitors(BugReporterContext& BRC,
+ const ExplodedNode<GRState>* N) {}
+};
+
+//===----------------------------------------------------------------------===//
+// BugTypes (collections of related reports).
+//===----------------------------------------------------------------------===//
+
+class BugReportEquivClass : public llvm::FoldingSetNode {
+ // List of *owned* BugReport objects.
+ std::list<BugReport*> Reports;
+
+ friend class BugReporter;
+ void AddReport(BugReport* R) { Reports.push_back(R); }
+public:
+ BugReportEquivClass(BugReport* R) { Reports.push_back(R); }
+ ~BugReportEquivClass();
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ assert(!Reports.empty());
+ (*Reports.begin())->Profile(ID);
+ }
+
+ class iterator {
+ std::list<BugReport*>::iterator impl;
+ public:
+ iterator(std::list<BugReport*>::iterator i) : impl(i) {}
+ iterator& operator++() { ++impl; return *this; }
+ bool operator==(const iterator& I) const { return I.impl == impl; }
+ bool operator!=(const iterator& I) const { return I.impl != impl; }
+ BugReport* operator*() const { return *impl; }
+ BugReport* operator->() const { return *impl; }
+ };
+
+ class const_iterator {
+ std::list<BugReport*>::const_iterator impl;
+ public:
+ const_iterator(std::list<BugReport*>::const_iterator i) : impl(i) {}
+ const_iterator& operator++() { ++impl; return *this; }
+ bool operator==(const const_iterator& I) const { return I.impl == impl; }
+ bool operator!=(const const_iterator& I) const { return I.impl != impl; }
+ const BugReport* operator*() const { return *impl; }
+ const BugReport* operator->() const { return *impl; }
+ };
+
+ iterator begin() { return iterator(Reports.begin()); }
+ iterator end() { return iterator(Reports.end()); }
+
+ const_iterator begin() const { return const_iterator(Reports.begin()); }
+ const_iterator end() const { return const_iterator(Reports.end()); }
+};
+
+class BugType {
+private:
+ const std::string Name;
+ const std::string Category;
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+ friend class BugReporter;
+public:
+ BugType(const char *name, const char* cat) : Name(name), Category(cat) {}
+ virtual ~BugType();
+
+ // FIXME: Should these be made strings as well?
+ const std::string& getName() const { return Name; }
+ const std::string& getCategory() const { return Category; }
+
+ virtual void FlushReports(BugReporter& BR);
+ void AddReport(BugReport* BR);
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
+ iterator begin() { return EQClasses.begin(); }
+ iterator end() { return EQClasses.end(); }
+
+ typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
+ const_iterator begin() const { return EQClasses.begin(); }
+ const_iterator end() const { return EQClasses.end(); }
+};
+
+//===----------------------------------------------------------------------===//
+// Specialized subclasses of BugReport.
+//===----------------------------------------------------------------------===//
+
+// FIXME: Collapse this with the default BugReport class.
+class RangedBugReport : public BugReport {
+ std::vector<SourceRange> Ranges;
+public:
+ RangedBugReport(BugType& D, const char* description, ExplodedNode<GRState> *n)
+ : BugReport(D, description, n) {}
+
+ RangedBugReport(BugType& D, const char *shortDescription,
+ const char *description, ExplodedNode<GRState> *n)
+ : BugReport(D, shortDescription, description, n) {}
+
+ ~RangedBugReport();
+
+ // FIXME: Move this out of line.
+ void addRange(SourceRange R) { Ranges.push_back(R); }
+
+ // FIXME: Move this out of line.
+ void getRanges(BugReporter& BR,const SourceRange*& beg,
+ const SourceRange*& end) {
+
+ if (Ranges.empty()) {
+ beg = NULL;
+ end = NULL;
+ }
+ else {
+ beg = &Ranges[0];
+ end = beg + Ranges.size();
+ }
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// BugReporter and friends.
+//===----------------------------------------------------------------------===//
+
+class BugReporterData {
+public:
+ virtual ~BugReporterData();
+ virtual Diagnostic& getDiagnostic() = 0;
+ virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
+ virtual ASTContext& getContext() = 0;
+ virtual SourceManager& getSourceManager() = 0;
+ virtual CFG* getCFG() = 0;
+ virtual ParentMap& getParentMap() = 0;
+ virtual LiveVariables* getLiveVariables() = 0;
+};
+
+class BugReporter {
+public:
+ enum Kind { BaseBRKind, GRBugReporterKind };
+
+private:
+ typedef llvm::ImmutableSet<BugType*> BugTypesTy;
+ BugTypesTy::Factory F;
+ BugTypesTy BugTypes;
+
+ const Kind kind;
+ BugReporterData& D;
+
+ void FlushReport(BugReportEquivClass& EQ);
+
+protected:
+ BugReporter(BugReporterData& d, Kind k) : BugTypes(F.GetEmptySet()), kind(k), D(d) {}
+
+public:
+ BugReporter(BugReporterData& d) : BugTypes(F.GetEmptySet()), kind(BaseBRKind), D(d) {}
+ virtual ~BugReporter();
+
+ void FlushReports();
+
+ Kind getKind() const { return kind; }
+
+ Diagnostic& getDiagnostic() {
+ return D.getDiagnostic();
+ }
+
+ PathDiagnosticClient* getPathDiagnosticClient() {
+ return D.getPathDiagnosticClient();
+ }
+
+ typedef BugTypesTy::iterator iterator;
+ iterator begin() { return BugTypes.begin(); }
+ iterator end() { return BugTypes.end(); }
+
+ ASTContext& getContext() { return D.getContext(); }
+
+ SourceManager& getSourceManager() { return D.getSourceManager(); }
+
+ CFG* getCFG() { return D.getCFG(); }
+
+ ParentMap& getParentMap() { return D.getParentMap(); }
+
+ LiveVariables* getLiveVariables() { return D.getLiveVariables(); }
+
+ virtual void GeneratePathDiagnostic(PathDiagnostic& PD,
+ BugReportEquivClass& EQ) {}
+
+ void Register(BugType *BT);
+
+ void EmitReport(BugReport *R);
+
+ void EmitBasicReport(const char* BugName, const char* BugStr,
+ SourceLocation Loc,
+ SourceRange* RangeBeg, unsigned NumRanges);
+
+ void EmitBasicReport(const char* BugName, const char* BugCategory,
+ const char* BugStr, SourceLocation Loc,
+ SourceRange* RangeBeg, unsigned NumRanges);
+
+
+ void EmitBasicReport(const char* BugName, const char* BugStr,
+ SourceLocation Loc) {
+ EmitBasicReport(BugName, BugStr, Loc, 0, 0);
+ }
+
+ void EmitBasicReport(const char* BugName, const char* BugCategory,
+ const char* BugStr, SourceLocation Loc) {
+ EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
+ }
+
+ void EmitBasicReport(const char* BugName, const char* BugStr,
+ SourceLocation Loc, SourceRange R) {
+ EmitBasicReport(BugName, BugStr, Loc, &R, 1);
+ }
+
+ void EmitBasicReport(const char* BugName, const char* Category,
+ const char* BugStr, SourceLocation Loc, SourceRange R) {
+ EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
+ }
+
+ static bool classof(const BugReporter* R) { return true; }
+};
+
+// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
+class GRBugReporter : public BugReporter {
+ GRExprEngine& Eng;
+ llvm::SmallSet<SymbolRef, 10> NotableSymbols;
+public:
+ GRBugReporter(BugReporterData& d, GRExprEngine& eng)
+ : BugReporter(d, GRBugReporterKind), Eng(eng) {}
+
+ virtual ~GRBugReporter();
+
+ /// getEngine - Return the analysis engine used to analyze a given
+ /// function or method.
+ GRExprEngine& getEngine() { return Eng; }
+
+ /// getGraph - Get the exploded graph created by the analysis engine
+ /// for the analyzed method or function.
+ ExplodedGraph<GRState>& getGraph();
+
+ /// getStateManager - Return the state manager used by the analysis
+ /// engine.
+ GRStateManager& getStateManager();
+
+ virtual void GeneratePathDiagnostic(PathDiagnostic& PD,
+ BugReportEquivClass& R);
+
+ void addNotableSymbol(SymbolRef Sym) {
+ NotableSymbols.insert(Sym);
+ }
+
+ bool isNotable(SymbolRef Sym) const {
+ return (bool) NotableSymbols.count(Sym);
+ }
+
+ /// classof - Used by isa<>, cast<>, and dyn_cast<>.
+ static bool classof(const BugReporter* R) {
+ return R->getKind() == GRBugReporterKind;
+ }
+};
+
+class BugReporterContext {
+ GRBugReporter &BR;
+ std::vector<BugReporterVisitor*> Callbacks;
+public:
+ BugReporterContext(GRBugReporter& br) : BR(br) {}
+ virtual ~BugReporterContext();
+
+ void addVisitor(BugReporterVisitor* visitor) {
+ if (visitor) Callbacks.push_back(visitor);
+ }
+
+ typedef std::vector<BugReporterVisitor*>::iterator visitor_iterator;
+ visitor_iterator visitor_begin() { return Callbacks.begin(); }
+ visitor_iterator visitor_end() { return Callbacks.end(); }
+
+ GRBugReporter& getBugReporter() { return BR; }
+
+ ExplodedGraph<GRState>& getGraph() { return BR.getGraph(); }
+
+ void addNotableSymbol(SymbolRef Sym) {
+ // FIXME: For now forward to GRBugReporter.
+ BR.addNotableSymbol(Sym);
+ }
+
+ bool isNotable(SymbolRef Sym) const {
+ // FIXME: For now forward to GRBugReporter.
+ return BR.isNotable(Sym);
+ }
+
+ GRStateManager& getStateManager() {
+ return BR.getStateManager();
+ }
+
+ ValueManager& getValueManager() {
+ return getStateManager().getValueManager();
+ }
+
+ ASTContext& getASTContext() {
+ return BR.getContext();
+ }
+
+ SourceManager& getSourceManager() {
+ return BR.getSourceManager();
+ }
+
+ const Decl& getCodeDecl() {
+ return getStateManager().getCodeDecl();
+ }
+
+ const CFG& getCFG() {
+ return *BR.getCFG();
+ }
+
+ virtual BugReport::NodeResolver& getNodeResolver() = 0;
+};
+
+class DiagBugReport : public RangedBugReport {
+ std::list<std::string> Strs;
+ FullSourceLoc L;
+public:
+ DiagBugReport(BugType& D, const char* desc, FullSourceLoc l) :
+ RangedBugReport(D, desc, 0), L(l) {}
+
+ virtual ~DiagBugReport() {}
+
+ // FIXME: Move out-of-line (virtual function).
+ SourceLocation getLocation() const { return L; }
+
+ void addString(const std::string& s) { Strs.push_back(s); }
+
+ typedef std::list<std::string>::const_iterator str_iterator;
+ str_iterator str_begin() const { return Strs.begin(); }
+ str_iterator str_end() const { return Strs.end(); }
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ConstraintManager.h b/include/clang/Analysis/PathSensitive/ConstraintManager.h
new file mode 100644
index 000000000000..c8e5e85c8a1a
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/ConstraintManager.h
@@ -0,0 +1,67 @@
+//== ConstraintManager.h - Constraints on symbolic values.-------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the interface to manage constraints on symbolic values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
+#define LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
+
+// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place.
+#include "clang/Analysis/PathSensitive/Store.h"
+
+namespace llvm {
+class APSInt;
+}
+
+namespace clang {
+
+class GRState;
+class GRStateManager;
+class SVal;
+
+class ConstraintManager {
+public:
+ virtual ~ConstraintManager();
+ virtual const GRState* Assume(const GRState* St, SVal Cond,
+ bool Assumption, bool& isFeasible) = 0;
+
+ virtual const GRState* AssumeInBound(const GRState* St, SVal Idx,
+ SVal UpperBound, bool Assumption,
+ bool& isFeasible) = 0;
+
+ virtual const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym)
+ const = 0;
+
+ virtual bool isEqual(const GRState* St, SymbolRef sym,
+ const llvm::APSInt& V) const = 0;
+
+ virtual const GRState* RemoveDeadBindings(const GRState* St,
+ SymbolReaper& SymReaper) = 0;
+
+ virtual void print(const GRState* St, std::ostream& Out,
+ const char* nl, const char *sep) = 0;
+
+ virtual void EndPath(const GRState* St) {}
+
+ /// canReasonAbout - Not all ConstraintManagers can accurately reason about
+ /// all SVal values. This method returns true if the ConstraintManager can
+ /// reasonably handle a given SVal value. This is typically queried by
+ /// GRExprEngine to determine if the value should be replaced with a
+ /// conjured symbolic value in order to recover some precision.
+ virtual bool canReasonAbout(SVal X) const = 0;
+};
+
+ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr);
+ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr);
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Environment.h b/include/clang/Analysis/PathSensitive/Environment.h
new file mode 100644
index 000000000000..fde8b167f3c7
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Environment.h
@@ -0,0 +1,151 @@
+//== Environment.h - Map from Stmt* to Locations/Values ---------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the Environment and EnvironmentManager classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ENVIRONMENT_H
+#define LLVM_CLANG_ANALYSIS_ENVIRONMENT_H
+
+// For using typedefs in StoreManager. Should find a better place for these
+// typedefs.
+#include "clang/Analysis/PathSensitive/Store.h"
+
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/Analysis/PathSensitive/SVals.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang {
+
+class EnvironmentManager;
+class BasicValueFactory;
+class LiveVariables;
+
+class Environment : public llvm::FoldingSetNode {
+private:
+
+ friend class EnvironmentManager;
+
+ // Type definitions.
+ typedef llvm::ImmutableMap<Stmt*,SVal> BindingsTy;
+
+ // Data.
+ BindingsTy SubExprBindings;
+ BindingsTy BlkExprBindings;
+
+ Environment(BindingsTy seb, BindingsTy beb)
+ : SubExprBindings(seb), BlkExprBindings(beb) {}
+
+public:
+
+ typedef BindingsTy::iterator seb_iterator;
+ seb_iterator seb_begin() const { return SubExprBindings.begin(); }
+ seb_iterator seb_end() const { return SubExprBindings.end(); }
+
+ typedef BindingsTy::iterator beb_iterator;
+ beb_iterator beb_begin() const { return BlkExprBindings.begin(); }
+ beb_iterator beb_end() const { return BlkExprBindings.end(); }
+
+ SVal LookupSubExpr(Stmt* E) const {
+ const SVal* X = SubExprBindings.lookup(cast<Expr>(E));
+ return X ? *X : UnknownVal();
+ }
+
+ SVal LookupBlkExpr(Stmt* E) const {
+ const SVal* X = BlkExprBindings.lookup(E);
+ return X ? *X : UnknownVal();
+ }
+
+ SVal LookupExpr(Stmt* E) const {
+ const SVal* X = SubExprBindings.lookup(E);
+ if (X) return *X;
+ X = BlkExprBindings.lookup(E);
+ return X ? *X : UnknownVal();
+ }
+
+ SVal GetSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
+ SVal GetBlkExprSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
+
+ /// Profile - Profile the contents of an Environment object for use
+ /// in a FoldingSet.
+ static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) {
+ E->SubExprBindings.Profile(ID);
+ E->BlkExprBindings.Profile(ID);
+ }
+
+ /// Profile - Used to profile the contents of this object for inclusion
+ /// in a FoldingSet.
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ Profile(ID, this);
+ }
+
+ bool operator==(const Environment& RHS) const {
+ return SubExprBindings == RHS.SubExprBindings &&
+ BlkExprBindings == RHS.BlkExprBindings;
+ }
+};
+
+class EnvironmentManager {
+private:
+ typedef Environment::BindingsTy::Factory FactoryTy;
+ FactoryTy F;
+
+public:
+
+ EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
+ ~EnvironmentManager() {}
+
+ /// RemoveBlkExpr - Return a new environment object with the same bindings as
+ /// the provided environment except with any bindings for the provided Stmt*
+ /// removed. This method only removes bindings for block-level expressions.
+ /// Using this method on a non-block level expression will return the
+ /// same environment object.
+ Environment RemoveBlkExpr(const Environment& Env, Stmt* E) {
+ return Environment(Env.SubExprBindings, F.Remove(Env.BlkExprBindings, E));
+ }
+
+ Environment RemoveSubExpr(const Environment& Env, Stmt* E) {
+ return Environment(F.Remove(Env.SubExprBindings, E), Env.BlkExprBindings);
+ }
+
+ Environment AddBlkExpr(const Environment& Env, Stmt* E, SVal V) {
+ return Environment(Env.SubExprBindings, F.Add(Env.BlkExprBindings, E, V));
+ }
+
+ Environment AddSubExpr(const Environment& Env, Stmt* E, SVal V) {
+ return Environment(F.Add(Env.SubExprBindings, E, V), Env.BlkExprBindings);
+ }
+
+ /// RemoveSubExprBindings - Return a new environment object with
+ /// the same bindings as the provided environment except with all the
+ /// subexpression bindings removed.
+ Environment RemoveSubExprBindings(const Environment& Env) {
+ return Environment(F.GetEmptyMap(), Env.BlkExprBindings);
+ }
+
+ Environment getInitialEnvironment() {
+ return Environment(F.GetEmptyMap(), F.GetEmptyMap());
+ }
+
+ Environment BindExpr(const Environment& Env, Stmt* E, SVal V,
+ bool isBlkExpr, bool Invalidate);
+
+ Environment
+ RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper,
+ GRStateManager& StateMgr, const GRState *state,
+ llvm::SmallVectorImpl<const MemRegion*>& DRoots);
+
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
new file mode 100644
index 000000000000..8494d935650d
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
@@ -0,0 +1,582 @@
+//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the template classes ExplodedNode and ExplodedGraph,
+// which represent a path-sensitive, intra-procedural "exploded graph."
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
+#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/Support/Casting.h"
+
+namespace clang {
+
+class GRCoreEngineImpl;
+class ExplodedNodeImpl;
+class CFG;
+class ASTContext;
+
+class GRStmtNodeBuilderImpl;
+class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
+class GRSwitchNodeBuilderImpl;
+class GREndPathNodebuilderImpl;
+
+//===----------------------------------------------------------------------===//
+// ExplodedGraph "implementation" classes. These classes are not typed to
+// contain a specific kind of state. Typed-specialized versions are defined
+// on top of these classes.
+//===----------------------------------------------------------------------===//
+
+class ExplodedNodeImpl : public llvm::FoldingSetNode {
+protected:
+ friend class ExplodedGraphImpl;
+ friend class GRCoreEngineImpl;
+ friend class GRStmtNodeBuilderImpl;
+ friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
+ friend class GRSwitchNodeBuilderImpl;
+ friend class GREndPathNodeBuilderImpl;
+
+ class NodeGroup {
+ enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
+ uintptr_t P;
+
+ unsigned getKind() const {
+ return P & 0x1;
+ }
+
+ void* getPtr() const {
+ assert (!getFlag());
+ return reinterpret_cast<void*>(P & ~Mask);
+ }
+
+ ExplodedNodeImpl* getNode() const {
+ return reinterpret_cast<ExplodedNodeImpl*>(getPtr());
+ }
+
+ public:
+ NodeGroup() : P(0) {}
+
+ ~NodeGroup();
+
+ ExplodedNodeImpl** begin() const;
+
+ ExplodedNodeImpl** end() const;
+
+ unsigned size() const;
+
+ bool empty() const { return size() == 0; }
+
+ void addNode(ExplodedNodeImpl* N);
+
+ void setFlag() {
+ assert (P == 0);
+ P = AuxFlag;
+ }
+
+ bool getFlag() const {
+ return P & AuxFlag ? true : false;
+ }
+ };
+
+ /// Location - The program location (within a function body) associated
+ /// with this node.
+ const ProgramPoint Location;
+
+ /// State - The state associated with this node.
+ const void* State;
+
+ /// Preds - The predecessors of this node.
+ NodeGroup Preds;
+
+ /// Succs - The successors of this node.
+ NodeGroup Succs;
+
+ /// Construct a ExplodedNodeImpl with the provided location and state.
+ explicit ExplodedNodeImpl(const ProgramPoint& loc, const void* state)
+ : Location(loc), State(state) {}
+
+ /// addPredeccessor - Adds a predecessor to the current node, and
+ /// in tandem add this node as a successor of the other node.
+ void addPredecessor(ExplodedNodeImpl* V);
+
+public:
+
+ /// getLocation - Returns the edge associated with the given node.
+ ProgramPoint getLocation() const { return Location; }
+
+ template <typename T>
+ const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
+
+ unsigned succ_size() const { return Succs.size(); }
+ unsigned pred_size() const { return Preds.size(); }
+ bool succ_empty() const { return Succs.empty(); }
+ bool pred_empty() const { return Preds.empty(); }
+
+ bool isSink() const { return Succs.getFlag(); }
+ void markAsSink() { Succs.setFlag(); }
+
+ // For debugging.
+
+public:
+
+ class Auditor {
+ public:
+ virtual ~Auditor();
+ virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) = 0;
+ };
+
+ static void SetAuditor(Auditor* A);
+};
+
+
+template <typename StateTy>
+struct GRTrait {
+ static inline void Profile(llvm::FoldingSetNodeID& ID, const StateTy* St) {
+ St->Profile(ID);
+ }
+};
+
+
+template <typename StateTy>
+class ExplodedNode : public ExplodedNodeImpl {
+public:
+ /// Construct a ExplodedNodeImpl with the given node ID, program edge,
+ /// and state.
+ explicit ExplodedNode(const ProgramPoint& loc, const StateTy* St)
+ : ExplodedNodeImpl(loc, St) {}
+
+ /// getState - Returns the state associated with the node.
+ inline const StateTy* getState() const {
+ return static_cast<const StateTy*>(State);
+ }
+
+ // Profiling (for FoldingSet).
+
+ static inline void Profile(llvm::FoldingSetNodeID& ID,
+ const ProgramPoint& Loc,
+ const StateTy* state) {
+ ID.Add(Loc);
+ GRTrait<StateTy>::Profile(ID, state);
+ }
+
+ inline void Profile(llvm::FoldingSetNodeID& ID) const {
+ Profile(ID, getLocation(), getState());
+ }
+
+ void addPredecessor(ExplodedNode* V) {
+ ExplodedNodeImpl::addPredecessor(V);
+ }
+
+ ExplodedNode* getFirstPred() {
+ return pred_empty() ? NULL : *(pred_begin());
+ }
+
+ const ExplodedNode* getFirstPred() const {
+ return const_cast<ExplodedNode*>(this)->getFirstPred();
+ }
+
+ // Iterators over successor and predecessor vertices.
+ typedef ExplodedNode** succ_iterator;
+ typedef const ExplodedNode* const * const_succ_iterator;
+ typedef ExplodedNode** pred_iterator;
+ typedef const ExplodedNode* const * const_pred_iterator;
+
+ pred_iterator pred_begin() { return (ExplodedNode**) Preds.begin(); }
+ pred_iterator pred_end() { return (ExplodedNode**) Preds.end(); }
+
+ const_pred_iterator pred_begin() const {
+ return const_cast<ExplodedNode*>(this)->pred_begin();
+ }
+ const_pred_iterator pred_end() const {
+ return const_cast<ExplodedNode*>(this)->pred_end();
+ }
+
+ succ_iterator succ_begin() { return (ExplodedNode**) Succs.begin(); }
+ succ_iterator succ_end() { return (ExplodedNode**) Succs.end(); }
+
+ const_succ_iterator succ_begin() const {
+ return const_cast<ExplodedNode*>(this)->succ_begin();
+ }
+ const_succ_iterator succ_end() const {
+ return const_cast<ExplodedNode*>(this)->succ_end();
+ }
+};
+
+class InterExplodedGraphMapImpl;
+
+class ExplodedGraphImpl {
+protected:
+ friend class GRCoreEngineImpl;
+ friend class GRStmtNodeBuilderImpl;
+ friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
+ friend class GRSwitchNodeBuilderImpl;
+ friend class GREndPathNodeBuilderImpl;
+
+ // Type definitions.
+ typedef llvm::SmallVector<ExplodedNodeImpl*,2> RootsTy;
+ typedef llvm::SmallVector<ExplodedNodeImpl*,10> EndNodesTy;
+
+ /// Roots - The roots of the simulation graph. Usually there will be only
+ /// one, but clients are free to establish multiple subgraphs within a single
+ /// SimulGraph. Moreover, these subgraphs can often merge when paths from
+ /// different roots reach the same state at the same program location.
+ RootsTy Roots;
+
+ /// EndNodes - The nodes in the simulation graph which have been
+ /// specially marked as the endpoint of an abstract simulation path.
+ EndNodesTy EndNodes;
+
+ /// Allocator - BumpPtrAllocator to create nodes.
+ llvm::BumpPtrAllocator Allocator;
+
+ /// cfg - The CFG associated with this analysis graph.
+ CFG& cfg;
+
+ /// CodeDecl - The declaration containing the code being analyzed. This
+ /// can be a FunctionDecl or and ObjCMethodDecl.
+ Decl& CodeDecl;
+
+ /// Ctx - The ASTContext used to "interpret" CodeDecl.
+ ASTContext& Ctx;
+
+ /// NumNodes - The number of nodes in the graph.
+ unsigned NumNodes;
+
+ /// getNodeImpl - Retrieve the node associated with a (Location,State)
+ /// pair, where 'State' is represented as an opaque void*. This method
+ /// is intended to be used only by GRCoreEngineImpl.
+ virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L,
+ const void* State,
+ bool* IsNew) = 0;
+
+ virtual ExplodedGraphImpl* MakeEmptyGraph() const = 0;
+
+ /// addRoot - Add an untyped node to the set of roots.
+ ExplodedNodeImpl* addRoot(ExplodedNodeImpl* V) {
+ Roots.push_back(V);
+ return V;
+ }
+
+ /// addEndOfPath - Add an untyped node to the set of EOP nodes.
+ ExplodedNodeImpl* addEndOfPath(ExplodedNodeImpl* V) {
+ EndNodes.push_back(V);
+ return V;
+ }
+
+ // ctor.
+ ExplodedGraphImpl(CFG& c, Decl& cd, ASTContext& ctx)
+ : cfg(c), CodeDecl(cd), Ctx(ctx), NumNodes(0) {}
+
+public:
+ virtual ~ExplodedGraphImpl() {}
+
+ unsigned num_roots() const { return Roots.size(); }
+ unsigned num_eops() const { return EndNodes.size(); }
+
+ bool empty() const { return NumNodes == 0; }
+ unsigned size() const { return NumNodes; }
+
+ llvm::BumpPtrAllocator& getAllocator() { return Allocator; }
+ CFG& getCFG() { return cfg; }
+ ASTContext& getContext() { return Ctx; }
+
+ Decl& getCodeDecl() { return CodeDecl; }
+ const Decl& getCodeDecl() const { return CodeDecl; }
+
+ const FunctionDecl* getFunctionDecl() const {
+ return llvm::dyn_cast<FunctionDecl>(&CodeDecl);
+ }
+
+ typedef llvm::DenseMap<const ExplodedNodeImpl*, ExplodedNodeImpl*> NodeMap;
+
+ ExplodedGraphImpl* Trim(const ExplodedNodeImpl* const * NBeg,
+ const ExplodedNodeImpl* const * NEnd,
+ InterExplodedGraphMapImpl *M,
+ llvm::DenseMap<const void*, const void*> *InverseMap)
+ const;
+};
+
+class InterExplodedGraphMapImpl {
+ llvm::DenseMap<const ExplodedNodeImpl*, ExplodedNodeImpl*> M;
+ friend class ExplodedGraphImpl;
+ void add(const ExplodedNodeImpl* From, ExplodedNodeImpl* To);
+
+protected:
+ ExplodedNodeImpl* getMappedImplNode(const ExplodedNodeImpl* N) const;
+
+ InterExplodedGraphMapImpl();
+public:
+ virtual ~InterExplodedGraphMapImpl() {}
+};
+
+//===----------------------------------------------------------------------===//
+// Type-specialized ExplodedGraph classes.
+//===----------------------------------------------------------------------===//
+
+template <typename STATE>
+class InterExplodedGraphMap : public InterExplodedGraphMapImpl {
+public:
+ InterExplodedGraphMap() {};
+ ~InterExplodedGraphMap() {};
+
+ ExplodedNode<STATE>* getMappedNode(const ExplodedNode<STATE>* N) const {
+ return static_cast<ExplodedNode<STATE>*>(getMappedImplNode(N));
+ }
+};
+
+template <typename STATE>
+class ExplodedGraph : public ExplodedGraphImpl {
+public:
+ typedef STATE StateTy;
+ typedef ExplodedNode<StateTy> NodeTy;
+ typedef llvm::FoldingSet<NodeTy> AllNodesTy;
+
+protected:
+ /// Nodes - The nodes in the graph.
+ AllNodesTy Nodes;
+
+protected:
+ virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L,
+ const void* State,
+ bool* IsNew) {
+
+ return getNode(L, static_cast<const StateTy*>(State), IsNew);
+ }
+
+ virtual ExplodedGraphImpl* MakeEmptyGraph() const {
+ return new ExplodedGraph(cfg, CodeDecl, Ctx);
+ }
+
+public:
+ ExplodedGraph(CFG& c, Decl& cd, ASTContext& ctx)
+ : ExplodedGraphImpl(c, cd, ctx) {}
+
+ /// getNode - Retrieve the node associated with a (Location,State) pair,
+ /// where the 'Location' is a ProgramPoint in the CFG. If no node for
+ /// this pair exists, it is created. IsNew is set to true if
+ /// the node was freshly created.
+ NodeTy* getNode(const ProgramPoint& L, const StateTy* State,
+ bool* IsNew = NULL) {
+
+ // Profile 'State' to determine if we already have an existing node.
+ llvm::FoldingSetNodeID profile;
+ void* InsertPos = 0;
+
+ NodeTy::Profile(profile, L, State);
+ NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
+
+ if (!V) {
+ // Allocate a new node.
+ V = (NodeTy*) Allocator.Allocate<NodeTy>();
+ new (V) NodeTy(L, State);
+
+ // Insert the node into the node set and return it.
+ Nodes.InsertNode(V, InsertPos);
+
+ ++NumNodes;
+
+ if (IsNew) *IsNew = true;
+ }
+ else
+ if (IsNew) *IsNew = false;
+
+ return V;
+ }
+
+ // Iterators.
+ typedef NodeTy** roots_iterator;
+ typedef const NodeTy** const_roots_iterator;
+ typedef NodeTy** eop_iterator;
+ typedef const NodeTy** const_eop_iterator;
+ typedef typename AllNodesTy::iterator node_iterator;
+ typedef typename AllNodesTy::const_iterator const_node_iterator;
+
+ node_iterator nodes_begin() {
+ return Nodes.begin();
+ }
+
+ node_iterator nodes_end() {
+ return Nodes.end();
+ }
+
+ const_node_iterator nodes_begin() const {
+ return Nodes.begin();
+ }
+
+ const_node_iterator nodes_end() const {
+ return Nodes.end();
+ }
+
+ roots_iterator roots_begin() {
+ return reinterpret_cast<roots_iterator>(Roots.begin());
+ }
+
+ roots_iterator roots_end() {
+ return reinterpret_cast<roots_iterator>(Roots.end());
+ }
+
+ const_roots_iterator roots_begin() const {
+ return const_cast<ExplodedGraph>(this)->roots_begin();
+ }
+
+ const_roots_iterator roots_end() const {
+ return const_cast<ExplodedGraph>(this)->roots_end();
+ }
+
+ eop_iterator eop_begin() {
+ return reinterpret_cast<eop_iterator>(EndNodes.begin());
+ }
+
+ eop_iterator eop_end() {
+ return reinterpret_cast<eop_iterator>(EndNodes.end());
+ }
+
+ const_eop_iterator eop_begin() const {
+ return const_cast<ExplodedGraph>(this)->eop_begin();
+ }
+
+ const_eop_iterator eop_end() const {
+ return const_cast<ExplodedGraph>(this)->eop_end();
+ }
+
+ std::pair<ExplodedGraph*, InterExplodedGraphMap<STATE>*>
+ Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
+ llvm::DenseMap<const void*, const void*> *InverseMap = 0) const {
+
+ if (NBeg == NEnd)
+ return std::make_pair((ExplodedGraph*) 0,
+ (InterExplodedGraphMap<STATE>*) 0);
+
+ assert (NBeg < NEnd);
+
+ const ExplodedNodeImpl* const* NBegImpl =
+ (const ExplodedNodeImpl* const*) NBeg;
+ const ExplodedNodeImpl* const* NEndImpl =
+ (const ExplodedNodeImpl* const*) NEnd;
+
+ llvm::OwningPtr<InterExplodedGraphMap<STATE> >
+ M(new InterExplodedGraphMap<STATE>());
+
+ ExplodedGraphImpl* G = ExplodedGraphImpl::Trim(NBegImpl, NEndImpl, M.get(),
+ InverseMap);
+
+ return std::make_pair(static_cast<ExplodedGraph*>(G), M.take());
+ }
+};
+
+template <typename StateTy>
+class ExplodedNodeSet {
+
+ typedef ExplodedNode<StateTy> NodeTy;
+ typedef llvm::SmallPtrSet<NodeTy*,5> ImplTy;
+ ImplTy Impl;
+
+public:
+ ExplodedNodeSet(NodeTy* N) {
+ assert (N && !static_cast<ExplodedNodeImpl*>(N)->isSink());
+ Impl.insert(N);
+ }
+
+ ExplodedNodeSet() {}
+
+ inline void Add(NodeTy* N) {
+ if (N && !static_cast<ExplodedNodeImpl*>(N)->isSink()) Impl.insert(N);
+ }
+
+ typedef typename ImplTy::iterator iterator;
+ typedef typename ImplTy::const_iterator const_iterator;
+
+ inline unsigned size() const { return Impl.size(); }
+ inline bool empty() const { return Impl.empty(); }
+
+ inline void clear() { Impl.clear(); }
+
+ inline iterator begin() { return Impl.begin(); }
+ inline iterator end() { return Impl.end(); }
+
+ inline const_iterator begin() const { return Impl.begin(); }
+ inline const_iterator end() const { return Impl.end(); }
+};
+
+} // end clang namespace
+
+// GraphTraits
+
+namespace llvm {
+ template<typename StateTy>
+ struct GraphTraits<clang::ExplodedNode<StateTy>*> {
+ typedef clang::ExplodedNode<StateTy> NodeType;
+ typedef typename NodeType::succ_iterator ChildIteratorType;
+ typedef llvm::df_iterator<NodeType*> nodes_iterator;
+
+ static inline NodeType* getEntryNode(NodeType* N) {
+ return N;
+ }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ return N->succ_begin();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ return N->succ_end();
+ }
+
+ static inline nodes_iterator nodes_begin(NodeType* N) {
+ return df_begin(N);
+ }
+
+ static inline nodes_iterator nodes_end(NodeType* N) {
+ return df_end(N);
+ }
+ };
+
+ template<typename StateTy>
+ struct GraphTraits<const clang::ExplodedNode<StateTy>*> {
+ typedef const clang::ExplodedNode<StateTy> NodeType;
+ typedef typename NodeType::succ_iterator ChildIteratorType;
+ typedef llvm::df_iterator<NodeType*> nodes_iterator;
+
+ static inline NodeType* getEntryNode(NodeType* N) {
+ return N;
+ }
+
+ static inline ChildIteratorType child_begin(NodeType* N) {
+ return N->succ_begin();
+ }
+
+ static inline ChildIteratorType child_end(NodeType* N) {
+ return N->succ_end();
+ }
+
+ static inline nodes_iterator nodes_begin(NodeType* N) {
+ return df_begin(N);
+ }
+
+ static inline nodes_iterator nodes_end(NodeType* N) {
+ return df_end(N);
+ }
+ };
+
+} // end llvm namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRAuditor.h b/include/clang/Analysis/PathSensitive/GRAuditor.h
new file mode 100644
index 000000000000..eca591d4af0e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRAuditor.h
@@ -0,0 +1,39 @@
+//==- GRAuditor.h - Observers of the creation of ExplodedNodes------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines GRAuditor and its primary subclasses, an interface
+// to audit the creation of ExplodedNodes. This interface can be used
+// to implement simple checkers that do not mutate analysis state but
+// instead operate by perfoming simple logical checks at key monitoring
+// locations (e.g., function calls).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRAUDITOR
+#define LLVM_CLANG_ANALYSIS_GRAUDITOR
+
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+
+namespace clang {
+
+template <typename STATE>
+class GRAuditor {
+public:
+ typedef ExplodedNode<STATE> NodeTy;
+ typedef typename STATE::ManagerTy ManagerTy;
+
+ virtual ~GRAuditor() {}
+ virtual bool Audit(NodeTy* N, ManagerTy& M) = 0;
+};
+
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRBlockCounter.h b/include/clang/Analysis/PathSensitive/GRBlockCounter.h
new file mode 100644
index 000000000000..b4fd2704b81a
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRBlockCounter.h
@@ -0,0 +1,50 @@
+//==- GRBlockCounter.h - ADT for counting block visits -------------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines GRBlockCounter, an abstract data type used to count
+// the number of times a given block has been visited along a path
+// analyzed by GRCoreEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
+#define LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
+
+namespace llvm {
+ class BumpPtrAllocator;
+}
+
+namespace clang {
+
+class GRBlockCounter {
+ void* Data;
+
+ GRBlockCounter(void* D) : Data(D) {}
+
+public:
+ GRBlockCounter() : Data(0) {}
+
+ unsigned getNumVisited(unsigned BlockID) const;
+
+ class Factory {
+ void* F;
+ public:
+ Factory(llvm::BumpPtrAllocator& Alloc);
+ ~Factory();
+
+ GRBlockCounter GetEmptyCounter();
+ GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID);
+ };
+
+ friend class Factory;
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
new file mode 100644
index 000000000000..0fbdbde55bd5
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
@@ -0,0 +1,668 @@
+//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine ------------------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a generic engine for intraprocedural, path-sensitive,
+// dataflow analysis via graph reachability.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRENGINE
+#define LLVM_CLANG_ANALYSIS_GRENGINE
+
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
+#include "clang/Analysis/PathSensitive/GRWorkList.h"
+#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
+#include "clang/Analysis/PathSensitive/GRAuditor.h"
+#include "llvm/ADT/OwningPtr.h"
+
+namespace clang {
+
+class GRStmtNodeBuilderImpl;
+class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
+class GRSwitchNodeBuilderImpl;
+class GREndPathNodeBuilderImpl;
+class GRWorkList;
+
+//===----------------------------------------------------------------------===//
+/// GRCoreEngineImpl - Implements the core logic of the graph-reachability
+/// analysis. It traverses the CFG and generates the ExplodedGraph.
+/// Program "states" are treated as opaque void pointers.
+/// The template class GRCoreEngine (which subclasses GRCoreEngineImpl)
+/// provides the matching component to the engine that knows the actual types
+/// for states. Note that this engine only dispatches to transfer functions
+/// at the statement and block-level. The analyses themselves must implement
+/// any transfer function logic and the sub-expression level (if any).
+class GRCoreEngineImpl {
+protected:
+ friend class GRStmtNodeBuilderImpl;
+ friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
+ friend class GRSwitchNodeBuilderImpl;
+ friend class GREndPathNodeBuilderImpl;
+
+ /// G - The simulation graph. Each node is a (location,state) pair.
+ llvm::OwningPtr<ExplodedGraphImpl> G;
+
+ /// WList - A set of queued nodes that need to be processed by the
+ /// worklist algorithm. It is up to the implementation of WList to decide
+ /// the order that nodes are processed.
+ GRWorkList* WList;
+
+ /// BCounterFactory - A factory object for created GRBlockCounter objects.
+ /// These are used to record for key nodes in the ExplodedGraph the
+ /// number of times different CFGBlocks have been visited along a path.
+ GRBlockCounter::Factory BCounterFactory;
+
+ void GenerateNode(const ProgramPoint& Loc, const void* State,
+ ExplodedNodeImpl* Pred);
+
+ /// getInitialState - Gets the void* representing the initial 'state'
+ /// of the analysis. This is simply a wrapper (implemented
+ /// in GRCoreEngine) that performs type erasure on the initial
+ /// state returned by the checker object.
+ virtual const void* getInitialState() = 0;
+
+ void HandleBlockEdge(const BlockEdge& E, ExplodedNodeImpl* Pred);
+ void HandleBlockEntrance(const BlockEntrance& E, ExplodedNodeImpl* Pred);
+ void HandleBlockExit(CFGBlock* B, ExplodedNodeImpl* Pred);
+ void HandlePostStmt(const PostStmt& S, CFGBlock* B,
+ unsigned StmtIdx, ExplodedNodeImpl *Pred);
+
+ void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
+ ExplodedNodeImpl* Pred);
+
+ virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0;
+
+ virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State,
+ GRBlockCounter BC) = 0;
+
+ virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0;
+
+ virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator,
+ GRBranchNodeBuilderImpl& Builder) = 0;
+
+ virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
+
+ virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& Builder) = 0;
+
+private:
+ GRCoreEngineImpl(const GRCoreEngineImpl&); // Do not implement.
+ GRCoreEngineImpl& operator=(const GRCoreEngineImpl&);
+
+protected:
+ GRCoreEngineImpl(ExplodedGraphImpl* g, GRWorkList* wl)
+ : G(g), WList(wl), BCounterFactory(g->getAllocator()) {}
+
+public:
+ /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
+ /// steps. Returns true if there is still simulation state on the worklist.
+ bool ExecuteWorkList(unsigned Steps);
+
+ virtual ~GRCoreEngineImpl();
+
+ CFG& getCFG() { return G->getCFG(); }
+};
+
+class GRStmtNodeBuilderImpl {
+ GRCoreEngineImpl& Eng;
+ CFGBlock& B;
+ const unsigned Idx;
+ ExplodedNodeImpl* Pred;
+ ExplodedNodeImpl* LastNode;
+
+ typedef llvm::SmallPtrSet<ExplodedNodeImpl*,5> DeferredTy;
+ DeferredTy Deferred;
+
+ void GenerateAutoTransition(ExplodedNodeImpl* N);
+
+public:
+ GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
+ ExplodedNodeImpl* N, GRCoreEngineImpl* e);
+
+ ~GRStmtNodeBuilderImpl();
+
+ ExplodedNodeImpl* getBasePredecessor() const { return Pred; }
+
+ ExplodedNodeImpl* getLastNode() const {
+ return LastNode ? (LastNode->isSink() ? NULL : LastNode) : NULL;
+ }
+
+ GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+
+ unsigned getCurrentBlockCount() const {
+ return getBlockCounter().getNumVisited(B.getBlockID());
+ }
+
+ ExplodedNodeImpl*
+ generateNodeImpl(PostStmt PP, const void* State, ExplodedNodeImpl* Pred);
+
+ ExplodedNodeImpl*
+ generateNodeImpl(Stmt* S, const void* State, ExplodedNodeImpl* Pred,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+ const void *tag = 0);
+
+ ExplodedNodeImpl*
+ generateNodeImpl(Stmt* S, const void* State,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+ const void *tag = 0) {
+ ExplodedNodeImpl* N = getLastNode();
+ assert (N && "Predecessor of new node is infeasible.");
+ return generateNodeImpl(S, State, N, K, tag);
+ }
+
+ ExplodedNodeImpl*
+ generateNodeImpl(Stmt* S, const void* State, const void *tag = 0) {
+ ExplodedNodeImpl* N = getLastNode();
+ assert (N && "Predecessor of new node is infeasible.");
+ return generateNodeImpl(S, State, N, ProgramPoint::PostStmtKind, tag);
+ }
+
+ /// getStmt - Return the current block-level expression associated with
+ /// this builder.
+ Stmt* getStmt() const { return B[Idx]; }
+
+ /// getBlock - Return the CFGBlock associated with the block-level expression
+ /// of this builder.
+ CFGBlock* getBlock() const { return &B; }
+};
+
+
+template<typename STATE>
+class GRStmtNodeBuilder {
+public:
+ typedef STATE StateTy;
+ typedef typename StateTy::ManagerTy StateManagerTy;
+ typedef ExplodedNode<StateTy> NodeTy;
+
+private:
+ GRStmtNodeBuilderImpl& NB;
+ StateManagerTy& Mgr;
+ const StateTy* CleanedState;
+ GRAuditor<StateTy>* Auditor;
+
+public:
+ GRStmtNodeBuilder(GRStmtNodeBuilderImpl& nb, StateManagerTy& mgr) :
+ NB(nb), Mgr(mgr), Auditor(0), PurgingDeadSymbols(false),
+ BuildSinks(false), HasGeneratedNode(false),
+ PointKind(ProgramPoint::PostStmtKind), Tag(0) {
+
+ CleanedState = getLastNode()->getState();
+ }
+
+ void setAuditor(GRAuditor<StateTy>* A) {
+ Auditor = A;
+ }
+
+ NodeTy* getLastNode() const {
+ return static_cast<NodeTy*>(NB.getLastNode());
+ }
+
+ NodeTy* generateNode(PostStmt PP, const StateTy* St, NodeTy* Pred) {
+ HasGeneratedNode = true;
+ return static_cast<NodeTy*>(NB.generateNodeImpl(PP, St, Pred));
+ }
+
+ NodeTy* generateNode(Stmt* S, const StateTy* St, NodeTy* Pred,
+ ProgramPoint::Kind K) {
+ HasGeneratedNode = true;
+ if (PurgingDeadSymbols) K = ProgramPoint::PostPurgeDeadSymbolsKind;
+ return static_cast<NodeTy*>(NB.generateNodeImpl(S, St, Pred, K, Tag));
+ }
+
+ NodeTy* generateNode(Stmt* S, const StateTy* St, NodeTy* Pred) {
+ return generateNode(S, St, Pred, PointKind);
+ }
+
+ NodeTy* generateNode(Stmt* S, const StateTy* St, ProgramPoint::Kind K) {
+ HasGeneratedNode = true;
+ if (PurgingDeadSymbols) K = ProgramPoint::PostPurgeDeadSymbolsKind;
+ return static_cast<NodeTy*>(NB.generateNodeImpl(S, St, K, Tag));
+ }
+
+ NodeTy* generateNode(Stmt* S, const StateTy* St) {
+ return generateNode(S, St, PointKind);
+ }
+
+
+ GRBlockCounter getBlockCounter() const {
+ return NB.getBlockCounter();
+ }
+
+ unsigned getCurrentBlockCount() const {
+ return NB.getCurrentBlockCount();
+ }
+
+ const StateTy* GetState(NodeTy* Pred) const {
+ if ((ExplodedNodeImpl*) Pred == NB.getBasePredecessor())
+ return CleanedState;
+ else
+ return Pred->getState();
+ }
+
+ void SetCleanedState(const StateTy* St) {
+ CleanedState = St;
+ }
+
+ NodeTy* MakeNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
+ NodeTy* Pred, const StateTy* St) {
+ return MakeNode(Dst, S, Pred, St, PointKind);
+ }
+
+ NodeTy* MakeNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
+ NodeTy* Pred, const StateTy* St, ProgramPoint::Kind K) {
+
+ const StateTy* PredState = GetState(Pred);
+
+ // If the state hasn't changed, don't generate a new node.
+ if (!BuildSinks && St == PredState && Auditor == 0) {
+ Dst.Add(Pred);
+ return NULL;
+ }
+
+ NodeTy* N = generateNode(S, St, Pred, K);
+
+ if (N) {
+ if (BuildSinks)
+ N->markAsSink();
+ else {
+ if (Auditor && Auditor->Audit(N, Mgr))
+ N->markAsSink();
+
+ Dst.Add(N);
+ }
+ }
+
+ return N;
+ }
+
+ NodeTy* MakeSinkNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
+ NodeTy* Pred, const StateTy* St) {
+ bool Tmp = BuildSinks;
+ BuildSinks = true;
+ NodeTy* N = MakeNode(Dst, S, Pred, St);
+ BuildSinks = Tmp;
+ return N;
+ }
+
+ bool PurgingDeadSymbols;
+ bool BuildSinks;
+ bool HasGeneratedNode;
+ ProgramPoint::Kind PointKind;
+ const void *Tag;
+};
+
+class GRBranchNodeBuilderImpl {
+ GRCoreEngineImpl& Eng;
+ CFGBlock* Src;
+ CFGBlock* DstT;
+ CFGBlock* DstF;
+ ExplodedNodeImpl* Pred;
+
+ typedef llvm::SmallVector<ExplodedNodeImpl*,3> DeferredTy;
+ DeferredTy Deferred;
+
+ bool GeneratedTrue;
+ bool GeneratedFalse;
+
+public:
+ GRBranchNodeBuilderImpl(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
+ ExplodedNodeImpl* pred, GRCoreEngineImpl* e)
+ : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
+ GeneratedTrue(false), GeneratedFalse(false) {}
+
+ ~GRBranchNodeBuilderImpl();
+
+ ExplodedNodeImpl* getPredecessor() const { return Pred; }
+ const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
+ GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+
+ ExplodedNodeImpl* generateNodeImpl(const void* State, bool branch);
+
+ CFGBlock* getTargetBlock(bool branch) const {
+ return branch ? DstT : DstF;
+ }
+
+ void markInfeasible(bool branch) {
+ if (branch) GeneratedTrue = true;
+ else GeneratedFalse = true;
+ }
+};
+
+template<typename STATE>
+class GRBranchNodeBuilder {
+ typedef STATE StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+ GRBranchNodeBuilderImpl& NB;
+
+public:
+ GRBranchNodeBuilder(GRBranchNodeBuilderImpl& nb) : NB(nb) {}
+
+ const GraphTy& getGraph() const {
+ return static_cast<const GraphTy&>(NB.getGraph());
+ }
+
+ NodeTy* getPredecessor() const {
+ return static_cast<NodeTy*>(NB.getPredecessor());
+ }
+
+ const StateTy* getState() const {
+ return getPredecessor()->getState();
+ }
+
+ NodeTy* generateNode(const StateTy* St, bool branch) {
+ return static_cast<NodeTy*>(NB.generateNodeImpl(St, branch));
+ }
+
+ GRBlockCounter getBlockCounter() const {
+ return NB.getBlockCounter();
+ }
+
+ CFGBlock* getTargetBlock(bool branch) const {
+ return NB.getTargetBlock(branch);
+ }
+
+ void markInfeasible(bool branch) {
+ NB.markInfeasible(branch);
+ }
+};
+
+class GRIndirectGotoNodeBuilderImpl {
+ GRCoreEngineImpl& Eng;
+ CFGBlock* Src;
+ CFGBlock& DispatchBlock;
+ Expr* E;
+ ExplodedNodeImpl* Pred;
+public:
+ GRIndirectGotoNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
+ Expr* e, CFGBlock* dispatch,
+ GRCoreEngineImpl* eng)
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+
+
+ class Iterator {
+ CFGBlock::succ_iterator I;
+
+ friend class GRIndirectGotoNodeBuilderImpl;
+ Iterator(CFGBlock::succ_iterator i) : I(i) {}
+ public:
+
+ Iterator& operator++() { ++I; return *this; }
+ bool operator!=(const Iterator& X) const { return I != X.I; }
+
+ LabelStmt* getLabel() const {
+ return llvm::cast<LabelStmt>((*I)->getLabel());
+ }
+
+ CFGBlock* getBlock() const {
+ return *I;
+ }
+ };
+
+ Iterator begin() { return Iterator(DispatchBlock.succ_begin()); }
+ Iterator end() { return Iterator(DispatchBlock.succ_end()); }
+
+ ExplodedNodeImpl* generateNodeImpl(const Iterator& I, const void* State,
+ bool isSink);
+
+ Expr* getTarget() const { return E; }
+ const void* getState() const { return Pred->State; }
+};
+
+template<typename STATE>
+class GRIndirectGotoNodeBuilder {
+ typedef STATE StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+ GRIndirectGotoNodeBuilderImpl& NB;
+
+public:
+ GRIndirectGotoNodeBuilder(GRIndirectGotoNodeBuilderImpl& nb) : NB(nb) {}
+
+ typedef GRIndirectGotoNodeBuilderImpl::Iterator iterator;
+
+ iterator begin() { return NB.begin(); }
+ iterator end() { return NB.end(); }
+
+ Expr* getTarget() const { return NB.getTarget(); }
+
+ NodeTy* generateNode(const iterator& I, const StateTy* St, bool isSink=false){
+ return static_cast<NodeTy*>(NB.generateNodeImpl(I, St, isSink));
+ }
+
+ const StateTy* getState() const {
+ return static_cast<const StateTy*>(NB.getState());
+ }
+};
+
+class GRSwitchNodeBuilderImpl {
+ GRCoreEngineImpl& Eng;
+ CFGBlock* Src;
+ Expr* Condition;
+ ExplodedNodeImpl* Pred;
+public:
+ GRSwitchNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
+ Expr* condition, GRCoreEngineImpl* eng)
+ : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
+
+ class Iterator {
+ CFGBlock::succ_reverse_iterator I;
+
+ friend class GRSwitchNodeBuilderImpl;
+ Iterator(CFGBlock::succ_reverse_iterator i) : I(i) {}
+ public:
+
+ Iterator& operator++() { ++I; return *this; }
+ bool operator!=(const Iterator& X) const { return I != X.I; }
+
+ CaseStmt* getCase() const {
+ return llvm::cast<CaseStmt>((*I)->getLabel());
+ }
+
+ CFGBlock* getBlock() const {
+ return *I;
+ }
+ };
+
+ Iterator begin() { return Iterator(Src->succ_rbegin()+1); }
+ Iterator end() { return Iterator(Src->succ_rend()); }
+
+ ExplodedNodeImpl* generateCaseStmtNodeImpl(const Iterator& I,
+ const void* State);
+
+ ExplodedNodeImpl* generateDefaultCaseNodeImpl(const void* State,
+ bool isSink);
+
+ Expr* getCondition() const { return Condition; }
+ const void* getState() const { return Pred->State; }
+};
+
+template<typename STATE>
+class GRSwitchNodeBuilder {
+ typedef STATE StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+ GRSwitchNodeBuilderImpl& NB;
+
+public:
+ GRSwitchNodeBuilder(GRSwitchNodeBuilderImpl& nb) : NB(nb) {}
+
+ typedef GRSwitchNodeBuilderImpl::Iterator iterator;
+
+ iterator begin() { return NB.begin(); }
+ iterator end() { return NB.end(); }
+
+ Expr* getCondition() const { return NB.getCondition(); }
+
+ NodeTy* generateCaseStmtNode(const iterator& I, const StateTy* St) {
+ return static_cast<NodeTy*>(NB.generateCaseStmtNodeImpl(I, St));
+ }
+
+ NodeTy* generateDefaultCaseNode(const StateTy* St, bool isSink = false) {
+ return static_cast<NodeTy*>(NB.generateDefaultCaseNodeImpl(St, isSink));
+ }
+
+ const StateTy* getState() const {
+ return static_cast<const StateTy*>(NB.getState());
+ }
+};
+
+
+class GREndPathNodeBuilderImpl {
+ GRCoreEngineImpl& Eng;
+ CFGBlock& B;
+ ExplodedNodeImpl* Pred;
+ bool HasGeneratedNode;
+
+public:
+ GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNodeImpl* N,
+ GRCoreEngineImpl* e)
+ : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
+
+ ~GREndPathNodeBuilderImpl();
+
+ ExplodedNodeImpl* getPredecessor() const { return Pred; }
+
+ GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+
+ unsigned getCurrentBlockCount() const {
+ return getBlockCounter().getNumVisited(B.getBlockID());
+ }
+
+ ExplodedNodeImpl* generateNodeImpl(const void* State,
+ const void *tag = 0,
+ ExplodedNodeImpl *P = 0);
+
+ CFGBlock* getBlock() const { return &B; }
+};
+
+
+template<typename STATE>
+class GREndPathNodeBuilder {
+ typedef STATE StateTy;
+ typedef ExplodedNode<StateTy> NodeTy;
+
+ GREndPathNodeBuilderImpl& NB;
+
+public:
+ GREndPathNodeBuilder(GREndPathNodeBuilderImpl& nb) : NB(nb) {}
+
+ NodeTy* getPredecessor() const {
+ return static_cast<NodeTy*>(NB.getPredecessor());
+ }
+
+ GRBlockCounter getBlockCounter() const {
+ return NB.getBlockCounter();
+ }
+
+ unsigned getCurrentBlockCount() const {
+ return NB.getCurrentBlockCount();
+ }
+
+ const StateTy* getState() const {
+ return getPredecessor()->getState();
+ }
+
+ NodeTy* MakeNode(const StateTy* St, const void *tag = 0) {
+ return static_cast<NodeTy*>(NB.generateNodeImpl(St, tag));
+ }
+
+ NodeTy *generateNode(const StateTy *St, NodeTy *Pred, const void *tag = 0) {
+ return static_cast<NodeTy*>(NB.generateNodeImpl(St, tag, Pred));
+ }
+};
+
+
+template<typename SUBENGINE>
+class GRCoreEngine : public GRCoreEngineImpl {
+public:
+ typedef SUBENGINE SubEngineTy;
+ typedef typename SubEngineTy::StateTy StateTy;
+ typedef typename StateTy::ManagerTy StateManagerTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+protected:
+ SubEngineTy& SubEngine;
+
+ virtual const void* getInitialState() {
+ return SubEngine.getInitialState();
+ }
+
+ virtual void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) {
+ GREndPathNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessEndPath(Builder);
+ }
+
+ virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) {
+ GRStmtNodeBuilder<StateTy> Builder(BuilderImpl,SubEngine.getStateManager());
+ SubEngine.ProcessStmt(S, Builder);
+ }
+
+ virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State,
+ GRBlockCounter BC) {
+ return SubEngine.ProcessBlockEntrance(Blk,
+ static_cast<const StateTy*>(State),
+ BC);
+ }
+
+ virtual void ProcessBranch(Stmt* Condition, Stmt* Terminator,
+ GRBranchNodeBuilderImpl& BuilderImpl) {
+ GRBranchNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessBranch(Condition, Terminator, Builder);
+ }
+
+ virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
+ GRIndirectGotoNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessIndirectGoto(Builder);
+ }
+
+ virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) {
+ GRSwitchNodeBuilder<StateTy> Builder(BuilderImpl);
+ SubEngine.ProcessSwitch(Builder);
+ }
+
+public:
+ /// Construct a GRCoreEngine object to analyze the provided CFG using
+ /// a DFS exploration of the exploded graph.
+ GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine)
+ : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx),
+ GRWorkList::MakeBFS()),
+ SubEngine(subengine) {}
+
+ /// Construct a GRCoreEngine object to analyze the provided CFG and to
+ /// use the provided worklist object to execute the worklist algorithm.
+ /// The GRCoreEngine object assumes ownership of 'wlist'.
+ GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist,
+ SubEngineTy& subengine)
+ : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), wlist),
+ SubEngine(subengine) {}
+
+ virtual ~GRCoreEngine() {}
+
+ /// getGraph - Returns the exploded graph.
+ GraphTy& getGraph() {
+ return *static_cast<GraphTy*>(G.get());
+ }
+
+ /// takeGraph - Returns the exploded graph. Ownership of the graph is
+ /// transfered to the caller.
+ GraphTy* takeGraph() {
+ return static_cast<GraphTy*>(G.take());
+ }
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
new file mode 100644
index 000000000000..2068b1beaa13
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -0,0 +1,738 @@
+//===-- GRExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a meta-engine for path-sensitive dataflow analysis that
+// is built on GRCoreEngine, but provides the boilerplate to execute transfer
+// functions and build the ExplodedGraph at the expression level.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
+#define LLVM_CLANG_ANALYSIS_GREXPRENGINE
+
+#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
+#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/ExprObjC.h"
+
+namespace clang {
+
+ class PathDiagnosticClient;
+ class Diagnostic;
+ class ObjCForCollectionStmt;
+
+class GRExprEngine {
+public:
+ typedef GRState StateTy;
+ typedef ExplodedGraph<StateTy> GraphTy;
+ typedef GraphTy::NodeTy NodeTy;
+
+ // Builders.
+ typedef GRStmtNodeBuilder<StateTy> StmtNodeBuilder;
+ typedef GRBranchNodeBuilder<StateTy> BranchNodeBuilder;
+ typedef GRIndirectGotoNodeBuilder<StateTy> IndirectGotoNodeBuilder;
+ typedef GRSwitchNodeBuilder<StateTy> SwitchNodeBuilder;
+ typedef GREndPathNodeBuilder<StateTy> EndPathNodeBuilder;
+ typedef ExplodedNodeSet<StateTy> NodeSet;
+
+protected:
+ GRCoreEngine<GRExprEngine> CoreEngine;
+
+ /// G - the simulation graph.
+ GraphTy& G;
+
+ /// Liveness - live-variables information the ValueDecl* and block-level
+ /// Expr* in the CFG. Used to prune out dead state.
+ LiveVariables& Liveness;
+
+ /// Builder - The current GRStmtNodeBuilder which is used when building the
+ /// nodes for a given statement.
+ StmtNodeBuilder* Builder;
+
+ /// StateMgr - Object that manages the data for all created states.
+ GRStateManager StateMgr;
+
+ /// SymMgr - Object that manages the symbol information.
+ SymbolManager& SymMgr;
+
+ /// ValMgr - Object that manages/creates SVals.
+ ValueManager &ValMgr;
+
+ /// EntryNode - The immediate predecessor node.
+ NodeTy* EntryNode;
+
+ /// CleanedState - The state for EntryNode "cleaned" of all dead
+ /// variables and symbols (as determined by a liveness analysis).
+ const GRState* CleanedState;
+
+ /// CurrentStmt - The current block-level statement.
+ Stmt* CurrentStmt;
+
+ // Obj-C Class Identifiers.
+ IdentifierInfo* NSExceptionII;
+
+ // Obj-C Selectors.
+ Selector* NSExceptionInstanceRaiseSelectors;
+ Selector RaiseSel;
+
+ llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
+
+ /// PurgeDead - Remove dead bindings before processing a statement.
+ bool PurgeDead;
+
+ /// BR - The BugReporter associated with this engine. It is important that
+ // this object be placed at the very end of member variables so that its
+ // destructor is called before the rest of the GRExprEngine is destroyed.
+ GRBugReporter BR;
+
+ /// EargerlyAssume - A flag indicating how the engine should handle
+ // expressions such as: 'x = (y != 0)'. When this flag is true then
+ // the subexpression 'y != 0' will be eagerly assumed to be true or false,
+ // thus evaluating it to the integers 0 or 1 respectively. The upside
+ // is that this can increase analysis precision until we have a better way
+ // to lazily evaluate such logic. The downside is that it eagerly
+ // bifurcates paths.
+ const bool EagerlyAssume;
+
+public:
+ typedef llvm::SmallPtrSet<NodeTy*,2> ErrorNodes;
+ typedef llvm::DenseMap<NodeTy*, Expr*> UndefArgsTy;
+
+ /// NilReceiverStructRetExplicit - Nodes in the ExplodedGraph that resulted
+ /// from [x ...] with 'x' definitely being nil and the result was a 'struct'
+ // (an undefined value).
+ ErrorNodes NilReceiverStructRetExplicit;
+
+ /// NilReceiverStructRetImplicit - Nodes in the ExplodedGraph that resulted
+ /// from [x ...] with 'x' possibly being nil and the result was a 'struct'
+ // (an undefined value).
+ ErrorNodes NilReceiverStructRetImplicit;
+
+ /// NilReceiverLargerThanVoidPtrRetExplicit - Nodes in the ExplodedGraph that
+ /// resulted from [x ...] with 'x' definitely being nil and the result's size
+ // was larger than sizeof(void *) (an undefined value).
+ ErrorNodes NilReceiverLargerThanVoidPtrRetExplicit;
+
+ /// NilReceiverLargerThanVoidPtrRetImplicit - Nodes in the ExplodedGraph that
+ /// resulted from [x ...] with 'x' possibly being nil and the result's size
+ // was larger than sizeof(void *) (an undefined value).
+ ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit;
+
+ /// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
+ /// the address of a stack variable.
+ ErrorNodes RetsStackAddr;
+
+ /// RetsUndef - Nodes in the ExplodedGraph that result from returning
+ /// an undefined value.
+ ErrorNodes RetsUndef;
+
+ /// UndefBranches - Nodes in the ExplodedGraph that result from
+ /// taking a branch based on an undefined value.
+ ErrorNodes UndefBranches;
+
+ /// UndefStores - Sinks in the ExplodedGraph that result from
+ /// making a store to an undefined lvalue.
+ ErrorNodes UndefStores;
+
+ /// NoReturnCalls - Sinks in the ExplodedGraph that result from
+ // calling a function with the attribute "noreturn".
+ ErrorNodes NoReturnCalls;
+
+ /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
+ /// taking a dereference on a symbolic pointer that MAY be NULL.
+ ErrorNodes ImplicitNullDeref;
+
+ /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
+ /// taking a dereference on a symbolic pointer that MUST be NULL.
+ ErrorNodes ExplicitNullDeref;
+
+ /// UnitDeref - Nodes in the ExplodedGraph that result from
+ /// taking a dereference on an undefined value.
+ ErrorNodes UndefDeref;
+
+ /// ImplicitBadDivides - Nodes in the ExplodedGraph that result from
+ /// evaluating a divide or modulo operation where the denominator
+ /// MAY be zero.
+ ErrorNodes ImplicitBadDivides;
+
+ /// ExplicitBadDivides - Nodes in the ExplodedGraph that result from
+ /// evaluating a divide or modulo operation where the denominator
+ /// MUST be zero or undefined.
+ ErrorNodes ExplicitBadDivides;
+
+ /// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
+ /// constructing a zero-sized VLA where the size may be zero.
+ ErrorNodes ImplicitBadSizedVLA;
+
+ /// ExplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
+ /// constructing a zero-sized VLA where the size must be zero.
+ ErrorNodes ExplicitBadSizedVLA;
+
+ /// UndefResults - Nodes in the ExplodedGraph where the operands are defined
+ /// by the result is not. Excludes divide-by-zero errors.
+ ErrorNodes UndefResults;
+
+ /// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
+ /// pointers that are NULL (or other constants) or Undefined.
+ ErrorNodes BadCalls;
+
+ /// UndefReceiver - Nodes in the ExplodedGraph resulting from message
+ /// ObjC message expressions where the receiver is undefined (uninitialized).
+ ErrorNodes UndefReceivers;
+
+ /// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
+ /// where a pass-by-value argument has an undefined value.
+ UndefArgsTy UndefArgs;
+
+ /// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
+ /// message expressions where a pass-by-value argument has an undefined
+ /// value.
+ UndefArgsTy MsgExprUndefArgs;
+
+ /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
+ /// out-of-bound memory accesses where the index MAY be out-of-bound.
+ ErrorNodes ImplicitOOBMemAccesses;
+
+ /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
+ /// out-of-bound memory accesses where the index MUST be out-of-bound.
+ ErrorNodes ExplicitOOBMemAccesses;
+
+public:
+ GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, LiveVariables& L,
+ BugReporterData& BRD,
+ bool purgeDead, bool eagerlyAssume = true,
+ StoreManagerCreator SMC = CreateBasicStoreManager,
+ ConstraintManagerCreator CMC = CreateBasicConstraintManager);
+
+ ~GRExprEngine();
+
+ void ExecuteWorkList(unsigned Steps = 150000) {
+ CoreEngine.ExecuteWorkList(Steps);
+ }
+
+ /// getContext - Return the ASTContext associated with this analysis.
+ ASTContext& getContext() const { return G.getContext(); }
+
+ /// getCFG - Returns the CFG associated with this analysis.
+ CFG& getCFG() { return G.getCFG(); }
+
+ GRTransferFuncs& getTF() { return *StateMgr.TF; }
+
+ BugReporter& getBugReporter() { return BR; }
+
+ /// setTransferFunctions
+ void setTransferFunctions(GRTransferFuncs* tf);
+
+ void setTransferFunctions(GRTransferFuncs& tf) {
+ setTransferFunctions(&tf);
+ }
+
+ /// ViewGraph - Visualize the ExplodedGraph created by executing the
+ /// simulation.
+ void ViewGraph(bool trim = false);
+
+ void ViewGraph(NodeTy** Beg, NodeTy** End);
+
+ /// getLiveness - Returned computed live-variables information for the
+ /// analyzed function.
+ const LiveVariables& getLiveness() const { return Liveness; }
+ LiveVariables& getLiveness() { return Liveness; }
+
+ /// getInitialState - Return the initial state used for the root vertex
+ /// in the ExplodedGraph.
+ const GRState* getInitialState();
+
+ GraphTy& getGraph() { return G; }
+ const GraphTy& getGraph() const { return G; }
+
+ void RegisterInternalChecks();
+
+ bool isRetStackAddr(const NodeTy* N) const {
+ return N->isSink() && RetsStackAddr.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isUndefControlFlow(const NodeTy* N) const {
+ return N->isSink() && UndefBranches.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isUndefStore(const NodeTy* N) const {
+ return N->isSink() && UndefStores.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isImplicitNullDeref(const NodeTy* N) const {
+ return N->isSink() && ImplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isExplicitNullDeref(const NodeTy* N) const {
+ return N->isSink() && ExplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isUndefDeref(const NodeTy* N) const {
+ return N->isSink() && UndefDeref.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isImplicitBadDivide(const NodeTy* N) const {
+ return N->isSink() && ImplicitBadDivides.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isExplicitBadDivide(const NodeTy* N) const {
+ return N->isSink() && ExplicitBadDivides.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isNoReturnCall(const NodeTy* N) const {
+ return N->isSink() && NoReturnCalls.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isUndefResult(const NodeTy* N) const {
+ return N->isSink() && UndefResults.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isBadCall(const NodeTy* N) const {
+ return N->isSink() && BadCalls.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ bool isUndefArg(const NodeTy* N) const {
+ return N->isSink() &&
+ (UndefArgs.find(const_cast<NodeTy*>(N)) != UndefArgs.end() ||
+ MsgExprUndefArgs.find(const_cast<NodeTy*>(N)) != MsgExprUndefArgs.end());
+ }
+
+ bool isUndefReceiver(const NodeTy* N) const {
+ return N->isSink() && UndefReceivers.count(const_cast<NodeTy*>(N)) != 0;
+ }
+
+ typedef ErrorNodes::iterator ret_stackaddr_iterator;
+ ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
+ ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
+
+ typedef ErrorNodes::iterator ret_undef_iterator;
+ ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); }
+ ret_undef_iterator ret_undef_end() { return RetsUndef.end(); }
+
+ typedef ErrorNodes::iterator undef_branch_iterator;
+ undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
+ undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
+
+ typedef ErrorNodes::iterator null_deref_iterator;
+ null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
+ null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
+
+ null_deref_iterator implicit_null_derefs_begin() {
+ return ImplicitNullDeref.begin();
+ }
+ null_deref_iterator implicit_null_derefs_end() {
+ return ImplicitNullDeref.end();
+ }
+
+ typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
+
+ nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
+ return NilReceiverStructRetExplicit.begin();
+ }
+
+ nil_receiver_struct_ret_iterator nil_receiver_struct_ret_end() {
+ return NilReceiverStructRetExplicit.end();
+ }
+
+ typedef ErrorNodes::iterator nil_receiver_larger_than_voidptr_ret_iterator;
+
+ nil_receiver_larger_than_voidptr_ret_iterator
+ nil_receiver_larger_than_voidptr_ret_begin() {
+ return NilReceiverLargerThanVoidPtrRetExplicit.begin();
+ }
+
+ nil_receiver_larger_than_voidptr_ret_iterator
+ nil_receiver_larger_than_voidptr_ret_end() {
+ return NilReceiverLargerThanVoidPtrRetExplicit.end();
+ }
+
+ typedef ErrorNodes::iterator undef_deref_iterator;
+ undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
+ undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
+
+ typedef ErrorNodes::iterator bad_divide_iterator;
+
+ bad_divide_iterator explicit_bad_divides_begin() {
+ return ExplicitBadDivides.begin();
+ }
+
+ bad_divide_iterator explicit_bad_divides_end() {
+ return ExplicitBadDivides.end();
+ }
+
+ bad_divide_iterator implicit_bad_divides_begin() {
+ return ImplicitBadDivides.begin();
+ }
+
+ bad_divide_iterator implicit_bad_divides_end() {
+ return ImplicitBadDivides.end();
+ }
+
+ typedef ErrorNodes::iterator undef_result_iterator;
+ undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
+ undef_result_iterator undef_results_end() { return UndefResults.end(); }
+
+ typedef ErrorNodes::iterator bad_calls_iterator;
+ bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
+ bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
+
+ typedef UndefArgsTy::iterator undef_arg_iterator;
+ undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); }
+ undef_arg_iterator undef_arg_end() { return UndefArgs.end(); }
+
+ undef_arg_iterator msg_expr_undef_arg_begin() {
+ return MsgExprUndefArgs.begin();
+ }
+ undef_arg_iterator msg_expr_undef_arg_end() {
+ return MsgExprUndefArgs.end();
+ }
+
+ typedef ErrorNodes::iterator undef_receivers_iterator;
+
+ undef_receivers_iterator undef_receivers_begin() {
+ return UndefReceivers.begin();
+ }
+
+ undef_receivers_iterator undef_receivers_end() {
+ return UndefReceivers.end();
+ }
+
+ typedef ErrorNodes::iterator oob_memacc_iterator;
+ oob_memacc_iterator implicit_oob_memacc_begin() {
+ return ImplicitOOBMemAccesses.begin();
+ }
+ oob_memacc_iterator implicit_oob_memacc_end() {
+ return ImplicitOOBMemAccesses.end();
+ }
+ oob_memacc_iterator explicit_oob_memacc_begin() {
+ return ExplicitOOBMemAccesses.begin();
+ }
+ oob_memacc_iterator explicit_oob_memacc_end() {
+ return ExplicitOOBMemAccesses.end();
+ }
+
+ void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
+ void AddCheck(GRSimpleAPICheck* A);
+
+ /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
+ /// nodes by processing the 'effects' of a block-level statement.
+ void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
+
+ /// ProcessBlockEntrance - Called by GRCoreEngine when start processing
+ /// a CFGBlock. This method returns true if the analysis should continue
+ /// exploring the given path, and false otherwise.
+ bool ProcessBlockEntrance(CFGBlock* B, const GRState* St,
+ GRBlockCounter BC);
+
+ /// ProcessBranch - Called by GRCoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a branch condition.
+ void ProcessBranch(Stmt* Condition, Stmt* Term, BranchNodeBuilder& builder);
+
+ /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a computed goto jump.
+ void ProcessIndirectGoto(IndirectGotoNodeBuilder& builder);
+
+ /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a switch statement.
+ void ProcessSwitch(SwitchNodeBuilder& builder);
+
+ /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
+ /// nodes when the control reaches the end of a function.
+ void ProcessEndPath(EndPathNodeBuilder& builder) {
+ getTF().EvalEndPath(*this, builder);
+ StateMgr.EndPath(builder.getState());
+ }
+
+ GRStateManager& getStateManager() { return StateMgr; }
+ const GRStateManager& getStateManager() const { return StateMgr; }
+
+ StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
+
+ ConstraintManager& getConstraintManager() {
+ return StateMgr.getConstraintManager();
+ }
+
+ // FIXME: Remove when we migrate over to just using ValueManager.
+ BasicValueFactory& getBasicVals() {
+ return StateMgr.getBasicVals();
+ }
+ const BasicValueFactory& getBasicVals() const {
+ return StateMgr.getBasicVals();
+ }
+
+ ValueManager &getValueManager() { return ValMgr; }
+ const ValueManager &getValueManager() const { return ValMgr; }
+
+ // FIXME: Remove when we migrate over to just using ValueManager.
+ SymbolManager& getSymbolManager() { return SymMgr; }
+ const SymbolManager& getSymbolManager() const { return SymMgr; }
+
+protected:
+
+ const GRState* GetState(NodeTy* N) {
+ return N == EntryNode ? CleanedState : N->getState();
+ }
+
+public:
+
+ const GRState* BindExpr(const GRState* St, Expr* Ex, SVal V) {
+ return StateMgr.BindExpr(St, Ex, V);
+ }
+
+ const GRState* BindExpr(const GRState* St, const Expr* Ex, SVal V) {
+ return BindExpr(St, const_cast<Expr*>(Ex), V);
+ }
+
+protected:
+
+ const GRState* BindBlkExpr(const GRState* St, Expr* Ex, SVal V) {
+ return StateMgr.BindExpr(St, Ex, V, true, false);
+ }
+
+ const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
+ return StateMgr.BindLoc(St, LV, V);
+ }
+
+ SVal GetSVal(const GRState* St, Stmt* Ex) {
+ return StateMgr.GetSVal(St, Ex);
+ }
+
+ SVal GetSVal(const GRState* St, const Stmt* Ex) {
+ return GetSVal(St, const_cast<Stmt*>(Ex));
+ }
+
+ SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
+ return StateMgr.GetBlkExprSVal(St, Ex);
+ }
+
+ SVal GetSVal(const GRState* St, Loc LV, QualType T = QualType()) {
+ return StateMgr.GetSVal(St, LV, T);
+ }
+
+ inline NonLoc MakeConstantVal(uint64_t X, Expr* Ex) {
+ return NonLoc::MakeVal(getBasicVals(), X, Ex->getType());
+ }
+
+ /// Assume - Create new state by assuming that a given expression
+ /// is true or false.
+ const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
+ bool& isFeasible) {
+ return StateMgr.Assume(St, Cond, Assumption, isFeasible);
+ }
+
+ const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
+ bool& isFeasible) {
+ return StateMgr.Assume(St, Cond, Assumption, isFeasible);
+ }
+
+ const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
+ bool Assumption, bool& isFeasible) {
+ return StateMgr.AssumeInBound(St, Idx, UpperBound, Assumption, isFeasible);
+ }
+
+public:
+ NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const GRState* St,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+ const void *tag = 0);
+protected:
+
+ /// Visit - Transfer function logic for all statements. Dispatches to
+ /// other functions that handle specific kinds of statements.
+ void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
+ /// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
+ /// storage location. Note that not all kinds of expressions has lvalue.
+ void VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitArraySubscriptExpr - Transfer function for array accesses.
+ void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, NodeTy* Pred,
+ NodeSet& Dst, bool asLValue);
+
+ /// VisitAsmStmt - Transfer function logic for inline asm.
+ void VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst);
+
+ void VisitAsmStmtHelperOutputs(AsmStmt* A,
+ AsmStmt::outputs_iterator I,
+ AsmStmt::outputs_iterator E,
+ NodeTy* Pred, NodeSet& Dst);
+
+ void VisitAsmStmtHelperInputs(AsmStmt* A,
+ AsmStmt::inputs_iterator I,
+ AsmStmt::inputs_iterator E,
+ NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitBinaryOperator - Transfer function logic for binary operators.
+ void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+
+
+ /// VisitCall - Transfer function for function calls.
+ void VisitCall(CallExpr* CE, NodeTy* Pred,
+ CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
+ NodeSet& Dst);
+ void VisitCallRec(CallExpr* CE, NodeTy* Pred,
+ CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
+ NodeSet& Dst, const FunctionProtoType *,
+ unsigned ParamIdx = 0);
+
+ /// VisitCast - Transfer function logic for all casts (implicit and explicit).
+ void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitCastPointerToInteger - Transfer function (called by VisitCast) that
+ /// handles pointer to integer casts and array to integer casts.
+ void VisitCastPointerToInteger(SVal V, const GRState* state, QualType PtrTy,
+ Expr* CastE, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
+ void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
+ NodeSet& Dst, bool asLValue);
+
+ /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
+ void VisitDeclRefExpr(DeclRefExpr* DR, NodeTy* Pred, NodeSet& Dst,
+ bool asLValue);
+
+ /// VisitDeclStmt - Transfer function logic for DeclStmts.
+ void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
+ void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, NodeTy* Pred, NodeSet& Dst);
+
+ void VisitInitListExpr(InitListExpr* E, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitLogicalExpr - Transfer function logic for '&&', '||'
+ void VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitMemberExpr - Transfer function for member expressions.
+ void VisitMemberExpr(MemberExpr* M, NodeTy* Pred, NodeSet& Dst,bool asLValue);
+
+ /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, NodeTy* Pred, NodeSet& Dst,
+ bool asLValue);
+
+ /// VisitObjCForCollectionStmt - Transfer function logic for
+ /// ObjCForCollectionStmt.
+ void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, NodeTy* Pred,
+ NodeSet& Dst);
+
+ void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, NodeTy* Pred,
+ NodeSet& Dst, SVal ElementV);
+
+ /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
+ void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
+
+ void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
+ ObjCMessageExpr::arg_iterator I,
+ ObjCMessageExpr::arg_iterator E,
+ NodeTy* Pred, NodeSet& Dst);
+
+ void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, NodeTy* Pred,
+ NodeSet& Dst);
+
+ /// VisitReturnStmt - Transfer function logic for return statements.
+ void VisitReturnStmt(ReturnStmt* R, NodeTy* Pred, NodeSet& Dst);
+
+ /// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
+ void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, NodeTy* Pred,
+ NodeSet& Dst);
+
+ /// VisitUnaryOperator - Transfer function logic for unary operators.
+ void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst,
+ bool asLValue);
+
+ const GRState* CheckDivideZero(Expr* Ex, const GRState* St, NodeTy* Pred,
+ SVal Denom);
+
+ /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
+ /// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
+ /// with those assumptions.
+ void EvalEagerlyAssume(NodeSet& Dst, NodeSet& Src, Expr *Ex);
+
+ SVal EvalCast(SVal X, QualType CastT) {
+ if (X.isUnknownOrUndef())
+ return X;
+
+ if (isa<Loc>(X))
+ return getTF().EvalCast(*this, cast<Loc>(X), CastT);
+ else
+ return getTF().EvalCast(*this, cast<NonLoc>(X), CastT);
+ }
+
+ SVal EvalMinus(UnaryOperator* U, SVal X) {
+ return X.isValid() ? getTF().EvalMinus(*this, U, cast<NonLoc>(X)) : X;
+ }
+
+ SVal EvalComplement(SVal X) {
+ return X.isValid() ? getTF().EvalComplement(*this, cast<NonLoc>(X)) : X;
+ }
+
+public:
+
+ SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T) {
+ return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R, T)
+ : R;
+ }
+
+ SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R, QualType T) {
+ return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L,
+ cast<NonLoc>(R), T) : R;
+ }
+
+ void EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
+ BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
+ ExplodedNode<GRState>* Pred, QualType T);
+
+ void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex,
+ BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T);
+
+ SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op, SVal L,SVal R,
+ QualType T);
+
+protected:
+
+ void EvalCall(NodeSet& Dst, CallExpr* CE, SVal L, NodeTy* Pred);
+
+ void EvalObjCMessageExpr(NodeSet& Dst, ObjCMessageExpr* ME, NodeTy* Pred) {
+ assert (Builder && "GRStmtNodeBuilder must be defined.");
+ getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
+ }
+
+ void EvalReturn(NodeSet& Dst, ReturnStmt* s, NodeTy* Pred);
+
+ const GRState* MarkBranch(const GRState* St, Stmt* Terminator,
+ bool branchTaken);
+
+ /// EvalBind - Handle the semantics of binding a value to a specific location.
+ /// This method is used by EvalStore, VisitDeclStmt, and others.
+ void EvalBind(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
+ const GRState* St, SVal location, SVal Val);
+
+public:
+ void EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
+ const GRState* St, SVal location, const void *tag = 0);
+
+ NodeTy* EvalLocation(Stmt* Ex, NodeTy* Pred,
+ const GRState* St, SVal location,
+ const void *tag = 0);
+
+
+ void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, const GRState* St,
+ SVal TargetLV, SVal Val, const void *tag = 0);
+
+ void EvalStore(NodeSet& Dst, Expr* E, Expr* StoreE, NodeTy* Pred,
+ const GRState* St, SVal TargetLV, SVal Val,
+ const void *tag = 0);
+
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h b/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
new file mode 100644
index 000000000000..6c23745de23a
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
@@ -0,0 +1,101 @@
+//===-- GRExprEngineBuilders.h - "Builder" classes for GRExprEngine -*- C++ -*-=
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines smart builder "references" which are used to marshal
+// builders between GRExprEngine objects and their related components.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS
+#define LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+
+namespace clang {
+
+
+// SaveAndRestore - A utility class that uses RAII to save and restore
+// the value of a variable.
+template<typename T>
+struct SaveAndRestore {
+ SaveAndRestore(T& x) : X(x), old_value(x) {}
+ ~SaveAndRestore() { X = old_value; }
+ T get() { return old_value; }
+private:
+ T& X;
+ T old_value;
+};
+
+// SaveOr - Similar to SaveAndRestore. Operates only on bools; the old
+// value of a variable is saved, and during the dstor the old value is
+// or'ed with the new value.
+struct SaveOr {
+ SaveOr(bool& x) : X(x), old_value(x) { x = false; }
+ ~SaveOr() { X |= old_value; }
+private:
+ bool& X;
+ const bool old_value;
+};
+
+class GRStmtNodeBuilderRef {
+ GRExprEngine::NodeSet &Dst;
+ GRExprEngine::StmtNodeBuilder &B;
+ GRExprEngine& Eng;
+ GRExprEngine::NodeTy* Pred;
+ const GRState* state;
+ const Stmt* stmt;
+ const unsigned OldSize;
+ const bool AutoCreateNode;
+ SaveAndRestore<bool> OldSink;
+ SaveAndRestore<const void*> OldTag;
+ SaveOr OldHasGen;
+
+private:
+ friend class GRExprEngine;
+
+ GRStmtNodeBuilderRef(); // do not implement
+ void operator=(const GRStmtNodeBuilderRef&); // do not implement
+
+ GRStmtNodeBuilderRef(GRExprEngine::NodeSet &dst,
+ GRExprEngine::StmtNodeBuilder &builder,
+ GRExprEngine& eng,
+ GRExprEngine::NodeTy* pred,
+ const GRState *st,
+ const Stmt* s, bool auto_create_node)
+ : Dst(dst), B(builder), Eng(eng), Pred(pred),
+ state(st), stmt(s), OldSize(Dst.size()), AutoCreateNode(auto_create_node),
+ OldSink(B.BuildSinks), OldTag(B.Tag), OldHasGen(B.HasGeneratedNode) {}
+
+public:
+
+ ~GRStmtNodeBuilderRef() {
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+ if (!B.BuildSinks && Dst.size() == OldSize && !B.HasGeneratedNode) {
+ if (AutoCreateNode)
+ B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
+ else
+ Dst.Add(Pred);
+ }
+ }
+
+ GRStateRef getState() {
+ return GRStateRef(state, Eng.getStateManager());
+ }
+
+ GRStateManager& getStateManager() {
+ return Eng.getStateManager();
+ }
+
+ GRExprEngine::NodeTy* MakeNode(const GRState* state) {
+ return B.MakeNode(Dst, const_cast<Stmt*>(stmt), Pred, state);
+ }
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h b/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
new file mode 100644
index 000000000000..e54b31dfe883
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
@@ -0,0 +1,40 @@
+// GRCheckAPI.h - Simple API checks based on GRAuditor ------------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for building simple, path-sensitive checks
+// that are stateless and only emit warnings at errors that occur at
+// CallExpr or ObjCMessageExpr.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRAPICHECKS
+#define LLVM_CLANG_ANALYSIS_GRAPICHECKS
+
+#include "clang/Analysis/PathSensitive/GRAuditor.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+
+namespace clang {
+
+class Diagnostic;
+class BugReporter;
+class ASTContext;
+class GRExprEngine;
+class PathDiagnosticClient;
+template <typename T> class ExplodedGraph;
+
+
+class GRSimpleAPICheck : public GRAuditor<GRState> {
+public:
+ GRSimpleAPICheck() {}
+ virtual ~GRSimpleAPICheck() {}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
new file mode 100644
index 000000000000..d61feea4819e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -0,0 +1,820 @@
+//== GRState*h - Path-Sens. "State" for tracking valuues -----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines SymbolRef, ExprBindKey, and GRState*
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H
+#define LLVM_CLANG_ANALYSIS_VALUESTATE_H
+
+// FIXME: Reduce the number of includes.
+
+#include "clang/Analysis/PathSensitive/Environment.h"
+#include "clang/Analysis/PathSensitive/Store.h"
+#include "clang/Analysis/PathSensitive/ConstraintManager.h"
+#include "clang/Analysis/PathSensitive/ValueManager.h"
+#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Streams.h"
+
+#include <functional>
+
+namespace clang {
+
+class GRStateManager;
+class GRTransferFuncs;
+
+typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
+typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
+
+//===----------------------------------------------------------------------===//
+// GRStateTrait - Traits used by the Generic Data Map of a GRState.
+//===----------------------------------------------------------------------===//
+
+template <typename T> struct GRStatePartialTrait;
+
+template <typename T> struct GRStateTrait {
+ typedef typename T::data_type data_type;
+ static inline void* GDMIndex() { return &T::TagInt; }
+ static inline void* MakeVoidPtr(data_type D) { return (void*) D; }
+ static inline data_type MakeData(void* const* P) {
+ return P ? (data_type) *P : (data_type) 0;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to SVals.
+//===----------------------------------------------------------------------===//
+
+/// GRState - This class encapsulates the actual data values for
+/// for a "state" in our symbolic value tracking. It is intended to be
+/// used as a functional object; that is once it is created and made
+/// "persistent" in a FoldingSet its values will never change.
+class GRState : public llvm::FoldingSetNode {
+public:
+ // Typedefs.
+ typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
+ typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
+
+ typedef GRStateManager ManagerTy;
+
+private:
+ void operator=(const GRState& R) const;
+
+ friend class GRStateManager;
+
+ Environment Env;
+ Store St;
+
+ // FIXME: Make these private.
+public:
+ GenericDataMap GDM;
+
+public:
+
+ /// This ctor is used when creating the first GRState object.
+ GRState(const Environment& env, Store st, GenericDataMap gdm)
+ : Env(env),
+ St(st),
+ GDM(gdm) {}
+
+ /// Copy ctor - We must explicitly define this or else the "Next" ptr
+ /// in FoldingSetNode will also get copied.
+ GRState(const GRState& RHS)
+ : llvm::FoldingSetNode(),
+ Env(RHS.Env),
+ St(RHS.St),
+ GDM(RHS.GDM) {}
+
+ /// getEnvironment - Return the environment associated with this state.
+ /// The environment is the mapping from expressions to values.
+ const Environment& getEnvironment() const { return Env; }
+
+ /// getStore - Return the store associated with this state. The store
+ /// is a mapping from locations to values.
+ Store getStore() const { return St; }
+
+ /// getGDM - Return the generic data map associated with this state.
+ GenericDataMap getGDM() const { return GDM; }
+
+ /// Profile - Profile the contents of a GRState object for use
+ /// in a FoldingSet.
+ static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) {
+ V->Env.Profile(ID);
+ ID.AddPointer(V->St);
+ V->GDM.Profile(ID);
+ }
+
+ /// Profile - Used to profile the contents of this object for inclusion
+ /// in a FoldingSet.
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ Profile(ID, this);
+ }
+
+ SVal LookupExpr(Expr* E) const {
+ return Env.LookupExpr(E);
+ }
+
+ // Iterators.
+ typedef Environment::seb_iterator seb_iterator;
+ seb_iterator seb_begin() const { return Env.seb_begin(); }
+ seb_iterator seb_end() const { return Env.beb_end(); }
+
+ typedef Environment::beb_iterator beb_iterator;
+ beb_iterator beb_begin() const { return Env.beb_begin(); }
+ beb_iterator beb_end() const { return Env.beb_end(); }
+
+ // Trait based GDM dispatch.
+ void* const* FindGDM(void* K) const;
+
+ template <typename T>
+ typename GRStateTrait<T>::data_type
+ get() const {
+ return GRStateTrait<T>::MakeData(FindGDM(GRStateTrait<T>::GDMIndex()));
+ }
+
+ template<typename T>
+ typename GRStateTrait<T>::lookup_type
+ get(typename GRStateTrait<T>::key_type key) const {
+ void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
+ return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
+ }
+
+ template<typename T>
+ bool contains(typename GRStateTrait<T>::key_type key) const {
+ void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
+ return GRStateTrait<T>::Contains(GRStateTrait<T>::MakeData(d), key);
+ }
+
+ // State pretty-printing.
+ class Printer {
+ public:
+ virtual ~Printer() {}
+ virtual void Print(std::ostream& Out, const GRState* state,
+ const char* nl, const char* sep) = 0;
+ };
+
+ void print(std::ostream& Out, StoreManager& StoreMgr,
+ ConstraintManager& ConstraintMgr,
+ Printer **Beg = 0, Printer **End = 0,
+ const char* nl = "\n", const char *sep = "") const;
+
+ // Tags used for the Generic Data Map.
+ struct NullDerefTag {
+ static int TagInt;
+ typedef const SVal* data_type;
+ };
+};
+
+template<> struct GRTrait<GRState*> {
+ static inline void* toPtr(GRState* St) { return (void*) St; }
+ static inline GRState* toState(void* P) { return (GRState*) P; }
+ static inline void Profile(llvm::FoldingSetNodeID& profile, GRState* St) {
+ // At this point states have already been uniqued. Just
+ // add the pointer.
+ profile.AddPointer(St);
+ }
+};
+
+
+class GRStateSet {
+ typedef llvm::SmallPtrSet<const GRState*,5> ImplTy;
+ ImplTy Impl;
+public:
+ GRStateSet() {}
+
+ inline void Add(const GRState* St) {
+ Impl.insert(St);
+ }
+
+ typedef ImplTy::const_iterator iterator;
+
+ inline unsigned size() const { return Impl.size(); }
+ inline bool empty() const { return Impl.empty(); }
+
+ inline iterator begin() const { return Impl.begin(); }
+ inline iterator end() const { return Impl.end(); }
+
+ class AutoPopulate {
+ GRStateSet& S;
+ unsigned StartSize;
+ const GRState* St;
+ public:
+ AutoPopulate(GRStateSet& s, const GRState* st)
+ : S(s), StartSize(S.size()), St(st) {}
+
+ ~AutoPopulate() {
+ if (StartSize == S.size())
+ S.Add(St);
+ }
+ };
+};
+
+//===----------------------------------------------------------------------===//
+// GRStateManager - Factory object for GRStates.
+//===----------------------------------------------------------------------===//
+
+class GRStateRef;
+
+class GRStateManager {
+ friend class GRExprEngine;
+ friend class GRStateRef;
+
+private:
+ EnvironmentManager EnvMgr;
+ llvm::OwningPtr<StoreManager> StoreMgr;
+ llvm::OwningPtr<ConstraintManager> ConstraintMgr;
+ GRState::IntSetTy::Factory ISetFactory;
+
+ GRState::GenericDataMap::Factory GDMFactory;
+
+ typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
+ GDMContextsTy GDMContexts;
+
+ /// Printers - A set of printer objects used for pretty-printing a GRState.
+ /// GRStateManager owns these objects.
+ std::vector<GRState::Printer*> Printers;
+
+ /// StateSet - FoldingSet containing all the states created for analyzing
+ /// a particular function. This is used to unique states.
+ llvm::FoldingSet<GRState> StateSet;
+
+ /// ValueMgr - Object that manages the data for all created SVals.
+ ValueManager ValueMgr;
+
+ /// Alloc - A BumpPtrAllocator to allocate states.
+ llvm::BumpPtrAllocator& Alloc;
+
+ /// CurrentStmt - The block-level statement currently being visited. This
+ /// is set by GRExprEngine.
+ Stmt* CurrentStmt;
+
+ /// cfg - The CFG for the analyzed function/method.
+ CFG& cfg;
+
+ /// codedecl - The Decl representing the function/method being analyzed.
+ const Decl& codedecl;
+
+ /// TF - Object that represents a bundle of transfer functions
+ /// for manipulating and creating SVals.
+ GRTransferFuncs* TF;
+
+ /// Liveness - live-variables information of the ValueDecl* and block-level
+ /// Expr* in the CFG. Used to get initial store and prune out dead state.
+ LiveVariables& Liveness;
+
+private:
+
+ Environment RemoveBlkExpr(const Environment& Env, Expr* E) {
+ return EnvMgr.RemoveBlkExpr(Env, E);
+ }
+
+ // FIXME: Remove when we do lazy initializaton of variable bindings.
+// const GRState* BindVar(const GRState* St, VarDecl* D, SVal V) {
+// return SetSVal(St, getLoc(D), V);
+// }
+
+public:
+
+ GRStateManager(ASTContext& Ctx,
+ StoreManagerCreator CreateStoreManager,
+ ConstraintManagerCreator CreateConstraintManager,
+ llvm::BumpPtrAllocator& alloc, CFG& c,
+ const Decl& cd, LiveVariables& L)
+ : EnvMgr(alloc),
+ ISetFactory(alloc),
+ GDMFactory(alloc),
+ ValueMgr(alloc, Ctx),
+ Alloc(alloc),
+ cfg(c),
+ codedecl(cd),
+ Liveness(L) {
+ StoreMgr.reset((*CreateStoreManager)(*this));
+ ConstraintMgr.reset((*CreateConstraintManager)(*this));
+ }
+
+ ~GRStateManager();
+
+ const GRState* getInitialState();
+
+ ASTContext &getContext() { return ValueMgr.getContext(); }
+ const ASTContext &getContext() const { return ValueMgr.getContext(); }
+
+ const Decl &getCodeDecl() { return codedecl; }
+ GRTransferFuncs& getTransferFuncs() { return *TF; }
+
+ BasicValueFactory &getBasicVals() {
+ return ValueMgr.getBasicValueFactory();
+ }
+ const BasicValueFactory& getBasicVals() const {
+ return ValueMgr.getBasicValueFactory();
+ }
+
+ SymbolManager &getSymbolManager() {
+ return ValueMgr.getSymbolManager();
+ }
+ const SymbolManager &getSymbolManager() const {
+ return ValueMgr.getSymbolManager();
+ }
+
+ ValueManager &getValueManager() { return ValueMgr; }
+ const ValueManager &getValueManager() const { return ValueMgr; }
+
+ LiveVariables& getLiveVariables() { return Liveness; }
+ llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
+
+ MemRegionManager& getRegionManager() {
+ return ValueMgr.getRegionManager();
+ }
+ const MemRegionManager& getRegionManager() const {
+ return ValueMgr.getRegionManager();
+ }
+
+ StoreManager& getStoreManager() { return *StoreMgr; }
+ ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
+
+ const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal IVal) {
+ // Store manager should return a persistent state.
+ return StoreMgr->BindDecl(St, VD, IVal);
+ }
+
+ const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
+ // Store manager should return a persistent state.
+ return StoreMgr->BindDeclWithNoInit(St, VD);
+ }
+
+ /// BindCompoundLiteral - Return the state that has the bindings currently
+ /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
+ /// for the compound literal and 'BegInit' and 'EndInit' represent an
+ /// array of initializer values.
+ const GRState* BindCompoundLiteral(const GRState* St,
+ const CompoundLiteralExpr* CL, SVal V) {
+ return StoreMgr->BindCompoundLiteral(St, CL, V);
+ }
+
+ const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
+ SymbolReaper& SymReaper);
+
+ const GRState* RemoveSubExprBindings(const GRState* St) {
+ GRState NewSt = *St;
+ NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
+ return getPersistentState(NewSt);
+ }
+
+
+ // Utility methods for getting regions.
+
+ VarRegion* getRegion(const VarDecl* D) {
+ return getRegionManager().getVarRegion(D);
+ }
+
+ const MemRegion* getSelfRegion(const GRState* state) {
+ return StoreMgr->getSelfRegion(state->getStore());
+ }
+
+ // Get the lvalue for a variable reference.
+ SVal GetLValue(const GRState* St, const VarDecl* D) {
+ return StoreMgr->getLValueVar(St, D);
+ }
+
+ // Get the lvalue for a StringLiteral.
+ SVal GetLValue(const GRState* St, const StringLiteral* E) {
+ return StoreMgr->getLValueString(St, E);
+ }
+
+ SVal GetLValue(const GRState* St, const CompoundLiteralExpr* CL) {
+ return StoreMgr->getLValueCompoundLiteral(St, CL);
+ }
+
+ // Get the lvalue for an ivar reference.
+ SVal GetLValue(const GRState* St, const ObjCIvarDecl* D, SVal Base) {
+ return StoreMgr->getLValueIvar(St, D, Base);
+ }
+
+ // Get the lvalue for a field reference.
+ SVal GetLValue(const GRState* St, SVal Base, const FieldDecl* D) {
+ return StoreMgr->getLValueField(St, Base, D);
+ }
+
+ // Get the lvalue for an array index.
+ SVal GetLValue(const GRState* St, QualType ElementType, SVal Base, SVal Idx) {
+ return StoreMgr->getLValueElement(St, ElementType, Base, Idx);
+ }
+
+ // Methods that query & manipulate the Environment.
+
+ SVal GetSVal(const GRState* St, Stmt* Ex) {
+ return St->getEnvironment().GetSVal(Ex, getBasicVals());
+ }
+
+ SVal GetSValAsScalarOrLoc(const GRState* state, const Stmt *S) {
+ if (const Expr *Ex = dyn_cast<Expr>(S)) {
+ QualType T = Ex->getType();
+ if (Loc::IsLocType(T) || T->isIntegerType())
+ return GetSVal(state, S);
+ }
+
+ return UnknownVal();
+ }
+
+
+ SVal GetSVal(const GRState* St, const Stmt* Ex) {
+ return St->getEnvironment().GetSVal(const_cast<Stmt*>(Ex), getBasicVals());
+ }
+
+ SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
+ return St->getEnvironment().GetBlkExprSVal(Ex, getBasicVals());
+ }
+
+
+
+ const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
+ bool isBlkExpr, bool Invalidate) {
+
+ const Environment& OldEnv = St->getEnvironment();
+ Environment NewEnv = EnvMgr.BindExpr(OldEnv, Ex, V, isBlkExpr, Invalidate);
+
+ if (NewEnv == OldEnv)
+ return St;
+
+ GRState NewSt = *St;
+ NewSt.Env = NewEnv;
+ return getPersistentState(NewSt);
+ }
+
+ const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
+ bool Invalidate = true) {
+
+ bool isBlkExpr = false;
+
+ if (Ex == CurrentStmt) {
+ // FIXME: Should this just be an assertion? When would we want to set
+ // the value of a block-level expression if it wasn't CurrentStmt?
+ isBlkExpr = cfg.isBlkExpr(Ex);
+
+ if (!isBlkExpr)
+ return St;
+ }
+
+ return BindExpr(St, Ex, V, isBlkExpr, Invalidate);
+ }
+
+ SVal ArrayToPointer(Loc Array) {
+ return StoreMgr->ArrayToPointer(Array);
+ }
+
+ // Methods that manipulate the GDM.
+ const GRState* addGDM(const GRState* St, void* Key, void* Data);
+
+ // Methods that query or create regions.
+ bool hasStackStorage(const MemRegion* R) {
+ return getRegionManager().hasStackStorage(R);
+ }
+
+ // Methods that query & manipulate the Store.
+
+ void iterBindings(const GRState* state, StoreManager::BindingsHandler& F) {
+ StoreMgr->iterBindings(state->getStore(), F);
+ }
+
+
+ SVal GetSVal(const GRState* state, Loc LV, QualType T = QualType()) {
+ return StoreMgr->Retrieve(state, LV, T);
+ }
+
+ SVal GetSVal(const GRState* state, const MemRegion* R) {
+ return StoreMgr->Retrieve(state, loc::MemRegionVal(R));
+ }
+
+ SVal GetSValAsScalarOrLoc(const GRState* state, const MemRegion *R) {
+ // We only want to do fetches from regions that we can actually bind
+ // values. For example, SymbolicRegions of type 'id<...>' cannot
+ // have direct bindings (but their can be bindings on their subregions).
+ if (!R->isBoundable(getContext()))
+ return UnknownVal();
+
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
+ QualType T = TR->getValueType(getContext());
+ if (Loc::IsLocType(T) || T->isIntegerType())
+ return GetSVal(state, R);
+ }
+
+ return UnknownVal();
+ }
+
+ const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
+ return StoreMgr->Bind(St, LV, V);
+ }
+
+ void Unbind(GRState& St, Loc LV) {
+ St.St = StoreMgr->Remove(St.St, LV);
+ }
+
+ const GRState* Unbind(const GRState* St, Loc LV);
+
+ const GRState* getPersistentState(GRState& Impl);
+
+ // MakeStateWithStore - get a persistent state with the new store.
+ const GRState* MakeStateWithStore(const GRState* St, Store store);
+
+ bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
+ bool isEqual(const GRState* state, Expr* Ex, uint64_t);
+
+
+ //==---------------------------------------------------------------------==//
+ // Generic Data Map methods.
+ //==---------------------------------------------------------------------==//
+ //
+ // GRStateManager and GRState support a "generic data map" that allows
+ // different clients of GRState objects to embed arbitrary data within a
+ // GRState object. The generic data map is essentially an immutable map
+ // from a "tag" (that acts as the "key" for a client) and opaque values.
+ // Tags/keys and values are simply void* values. The typical way that clients
+ // generate unique tags are by taking the address of a static variable.
+ // Clients are responsible for ensuring that data values referred to by a
+ // the data pointer are immutable (and thus are essentially purely functional
+ // data).
+ //
+ // The templated methods below use the GRStateTrait<T> class
+ // to resolve keys into the GDM and to return data values to clients.
+ //
+
+ // Trait based GDM dispatch.
+ template <typename T>
+ const GRState* set(const GRState* st, typename GRStateTrait<T>::data_type D) {
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(D));
+ }
+
+ template<typename T>
+ const GRState* set(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type V,
+ typename GRStateTrait<T>::context_type C) {
+
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C)));
+ }
+
+ template <typename T>
+ const GRState* add(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Add(st->get<T>(), K, C)));
+ }
+
+ template <typename T>
+ const GRState* remove(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));
+ }
+
+
+ void* FindGDMContext(void* index,
+ void* (*CreateContext)(llvm::BumpPtrAllocator&),
+ void (*DeleteContext)(void*));
+
+ template <typename T>
+ typename GRStateTrait<T>::context_type get_context() {
+ void* p = FindGDMContext(GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::CreateContext,
+ GRStateTrait<T>::DeleteContext);
+
+ return GRStateTrait<T>::MakeContext(p);
+ }
+
+ //==---------------------------------------------------------------------==//
+ // Constraints on values.
+ //==---------------------------------------------------------------------==//
+ //
+ // Each GRState records constraints on symbolic values. These constraints
+ // are managed using the ConstraintManager associated with a GRStateManager.
+ // As constraints gradually accrue on symbolic values, added constraints
+ // may conflict and indicate that a state is infeasible (as no real values
+ // could satisfy all the constraints). This is the principal mechanism
+ // for modeling path-sensitivity in GRExprEngine/GRState.
+ //
+ // Various "Assume" methods form the interface for adding constraints to
+ // symbolic values. A call to "Assume" indicates an assumption being placed
+ // on one or symbolic values. Assume methods take the following inputs:
+ //
+ // (1) A GRState object representing the current state.
+ //
+ // (2) The assumed constraint (which is specific to a given "Assume" method).
+ //
+ // (3) A binary value "Assumption" that indicates whether the constraint is
+ // assumed to be true or false.
+ //
+ // The output of "Assume" are two values:
+ //
+ // (a) "isFeasible" is set to true or false to indicate whether or not
+ // the assumption is feasible.
+ //
+ // (b) A new GRState object with the added constraints.
+ //
+ // FIXME: (a) should probably disappear since it is redundant with (b).
+ // (i.e., (b) could just be set to NULL).
+ //
+
+ const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
+ bool& isFeasible) {
+ const GRState *state =
+ ConstraintMgr->Assume(St, Cond, Assumption, isFeasible);
+ assert(!isFeasible || state);
+ return isFeasible ? state : NULL;
+ }
+
+ const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
+ bool Assumption, bool& isFeasible) {
+ const GRState *state =
+ ConstraintMgr->AssumeInBound(St, Idx, UpperBound, Assumption,
+ isFeasible);
+ assert(!isFeasible || state);
+ return isFeasible ? state : NULL;
+ }
+
+ const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) {
+ return ConstraintMgr->getSymVal(St, sym);
+ }
+
+ void EndPath(const GRState* St) {
+ ConstraintMgr->EndPath(St);
+ }
+
+ bool scanReachableSymbols(SVal val, const GRState* state,
+ SymbolVisitor& visitor);
+};
+
+//===----------------------------------------------------------------------===//
+// GRStateRef - A "fat" reference to GRState that also bundles GRStateManager.
+//===----------------------------------------------------------------------===//
+
+class GRStateRef {
+ const GRState* St;
+ GRStateManager* Mgr;
+public:
+ GRStateRef(const GRState* st, GRStateManager& mgr) : St(st), Mgr(&mgr) {}
+
+ const GRState* getState() const { return St; }
+ operator const GRState*() const { return St; }
+ GRStateManager& getManager() const { return *Mgr; }
+
+ SVal GetSVal(Expr* Ex) {
+ return Mgr->GetSVal(St, Ex);
+ }
+
+ SVal GetBlkExprSVal(Expr* Ex) {
+ return Mgr->GetBlkExprSVal(St, Ex);
+ }
+
+ SVal GetSValAsScalarOrLoc(const Expr *Ex) {
+ return Mgr->GetSValAsScalarOrLoc(St, Ex);
+ }
+
+ SVal GetSVal(Loc LV, QualType T = QualType()) {
+ return Mgr->GetSVal(St, LV, T);
+ }
+
+ SVal GetSVal(const MemRegion* R) {
+ return Mgr->GetSVal(St, R);
+ }
+
+ SVal GetSValAsScalarOrLoc(const MemRegion *R) {
+ return Mgr->GetSValAsScalarOrLoc(St, R);
+ }
+
+ GRStateRef BindExpr(Stmt* Ex, SVal V, bool isBlkExpr, bool Invalidate) {
+ return GRStateRef(Mgr->BindExpr(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
+ }
+
+ GRStateRef BindExpr(Stmt* Ex, SVal V, bool Invalidate = true) {
+ return GRStateRef(Mgr->BindExpr(St, Ex, V, Invalidate), *Mgr);
+ }
+
+ GRStateRef BindDecl(const VarDecl* VD, SVal InitVal) {
+ return GRStateRef(Mgr->BindDecl(St, VD, InitVal), *Mgr);
+ }
+
+ GRStateRef BindLoc(Loc LV, SVal V) {
+ return GRStateRef(Mgr->BindLoc(St, LV, V), *Mgr);
+ }
+
+ GRStateRef BindLoc(SVal LV, SVal V) {
+ if (!isa<Loc>(LV)) return *this;
+ return BindLoc(cast<Loc>(LV), V);
+ }
+
+ GRStateRef Unbind(Loc LV) {
+ return GRStateRef(Mgr->Unbind(St, LV), *Mgr);
+ }
+
+ // Trait based GDM dispatch.
+ template<typename T>
+ typename GRStateTrait<T>::data_type get() const {
+ return St->get<T>();
+ }
+
+ template<typename T>
+ typename GRStateTrait<T>::lookup_type
+ get(typename GRStateTrait<T>::key_type key) const {
+ return St->get<T>(key);
+ }
+
+ template<typename T>
+ GRStateRef set(typename GRStateTrait<T>::data_type D) {
+ return GRStateRef(Mgr->set<T>(St, D), *Mgr);
+ }
+
+ template <typename T>
+ typename GRStateTrait<T>::context_type get_context() {
+ return Mgr->get_context<T>();
+ }
+
+ template<typename T>
+ GRStateRef set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E,
+ typename GRStateTrait<T>::context_type C) {
+ return GRStateRef(Mgr->set<T>(St, K, E, C), *Mgr);
+ }
+
+ template<typename T>
+ GRStateRef set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E) {
+ return GRStateRef(Mgr->set<T>(St, K, E, get_context<T>()), *Mgr);
+ }
+
+ template<typename T>
+ GRStateRef add(typename GRStateTrait<T>::key_type K) {
+ return GRStateRef(Mgr->add<T>(St, K, get_context<T>()), *Mgr);
+ }
+
+ template<typename T>
+ GRStateRef remove(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+ return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
+ }
+
+ template<typename T>
+ GRStateRef remove(typename GRStateTrait<T>::key_type K) {
+ return GRStateRef(Mgr->remove<T>(St, K, get_context<T>()), *Mgr);
+ }
+
+ template<typename T>
+ bool contains(typename GRStateTrait<T>::key_type key) const {
+ return St->contains<T>(key);
+ }
+
+ // Lvalue methods.
+ SVal GetLValue(const VarDecl* VD) {
+ return Mgr->GetLValue(St, VD);
+ }
+
+ GRStateRef Assume(SVal Cond, bool Assumption, bool& isFeasible) {
+ return GRStateRef(Mgr->Assume(St, Cond, Assumption, isFeasible), *Mgr);
+ }
+
+ template <typename CB>
+ CB scanReachableSymbols(SVal val) {
+ CB cb(*this);
+ Mgr->scanReachableSymbols(val, St, cb);
+ return cb;
+ }
+
+ SymbolManager& getSymbolManager() { return Mgr->getSymbolManager(); }
+ BasicValueFactory& getBasicVals() { return Mgr->getBasicVals(); }
+
+ // Pretty-printing.
+ void print(std::ostream& Out, const char* nl = "\n",
+ const char *sep = "") const;
+
+ void printStdErr() const;
+
+ void printDOT(std::ostream& Out) const;
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRStateTrait.h b/include/clang/Analysis/PathSensitive/GRStateTrait.h
new file mode 100644
index 000000000000..ce43cda31e9e
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRStateTrait.h
@@ -0,0 +1,148 @@
+//==- GRStateTrait.h - Partial implementations of GRStateTrait -----*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines partial implementations of template specializations of
+// the class GRStateTrait<>. GRStateTrait<> is used by GRState to implement
+// set/get methods for mapulating a GRState's generic data map.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H
+#define LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H
+
+namespace llvm {
+ class BumpPtrAllocator;
+ template <typename K, typename D, typename I> class ImmutableMap;
+ template <typename K, typename I> class ImmutableSet;
+ template <typename T> class ImmutableList;
+ template <typename T> class ImmutableListImpl;
+}
+
+namespace clang {
+ template <typename T> struct GRStatePartialTrait;
+
+ // Partial-specialization for ImmutableMap.
+
+ template <typename Key, typename Data, typename Info>
+ struct GRStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
+ typedef llvm::ImmutableMap<Key,Data,Info> data_type;
+ typedef typename data_type::Factory& context_type;
+ typedef Key key_type;
+ typedef Data value_type;
+ typedef const value_type* lookup_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
+ }
+ static inline void* MakeVoidPtr(data_type B) {
+ return B.getRoot();
+ }
+ static lookup_type Lookup(data_type B, key_type K) {
+ return B.lookup(K);
+ }
+ static data_type Set(data_type B, key_type K, value_type E,context_type F){
+ return F.Add(B, K, E);
+ }
+
+ static data_type Remove(data_type B, key_type K, context_type F) {
+ return F.Remove(B, K);
+ }
+
+ static inline context_type MakeContext(void* p) {
+ return *((typename data_type::Factory*) p);
+ }
+
+ static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ return new typename data_type::Factory(Alloc);
+ }
+
+ static void DeleteContext(void* Ctx) {
+ delete (typename data_type::Factory*) Ctx;
+ }
+ };
+
+
+ // Partial-specialization for ImmutableSet.
+
+ template <typename Key, typename Info>
+ struct GRStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
+ typedef llvm::ImmutableSet<Key,Info> data_type;
+ typedef typename data_type::Factory& context_type;
+ typedef Key key_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
+ }
+
+ static inline void* MakeVoidPtr(data_type B) {
+ return B.getRoot();
+ }
+
+ static data_type Add(data_type B, key_type K, context_type F) {
+ return F.Add(B, K);
+ }
+
+ static data_type Remove(data_type B, key_type K, context_type F) {
+ return F.Remove(B, K);
+ }
+
+ static bool Contains(data_type B, key_type K) {
+ return B.contains(K);
+ }
+
+ static inline context_type MakeContext(void* p) {
+ return *((typename data_type::Factory*) p);
+ }
+
+ static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ return new typename data_type::Factory(Alloc);
+ }
+
+ static void DeleteContext(void* Ctx) {
+ delete (typename data_type::Factory*) Ctx;
+ }
+ };
+
+ // Partial-specialization for ImmutableList.
+
+ template <typename T>
+ struct GRStatePartialTrait< llvm::ImmutableList<T> > {
+ typedef llvm::ImmutableList<T> data_type;
+ typedef T key_type;
+ typedef typename data_type::Factory& context_type;
+
+ static data_type Add(data_type L, key_type K, context_type F) {
+ return F.Add(K, L);
+ }
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
+ : data_type(0);
+ }
+
+ static inline void* MakeVoidPtr(data_type D) {
+ return (void*) D.getInternalPointer();
+ }
+
+ static inline context_type MakeContext(void* p) {
+ return *((typename data_type::Factory*) p);
+ }
+
+ static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+ return new typename data_type::Factory(Alloc);
+ }
+
+ static void DeleteContext(void* Ctx) {
+ delete (typename data_type::Factory*) Ctx;
+ }
+ };
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
new file mode 100644
index 000000000000..0f353d07004f
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
@@ -0,0 +1,123 @@
+//== GRTransferFuncs.h - Path-Sens. Transfer Functions Interface -*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines GRTransferFuncs, which provides a base-class that
+// defines an interface for transfer functions used by GRExprEngine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRTF
+#define LLVM_CLANG_ANALYSIS_GRTF
+
+#include "clang/Analysis/PathSensitive/SVals.h"
+#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+#include <vector>
+
+namespace clang {
+
+ class GRExprEngine;
+ class BugReporter;
+ class ObjCMessageExpr;
+ class GRStmtNodeBuilderRef;
+
+class GRTransferFuncs {
+ friend class GRExprEngine;
+protected:
+ virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng,
+ BinaryOperator::Opcode Op,
+ NonLoc L, NonLoc R, QualType T) {
+ return UnknownVal();
+ }
+
+public:
+ GRTransferFuncs() {}
+ virtual ~GRTransferFuncs() {}
+
+ virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
+ virtual void RegisterChecks(BugReporter& BR) {}
+
+ // Casts.
+
+ virtual SVal EvalCast(GRExprEngine& Engine, NonLoc V, QualType CastT) =0;
+ virtual SVal EvalCast(GRExprEngine& Engine, Loc V, QualType CastT) = 0;
+
+ // Unary Operators.
+
+ virtual SVal EvalMinus(GRExprEngine& Engine, UnaryOperator* U, NonLoc X) = 0;
+
+ virtual SVal EvalComplement(GRExprEngine& Engine, NonLoc X) = 0;
+
+ // Binary Operators.
+ // FIXME: We're moving back towards using GREXprEngine directly. No need
+ // for OStates
+ virtual void EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng,
+ const GRState* St, Expr* Ex,
+ BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
+ QualType T);
+
+ virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
+ Loc L, Loc R) = 0;
+
+ // Pointer arithmetic.
+
+ virtual SVal EvalBinOp(GRExprEngine& Engine, const GRState *state,
+ BinaryOperator::Opcode Op, Loc L, NonLoc R) = 0;
+
+ // Calls.
+
+ virtual void EvalCall(ExplodedNodeSet<GRState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<GRState>& Builder,
+ CallExpr* CE, SVal L,
+ ExplodedNode<GRState>* Pred) {}
+
+ virtual void EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<GRState>& Builder,
+ ObjCMessageExpr* ME,
+ ExplodedNode<GRState>* Pred) {}
+
+ // Stores.
+
+ virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {}
+
+ // End-of-path and dead symbol notification.
+
+ virtual void EvalEndPath(GRExprEngine& Engine,
+ GREndPathNodeBuilder<GRState>& Builder) {}
+
+
+ virtual void EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<GRState>& Builder,
+ ExplodedNode<GRState>* Pred,
+ Stmt* S, const GRState* state,
+ SymbolReaper& SymReaper) {}
+
+ // Return statements.
+ virtual void EvalReturn(ExplodedNodeSet<GRState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<GRState>& Builder,
+ ReturnStmt* S,
+ ExplodedNode<GRState>* Pred) {}
+
+ // Assumptions.
+
+ virtual const GRState* EvalAssume(GRStateManager& VMgr,
+ const GRState* St,
+ SVal Cond, bool Assumption,
+ bool& isFeasible) {
+ return St;
+ }
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Analysis/PathSensitive/GRWorkList.h
new file mode 100644
index 000000000000..c76532294c1f
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/GRWorkList.h
@@ -0,0 +1,76 @@
+//==- GRWorkList.h - Worklist class used by GRCoreEngine -----------*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines GRWorkList, a pure virtual class that represents an opaque
+// worklist used by GRCoreEngine to explore the reachability state space.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST
+#define LLVM_CLANG_ANALYSIS_GRWORKLIST
+
+#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
+
+namespace clang {
+
+class ExplodedNodeImpl;
+
+class GRWorkListUnit {
+ ExplodedNodeImpl* Node;
+ GRBlockCounter Counter;
+ CFGBlock* Block;
+ unsigned BlockIdx;
+
+public:
+ GRWorkListUnit(ExplodedNodeImpl* N, GRBlockCounter C,
+ CFGBlock* B, unsigned idx)
+ : Node(N),
+ Counter(C),
+ Block(B),
+ BlockIdx(idx) {}
+
+ explicit GRWorkListUnit(ExplodedNodeImpl* N, GRBlockCounter C)
+ : Node(N),
+ Counter(C),
+ Block(NULL),
+ BlockIdx(0) {}
+
+ ExplodedNodeImpl* getNode() const { return Node; }
+ GRBlockCounter getBlockCounter() const { return Counter; }
+ CFGBlock* getBlock() const { return Block; }
+ unsigned getIndex() const { return BlockIdx; }
+};
+
+class GRWorkList {
+ GRBlockCounter CurrentCounter;
+public:
+ virtual ~GRWorkList();
+ virtual bool hasWork() const = 0;
+
+ virtual void Enqueue(const GRWorkListUnit& U) = 0;
+
+ void Enqueue(ExplodedNodeImpl* N, CFGBlock& B, unsigned idx) {
+ Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx));
+ }
+
+ void Enqueue(ExplodedNodeImpl* N) {
+ Enqueue(GRWorkListUnit(N, CurrentCounter));
+ }
+
+ virtual GRWorkListUnit Dequeue() = 0;
+
+ void setBlockCounter(GRBlockCounter C) { CurrentCounter = C; }
+ GRBlockCounter getBlockCounter() const { return CurrentCounter; }
+
+ static GRWorkList *MakeDFS();
+ static GRWorkList *MakeBFS();
+ static GRWorkList *MakeBFSBlockDFSContents();
+};
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
new file mode 100644
index 000000000000..0e8da2aee318
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -0,0 +1,665 @@
+//== MemRegion.h - Abstract memory regions for static analysis --*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines MemRegion and its subclasses. MemRegion defines a
+// partially-typed abstraction of memory useful for path-sensitive dataflow
+// analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_MEMREGION_H
+#define LLVM_CLANG_ANALYSIS_MEMREGION_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+#include "clang/Analysis/PathSensitive/SVals.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/Support/Allocator.h"
+#include <string>
+
+namespace llvm { class raw_ostream; }
+
+namespace clang {
+
+class MemRegionManager;
+
+
+/// MemRegion - The root abstract class for all memory regions.
+class MemRegion : public llvm::FoldingSetNode {
+public:
+ enum Kind { MemSpaceRegionKind,
+ SymbolicRegionKind,
+ AllocaRegionKind,
+ // Typed regions.
+ BEG_TYPED_REGIONS,
+ CodeTextRegionKind,
+ CompoundLiteralRegionKind,
+ StringRegionKind, ElementRegionKind,
+ TypedViewRegionKind,
+ // Decl Regions.
+ BEG_DECL_REGIONS,
+ VarRegionKind, FieldRegionKind,
+ ObjCIvarRegionKind, ObjCObjectRegionKind,
+ END_DECL_REGIONS,
+ END_TYPED_REGIONS };
+private:
+ const Kind kind;
+
+protected:
+ MemRegion(Kind k) : kind(k) {}
+ virtual ~MemRegion();
+
+public:
+ // virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
+ virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
+
+ std::string getString() const;
+
+ virtual void print(llvm::raw_ostream& os) const;
+
+ Kind getKind() const { return kind; }
+
+ template<typename RegionTy> const RegionTy* getAs() const;
+
+ virtual bool isBoundable(ASTContext&) const { return true; }
+
+ static bool classof(const MemRegion*) { return true; }
+};
+
+/// MemSpaceRegion - A memory region that represents and "memory space";
+/// for example, the set of global variables, the stack frame, etc.
+class MemSpaceRegion : public MemRegion {
+ friend class MemRegionManager;
+ MemSpaceRegion() : MemRegion(MemSpaceRegionKind) {}
+
+public:
+ //RegionExtent getExtent() const { return UndefinedExtent(); }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ bool isBoundable(ASTContext &) const { return false; }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == MemSpaceRegionKind;
+ }
+};
+
+/// SubRegion - A region that subsets another larger region. Most regions
+/// are subclasses of SubRegion.
+class SubRegion : public MemRegion {
+protected:
+ const MemRegion* superRegion;
+ SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
+
+public:
+ const MemRegion* getSuperRegion() const {
+ return superRegion;
+ }
+
+ bool isSubRegionOf(const MemRegion* R) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() > MemSpaceRegionKind;
+ }
+};
+
+/// AllocaRegion - A region that represents an untyped blob of bytes created
+/// by a call to 'alloca'.
+class AllocaRegion : public SubRegion {
+ friend class MemRegionManager;
+protected:
+ unsigned Cnt; // Block counter. Used to distinguish different pieces of
+ // memory allocated by alloca at the same call site.
+ const Expr* Ex;
+
+ AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion* superRegion)
+ : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
+
+public:
+
+ const Expr* getExpr() const { return Ex; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex,
+ unsigned Cnt);
+
+ void print(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == AllocaRegionKind;
+ }
+};
+
+/// TypedRegion - An abstract class representing regions that are typed.
+class TypedRegion : public SubRegion {
+protected:
+ TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
+
+public:
+ virtual QualType getValueType(ASTContext &C) const = 0;
+
+ virtual QualType getLocationType(ASTContext& C) const {
+ // FIXME: We can possibly optimize this later to cache this value.
+ return C.getPointerType(getValueType(C));
+ }
+
+ QualType getDesugaredValueType(ASTContext& C) const {
+ QualType T = getValueType(C);
+ return T.getTypePtr() ? T->getDesugaredType() : T;
+ }
+
+ QualType getDesugaredLocationType(ASTContext& C) const {
+ return getLocationType(C)->getDesugaredType();
+ }
+
+ bool isBoundable(ASTContext &C) const {
+ return !getValueType(C).isNull();
+ }
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
+ }
+};
+
+/// CodeTextRegion - A region that represents code texts of a function. It wraps
+/// two kinds of code texts: real function and symbolic function. Real function
+/// is a function declared in the program. Symbolic function is a function
+/// pointer that we don't know which function it points to.
+class CodeTextRegion : public TypedRegion {
+public:
+ enum CodeKind { Declared, Symbolic };
+
+private:
+ // The function pointer kind that this CodeTextRegion represents.
+ CodeKind codekind;
+
+ // Data may be a SymbolRef or FunctionDecl*.
+ const void* Data;
+
+ // Cached function pointer type.
+ QualType LocationType;
+
+public:
+
+ CodeTextRegion(const FunctionDecl* fd, QualType t, const MemRegion* sreg)
+ : TypedRegion(sreg, CodeTextRegionKind),
+ codekind(Declared),
+ Data(fd),
+ LocationType(t) {}
+
+ CodeTextRegion(SymbolRef sym, QualType t, const MemRegion* sreg)
+ : TypedRegion(sreg, CodeTextRegionKind),
+ codekind(Symbolic),
+ Data(sym),
+ LocationType(t) {}
+
+ QualType getValueType(ASTContext &C) const {
+ // Do not get the object type of a CodeTextRegion.
+ assert(0);
+ return QualType();
+ }
+
+ QualType getLocationType(ASTContext &C) const {
+ return LocationType;
+ }
+
+ bool isDeclared() const { return codekind == Declared; }
+ bool isSymbolic() const { return codekind == Symbolic; }
+
+ const FunctionDecl* getDecl() const {
+ assert(codekind == Declared);
+ return static_cast<const FunctionDecl*>(Data);
+ }
+
+ SymbolRef getSymbol() const {
+ assert(codekind == Symbolic);
+ return const_cast<SymbolRef>(static_cast<const SymbolRef>(Data));
+ }
+
+ bool isBoundable(ASTContext&) const { return false; }
+
+ virtual void print(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const void* data, QualType t);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CodeTextRegionKind;
+ }
+};
+
+/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
+/// clases, SymbolicRegion represents a region that serves as an alias for
+/// either a real region, a NULL pointer, etc. It essentially is used to
+/// map the concept of symbolic values into the domain of regions. Symbolic
+/// regions do not need to be typed.
+class SymbolicRegion : public SubRegion {
+protected:
+ const SymbolRef sym;
+
+public:
+ SymbolicRegion(const SymbolRef s, const MemRegion* sreg)
+ : SubRegion(sreg, SymbolicRegionKind), sym(s) {}
+
+ SymbolRef getSymbol() const {
+ return sym;
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym);
+
+ void print(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == SymbolicRegionKind;
+ }
+};
+
+/// StringRegion - Region associated with a StringLiteral.
+class StringRegion : public TypedRegion {
+ friend class MemRegionManager;
+ const StringLiteral* Str;
+protected:
+
+ StringRegion(const StringLiteral* str, MemRegion* sreg)
+ : TypedRegion(sreg, StringRegionKind), Str(str) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const StringLiteral* Str,
+ const MemRegion* superRegion);
+
+public:
+
+ const StringLiteral* getStringLiteral() const { return Str; }
+
+ QualType getValueType(ASTContext& C) const {
+ return Str->getType();
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ProfileRegion(ID, Str, superRegion);
+ }
+
+ void print(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == StringRegionKind;
+ }
+};
+
+class TypedViewRegion : public TypedRegion {
+ friend class MemRegionManager;
+ QualType LValueType;
+
+ TypedViewRegion(QualType lvalueType, const MemRegion* sreg)
+ : TypedRegion(sreg, TypedViewRegionKind), LValueType(lvalueType) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
+ const MemRegion* superRegion);
+
+public:
+
+ void print(llvm::raw_ostream& os) const;
+
+ QualType getLocationType(ASTContext&) const {
+ return LValueType;
+ }
+
+ QualType getValueType(ASTContext&) const {
+ const PointerType* PTy = LValueType->getAsPointerType();
+ assert(PTy);
+ return PTy->getPointeeType();
+ }
+
+ bool isBoundable(ASTContext &C) const {
+ return isa<PointerType>(LValueType);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ProfileRegion(ID, LValueType, superRegion);
+ }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == TypedViewRegionKind;
+ }
+
+ const MemRegion *removeViews() const;
+};
+
+
+/// CompoundLiteralRegion - A memory region representing a compound literal.
+/// Compound literals are essentially temporaries that are stack allocated
+/// or in the global constant pool.
+class CompoundLiteralRegion : public TypedRegion {
+private:
+ friend class MemRegionManager;
+ const CompoundLiteralExpr* CL;
+
+ CompoundLiteralRegion(const CompoundLiteralExpr* cl, const MemRegion* sReg)
+ : TypedRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const CompoundLiteralExpr* CL,
+ const MemRegion* superRegion);
+public:
+ QualType getValueType(ASTContext& C) const {
+ return C.getCanonicalType(CL->getType());
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ void print(llvm::raw_ostream& os) const;
+
+ const CompoundLiteralExpr* getLiteralExpr() const { return CL; }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CompoundLiteralRegionKind;
+ }
+};
+
+class DeclRegion : public TypedRegion {
+protected:
+ const Decl* D;
+
+ DeclRegion(const Decl* d, const MemRegion* sReg, Kind k)
+ : TypedRegion(sReg, k), D(d) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
+ const MemRegion* superRegion, Kind k);
+
+public:
+ const Decl* getDecl() const { return D; }
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS;
+ }
+};
+
+class VarRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ VarRegion(const VarDecl* vd, const MemRegion* sReg)
+ : DeclRegion(vd, sReg, VarRegionKind) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, VarDecl* VD,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
+ }
+
+public:
+ const VarDecl* getDecl() const { return cast<VarDecl>(D); }
+
+ QualType getValueType(ASTContext& C) const {
+ // FIXME: We can cache this if needed.
+ return C.getCanonicalType(getDecl()->getType());
+ }
+
+ void print(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == VarRegionKind;
+ }
+};
+
+class FieldRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ FieldRegion(const FieldDecl* fd, const MemRegion* sReg)
+ : DeclRegion(fd, sReg, FieldRegionKind) {}
+
+public:
+
+ void print(llvm::raw_ostream& os) const;
+
+ const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
+
+ QualType getValueType(ASTContext& C) const {
+ // FIXME: We can cache this if needed.
+ return C.getCanonicalType(getDecl()->getType());
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
+ }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FieldRegionKind;
+ }
+};
+
+class ObjCObjectRegion : public DeclRegion {
+
+ friend class MemRegionManager;
+
+ ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg)
+ : DeclRegion(ivd, sReg, ObjCObjectRegionKind) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCInterfaceDecl* ivd,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind);
+ }
+
+public:
+ const ObjCInterfaceDecl* getInterface() const {
+ return cast<ObjCInterfaceDecl>(D);
+ }
+
+ QualType getValueType(ASTContext& C) const {
+ return C.getObjCInterfaceType(getInterface());
+ }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCObjectRegionKind;
+ }
+};
+
+class ObjCIvarRegion : public DeclRegion {
+
+ friend class MemRegionManager;
+
+ ObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* sReg)
+ : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCIvarDecl* ivd,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
+ }
+
+public:
+ const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
+ QualType getValueType(ASTContext&) const { return getDecl()->getType(); }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCIvarRegionKind;
+ }
+};
+
+class ElementRegion : public TypedRegion {
+ friend class MemRegionManager;
+
+ QualType ElementType;
+ SVal Index;
+
+ ElementRegion(QualType elementType, SVal Idx, const MemRegion* sReg)
+ : TypedRegion(sReg, ElementRegionKind),
+ ElementType(elementType), Index(Idx) {
+ assert((!isa<nonloc::ConcreteInt>(&Idx) ||
+ cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
+ "The index must be signed");
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
+ SVal Idx, const MemRegion* superRegion);
+
+public:
+
+ SVal getIndex() const { return Index; }
+
+ QualType getValueType(ASTContext&) const {
+ return ElementType;
+ }
+
+ QualType getElementType() const {
+ return ElementType;
+ }
+
+ void print(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ElementRegionKind;
+ }
+};
+
+template<typename RegionTy>
+const RegionTy* MemRegion::getAs() const {
+ const MemRegion *R = this;
+
+ do {
+ if (const RegionTy* RT = dyn_cast<RegionTy>(R))
+ return RT;
+
+ if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R)) {
+ R = TR->getSuperRegion();
+ continue;
+ }
+
+ break;
+ }
+ while (R);
+
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// MemRegionManager - Factory object for creating regions.
+//===----------------------------------------------------------------------===//
+
+class MemRegionManager {
+ llvm::BumpPtrAllocator& A;
+ llvm::FoldingSet<MemRegion> Regions;
+
+ MemSpaceRegion* globals;
+ MemSpaceRegion* stack;
+ MemSpaceRegion* heap;
+ MemSpaceRegion* unknown;
+ MemSpaceRegion* code;
+
+public:
+ MemRegionManager(llvm::BumpPtrAllocator& a)
+ : A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {}
+
+ ~MemRegionManager() {}
+
+ /// getStackRegion - Retrieve the memory region associated with the
+ /// current stack frame.
+ MemSpaceRegion* getStackRegion();
+
+ /// getGlobalsRegion - Retrieve the memory region associated with
+ /// all global variables.
+ MemSpaceRegion* getGlobalsRegion();
+
+ /// getHeapRegion - Retrieve the memory region associated with the
+ /// generic "heap".
+ MemSpaceRegion* getHeapRegion();
+
+ /// getUnknownRegion - Retrieve the memory region associated with unknown
+ /// memory space.
+ MemSpaceRegion* getUnknownRegion();
+
+ MemSpaceRegion* getCodeRegion();
+
+ bool isGlobalsRegion(const MemRegion* R) {
+ assert(R);
+ return R == globals;
+ }
+
+ /// onStack - check if the region is allocated on the stack.
+ bool onStack(const MemRegion* R);
+
+ /// onHeap - check if the region is allocated on the heap, usually by malloc.
+ bool onHeap(const MemRegion* R);
+
+ /// getAllocaRegion - Retrieve a region associated with a call to alloca().
+ AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt);
+
+ /// getCompoundLiteralRegion - Retrieve the region associated with a
+ /// given CompoundLiteral.
+ CompoundLiteralRegion*
+ getCompoundLiteralRegion(const CompoundLiteralExpr* CL);
+
+ /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
+ SymbolicRegion* getSymbolicRegion(SymbolRef sym);
+
+ StringRegion* getStringRegion(const StringLiteral* Str);
+
+ /// getVarRegion - Retrieve or create the memory region associated with
+ /// a specified VarDecl.
+ VarRegion* getVarRegion(const VarDecl* vd);
+
+ /// getElementRegion - Retrieve the memory region associated with the
+ /// associated element type, index, and super region.
+ ElementRegion* getElementRegion(QualType elementType, SVal Idx,
+ const MemRegion* superRegion);
+
+ /// getFieldRegion - Retrieve or create the memory region associated with
+ /// a specified FieldDecl. 'superRegion' corresponds to the containing
+ /// memory region (which typically represents the memory representing
+ /// a structure or class).
+ FieldRegion* getFieldRegion(const FieldDecl* fd,
+ const MemRegion* superRegion);
+
+ /// getObjCObjectRegion - Retrieve or create the memory region associated with
+ /// the instance of a specified Objective-C class.
+ ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID,
+ const MemRegion* superRegion);
+
+ /// getObjCIvarRegion - Retrieve or create the memory region associated with
+ /// a specified Objective-c instance variable. 'superRegion' corresponds
+ /// to the containing region (which typically represents the Objective-C
+ /// object).
+ ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
+ const MemRegion* superRegion);
+
+ TypedViewRegion* getTypedViewRegion(QualType LValueType,
+ const MemRegion* superRegion);
+
+ CodeTextRegion* getCodeTextRegion(SymbolRef sym, QualType t);
+ CodeTextRegion* getCodeTextRegion(const FunctionDecl* fd, QualType t);
+
+ bool hasStackStorage(const MemRegion* R);
+
+private:
+ MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
+};
+} // end clang namespace
+
+namespace llvm {
+static inline raw_ostream& operator<<(raw_ostream& O,
+ const clang::MemRegion* R) {
+ R->print(O);
+ return O;
+}
+} // end llvm namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
new file mode 100644
index 000000000000..ee6d4dcf1f37
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/SVals.h
@@ -0,0 +1,447 @@
+//== SVals.h - Abstract Values for Static Analysis ---------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines SVal, Loc, and NonLoc, classes that represent
+// abstract r-values for use with path-sensitive value tracking.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
+#define LLVM_CLANG_ANALYSIS_RVALUE_H
+
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/ImmutableList.h"
+
+//==------------------------------------------------------------------------==//
+// Base SVal types.
+//==------------------------------------------------------------------------==//
+
+namespace clang {
+
+class CompoundValData;
+class BasicValueFactory;
+class MemRegion;
+class MemRegionManager;
+class GRStateManager;
+
+class SVal {
+public:
+ enum BaseKind { UndefinedKind, UnknownKind, LocKind, NonLocKind };
+ enum { BaseBits = 2, BaseMask = 0x3 };
+
+protected:
+ void* Data;
+ unsigned Kind;
+
+protected:
+ SVal(const void* d, bool isLoc, unsigned ValKind)
+ : Data(const_cast<void*>(d)),
+ Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
+
+ explicit SVal(BaseKind k, void* D = NULL)
+ : Data(D), Kind(k) {}
+
+public:
+ SVal() : Data(0), Kind(0) {}
+ ~SVal() {};
+
+ /// BufferTy - A temporary buffer to hold a set of SVals.
+ typedef llvm::SmallVector<SVal,5> BufferTy;
+
+ inline unsigned getRawKind() const { return Kind; }
+ inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
+ inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
+
+ inline void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned) getRawKind());
+ ID.AddPointer(reinterpret_cast<void*>(Data));
+ }
+
+ inline bool operator==(const SVal& R) const {
+ return getRawKind() == R.getRawKind() && Data == R.Data;
+ }
+
+ inline bool operator!=(const SVal& R) const {
+ return !(*this == R);
+ }
+
+ inline bool isUnknown() const {
+ return getRawKind() == UnknownKind;
+ }
+
+ inline bool isUndef() const {
+ return getRawKind() == UndefinedKind;
+ }
+
+ inline bool isUnknownOrUndef() const {
+ return getRawKind() <= UnknownKind;
+ }
+
+ inline bool isValid() const {
+ return getRawKind() > UnknownKind;
+ }
+
+ bool isZeroConstant() const;
+
+ /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
+ bool hasConjuredSymbol() const;
+
+ /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
+ /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
+ /// Otherwise return 0.
+ const FunctionDecl* getAsFunctionDecl() const;
+
+ /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
+ /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolData*
+ SymbolRef getAsLocSymbol() const;
+
+ /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
+ /// Otherwise return a SymbolRef where 'isValid()' returns false.
+ SymbolRef getAsSymbol() const;
+
+ /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+ /// return that expression. Otherwise return NULL.
+ const SymExpr *getAsSymbolicExpression() const;
+
+ void print(std::ostream& OS) const;
+ void print(llvm::raw_ostream& OS) const;
+ void printStdErr() const;
+
+ // Iterators.
+ class symbol_iterator {
+ llvm::SmallVector<const SymExpr*, 5> itr;
+ void expand();
+ public:
+ symbol_iterator() {}
+ symbol_iterator(const SymExpr* SE);
+
+ symbol_iterator& operator++();
+ SymbolRef operator*();
+
+ bool operator==(const symbol_iterator& X) const;
+ bool operator!=(const symbol_iterator& X) const;
+ };
+
+ symbol_iterator symbol_begin() const {
+ const SymExpr *SE = getAsSymbolicExpression();
+ if (SE)
+ return symbol_iterator(SE);
+ else
+ return symbol_iterator();
+ }
+
+ symbol_iterator symbol_end() const { return symbol_iterator(); }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal*) { return true; }
+};
+
+class UnknownVal : public SVal {
+public:
+ UnknownVal() : SVal(UnknownKind) {}
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == UnknownKind;
+ }
+};
+
+class UndefinedVal : public SVal {
+public:
+ UndefinedVal() : SVal(UndefinedKind) {}
+ UndefinedVal(void* D) : SVal(UndefinedKind, D) {}
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == UndefinedKind;
+ }
+
+ void* getData() const { return Data; }
+};
+
+class NonLoc : public SVal {
+protected:
+ NonLoc(unsigned SubKind, const void* d) : SVal(d, false, SubKind) {}
+
+public:
+ void print(llvm::raw_ostream& Out) const;
+
+ // Utility methods to create NonLocs.
+
+ static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
+ bool isUnsigned);
+
+ static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X,
+ unsigned BitWidth, bool isUnsigned);
+
+ static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T);
+
+ static NonLoc MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I);
+
+ static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
+ bool isUnsigned);
+
+ static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I);
+
+ static NonLoc MakeIntTruthVal(BasicValueFactory& BasicVals, bool b);
+
+ static NonLoc MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
+ BasicValueFactory& BasicVals);
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind;
+ }
+};
+
+class Loc : public SVal {
+protected:
+ Loc(unsigned SubKind, const void* D)
+ : SVal(const_cast<void*>(D), true, SubKind) {}
+
+public:
+ void print(llvm::raw_ostream& Out) const;
+
+ Loc(const Loc& X) : SVal(X.Data, true, X.getSubKind()) {}
+ Loc& operator=(const Loc& X) { memcpy(this, &X, sizeof(Loc)); return *this; }
+
+ static Loc MakeVal(const MemRegion* R);
+
+ static Loc MakeVal(AddrLabelExpr* E);
+
+ static Loc MakeNull(BasicValueFactory &BasicVals);
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind;
+ }
+
+ static inline bool IsLocType(QualType T) {
+ return T->isPointerType() || T->isObjCQualifiedIdType()
+ || T->isBlockPointerType();
+ }
+};
+
+//==------------------------------------------------------------------------==//
+// Subclasses of NonLoc.
+//==------------------------------------------------------------------------==//
+
+namespace nonloc {
+
+enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
+ LocAsIntegerKind, CompoundValKind };
+
+class SymbolVal : public NonLoc {
+public:
+ SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
+
+ SymbolRef getSymbol() const {
+ return (const SymbolData*) Data;
+ }
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == SymbolValKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == SymbolValKind;
+ }
+};
+
+class SymExprVal : public NonLoc {
+public:
+ SymExprVal(const SymExpr *SE)
+ : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
+
+ const SymExpr *getSymbolicExpression() const {
+ return reinterpret_cast<SymExpr*>(Data);
+ }
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == SymExprValKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == SymExprValKind;
+ }
+};
+
+class ConcreteInt : public NonLoc {
+public:
+ ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
+
+ const llvm::APSInt& getValue() const {
+ return *static_cast<llvm::APSInt*>(Data);
+ }
+
+ // Transfer functions for binary/unary operations on ConcreteInts.
+ SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+ const ConcreteInt& R) const;
+
+ ConcreteInt EvalComplement(BasicValueFactory& BasicVals) const;
+
+ ConcreteInt EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == ConcreteIntKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == ConcreteIntKind;
+ }
+};
+
+class LocAsInteger : public NonLoc {
+ LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
+ NonLoc(LocAsIntegerKind, &data) {
+ assert (isa<Loc>(data.first));
+ }
+
+public:
+
+ Loc getLoc() const {
+ return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
+ }
+
+ const Loc& getPersistentLoc() const {
+ const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
+ return cast<Loc>(V);
+ }
+
+ unsigned getNumBits() const {
+ return ((std::pair<SVal, unsigned>*) Data)->second;
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind &&
+ V->getSubKind() == LocAsIntegerKind;
+ }
+
+ static inline bool classof(const NonLoc* V) {
+ return V->getSubKind() == LocAsIntegerKind;
+ }
+
+ static LocAsInteger Make(BasicValueFactory& Vals, Loc V, unsigned Bits);
+};
+
+class CompoundVal : public NonLoc {
+ friend class NonLoc;
+
+ CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
+
+public:
+ const CompoundValData* getValue() const {
+ return static_cast<CompoundValData*>(Data);
+ }
+
+ typedef llvm::ImmutableList<SVal>::iterator iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ static bool classof(const SVal* V) {
+ return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
+ }
+
+ static bool classof(const NonLoc* V) {
+ return V->getSubKind() == CompoundValKind;
+ }
+};
+
+} // end namespace clang::nonloc
+
+//==------------------------------------------------------------------------==//
+// Subclasses of Loc.
+//==------------------------------------------------------------------------==//
+
+namespace loc {
+
+enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
+
+class GotoLabel : public Loc {
+public:
+ GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
+
+ LabelStmt* getLabel() const {
+ return static_cast<LabelStmt*>(Data);
+ }
+
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == GotoLabelKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == GotoLabelKind;
+ }
+};
+
+
+class MemRegionVal : public Loc {
+public:
+ MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
+
+ const MemRegion* getRegion() const {
+ return static_cast<MemRegion*>(Data);
+ }
+
+ template <typename REGION>
+ const REGION* getRegionAs() const {
+ return llvm::dyn_cast<REGION>(getRegion());
+ }
+
+ inline bool operator==(const MemRegionVal& R) const {
+ return getRegion() == R.getRegion();
+ }
+
+ inline bool operator!=(const MemRegionVal& R) const {
+ return getRegion() != R.getRegion();
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == MemRegionKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == MemRegionKind;
+ }
+};
+
+class ConcreteInt : public Loc {
+public:
+ ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
+
+ const llvm::APSInt& getValue() const {
+ return *static_cast<llvm::APSInt*>(Data);
+ }
+
+ // Transfer functions for binary/unary operations on ConcreteInts.
+ SVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+ const ConcreteInt& R) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SVal* V) {
+ return V->getBaseKind() == LocKind &&
+ V->getSubKind() == ConcreteIntKind;
+ }
+
+ static inline bool classof(const Loc* V) {
+ return V->getSubKind() == ConcreteIntKind;
+ }
+};
+
+} // end clang::loc namespace
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
new file mode 100644
index 000000000000..1f081f4eb0d0
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -0,0 +1,204 @@
+//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the types Store and StoreManager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_STORE_H
+#define LLVM_CLANG_ANALYSIS_STORE_H
+
+#include "clang/Analysis/PathSensitive/SVals.h"
+#include "clang/Analysis/PathSensitive/MemRegion.h"
+#include "clang/Analysis/PathSensitive/ValueManager.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <iosfwd>
+
+namespace clang {
+
+typedef const void* Store;
+
+class GRState;
+class GRStateManager;
+class Stmt;
+class Expr;
+class ObjCIvarDecl;
+class SubRegionMap;
+
+class StoreManager {
+protected:
+ ValueManager &ValMgr;
+ GRStateManager &StateMgr;
+
+ /// MRMgr - Manages region objects associated with this StoreManager.
+ MemRegionManager &MRMgr;
+
+ StoreManager(GRStateManager &stateMgr);
+
+protected:
+ virtual const GRState* AddRegionView(const GRState* St,
+ const MemRegion* View,
+ const MemRegion* Base) {
+ return St;
+ }
+
+public:
+ virtual ~StoreManager() {}
+
+ /// Return the value bound to specified location in a given state.
+ /// \param[in] state The analysis state.
+ /// \param[in] loc The symbolic memory location.
+ /// \param[in] T An optional type that provides a hint indicating the
+ /// expected type of the returned value. This is used if the value is
+ /// lazily computed.
+ /// \return The value bound to the location \c loc.
+ virtual SVal Retrieve(const GRState* state, Loc loc,
+ QualType T = QualType()) = 0;
+
+ /// Return a state with the specified value bound to the given location.
+ /// \param[in] state The analysis state.
+ /// \param[in] loc The symbolic memory location.
+ /// \param[in] val The value to bind to location \c loc.
+ /// \return A pointer to a GRState object that contains the same bindings as
+ /// \c state with the addition of having the value specified by \c val bound
+ /// to the location given for \c loc.
+ virtual const GRState* Bind(const GRState* state, Loc loc, SVal val) = 0;
+
+ virtual Store Remove(Store St, Loc L) = 0;
+
+ /// BindCompoundLiteral - Return the store that has the bindings currently
+ /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
+ /// for the compound literal and 'BegInit' and 'EndInit' represent an
+ /// array of initializer values.
+ virtual const GRState* BindCompoundLiteral(const GRState* St,
+ const CompoundLiteralExpr* CL,
+ SVal V) = 0;
+
+ /// getInitialStore - Returns the initial "empty" store representing the
+ /// value bindings upon entry to an analyzed function.
+ virtual Store getInitialStore() = 0;
+
+ /// getRegionManager - Returns the internal RegionManager object that is
+ /// used to query and manipulate MemRegion objects.
+ MemRegionManager& getRegionManager() { return MRMgr; }
+
+ /// getSubRegionMap - Returns an opaque map object that clients can query
+ /// to get the subregions of a given MemRegion object. It is the
+ // caller's responsibility to 'delete' the returned map.
+ virtual SubRegionMap* getSubRegionMap(const GRState *state) = 0;
+
+ virtual SVal getLValueVar(const GRState* St, const VarDecl* VD) = 0;
+
+ virtual SVal getLValueString(const GRState* St, const StringLiteral* S) = 0;
+
+ virtual SVal getLValueCompoundLiteral(const GRState* St,
+ const CompoundLiteralExpr* CL) = 0;
+
+ virtual SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+ SVal Base) = 0;
+
+ virtual SVal getLValueField(const GRState* St, SVal Base,
+ const FieldDecl* D) = 0;
+
+ virtual SVal getLValueElement(const GRState* St, QualType elementType,
+ SVal Base, SVal Offset) = 0;
+
+ virtual SVal getSizeInElements(const GRState* St, const MemRegion* R) {
+ return UnknownVal();
+ }
+
+ /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
+ /// conversions between arrays and pointers.
+ virtual SVal ArrayToPointer(Loc Array) = 0;
+
+
+ class CastResult {
+ const GRState* State;
+ const MemRegion* R;
+ public:
+ const GRState* getState() const { return State; }
+ const MemRegion* getRegion() const { return R; }
+ CastResult(const GRState* s, const MemRegion* r = 0) : State(s), R(r) {}
+ };
+
+ /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ virtual CastResult CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy);
+
+ /// EvalBinOp - Perform pointer arithmetic.
+ virtual SVal EvalBinOp(const GRState *state,
+ BinaryOperator::Opcode Op, Loc L, NonLoc R) {
+ return UnknownVal();
+ }
+
+ /// getSelfRegion - Returns the region for the 'self' (Objective-C) or
+ /// 'this' object (C++). When used when analyzing a normal function this
+ /// method returns NULL.
+ virtual const MemRegion* getSelfRegion(Store store) = 0;
+
+ virtual Store
+ RemoveDeadBindings(const GRState* state, Stmt* Loc, SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
+
+ virtual const GRState* BindDecl(const GRState* St, const VarDecl* VD,
+ SVal InitVal) = 0;
+
+ virtual const GRState* BindDeclWithNoInit(const GRState* St,
+ const VarDecl* VD) = 0;
+
+ virtual const GRState* setExtent(const GRState* St,
+ const MemRegion* R, SVal Extent) {
+ return St;
+ }
+
+ virtual const GRState* setDefaultValue(const GRState* St,
+ const MemRegion* R, SVal V) {
+ return St;
+ }
+
+ virtual void print(Store store, std::ostream& Out,
+ const char* nl, const char *sep) = 0;
+
+ class BindingsHandler {
+ public:
+ virtual ~BindingsHandler();
+ virtual bool HandleBinding(StoreManager& SMgr, Store store,
+ const MemRegion* R, SVal val) = 0;
+ };
+
+ /// iterBindings - Iterate over the bindings in the Store.
+ virtual void iterBindings(Store store, BindingsHandler& f) = 0;
+};
+
+/// SubRegionMap - An abstract interface that represents a queryable map
+/// between MemRegion objects and their subregions.
+class SubRegionMap {
+public:
+ virtual ~SubRegionMap() {}
+
+ class Visitor {
+ public:
+ virtual ~Visitor() {};
+ virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
+ };
+
+ virtual bool iterSubRegions(const MemRegion* R, Visitor& V) const = 0;
+};
+
+StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);
+StoreManager* CreateRegionStoreManager(GRStateManager& StMgr);
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h
new file mode 100644
index 000000000000..d424526d4eb0
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/SymbolManager.h
@@ -0,0 +1,329 @@
+//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines SymbolManager, a class that manages symbolic values
+// created for use by GRExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H
+#define LLVM_CLANG_ANALYSIS_SYMMGR_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+ class MemRegion;
+ class ASTContext;
+ class BasicValueFactory;
+}
+
+namespace clang {
+
+class SymExpr : public llvm::FoldingSetNode {
+public:
+ enum Kind { BEGIN_SYMBOLS, RegionValueKind, ConjuredKind, END_SYMBOLS,
+ SymIntKind, SymSymKind };
+private:
+ Kind K;
+
+protected:
+ SymExpr(Kind k) : K(k) {}
+
+public:
+ virtual ~SymExpr() {}
+
+ Kind getKind() const { return K; }
+
+ virtual QualType getType(ASTContext&) const = 0;
+ virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr*) { return true; }
+};
+
+typedef unsigned SymbolID;
+
+class SymbolData : public SymExpr {
+private:
+ const SymbolID Sym;
+
+protected:
+ SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
+
+public:
+ virtual ~SymbolData() {}
+
+ SymbolID getSymbolID() const { return Sym; }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ Kind k = SE->getKind();
+ return k > BEGIN_SYMBOLS && k < END_SYMBOLS;
+ }
+};
+
+typedef const SymbolData* SymbolRef;
+
+class SymbolRegionValue : public SymbolData {
+ const MemRegion *R;
+public:
+ SymbolRegionValue(SymbolID sym, const MemRegion *r)
+ : SymbolData(RegionValueKind, sym), R(r) {}
+
+ const MemRegion* getRegion() const { return R; }
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R) {
+ profile.AddInteger((unsigned) RegionValueKind);
+ profile.AddPointer(R);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, R);
+ }
+
+ QualType getType(ASTContext&) const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == RegionValueKind;
+ }
+};
+
+class SymbolConjured : public SymbolData {
+ const Stmt* S;
+ QualType T;
+ unsigned Count;
+ const void* SymbolTag;
+
+public:
+ SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count,
+ const void* symbolTag)
+ : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
+ SymbolTag(symbolTag) {}
+
+ const Stmt* getStmt() const { return S; }
+ unsigned getCount() const { return Count; }
+ const void* getTag() const { return SymbolTag; }
+
+ QualType getType(ASTContext&) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const Stmt* S,
+ QualType T, unsigned Count, const void* SymbolTag) {
+ profile.AddInteger((unsigned) ConjuredKind);
+ profile.AddPointer(S);
+ profile.Add(T);
+ profile.AddInteger(Count);
+ profile.AddPointer(SymbolTag);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, S, T, Count, SymbolTag);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == ConjuredKind;
+ }
+};
+
+// SymIntExpr - Represents symbolic expression like 'x' + 3.
+class SymIntExpr : public SymExpr {
+ const SymExpr *LHS;
+ BinaryOperator::Opcode Op;
+ const llvm::APSInt& RHS;
+ QualType T;
+
+public:
+ SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t)
+ : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType(ASTContext& C) const { return T; }
+
+ BinaryOperator::Opcode getOpcode() const { return Op; }
+
+ const SymExpr *getLHS() const { return LHS; }
+ const llvm::APSInt &getRHS() const { return RHS; }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const llvm::APSInt& rhs,
+ QualType t) {
+ ID.AddInteger((unsigned) SymIntKind);
+ ID.AddPointer(lhs);
+ ID.AddInteger(op);
+ ID.AddPointer(&rhs);
+ ID.Add(t);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) {
+ Profile(ID, LHS, Op, RHS, T);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == SymIntKind;
+ }
+};
+
+// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
+class SymSymExpr : public SymExpr {
+ const SymExpr *LHS;
+ BinaryOperator::Opcode Op;
+ const SymExpr *RHS;
+ QualType T;
+
+public:
+ SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
+ QualType t)
+ : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
+
+ const SymExpr *getLHS() const { return LHS; }
+ const SymExpr *getRHS() const { return RHS; }
+
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType(ASTContext& C) const { return T; }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
+ ID.AddInteger((unsigned) SymSymKind);
+ ID.AddPointer(lhs);
+ ID.AddInteger(op);
+ ID.AddPointer(rhs);
+ ID.Add(t);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) {
+ Profile(ID, LHS, Op, RHS, T);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == SymSymKind;
+ }
+};
+
+class SymbolManager {
+ typedef llvm::FoldingSet<SymExpr> DataSetTy;
+ DataSetTy DataSet;
+ unsigned SymbolCounter;
+ llvm::BumpPtrAllocator& BPAlloc;
+ BasicValueFactory &BV;
+ ASTContext& Ctx;
+
+public:
+ SymbolManager(ASTContext& ctx, BasicValueFactory &bv,
+ llvm::BumpPtrAllocator& bpalloc)
+ : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
+
+ ~SymbolManager();
+
+ static bool canSymbolicate(QualType T);
+
+ /// Make a unique symbol for MemRegion R according to its kind.
+ const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R);
+ const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
+ unsigned VisitCount,
+ const void* SymbolTag = 0);
+
+ const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
+ const void* SymbolTag = 0) {
+ return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
+ }
+
+ const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t);
+
+ const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t) {
+ return getSymIntExpr(&lhs, op, rhs, t);
+ }
+
+ const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType t);
+
+ QualType getType(const SymExpr *SE) const {
+ return SE->getType(Ctx);
+ }
+
+ ASTContext &getContext() { return Ctx; }
+ BasicValueFactory &getBasicVals() { return BV; }
+};
+
+class SymbolReaper {
+ typedef llvm::ImmutableSet<SymbolRef> SetTy;
+ typedef SetTy::Factory FactoryTy;
+
+ FactoryTy F;
+ SetTy TheLiving;
+ SetTy TheDead;
+ LiveVariables& Liveness;
+ SymbolManager& SymMgr;
+
+public:
+ SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr)
+ : TheLiving(F.GetEmptySet()), TheDead(F.GetEmptySet()),
+ Liveness(liveness), SymMgr(symmgr) {}
+
+ bool isLive(SymbolRef sym);
+
+ bool isLive(const Stmt* Loc, const Stmt* ExprVal) const {
+ return Liveness.isLive(Loc, ExprVal);
+ }
+
+ bool isLive(const Stmt* Loc, const VarDecl* VD) const {
+ return Liveness.isLive(Loc, VD);
+ }
+
+ void markLive(SymbolRef sym);
+ bool maybeDead(SymbolRef sym);
+
+ typedef SetTy::iterator dead_iterator;
+ dead_iterator dead_begin() const { return TheDead.begin(); }
+ dead_iterator dead_end() const { return TheDead.end(); }
+
+ bool hasDeadSymbols() const {
+ return !TheDead.isEmpty();
+ }
+};
+
+class SymbolVisitor {
+public:
+ // VisitSymbol - A visitor method invoked by
+ // GRStateManager::scanReachableSymbols. The method returns \c true if
+ // symbols should continue be scanned and \c false otherwise.
+ virtual bool VisitSymbol(SymbolRef sym) = 0;
+ virtual ~SymbolVisitor();
+};
+
+} // end clang namespace
+
+namespace llvm {
+ llvm::raw_ostream& operator<<(llvm::raw_ostream& Out,
+ const clang::SymExpr *SE);
+}
+namespace std {
+ std::ostream& operator<<(std::ostream& Out,
+ const clang::SymExpr *SE);
+}
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h
new file mode 100644
index 000000000000..89af975de7af
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/ValueManager.h
@@ -0,0 +1,103 @@
+//== ValueManager.h - Aggregate manager of symbols and SVals ----*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ValueManager, a class that manages symbolic values
+// and SVals created for use by GRExprEngine and related classes. It
+// wraps SymbolManager, MemRegionManager, and BasicValueFactory.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H
+#define LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H
+
+#include "clang/Analysis/PathSensitive/MemRegion.h"
+#include "clang/Analysis/PathSensitive/SVals.h"
+#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+
+namespace llvm { class BumpPtrAllocator; }
+
+namespace clang {
+class ValueManager {
+
+ ASTContext &Context;
+ BasicValueFactory BasicVals;
+
+ /// SymMgr - Object that manages the symbol information.
+ SymbolManager SymMgr;
+
+
+ MemRegionManager MemMgr;
+
+public:
+ ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context)
+ : Context(context), BasicVals(Context, alloc),
+ SymMgr(Context, BasicVals, alloc),
+ MemMgr(alloc) {}
+
+ // Accessors to submanagers.
+
+ ASTContext &getContext() { return Context; }
+ const ASTContext &getContext() const { return Context; }
+
+ BasicValueFactory &getBasicValueFactory() { return BasicVals; }
+ const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
+
+ SymbolManager &getSymbolManager() { return SymMgr; }
+ const SymbolManager &getSymbolManager() const { return SymMgr; }
+
+ MemRegionManager &getRegionManager() { return MemMgr; }
+ const MemRegionManager &getRegionManager() const { return MemMgr; }
+
+ // Forwarding methods to SymbolManager.
+
+ const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
+ unsigned VisitCount,
+ const void* SymbolTag = 0) {
+ return SymMgr.getConjuredSymbol(E, T, VisitCount, SymbolTag);
+ }
+
+ const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount,
+ const void* SymbolTag = 0) {
+ return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag);
+ }
+
+ // Aggregation methods that use multiple submanagers.
+
+ Loc makeRegionVal(SymbolRef Sym) {
+ return Loc::MakeVal(MemMgr.getSymbolicRegion(Sym));
+ }
+
+ /// makeZeroVal - Construct an SVal representing '0' for the specified type.
+ SVal makeZeroVal(QualType T);
+ /// makeZeroArrayIndex - Construct an SVal representing '0' index for array
+ /// elements.
+ SVal makeZeroArrayIndex();
+
+ /// GetRegionValueSymbolVal - make a unique symbol for value of R.
+ SVal getRegionValueSymbolVal(const MemRegion* R);
+
+ SVal getConjuredSymbolVal(const Expr *E, unsigned Count);
+ SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count);
+
+ SVal getFunctionPointer(const FunctionDecl* FD);
+
+ NonLoc makeNonLoc(SymbolRef sym);
+
+ NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType T);
+
+ NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType T);
+
+ NonLoc makeTruthVal(bool b, QualType T);
+};
+} // end clang namespace
+#endif
+
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
new file mode 100644
index 000000000000..d2b536ca1cb2
--- /dev/null
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -0,0 +1,351 @@
+//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface ProgramPoint, which identifies a
+// distinct location in a function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+
+#include "clang/AST/CFG.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <utility>
+
+namespace clang {
+
+class ProgramPoint {
+public:
+ enum Kind { BlockEdgeKind = 0x0,
+ BlockEntranceKind = 0x1,
+ BlockExitKind = 0x2,
+ // Keep the following four together and in this order.
+ PostStmtKind = 0x3,
+ PostLocationChecksSucceedKind = 0x4,
+ PostOutOfBoundsCheckFailedKind = 0x5,
+ PostNullCheckFailedKind = 0x6,
+ PostUndefLocationCheckFailedKind = 0x7,
+ PostLoadKind = 0x8,
+ PostStoreKind = 0x9,
+ PostPurgeDeadSymbolsKind = 0x10,
+ PostStmtCustomKind = 0x11,
+ PostLValueKind = 0x12,
+ MinPostStmtKind = PostStmtKind,
+ MaxPostStmtKind = PostLValueKind };
+
+private:
+ enum { TwoPointers = 0x1, Custom = 0x2, Mask = 0x3 };
+
+ std::pair<uintptr_t,uintptr_t> Data;
+ const void *Tag;
+
+protected:
+ ProgramPoint(const void* P, Kind k, const void *tag = 0)
+ : Data(reinterpret_cast<uintptr_t>(P),
+ (uintptr_t) k), Tag(tag) {}
+
+ ProgramPoint(const void* P1, const void* P2, const void *tag = 0)
+ : Data(reinterpret_cast<uintptr_t>(P1) | TwoPointers,
+ reinterpret_cast<uintptr_t>(P2)), Tag(tag) {}
+
+ ProgramPoint(const void* P1, const void* P2, bool, const void *tag = 0)
+ : Data(reinterpret_cast<uintptr_t>(P1) | Custom,
+ reinterpret_cast<uintptr_t>(P2)), Tag(tag) {}
+
+protected:
+ void* getData1NoMask() const {
+ Kind k = getKind(); k = k;
+ assert(k == BlockEntranceKind || k == BlockExitKind);
+ return reinterpret_cast<void*>(Data.first);
+ }
+
+ void* getData1() const {
+ Kind k = getKind(); k = k;
+ assert(k == BlockEdgeKind ||(k >= MinPostStmtKind && k <= MaxPostStmtKind));
+ return reinterpret_cast<void*>(Data.first & ~Mask);
+ }
+
+ void* getData2() const {
+ Kind k = getKind(); k = k;
+ assert(k == BlockEdgeKind || k == PostStmtCustomKind);
+ return reinterpret_cast<void*>(Data.second);
+ }
+
+ const void *getTag() const { return Tag; }
+
+public:
+ Kind getKind() const {
+ switch (Data.first & Mask) {
+ case TwoPointers: return BlockEdgeKind;
+ case Custom: return PostStmtCustomKind;
+ default: return (Kind) Data.second;
+ }
+ }
+
+ // For use with DenseMap. This hash is probably slow.
+ unsigned getHashValue() const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(reinterpret_cast<void*>(Data.first));
+ ID.AddPointer(reinterpret_cast<void*>(Data.second));
+ ID.AddPointer(Tag);
+ return ID.ComputeHash();
+ }
+
+ static bool classof(const ProgramPoint*) { return true; }
+
+ bool operator==(const ProgramPoint & RHS) const {
+ return Data == RHS.Data && Tag == RHS.Tag;
+ }
+
+ bool operator!=(const ProgramPoint& RHS) const {
+ return Data != RHS.Data || Tag != RHS.Tag;
+ }
+
+ bool operator<(const ProgramPoint& RHS) const {
+ return Data < RHS.Data && Tag < RHS.Tag;
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddPointer(reinterpret_cast<void*>(Data.first));
+ if (getKind() != PostStmtCustomKind)
+ ID.AddPointer(reinterpret_cast<void*>(Data.second));
+ else {
+ const std::pair<const void*, const void*> *P =
+ reinterpret_cast<std::pair<const void*, const void*>*>(Data.second);
+ ID.AddPointer(P->first);
+ ID.AddPointer(P->second);
+ }
+ ID.AddPointer(Tag);
+ }
+};
+
+class BlockEntrance : public ProgramPoint {
+public:
+ BlockEntrance(const CFGBlock* B, const void *tag = 0)
+ : ProgramPoint(B, BlockEntranceKind, tag) {}
+
+ CFGBlock* getBlock() const {
+ return reinterpret_cast<CFGBlock*>(getData1NoMask());
+ }
+
+ Stmt* getFirstStmt() const {
+ CFGBlock* B = getBlock();
+ return B->empty() ? NULL : B->front();
+ }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == BlockEntranceKind;
+ }
+};
+
+class BlockExit : public ProgramPoint {
+public:
+ BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {}
+
+ CFGBlock* getBlock() const {
+ return reinterpret_cast<CFGBlock*>(getData1NoMask());
+ }
+
+ Stmt* getLastStmt() const {
+ CFGBlock* B = getBlock();
+ return B->empty() ? NULL : B->back();
+ }
+
+ Stmt* getTerminator() const {
+ return getBlock()->getTerminator();
+ }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == BlockExitKind;
+ }
+};
+
+class PostStmt : public ProgramPoint {
+protected:
+ PostStmt(const Stmt* S, Kind k,const void *tag = 0)
+ : ProgramPoint(S, k, tag) {}
+
+ PostStmt(const Stmt* S, const void* data, bool, const void *tag =0)
+ : ProgramPoint(S, data, true, tag) {}
+
+public:
+ PostStmt(const Stmt* S, const void *tag = 0)
+ : ProgramPoint(S, PostStmtKind, tag) {}
+
+ Stmt* getStmt() const { return (Stmt*) getData1(); }
+
+ template<typename T>
+ T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
+
+ static bool classof(const ProgramPoint* Location) {
+ unsigned k = Location->getKind();
+ return k >= MinPostStmtKind && k <= MaxPostStmtKind;
+ }
+};
+
+class PostLocationChecksSucceed : public PostStmt {
+public:
+ PostLocationChecksSucceed(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostLocationChecksSucceedKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostLocationChecksSucceedKind;
+ }
+};
+
+class PostStmtCustom : public PostStmt {
+public:
+ PostStmtCustom(const Stmt* S,
+ const std::pair<const void*, const void*>* TaggedData)
+ : PostStmt(S, TaggedData, true) {
+ assert(getKind() == PostStmtCustomKind);
+ }
+
+ const std::pair<const void*, const void*>& getTaggedPair() const {
+ return *reinterpret_cast<std::pair<const void*, const void*>*>(getData2());
+ }
+
+ const void* getTag() const { return getTaggedPair().first; }
+
+ const void* getTaggedData() const { return getTaggedPair().second; }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostStmtCustomKind;
+ }
+};
+
+class PostOutOfBoundsCheckFailed : public PostStmt {
+public:
+ PostOutOfBoundsCheckFailed(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostOutOfBoundsCheckFailedKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostOutOfBoundsCheckFailedKind;
+ }
+};
+
+class PostUndefLocationCheckFailed : public PostStmt {
+public:
+ PostUndefLocationCheckFailed(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostUndefLocationCheckFailedKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostUndefLocationCheckFailedKind;
+ }
+};
+
+class PostNullCheckFailed : public PostStmt {
+public:
+ PostNullCheckFailed(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostNullCheckFailedKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostNullCheckFailedKind;
+ }
+};
+
+class PostLoad : public PostStmt {
+public:
+ PostLoad(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostLoadKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostLoadKind;
+ }
+};
+
+class PostStore : public PostStmt {
+public:
+ PostStore(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostStoreKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostStoreKind;
+ }
+};
+
+class PostLValue : public PostStmt {
+public:
+ PostLValue(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostLValueKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostLValueKind;
+ }
+};
+
+class PostPurgeDeadSymbols : public PostStmt {
+public:
+ PostPurgeDeadSymbols(const Stmt* S, const void *tag = 0)
+ : PostStmt(S, PostPurgeDeadSymbolsKind, tag) {}
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == PostPurgeDeadSymbolsKind;
+ }
+};
+
+class BlockEdge : public ProgramPoint {
+public:
+ BlockEdge(const CFGBlock* B1, const CFGBlock* B2)
+ : ProgramPoint(B1, B2) {}
+
+ CFGBlock* getSrc() const {
+ return static_cast<CFGBlock*>(getData1());
+ }
+
+ CFGBlock* getDst() const {
+ return static_cast<CFGBlock*>(getData2());
+ }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == BlockEdgeKind;
+ }
+};
+
+
+} // end namespace clang
+
+
+namespace llvm { // Traits specialization for DenseMap
+
+template <> struct DenseMapInfo<clang::ProgramPoint> {
+
+static inline clang::ProgramPoint getEmptyKey() {
+ uintptr_t x =
+ reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
+ return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
+}
+
+static inline clang::ProgramPoint getTombstoneKey() {
+ uintptr_t x =
+ reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
+ return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
+}
+
+static unsigned getHashValue(const clang::ProgramPoint& Loc) {
+ return Loc.getHashValue();
+}
+
+static bool isEqual(const clang::ProgramPoint& L,
+ const clang::ProgramPoint& R) {
+ return L == R;
+}
+
+static bool isPod() {
+ return true;
+}
+};
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/include/clang/Analysis/Support/BlkExprDeclBitVector.h
new file mode 100644
index 000000000000..a592be815419
--- /dev/null
+++ b/include/clang/Analysis/Support/BlkExprDeclBitVector.h
@@ -0,0 +1,307 @@
+// BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*--
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides definition of dataflow types used by analyses such
+// as LiveVariables and UninitializedValues. The underlying dataflow values
+// are implemented as bitvectors, but the definitions in this file include
+// the necessary boilerplate to use with our dataflow framework.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STMTDECLBVDVAL_H
+#define LLVM_CLANG_STMTDECLBVDVAL_H
+
+#include "clang/AST/CFG.h"
+#include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+ class Stmt;
+ class ASTContext;
+
+struct DeclBitVector_Types {
+
+ class Idx {
+ unsigned I;
+ public:
+ explicit Idx(unsigned i) : I(i) {}
+ Idx() : I(~0U) {}
+
+ bool isValid() const {
+ return I != ~0U;
+ }
+ operator unsigned() const {
+ assert (isValid());
+ return I;
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // AnalysisDataTy - Whole-function meta data.
+ //===--------------------------------------------------------------------===//
+
+ class AnalysisDataTy {
+ public:
+ typedef llvm::DenseMap<const NamedDecl*, unsigned > DMapTy;
+ typedef DMapTy::const_iterator decl_iterator;
+
+ protected:
+ DMapTy DMap;
+ unsigned NDecls;
+
+ public:
+
+ AnalysisDataTy() : NDecls(0) {}
+ virtual ~AnalysisDataTy() {}
+
+ bool isTracked(const NamedDecl* SD) { return DMap.find(SD) != DMap.end(); }
+
+ Idx getIdx(const NamedDecl* SD) const {
+ DMapTy::const_iterator I = DMap.find(SD);
+ return I == DMap.end() ? Idx() : Idx(I->second);
+ }
+
+ unsigned getNumDecls() const { return NDecls; }
+
+ void Register(const NamedDecl* SD) {
+ if (!isTracked(SD)) DMap[SD] = NDecls++;
+ }
+
+ decl_iterator begin_decl() const { return DMap.begin(); }
+ decl_iterator end_decl() const { return DMap.end(); }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // ValTy - Dataflow value.
+ //===--------------------------------------------------------------------===//
+
+ class ValTy {
+ llvm::BitVector DeclBV;
+ public:
+
+ void resetDeclValues(AnalysisDataTy& AD) {
+ DeclBV.resize(AD.getNumDecls());
+ DeclBV.reset();
+ }
+
+ void setDeclValues(AnalysisDataTy& AD) {
+ DeclBV.resize(AD.getNumDecls());
+ DeclBV.set();
+ }
+
+ void resetValues(AnalysisDataTy& AD) {
+ resetDeclValues(AD);
+ }
+
+ bool operator==(const ValTy& RHS) const {
+ assert (sizesEqual(RHS));
+ return DeclBV == RHS.DeclBV;
+ }
+
+ void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; }
+
+ llvm::BitVector::reference getBit(unsigned i) {
+ return DeclBV[i];
+ }
+
+ bool getBit(unsigned i) const {
+ return DeclBV[i];
+ }
+
+ llvm::BitVector::reference
+ operator()(const NamedDecl* ND, const AnalysisDataTy& AD) {
+ return getBit(AD.getIdx(ND));
+ }
+
+ bool operator()(const NamedDecl* ND, const AnalysisDataTy& AD) const {
+ return getBit(AD.getIdx(ND));
+ }
+
+ llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; }
+ const llvm::BitVector::reference getDeclBit(unsigned i) const {
+ return const_cast<llvm::BitVector&>(DeclBV)[i];
+ }
+
+ ValTy& operator|=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ DeclBV |= RHS.DeclBV;
+ return *this;
+ }
+
+ ValTy& operator&=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ DeclBV &= RHS.DeclBV;
+ return *this;
+ }
+
+ ValTy& OrDeclBits(const ValTy& RHS) {
+ return operator|=(RHS);
+ }
+
+ ValTy& AndDeclBits(const ValTy& RHS) {
+ return operator&=(RHS);
+ }
+
+ bool sizesEqual(const ValTy& RHS) const {
+ return DeclBV.size() == RHS.DeclBV.size();
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // Some useful merge operations.
+ //===--------------------------------------------------------------------===//
+
+ struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
+ struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
+};
+
+
+struct StmtDeclBitVector_Types {
+
+ //===--------------------------------------------------------------------===//
+ // AnalysisDataTy - Whole-function meta data.
+ //===--------------------------------------------------------------------===//
+
+ class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
+ ASTContext* ctx;
+ CFG* cfg;
+ public:
+ AnalysisDataTy() : ctx(0), cfg(0) {}
+ virtual ~AnalysisDataTy() {}
+
+ void setContext(ASTContext& c) { ctx = &c; }
+ ASTContext& getContext() {
+ assert(ctx && "ASTContext should not be NULL.");
+ return *ctx;
+ }
+
+ void setCFG(CFG& c) { cfg = &c; }
+ CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
+
+ bool isTracked(const Stmt* S) { return cfg->isBlkExpr(S); }
+ using DeclBitVector_Types::AnalysisDataTy::isTracked;
+
+ unsigned getIdx(const Stmt* S) const {
+ CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
+ assert(I && "Stmtession not tracked for bitvector.");
+ return I;
+ }
+ using DeclBitVector_Types::AnalysisDataTy::getIdx;
+
+ unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // ValTy - Dataflow value.
+ //===--------------------------------------------------------------------===//
+
+ class ValTy : public DeclBitVector_Types::ValTy {
+ llvm::BitVector BlkExprBV;
+ typedef DeclBitVector_Types::ValTy ParentTy;
+
+ static inline ParentTy& ParentRef(ValTy& X) {
+ return static_cast<ParentTy&>(X);
+ }
+
+ static inline const ParentTy& ParentRef(const ValTy& X) {
+ return static_cast<const ParentTy&>(X);
+ }
+
+ public:
+
+ void resetBlkExprValues(AnalysisDataTy& AD) {
+ BlkExprBV.resize(AD.getNumBlkExprs());
+ BlkExprBV.reset();
+ }
+
+ void setBlkExprValues(AnalysisDataTy& AD) {
+ BlkExprBV.resize(AD.getNumBlkExprs());
+ BlkExprBV.set();
+ }
+
+ void resetValues(AnalysisDataTy& AD) {
+ resetDeclValues(AD);
+ resetBlkExprValues(AD);
+ }
+
+ void setValues(AnalysisDataTy& AD) {
+ setDeclValues(AD);
+ setBlkExprValues(AD);
+ }
+
+ bool operator==(const ValTy& RHS) const {
+ return ParentRef(*this) == ParentRef(RHS)
+ && BlkExprBV == RHS.BlkExprBV;
+ }
+
+ void copyValues(const ValTy& RHS) {
+ ParentRef(*this).copyValues(ParentRef(RHS));
+ BlkExprBV = RHS.BlkExprBV;
+ }
+
+ llvm::BitVector::reference
+ operator()(const Stmt* S, const AnalysisDataTy& AD) {
+ return BlkExprBV[AD.getIdx(S)];
+ }
+ const llvm::BitVector::reference
+ operator()(const Stmt* S, const AnalysisDataTy& AD) const {
+ return const_cast<ValTy&>(*this)(S,AD);
+ }
+
+ using DeclBitVector_Types::ValTy::operator();
+
+
+ llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; }
+ const llvm::BitVector::reference getStmtBit(unsigned i) const {
+ return const_cast<llvm::BitVector&>(BlkExprBV)[i];
+ }
+
+ ValTy& OrBlkExprBits(const ValTy& RHS) {
+ BlkExprBV |= RHS.BlkExprBV;
+ return *this;
+ }
+
+ ValTy& AndBlkExprBits(const ValTy& RHS) {
+ BlkExprBV &= RHS.BlkExprBV;
+ return *this;
+ }
+
+ ValTy& operator|=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ ParentRef(*this) |= ParentRef(RHS);
+ BlkExprBV |= RHS.BlkExprBV;
+ return *this;
+ }
+
+ ValTy& operator&=(const ValTy& RHS) {
+ assert (sizesEqual(RHS));
+ ParentRef(*this) &= ParentRef(RHS);
+ BlkExprBV &= RHS.BlkExprBV;
+ return *this;
+ }
+
+ bool sizesEqual(const ValTy& RHS) const {
+ return ParentRef(*this).sizesEqual(ParentRef(RHS))
+ && BlkExprBV.size() == RHS.BlkExprBV.size();
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // Some useful merge operations.
+ //===--------------------------------------------------------------------===//
+
+ struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
+ struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
+
+};
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
new file mode 100644
index 000000000000..ee79c517030f
--- /dev/null
+++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
@@ -0,0 +1,91 @@
+//= CFGRecStmtDeclVisitor - Recursive visitor of CFG stmts/decls -*- C++ --*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the template class CFGRecStmtDeclVisitor, which extends
+// CFGRecStmtVisitor by implementing (typed) visitation of decls.
+//
+// FIXME: This may not be fully complete. We currently explore only subtypes
+// of ScopedDecl.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
+
+#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+
+#define DISPATCH_CASE(CASE,CLASS) \
+case Decl::CASE: \
+static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<CLASS*>(D));\
+break;
+
+#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS(CLASS* D) {}
+#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS(CLASS* D)\
+ { static_cast<ImplClass*>(this)->VisitVarDecl(D); }
+
+
+namespace clang {
+template <typename ImplClass>
+class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
+public:
+
+ void VisitDeclRefExpr(DeclRefExpr* DR) {
+ static_cast<ImplClass*>(this)->VisitDecl(DR->getDecl());
+ }
+
+ void VisitDeclStmt(DeclStmt* DS) {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI) {
+ Decl* D = *DI;
+ static_cast<ImplClass*>(this)->VisitDecl(D);
+ // Visit the initializer.
+ if (VarDecl* VD = dyn_cast<VarDecl>(D))
+ if (Expr* I = VD->getInit())
+ static_cast<ImplClass*>(this)->Visit(I);
+ }
+ }
+
+ void VisitDecl(Decl* D) {
+ switch (D->getKind()) {
+ DISPATCH_CASE(Function,FunctionDecl)
+ DISPATCH_CASE(Var,VarDecl)
+ DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
+ DISPATCH_CASE(OriginalParmVar,OriginalParmVarDecl) // FIXME: (same)
+ DISPATCH_CASE(ImplicitParam,ImplicitParamDecl)
+ DISPATCH_CASE(EnumConstant,EnumConstantDecl)
+ DISPATCH_CASE(Typedef,TypedefDecl)
+ DISPATCH_CASE(Record,RecordDecl) // FIXME: Refine. VisitStructDecl?
+ DISPATCH_CASE(Enum,EnumDecl)
+ default:
+ assert(false && "Subtype of ScopedDecl not handled.");
+ }
+ }
+
+ DEFAULT_DISPATCH(VarDecl)
+ DEFAULT_DISPATCH(FunctionDecl)
+ DEFAULT_DISPATCH_VARDECL(OriginalParmVarDecl)
+ DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
+ DEFAULT_DISPATCH(ImplicitParamDecl)
+ DEFAULT_DISPATCH(EnumConstantDecl)
+ DEFAULT_DISPATCH(TypedefDecl)
+ DEFAULT_DISPATCH(RecordDecl)
+ DEFAULT_DISPATCH(EnumDecl)
+ DEFAULT_DISPATCH(ObjCInterfaceDecl)
+ DEFAULT_DISPATCH(ObjCClassDecl)
+ DEFAULT_DISPATCH(ObjCMethodDecl)
+ DEFAULT_DISPATCH(ObjCProtocolDecl)
+ DEFAULT_DISPATCH(ObjCCategoryDecl)
+};
+
+} // end namespace clang
+
+#undef DISPATCH_CASE
+#undef DEFAULT_DISPATCH
+#endif
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
new file mode 100644
index 000000000000..4d3201962250
--- /dev/null
+++ b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
@@ -0,0 +1,35 @@
+//==- CFGRecStmtVisitor - Recursive visitor of CFG statements ---*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the template class CFGRecStmtVisitor, which extends
+// CFGStmtVisitor by implementing a default recursive visit of all statements.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
+
+#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
+
+namespace clang {
+template <typename ImplClass>
+class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
+public:
+
+ void VisitStmt(Stmt* S) {
+ static_cast< ImplClass* >(this)->VisitChildren(S);
+ }
+
+ // Defining operator() allows the visitor to be used as a C++ style functor.
+ void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
new file mode 100644
index 000000000000..f42bbde8f148
--- /dev/null
+++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -0,0 +1,156 @@
+//===--- CFGStmtVisitor.h - Visitor for Stmts in a CFG ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CFGStmtVisitor interface, which extends
+// StmtVisitor. This interface is useful for visiting statements in a CFG
+// where some statements have implicit control-flow and thus should
+// be treated specially.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/CFG.h"
+
+namespace clang {
+
+#define DISPATCH_CASE(CLASS) \
+case Stmt::CLASS ## Class: return \
+static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
+
+#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\
+{ return\
+ static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\
+ cast<Expr>(S)); }
+
+template <typename ImplClass, typename RetTy=void>
+class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
+ Stmt* CurrentBlkStmt;
+
+ struct NullifyStmt {
+ Stmt*& S;
+
+ NullifyStmt(Stmt*& s) : S(s) {}
+ ~NullifyStmt() { S = NULL; }
+ };
+
+public:
+ CFGStmtVisitor() : CurrentBlkStmt(NULL) {}
+
+ Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; }
+
+ RetTy Visit(Stmt* S) {
+ if (S == CurrentBlkStmt ||
+ !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
+ return StmtVisitor<ImplClass,RetTy>::Visit(S);
+ else
+ return RetTy();
+ }
+
+ /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
+ /// CFGBlocks. Root statements are the statements that appear explicitly in
+ /// the list of statements in a CFGBlock. For substatements, or when there
+ /// is no implementation provided for a BlockStmt_XXX method, we default
+ /// to using StmtVisitor's Visit method.
+ RetTy BlockStmt_Visit(Stmt* S) {
+ CurrentBlkStmt = S;
+ NullifyStmt cleanup(CurrentBlkStmt);
+
+ switch (S->getStmtClass()) {
+
+ DISPATCH_CASE(StmtExpr)
+ DISPATCH_CASE(ConditionalOperator)
+ DISPATCH_CASE(ObjCForCollectionStmt)
+
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator* B = cast<BinaryOperator>(S);
+ if (B->isLogicalOp())
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
+ else if (B->getOpcode() == BinaryOperator::Comma)
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
+ // Fall through.
+ }
+
+ default:
+ if (isa<Expr>(S))
+ return
+ static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S));
+ else
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
+ }
+ }
+
+ DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
+ DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
+
+ RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
+ }
+
+ RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) {
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E);
+ }
+
+ RetTy BlockStmt_VisitExpr(Expr* E) {
+ return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E);
+ }
+
+ RetTy BlockStmt_VisitStmt(Stmt* S) {
+ return static_cast<ImplClass*>(this)->Visit(S);
+ }
+
+ RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) {
+ return
+ static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
+ }
+
+ RetTy BlockStmt_VisitComma(BinaryOperator* B) {
+ return
+ static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Utility methods. Not called by default (but subclasses may use them).
+ //===--------------------------------------------------------------------===//
+
+ /// VisitChildren: Call "Visit" on each child of S.
+ void VisitChildren(Stmt* S) {
+
+ switch (S->getStmtClass()) {
+ default:
+ break;
+
+ case Stmt::StmtExprClass: {
+ CompoundStmt* CS = cast<StmtExpr>(S)->getSubStmt();
+ if (CS->body_empty()) return;
+ static_cast<ImplClass*>(this)->Visit(CS->body_back());
+ return;
+ }
+
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator* B = cast<BinaryOperator>(S);
+ if (B->getOpcode() != BinaryOperator::Comma) break;
+ static_cast<ImplClass*>(this)->Visit(B->getRHS());
+ return;
+ }
+ }
+
+ for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
+ if (*I) static_cast<ImplClass*>(this)->Visit(*I);
+ }
+};
+
+#undef DEFAULT_BLOCKSTMT_VISIT
+#undef DISPATCH_CASE
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/Visitors/CFGVarDeclVisitor.h b/include/clang/Analysis/Visitors/CFGVarDeclVisitor.h
new file mode 100644
index 000000000000..25101235ddd2
--- /dev/null
+++ b/include/clang/Analysis/Visitors/CFGVarDeclVisitor.h
@@ -0,0 +1,64 @@
+//==- CFGVarDeclVisitor - Generic visitor of VarDecls in a CFG --*- C++ --*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the template class CFGVarDeclVisitor, which provides
+// a generic way to visit all the VarDecl's in a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
+#define LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
+
+#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/CFG.h"
+
+namespace clang {
+
+template <typename ImplClass>
+class CFGVarDeclVisitor : public CFGStmtVisitor<ImplClass> {
+ const CFG& cfg;
+public:
+ CFGVarDeclVisitor(const CFG& c) : cfg(c) {}
+
+ void VisitStmt(Stmt* S) {
+ static_cast<ImplClass*>(this)->VisitChildren(S);
+ }
+
+ void VisitDeclRefExpr(DeclRefExpr* DR) {
+ static_cast<ImplClass*>(this)->VisitDeclChain(DR->getDecl());
+ }
+
+ void VisitDeclStmt(DeclStmt* DS) {
+ static_cast<ImplClass*>(this)->VisitDeclChain(DS->getDecl());
+ }
+
+ void VisitDeclChain(ScopedDecl* D) {
+ for (; D != NULL ; D = D->getNextDeclarator())
+ static_cast<ImplClass*>(this)->VisitScopedDecl(D);
+ }
+
+ void VisitScopedDecl(ScopedDecl* D) {
+ if (VarDecl* V = dyn_cast<VarDecl>(D))
+ static_cast<ImplClass*>(this)->VisitVarDecl(V);
+ }
+
+ void VisitVarDecl(VarDecl* D) {}
+
+ void VisitAllDecls() {
+ for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI)
+ for (CFGBlock::const_iterator SI=BI->begin(),SE = BI->end();SI != SE;++SI)
+ static_cast<ImplClass*>(this)->BlockStmt_Visit(const_cast<Stmt*>(*SI));
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt
new file mode 100644
index 000000000000..9e643bb3c2c1
--- /dev/null
+++ b/include/clang/Basic/CMakeLists.txt
@@ -0,0 +1,20 @@
+macro(clang_diag_gen component)
+ tablegen(Diagnostic${component}Kinds.inc
+ -gen-clang-diags-defs -clang-component=${component})
+ add_custom_target(ClangDiagnostic${component}
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Diagnostic${component}Kinds.inc)
+endmacro(clang_diag_gen)
+
+set(LLVM_TARGET_DEFINITIONS Diagnostic.td)
+clang_diag_gen(Analysis)
+clang_diag_gen(AST)
+clang_diag_gen(Common)
+clang_diag_gen(Driver)
+clang_diag_gen(Frontend)
+clang_diag_gen(Lex)
+clang_diag_gen(Parse)
+clang_diag_gen(Sema)
+tablegen(DiagnosticGroups.inc
+ -gen-clang-diag-groups)
+add_custom_target(ClangDiagnosticGroups
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/DiagnosticGroups.inc)
diff --git a/include/clang/Basic/ConvertUTF.h b/include/clang/Basic/ConvertUTF.h
new file mode 100644
index 000000000000..73e2fcd12fee
--- /dev/null
+++ b/include/clang/Basic/ConvertUTF.h
@@ -0,0 +1,159 @@
+/*===--- ConvertUTF.h - Universal Character Names conversions ---------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ *==------------------------------------------------------------------------==*/
+/*
+ * Copyright 2001-2004 Unicode, Inc.
+ *
+ * Disclaimer
+ *
+ * This source code is provided as is by Unicode, Inc. No claims are
+ * made as to fitness for any particular purpose. No warranties of any
+ * kind are expressed or implied. The recipient agrees to determine
+ * applicability of information provided. If this file has been
+ * purchased on magnetic or optical media from Unicode, Inc., the
+ * sole remedy for any claim will be exchange of defective media
+ * within 90 days of receipt.
+ *
+ * Limitations on Rights to Redistribute This Code
+ *
+ * Unicode, Inc. hereby grants the right to freely use the information
+ * supplied in this file in the creation of products supporting the
+ * Unicode Standard, and to make copies of this file in any form
+ * for internal or external distribution as long as this notice
+ * remains attached.
+ */
+
+/* ---------------------------------------------------------------------
+
+ Conversions between UTF32, UTF-16, and UTF-8. Header file.
+
+ Several funtions are included here, forming a complete set of
+ conversions between the three formats. UTF-7 is not included
+ here, but is handled in a separate source file.
+
+ Each of these routines takes pointers to input buffers and output
+ buffers. The input buffers are const.
+
+ Each routine converts the text between *sourceStart and sourceEnd,
+ putting the result into the buffer between *targetStart and
+ targetEnd. Note: the end pointers are *after* the last item: e.g.
+ *(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+ and if not, whether the problem was in the source or target buffers.
+ (Only the first encountered problem is indicated.)
+
+ After the conversion, *sourceStart and *targetStart are both
+ updated to point to the end of last text successfully converted in
+ the respective buffers.
+
+ Input parameters:
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
+
+ These conversion functions take a ConversionFlags argument. When this
+ flag is set to strict, both irregular sequences and isolated surrogates
+ will cause an error. When the flag is set to lenient, both irregular
+ sequences and isolated surrogates are converted.
+
+ Whether the flag is strict or lenient, all illegal sequences will cause
+ an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
+ or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
+ must check for illegal sequences.
+
+ When the flag is set to lenient, characters over 0x10FFFF are converted
+ to the replacement character; otherwise (when the flag is set to strict)
+ they constitute an error.
+
+ Output parameters:
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
+
+ Author: Mark E. Davis, 1994.
+ Rev History: Rick McGowan, fixes & updates May 2001.
+ Fixes & updates, Sept 2001.
+
+------------------------------------------------------------------------ */
+
+/* ---------------------------------------------------------------------
+ The following 4 definitions are compiler-specific.
+ The C standard does not guarantee that wchar_t has at least
+ 16 bits, so wchar_t is no less portable than unsigned short!
+ All should be unsigned values to avoid sign extension during
+ bit mask & shift operations.
+------------------------------------------------------------------------ */
+
+typedef unsigned long UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
+
+/* Some fundamental constants */
+#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
+#define UNI_MAX_BMP (UTF32)0x0000FFFF
+#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
+#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
+#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
+
+typedef enum {
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
+} ConversionResult;
+
+typedef enum {
+ strictConversion = 0,
+ lenientConversion
+} ConversionFlags;
+
+/* This is for C++ and does no harm in C */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ConversionResult ConvertUTF8toUTF16 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+
+#ifdef CLANG_NEEDS_THESE_ONE_DAY
+ConversionResult ConvertUTF16toUTF8 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF8toUTF32 (
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF8 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF16toUTF32 (
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+
+ConversionResult ConvertUTF32toUTF16 (
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+#endif
+
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* --------------------------------------------------------------------- */
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
new file mode 100644
index 000000000000..22e7fb3f85ea
--- /dev/null
+++ b/include/clang/Basic/Diagnostic.h
@@ -0,0 +1,697 @@
+//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Diagnostic-related interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTIC_H
+#define LLVM_CLANG_DIAGNOSTIC_H
+
+#include "clang/Basic/SourceLocation.h"
+#include <string>
+#include <cassert>
+
+namespace llvm {
+ template <typename T> class SmallVectorImpl;
+}
+
+namespace clang {
+ class DiagnosticClient;
+ class SourceRange;
+ class DiagnosticBuilder;
+ class IdentifierInfo;
+ class LangOptions;
+
+ // Import the diagnostic enums themselves.
+ namespace diag {
+ // Start position for diagnostics.
+ enum {
+ DIAG_START_DRIVER = 300,
+ DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
+ DIAG_START_LEX = DIAG_START_FRONTEND + 100,
+ DIAG_START_PARSE = DIAG_START_LEX + 300,
+ DIAG_START_AST = DIAG_START_PARSE + 300,
+ DIAG_START_SEMA = DIAG_START_AST + 100,
+ DIAG_START_ANALYSIS = DIAG_START_SEMA + 1000,
+ DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
+ };
+
+ class CustomDiagInfo;
+
+ /// diag::kind - All of the diagnostics that can be emitted by the frontend.
+ typedef unsigned kind;
+
+ // Get typedefs for common diagnostics.
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+ NUM_BUILTIN_COMMON_DIAGNOSTICS
+#undef DIAG
+ };
+
+ /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
+ /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
+ /// (emit as an error). It allows clients to map errors to
+ /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
+ /// one).
+ enum Mapping {
+ // NOTE: 0 means "uncomputed".
+ MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
+ MAP_WARNING = 2, //< Map this diagnostic to a warning.
+ MAP_ERROR = 3, //< Map this diagnostic to an error.
+ MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
+
+ /// Map this diagnostic to "warning", but make it immune to -Werror. This
+ /// happens when you specify -Wno-error=foo.
+ MAP_WARNING_NO_WERROR = 5
+ };
+ }
+
+/// \brief Annotates a diagnostic with some code that should be
+/// inserted, removed, or replaced to fix the problem.
+///
+/// This kind of hint should be used when we are certain that the
+/// introduction, removal, or modification of a particular (small!)
+/// amount of code will correct a compilation error. The compiler
+/// should also provide full recovery from such errors, such that
+/// suppressing the diagnostic output can still result in successful
+/// compilation.
+class CodeModificationHint {
+public:
+ /// \brief Tokens that should be removed to correct the error.
+ SourceRange RemoveRange;
+
+ /// \brief The location at which we should insert code to correct
+ /// the error.
+ SourceLocation InsertionLoc;
+
+ /// \brief The actual code to insert at the insertion location, as a
+ /// string.
+ std::string CodeToInsert;
+
+ /// \brief Empty code modification hint, indicating that no code
+ /// modification is known.
+ CodeModificationHint() : RemoveRange(), InsertionLoc() { }
+
+ /// \brief Create a code modification hint that inserts the given
+ /// code string at a specific location.
+ static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
+ const std::string &Code) {
+ CodeModificationHint Hint;
+ Hint.InsertionLoc = InsertionLoc;
+ Hint.CodeToInsert = Code;
+ return Hint;
+ }
+
+ /// \brief Create a code modification hint that removes the given
+ /// source range.
+ static CodeModificationHint CreateRemoval(SourceRange RemoveRange) {
+ CodeModificationHint Hint;
+ Hint.RemoveRange = RemoveRange;
+ return Hint;
+ }
+
+ /// \brief Create a code modification hint that replaces the given
+ /// source range with the given code string.
+ static CodeModificationHint CreateReplacement(SourceRange RemoveRange,
+ const std::string &Code) {
+ CodeModificationHint Hint;
+ Hint.RemoveRange = RemoveRange;
+ Hint.InsertionLoc = RemoveRange.getBegin();
+ Hint.CodeToInsert = Code;
+ return Hint;
+ }
+};
+
+/// Diagnostic - This concrete class is used by the front-end to report
+/// 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 {
+public:
+ /// Level - The level of the diagnostic, after it has been through mapping.
+ enum Level {
+ Ignored, Note, Warning, Error, Fatal
+ };
+
+ /// ExtensionHandling - How do we handle otherwise-unmapped extension? This
+ /// is controlled by -pedantic and -pedantic-errors.
+ enum ExtensionHandling {
+ Ext_Ignore, Ext_Warn, Ext_Error
+ };
+
+ enum ArgumentKind {
+ ak_std_string, // std::string
+ ak_c_string, // const char *
+ ak_sint, // int
+ ak_uint, // unsigned
+ ak_identifierinfo, // IdentifierInfo
+ ak_qualtype, // QualType
+ ak_declarationname, // DeclarationName
+ ak_nameddecl // NamedDecl *
+ };
+
+private:
+ unsigned char AllExtensionsSilenced; // Used by __extension__
+ bool IgnoreAllWarnings; // Ignore all warnings: -w
+ bool WarningsAsErrors; // Treat warnings like errors:
+ bool SuppressSystemWarnings; // Suppress warnings in system headers.
+ ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
+ DiagnosticClient *Client;
+
+ /// DiagMappings - Mapping information for diagnostics. Mapping info is
+ /// packed into four bits per diagnostic. The low three bits are the mapping
+ /// (an instance of diag::Mapping), or zero if unset. The high bit is set
+ /// when the mapping was established as a user mapping. If the high bit is
+ /// clear, then the low bits are set to the default value, and should be
+ /// mapped with -pedantic, -Werror, etc.
+ mutable unsigned char DiagMappings[diag::DIAG_UPPER_LIMIT/2];
+
+ /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
+ /// fatal error is emitted, and is sticky.
+ bool ErrorOccurred;
+ bool FatalErrorOccurred;
+
+ /// LastDiagLevel - This is the level of the last diagnostic emitted. This is
+ /// used to emit continuation diagnostics with the same level as the
+ /// diagnostic that they follow.
+ Diagnostic::Level LastDiagLevel;
+
+ unsigned NumDiagnostics; // Number of diagnostics reported
+ unsigned NumErrors; // Number of diagnostics that are errors
+
+ /// CustomDiagInfo - Information for uniquing and looking up custom diags.
+ diag::CustomDiagInfo *CustomDiagInfo;
+
+ /// ArgToStringFn - A function pointer that converts an opaque diagnostic
+ /// argument to a strings. This takes the modifiers and argument that was
+ /// present in the diagnostic.
+ /// This is a hack to avoid a layering violation between libbasic and libsema.
+ typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
+ const char *Modifier, unsigned ModifierLen,
+ const char *Argument, unsigned ArgumentLen,
+ llvm::SmallVectorImpl<char> &Output,
+ void *Cookie);
+ void *ArgToStringCookie;
+ ArgToStringFnTy ArgToStringFn;
+public:
+ explicit Diagnostic(DiagnosticClient *client = 0);
+ ~Diagnostic();
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic characterization methods, used by a client to customize how
+ //
+
+ DiagnosticClient *getClient() { return Client; };
+ const DiagnosticClient *getClient() const { return Client; };
+
+ void setClient(DiagnosticClient* client) { Client = client; }
+
+ /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
+ /// ignored. If this and WarningsAsErrors are both set, then this one wins.
+ void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
+ bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
+
+ /// setWarningsAsErrors - When set to true, any warnings reported are issued
+ /// as errors.
+ void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
+ bool getWarningsAsErrors() const { return WarningsAsErrors; }
+
+ /// setSuppressSystemWarnings - When set to true mask warnings that
+ /// come from system headers.
+ void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
+ bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
+
+ /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
+ /// extension diagnostics are mapped onto ignore/warning/error. This
+ /// corresponds to the GCC -pedantic and -pedantic-errors option.
+ void setExtensionHandlingBehavior(ExtensionHandling H) {
+ ExtBehavior = H;
+ }
+
+ /// AllExtensionsSilenced - This is a counter bumped when an __extension__
+ /// block is encountered. When non-zero, all extension diagnostics are
+ /// entirely silenced, no matter how they are mapped.
+ void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
+ void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
+
+ /// setDiagnosticMapping - This allows the client to specify that certain
+ /// warnings are ignored. Notes can never be mapped, errors can only be
+ /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
+ void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
+ assert(Diag < diag::DIAG_UPPER_LIMIT &&
+ "Can only map builtin diagnostics");
+ assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) &&
+ "Cannot map errors!");
+ setDiagnosticMappingInternal(Diag, Map, true);
+ }
+
+ /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
+ /// "unknown-pragmas" to have the specified mapping. This returns true and
+ /// ignores the request if "Group" was unknown, false otherwise.
+ bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map);
+
+ bool hasErrorOccurred() const { return ErrorOccurred; }
+ bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
+
+ unsigned getNumErrors() const { return NumErrors; }
+ unsigned getNumDiagnostics() const { return NumDiagnostics; }
+
+ /// getCustomDiagID - Return an ID for a diagnostic with the specified message
+ /// and level. If this is the first request for this diagnosic, it is
+ /// registered and created, otherwise the existing ID is returned.
+ unsigned getCustomDiagID(Level L, const char *Message);
+
+
+ /// ConvertArgToString - This method converts a diagnostic argument (as an
+ /// intptr_t) into the string that represents it.
+ void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
+ const char *Modifier, unsigned ModLen,
+ const char *Argument, unsigned ArgLen,
+ llvm::SmallVectorImpl<char> &Output) const {
+ ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, Output,
+ ArgToStringCookie);
+ }
+
+ void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
+ ArgToStringFn = Fn;
+ ArgToStringCookie = Cookie;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic classification and reporting interfaces.
+ //
+
+ /// getDescription - Given a diagnostic ID, return a description of the
+ /// issue.
+ const char *getDescription(unsigned DiagID) const;
+
+ /// isNoteWarningOrExtension - Return true if the unmapped diagnostic
+ /// level of the specified diagnostic ID is a Warning or Extension.
+ /// This only works on builtin diagnostics, not custom ones, and is not legal to
+ /// call on NOTEs.
+ static bool isBuiltinWarningOrExtension(unsigned DiagID);
+
+ /// \brief Determine whether the given built-in diagnostic ID is a
+ /// Note.
+ static bool isBuiltinNote(unsigned DiagID);
+
+ /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+ /// ID is for an extension of some sort.
+ ///
+ static bool isBuiltinExtensionDiag(unsigned DiagID);
+
+ /// getWarningOptionForDiag - Return the lowest-level warning option that
+ /// enables the specified diagnostic. If there is no -Wfoo flag that controls
+ /// the diagnostic, this returns null.
+ static const char *getWarningOptionForDiag(unsigned DiagID);
+
+ /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+ /// object, classify the specified diagnostic ID into a Level, consumable by
+ /// the DiagnosticClient.
+ Level getDiagnosticLevel(unsigned DiagID) const;
+
+ /// Report - Issue the message to the client. @c DiagID is a member of the
+ /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
+ /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
+ /// @c Pos represents the source location associated with the diagnostic,
+ /// which can be an invalid location if no position information is available.
+ inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() { CurDiagID = ~0U; }
+
+private:
+ /// getDiagnosticMappingInfo - Return the mapping info currently set for the
+ /// specified builtin diagnostic. This returns the high bit encoding, or zero
+ /// if the field is completely uninitialized.
+ unsigned getDiagnosticMappingInfo(diag::kind Diag) const {
+ return (diag::Mapping)((DiagMappings[Diag/2] >> (Diag & 1)*4) & 15);
+ }
+
+ void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
+ bool isUser) const {
+ if (isUser) Map |= 8; // Set the high bit for user mappings.
+ unsigned char &Slot = DiagMappings[DiagId/2];
+ unsigned Shift = (DiagId & 1)*4;
+ Slot &= ~(15 << Shift);
+ Slot |= Map << Shift;
+ }
+
+ /// getDiagnosticLevel - This is an internal implementation helper used when
+ /// DiagClass is already known.
+ Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const;
+
+ // This is private state used by DiagnosticBuilder. We put it here instead of
+ // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
+ // object. This implementation choice means that we can only have one
+ // diagnostic "in flight" at a time, but this seems to be a reasonable
+ // tradeoff to keep these objects small. Assertions verify that only one
+ // diagnostic is in flight at a time.
+ friend class DiagnosticBuilder;
+ friend class DiagnosticInfo;
+
+ /// CurDiagLoc - This is the location of the current diagnostic that is in
+ /// flight.
+ FullSourceLoc CurDiagLoc;
+
+ /// CurDiagID - This is the ID of the current diagnostic that is in flight.
+ /// This is set to ~0U when there is no diagnostic in flight.
+ unsigned CurDiagID;
+
+ enum {
+ /// MaxArguments - The maximum number of arguments we can hold. We currently
+ /// only support up to 10 arguments (%0-%9). A single diagnostic with more
+ /// than that almost certainly has to be simplified anyway.
+ MaxArguments = 10
+ };
+
+ /// NumDiagArgs - This contains the number of entries in Arguments.
+ signed char NumDiagArgs;
+ /// NumRanges - This is the number of ranges in the DiagRanges array.
+ unsigned char NumDiagRanges;
+ /// \brief The number of code modifications hints in the
+ /// CodeModificationHints array.
+ unsigned char NumCodeModificationHints;
+
+ /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
+ /// values, with one for each argument. This specifies whether the argument
+ /// is in DiagArgumentsStr or in DiagArguments.
+ unsigned char DiagArgumentsKind[MaxArguments];
+
+ /// DiagArgumentsStr - This holds the values of each string argument for the
+ /// current diagnostic. This value is only used when the corresponding
+ /// ArgumentKind is ak_std_string.
+ std::string DiagArgumentsStr[MaxArguments];
+
+ /// DiagArgumentsVal - The values for the various substitution positions. This
+ /// is used when the argument is not an std::string. The specific value is
+ /// mangled into an intptr_t and the intepretation depends on exactly what
+ /// sort of argument kind it is.
+ intptr_t DiagArgumentsVal[MaxArguments];
+
+ /// DiagRanges - The list of ranges added to this diagnostic. It currently
+ /// only support 10 ranges, could easily be extended if needed.
+ const SourceRange *DiagRanges[10];
+
+ enum { MaxCodeModificationHints = 3 };
+
+ /// CodeModificationHints - If valid, provides a hint with some code
+ /// to insert, remove, or modify at a particular position.
+ CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
+
+ /// ProcessDiag - This is the method used to report a diagnostic that is
+ /// finally fully formed.
+ void ProcessDiag();
+};
+
+//===----------------------------------------------------------------------===//
+// DiagnosticBuilder
+//===----------------------------------------------------------------------===//
+
+/// DiagnosticBuilder - This is a little helper class used to produce
+/// diagnostics. This is constructed by the Diagnostic::Report method, and
+/// allows insertion of extra information (arguments and source ranges) into the
+/// currently "in flight" diagnostic. When the temporary for the builder is
+/// destroyed, the diagnostic is issued.
+///
+/// Note that many of these will be created as temporary objects (many call
+/// sites), so we want them to be small and we never want their address taken.
+/// This ensures that compilers with somewhat reasonable optimizers will promote
+/// the common fields to registers, eliminating increments of the NumArgs field,
+/// for example.
+class DiagnosticBuilder {
+ mutable Diagnostic *DiagObj;
+ mutable unsigned NumArgs, NumRanges, NumCodeModificationHints;
+
+ void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
+ friend class Diagnostic;
+ explicit DiagnosticBuilder(Diagnostic *diagObj)
+ : DiagObj(diagObj), NumArgs(0), NumRanges(0),
+ NumCodeModificationHints(0) {}
+
+public:
+ /// Copy constructor. When copied, this "takes" the diagnostic info from the
+ /// input and neuters it.
+ DiagnosticBuilder(const DiagnosticBuilder &D) {
+ DiagObj = D.DiagObj;
+ D.DiagObj = 0;
+ NumArgs = D.NumArgs;
+ NumRanges = D.NumRanges;
+ NumCodeModificationHints = D.NumCodeModificationHints;
+ }
+
+ /// \brief Force the diagnostic builder to emit the diagnostic now.
+ ///
+ /// Once this function has been called, the DiagnosticBuilder object
+ /// should not be used again before it is destroyed.
+ void Emit() {
+ // If DiagObj is null, then its soul was stolen by the copy ctor
+ // or the user called Emit().
+ if (DiagObj == 0) return;
+
+ // When emitting diagnostics, we set the final argument count into
+ // the Diagnostic object.
+ DiagObj->NumDiagArgs = NumArgs;
+ DiagObj->NumDiagRanges = NumRanges;
+ DiagObj->NumCodeModificationHints = NumCodeModificationHints;
+
+ // Process the diagnostic, sending the accumulated information to the
+ // DiagnosticClient.
+ DiagObj->ProcessDiag();
+
+ // Clear out the current diagnostic object.
+ DiagObj->Clear();
+
+ // This diagnostic is dead.
+ DiagObj = 0;
+ }
+
+ /// Destructor - The dtor emits the diagnostic if it hasn't already
+ /// been emitted.
+ ~DiagnosticBuilder() { Emit(); }
+
+ /// Operator bool: conversion of DiagnosticBuilder to bool always returns
+ /// true. This allows is to be used in boolean error contexts like:
+ /// return Diag(...);
+ operator bool() const { return true; }
+
+ void AddString(const std::string &S) const {
+ assert(NumArgs < Diagnostic::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
+ DiagObj->DiagArgumentsStr[NumArgs++] = S;
+ }
+
+ void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
+ assert(NumArgs < Diagnostic::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagArgumentsKind[NumArgs] = Kind;
+ DiagObj->DiagArgumentsVal[NumArgs++] = V;
+ }
+
+ void AddSourceRange(const SourceRange &R) const {
+ assert(NumRanges <
+ sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagRanges[NumRanges++] = &R;
+ }
+
+ void AddCodeModificationHint(const CodeModificationHint &Hint) const {
+ assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
+ "Too many code modification hints!");
+ DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
+ }
+};
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const std::string &S) {
+ DB.AddString(S);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const char *Str) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
+ Diagnostic::ak_c_string);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_sint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_sint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ unsigned I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_uint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const IdentifierInfo *II) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
+ Diagnostic::ak_identifierinfo);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const SourceRange &R) {
+ DB.AddSourceRange(R);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const CodeModificationHint &Hint) {
+ DB.AddCodeModificationHint(Hint);
+ return DB;
+}
+
+/// Report - Issue the message to the client. DiagID is a member of the
+/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
+/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
+inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
+ assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
+ CurDiagLoc = Loc;
+ CurDiagID = DiagID;
+ return DiagnosticBuilder(this);
+}
+
+//===----------------------------------------------------------------------===//
+// DiagnosticInfo
+//===----------------------------------------------------------------------===//
+
+/// DiagnosticInfo - This is a little helper class (which is basically a smart
+/// pointer that forward info from Diagnostic) that allows clients to enquire
+/// about the currently in-flight diagnostic.
+class DiagnosticInfo {
+ const Diagnostic *DiagObj;
+public:
+ explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
+
+ const Diagnostic *getDiags() const { return DiagObj; }
+ unsigned getID() const { return DiagObj->CurDiagID; }
+ const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
+
+ unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
+
+ /// getArgKind - Return the kind of the specified index. Based on the kind
+ /// of argument, the accessors below can be used to get the value.
+ Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Argument index out of range!");
+ return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
+ }
+
+ /// getArgStdStr - Return the provided argument string specified by Idx.
+ const std::string &getArgStdStr(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
+ "invalid argument accessor!");
+ return DiagObj->DiagArgumentsStr[Idx];
+ }
+
+ /// getArgCStr - Return the specified C string argument.
+ const char *getArgCStr(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
+ "invalid argument accessor!");
+ return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
+ }
+
+ /// getArgSInt - Return the specified signed integer argument.
+ int getArgSInt(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_sint &&
+ "invalid argument accessor!");
+ return (int)DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// getArgUInt - Return the specified unsigned integer argument.
+ unsigned getArgUInt(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_uint &&
+ "invalid argument accessor!");
+ return (unsigned)DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// getArgIdentifier - Return the specified IdentifierInfo argument.
+ const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
+ assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
+ "invalid argument accessor!");
+ return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
+ }
+
+ /// getRawArg - Return the specified non-string argument in an opaque form.
+ intptr_t getRawArg(unsigned Idx) const {
+ assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
+ "invalid argument accessor!");
+ return DiagObj->DiagArgumentsVal[Idx];
+ }
+
+
+ /// getNumRanges - Return the number of source ranges associated with this
+ /// diagnostic.
+ unsigned getNumRanges() const {
+ return DiagObj->NumDiagRanges;
+ }
+
+ const SourceRange &getRange(unsigned Idx) const {
+ assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
+ return *DiagObj->DiagRanges[Idx];
+ }
+
+ unsigned getNumCodeModificationHints() const {
+ return DiagObj->NumCodeModificationHints;
+ }
+
+ const CodeModificationHint &getCodeModificationHint(unsigned Idx) const {
+ return DiagObj->CodeModificationHints[Idx];
+ }
+
+ const CodeModificationHint *getCodeModificationHints() const {
+ return DiagObj->NumCodeModificationHints?
+ &DiagObj->CodeModificationHints[0] : 0;
+ }
+
+ /// FormatDiagnostic - Format this diagnostic into a string, substituting the
+ /// formal arguments into the %0 slots. The result is appended onto the Str
+ /// array.
+ void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
+};
+
+/// DiagnosticClient - This is an abstract interface implemented by clients of
+/// the front-end, which formats and prints fully processed diagnostics.
+class DiagnosticClient {
+public:
+ virtual ~DiagnosticClient();
+
+ /// setLangOptions - This is set by clients of diagnostics when they know the
+ /// language parameters of the diagnostics that may be sent through. Note
+ /// that this can change over time if a DiagClient has multiple languages sent
+ /// through it. It may also be set to null (e.g. when processing command line
+ /// options).
+ virtual void setLangOptions(const LangOptions *LO) {}
+
+ /// IncludeInDiagnosticCounts - This method (whose default implementation
+ /// returns true) indicates whether the diagnostics handled by this
+ /// DiagnosticClient should be included in the number of diagnostics
+ /// reported by Diagnostic.
+ virtual bool IncludeInDiagnosticCounts() const;
+
+ /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+ /// capturing it to a log as needed.
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) = 0;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
new file mode 100644
index 000000000000..67d8eaafc9ec
--- /dev/null
+++ b/include/clang/Basic/Diagnostic.td
@@ -0,0 +1,73 @@
+//===--- Diagnostic.td - C Language Family Diagnostic Handling ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TableGen core definitions for the diagnostics
+// and diagnostic control.
+//
+//===----------------------------------------------------------------------===//
+
+// Define the diagnostic mappings.
+class DiagMapping;
+def MAP_IGNORE : DiagMapping;
+def MAP_WARNING : DiagMapping;
+def MAP_ERROR : DiagMapping;
+def MAP_FATAL : DiagMapping;
+
+// Define the diagnostic classes.
+class DiagClass;
+def CLASS_NOTE : DiagClass;
+def CLASS_WARNING : DiagClass;
+def CLASS_EXTENSION : DiagClass;
+def CLASS_ERROR : DiagClass;
+
+// Diagnostic Groups.
+class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
+ string GroupName = Name;
+ list<DiagGroup> SubGroups = subgroups;
+}
+class InGroup<DiagGroup G> { DiagGroup Group = G; }
+//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
+
+
+// This defines the diagnostic groups that have references to them.
+include "DiagnosticGroups.td"
+
+
+// All diagnostics emitted by the compiler are an indirect subclass of this.
+class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
+ /// Component is specified by the file with a big let directive.
+ string Component = ?;
+ string Text = text;
+ DiagClass Class = DC;
+ DiagMapping DefaultMapping = defaultmapping;
+ DiagGroup Group;
+}
+
+class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>;
+class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>;
+class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>;
+class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>;
+class Note<string str> : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>;
+
+
+class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; }
+class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; }
+class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; }
+class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; }
+
+// Definitions for Diagnostics.
+include "DiagnosticASTKinds.td"
+include "DiagnosticAnalysisKinds.td"
+include "DiagnosticCommonKinds.td"
+include "DiagnosticDriverKinds.td"
+include "DiagnosticFrontendKinds.td"
+include "DiagnosticLexKinds.td"
+include "DiagnosticParseKinds.td"
+include "DiagnosticSemaKinds.td"
+
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
new file mode 100644
index 000000000000..f075aaaf422f
--- /dev/null
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -0,0 +1,29 @@
+//==--- DiagnosticASTKinds.td - libast diagnostics ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "AST" in {
+
+//def note_comma_in_ice : Note<
+// "C does not permit evaluated commas in an integer constant expression">;
+def note_expr_divide_by_zero : Note<"division by zero">;
+
+// inline asm related.
+def err_asm_invalid_escape : Error<
+ "invalid %% escape in inline assembly string">;
+def err_asm_unknown_symbolic_operand_name : Error<
+ "unknown symbolic operand name in inline assembly string">;
+
+def err_asm_unterminated_symbolic_operand_name : Error<
+ "unterminated symbolic operand name in inline assembly string">;
+def err_asm_empty_symbolic_operand_name : Error<
+ "empty symbolic operand name in inline assembly string">;
+def err_asm_invalid_operand_number : Error<
+ "invalid operand number in inline asm string">;
+
+}
diff --git a/include/clang/Basic/DiagnosticAnalysisKinds.td b/include/clang/Basic/DiagnosticAnalysisKinds.td
new file mode 100644
index 000000000000..46dc0e60a7eb
--- /dev/null
+++ b/include/clang/Basic/DiagnosticAnalysisKinds.td
@@ -0,0 +1,15 @@
+//==--- DiagnosticAnalysisKinds.td - libanalysis diagnostics --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Analysis" in {
+
+// CHECK: use of uninitialized values
+def warn_uninit_val : Warning<"use of uninitialized variable">;
+
+}
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
new file mode 100644
index 000000000000..e059d5e60520
--- /dev/null
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -0,0 +1,58 @@
+//==--- DiagnosticCommonKinds.td - common diagnostics ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Common Helpers
+//===----------------------------------------------------------------------===//
+
+let Component = "Common" in {
+
+def note_previous_definition : Note<"previous definition is here">;
+def note_previous_declaration : Note<"previous declaration is here">;
+def note_previous_implicit_declaration : Note<
+ "previous implicit declaration is here">;
+def note_previous_use : Note<"previous use is here">;
+def note_duplicate_case_prev : Note<"previous case defined here">;
+def note_forward_declaration : Note<"forward declaration of %0">;
+def note_type_being_defined : Note<
+ "definition of %0 is not complete until the closing '}'">;
+/// note_matching - this is used as a continuation of a previous diagnostic,
+/// e.g. to specify the '(' when we expected a ')'.
+def note_matching : Note<"to match this '%0'">;
+
+def note_using_decl : Note<"using">;
+def note_also_found_decl : Note<"also found">;
+
+// Parse && Lex
+def err_expected_colon : Error<"expected ':'">;
+
+// Parse && Sema
+def err_no_declarators : Error<"declaration does not declare anything">;
+def err_param_redefinition : Error<"redefinition of parameter %0">;
+def err_invalid_storage_class_in_func_decl : Error<
+ "invalid storage class specifier in function declarator">;
+def err_expected_namespace_name : Error<"expected namespace name">;
+
+// Sema && Lex
+def ext_longlong : Extension<
+ "'long long' is an extension when C99 mode is not enabled">;
+def warn_integer_too_large : Warning<
+ "integer constant is too large for its type">;
+def warn_integer_too_large_for_signed : Warning<
+ "integer constant is so large that it is unsigned">;
+
+// Sema && AST
+def note_invalid_subexpr_in_ice : Note<
+ "subexpression not valid in an integer constant expression">;
+
+// clang-cc
+def err_pp_I_dash_not_supported : Error<
+ "-I- not supported, please use -iquote instead">;
+
+}
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
new file mode 100644
index 000000000000..327db00e0b28
--- /dev/null
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -0,0 +1,64 @@
+//==--- DiagnosticDriverKinds.td - libdriver diagnostics ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Driver" in {
+
+def err_drv_no_such_file : Error<"no such file or directory: '%0'">;
+def err_drv_unsupported_opt : Error<"unsupported option '%0'">;
+def err_drv_unknown_stdin_type : Error<
+ "-E or -x required when input is from standard input">;
+def err_drv_unknown_language : Error<"language not recognized: '%0'">;
+def err_drv_invalid_opt_with_multiple_archs : Error<
+ "option '%0' cannot be used with multiple -arch options">;
+def err_drv_invalid_output_with_multiple_archs : Error<
+ "cannot use '%0' output with multiple -arch options">;
+def err_drv_no_input_files : Error<"no input files">;
+def err_drv_use_of_Z_option : Error<
+ "unsupported use of internal gcc -Z option '%0'">;
+def err_drv_output_argument_with_multiple_files : Error<
+ "cannot specify -o when generating multiple output files">;
+def err_drv_unable_to_make_temp : Error<
+ "unable to make temporary file: %0">;
+def err_drv_unable_to_remove_file : Error<
+ "unable to remove file: %0">;
+def err_drv_command_failure : Error<
+ "unable to execute command: %0">;
+def err_drv_invalid_darwin_version : Error<
+ "invalid Darwin version number: %0">;
+def err_drv_missing_argument : Error<
+ "argument to '%0' is missing (expected %1 %plural{1:value|:values}1)">;
+def err_drv_invalid_Xarch_argument : Error<
+ "invalid Xarch argument: '%0'">;
+def err_drv_argument_only_allowed_with : Error<
+ "invalid argument '%0' only allowed with '%1'">;
+def err_drv_argument_not_allowed_with : Error<
+ "invalid argument '%0' not allowed with '%1'">;
+def err_drv_invalid_version_number : Error<
+ "invalid version number in '%0'">;
+def err_drv_no_linker_llvm_support : Error<
+ "'%0': unable to pass LLVM bit-code files to linker">;
+def err_drv_clang_unsupported : Error<
+ "the clang compiler does not support '%0'">;
+
+def warn_drv_input_file_unused : Warning<
+ "%0: '%1' input unused when '%2' is present">;
+def warn_drv_unused_argument : Warning<
+ "argument unused during compilation: '%0'">;
+def warn_drv_pipe_ignored_with_save_temps : Warning<
+ "-pipe ignored because -save-temps specified">;
+def warn_drv_not_using_clang_cpp : Warning<
+ "not using the clang prepreprocessor due to user override">;
+def warn_drv_not_using_clang_cxx : Warning<
+ "not using the clang compiler for C++ inputs">;
+def warn_drv_not_using_clang_arch : Warning<
+ "not using the clang compiler for the '%0' architecture">;
+def warn_drv_clang_unsupported : Warning<
+ "the clang compiler does not support '%0'">;
+
+}
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
new file mode 100644
index 000000000000..1bc296babd3b
--- /dev/null
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -0,0 +1,136 @@
+//==--- DiagnosticFrontendKinds.td - frontend diagnostics -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Frontend" in {
+
+def err_fe_unknown_triple : Error<
+ "unknown target triple '%0', please use -triple or -arch">;
+def err_fe_error_reading : Error<"error reading '%0'">;
+def err_fe_error_reading_stdin : Error<"error reading stdin">;
+
+def note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
+def note_fixit_in_macro : Note<
+ "FIX-IT unable to apply suggested code changes in a macro">;
+def note_fixit_failed : Note<
+ "FIX-IT unable to apply suggested code changes">;
+def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">;
+def warn_fixit_no_changes : Note<
+ "FIX-IT detected errors it could not fix; no output will be generated">;
+
+// PCH reader
+def warn_pch_target_triple : Error<
+ "PCH file was compiled for the target '%0' but the current translation "
+ "unit is being compiled for target '%1'">;
+def warn_pch_c99 : Error<
+ "C99 support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_cplusplus : Error<
+ "C++ support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_cplusplus0x : Error<
+ "C++0x support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_objective_c : Error<
+ "Objective-C support was %select{disabled|enabled}0 in PCH file but is "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_objective_c2 : Error<
+ "Objective-C 2.0 support was %select{disabled|enabled}0 in PCH file but "
+ "is currently %select{disabled|enabled}1">;
+def warn_pch_nonfragile_abi : Error<
+ "PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C "
+ "ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">;
+def warn_pch_extensions : Error<
+ "extensions were %select{enabled|disabled}0 in PCH file but are "
+ "currently %select{enabled|disabled}1">;
+def warn_pch_gnu_extensions : Error<
+ "GNU extensions were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_microsoft_extensions : Error<
+ "Microsoft extensions were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_heinous_extensions : Error<
+ "heinous extensions were %select{disabled|enabled}0 in PCH file but are "
+ "currently %select{disabled|enabled}1">;
+def warn_pch_lax_vector_conversions : Error<
+ "lax vector conversions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_exceptions : Error<
+ "exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_objc_runtime : Error<
+ "PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
+ "%select{NeXT|GNU}1 runtime is selected">;
+def warn_pch_freestanding : Error<
+ "PCH file was compiled with a %select{hosted|freestanding}0 "
+ "implementation but a %select{hosted|freestanding}1 implementation "
+ "is selected">;
+def warn_pch_builtins : Error<
+ "PCH file was compiled with builtins %select{enabled|disabled}0 but "
+ "builtins are currently %select{enabled|disabled}1">;
+def warn_pch_thread_safe_statics : Error<
+ "PCH file was compiled %select{without|with}0 thread-safe statics but"
+ "thread-safe statics are currently %select{disabled|enabled}1">;
+def warn_pch_blocks : Error<
+ "blocks were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_math_errno : Error<
+ "math functions %select{do not respect|respect}0 'errno' in PCH "
+ "file but they are currently set to %select{not respect|respect}1 "
+ "'errno'">;
+def warn_pch_overflow_checking : Error<
+ "signed integer overflow checking was %select{disabled|enabled}0 in PCH "
+ "file but is currently %select{disabled|enabled}1">;
+def warn_pch_optimize : Error<
+ "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in "
+ "the PCH file but is currently %select{undefined|defined}1">;
+def warn_pch_optimize_size : Error<
+ "the macro '__OPTIMIZE_SIZE__' was %select{not defined|defined}0 in "
+ "the PCH file but is currently %select{undefined|defined}1">;
+def warn_pch_static : Error<
+ "the PCH file was compiled %select{dynamic|static}0 but the "
+ "current translation unit is being compiled as %select{dynamic|static}1">;
+def warn_pch_pic_level : Error<
+ "PCH file was compiled with PIC level %0, but the current translation "
+ "unit will be compiled with PIC level %1">;
+def warn_pch_gnu_inline : Error<
+ "PCH file was compiled with %select{C99|GNU|}0 inline semantics but "
+ "%select{C99|GNU}1 inline semantics are currently selected">;
+def warn_pch_no_inline : Error<
+ "the macro '__NO_INLINE__' was %select{not defined|defined}0 in "
+ "the PCH file but is currently %select{undefined|defined}1">;
+def warn_pch_gc_mode : Error<
+ "the PCH file was built with %select{no||hybrid}0 garbage collection but "
+ "the current translation unit will compiled with %select{no||hybrid}1 "
+ "garbage collection">;
+def warn_pch_version_too_old : Error<
+ "PCH file uses an older PCH format that is no longer supported">;
+def warn_pch_version_too_new : Error<
+ "PCH file uses a newer PCH format that cannot be read">;
+def warn_cmdline_conflicting_macro_def : Error<
+ "definition of the macro '%0' conflicts with the definition used to "
+ "build the precompiled header">;
+def note_pch_macro_defined_as : Note<
+ "definition of macro '%0' in the precompiled header">;
+def warn_cmdline_missing_macro_defs : Warning<
+ "macro definitions used to build the precompiled header are missing">;
+def note_using_macro_def_from_pch : Note<
+ "using this macro definition from precompiled header">;
+def warn_macro_name_used_in_pch : Error<
+ "definition of macro %0 conflicts with an identifier used in the "
+ "precompiled header">;
+def warn_pch_compiler_options_mismatch : Error<
+ "compiler options used when building the precompiled header differ from "
+ "the options used when using the precompiled header">;
+def warn_pch_access_control : Error<
+ "C++ access control was %select{disabled|enabled}0 in the PCH file but "
+ "is currently %select{disabled|enabled}1">;
+
+def err_not_a_pch_file : Error<
+ "'%0' does not appear to be a precompiled header file">, DefaultFatal;
+}
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
new file mode 100644
index 000000000000..700826fa658f
--- /dev/null
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -0,0 +1,133 @@
+//==--- DiagnosticGroups.td - Diagnostic Group Definitions ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+def ImplicitFunctionDeclare : DiagGroup<"implicit-function-declaration">;
+def ImplicitInt : DiagGroup<"implicit-int">;
+
+// Aggregation warning settings.
+def Implicit : DiagGroup<"implicit", [
+ ImplicitFunctionDeclare,
+ ImplicitInt
+]>;
+
+
+
+// Empty DiagGroups: these are recognized by clang but ignored.
+def : DiagGroup<"aggregate-return">;
+def : DiagGroup<"bad-function-cast">;
+def : DiagGroup<"cast-align">;
+def : DiagGroup<"cast-qual">;
+def : DiagGroup<"char-align">;
+def : DiagGroup<"char-subscripts">;
+def Comment : DiagGroup<"comment">;
+def : DiagGroup<"conversion">;
+def : DiagGroup<"declaration-after-statement">;
+def : DiagGroup<"disabled-optimization">;
+def : DiagGroup<"discard-qual">;
+def ExtraTokens : DiagGroup<"extra-tokens">;
+
+def FormatExtraArgs : DiagGroup<"format-extra-args">;
+def FormatZeroLength : DiagGroup<"format-zero-length">;
+
+def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def : DiagGroup<"init-self">;
+def : DiagGroup<"inline">;
+def : DiagGroup<"int-to-pointer-cast">;
+def : DiagGroup<"missing-braces">;
+def : DiagGroup<"missing-declarations">;
+def : DiagGroup<"missing-format-attribute">;
+def : DiagGroup<"missing-noreturn">;
+def MultiChar : DiagGroup<"multichar">;
+def : DiagGroup<"nested-externs">;
+def : DiagGroup<"newline-eof">;
+def : DiagGroup<"long-long">;
+def MismatchedTags : DiagGroup<"mismatched-tags">;
+def : DiagGroup<"missing-field-initializers">;
+def NonNull : DiagGroup<"nonnull">;
+def : DiagGroup<"nonportable-cfstrings">;
+def : DiagGroup<"old-style-definition">;
+def : DiagGroup<"packed">;
+def Parentheses : DiagGroup<"parentheses">;
+def : DiagGroup<"pointer-arith">;
+def : DiagGroup<"pointer-to-int-cast">;
+def : DiagGroup<"redundant-decls">;
+def ReturnType : DiagGroup<"return-type">;
+def : DiagGroup<"sequence-point">;
+def : DiagGroup<"shadow">;
+def : DiagGroup<"shorten-64-to-32">;
+def : DiagGroup<"sign-compare">;
+
+// Just silence warnings about common forms of -Wstrict-aliasing for now.
+def : DiagGroup<"strict-aliasing=0">;
+def : DiagGroup<"strict-aliasing=1">;
+def : DiagGroup<"strict-aliasing=2">;
+def : DiagGroup<"strict-aliasing">;
+
+// Just silence warnings about common forms of -Wstrict-aliasing for now.
+def : DiagGroup<"strict-overflow=0">;
+def : DiagGroup<"strict-overflow=1">;
+def : DiagGroup<"strict-overflow=2">;
+def : DiagGroup<"strict-overflow">;
+
+def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
+def : DiagGroup<"strict-prototypes">;
+def : DiagGroup<"strict-selector-match">;
+def Switch : DiagGroup<"switch">;
+def Trigraphs : DiagGroup<"trigraphs">;
+
+def : DiagGroup<"type-limits">;
+def Uninitialized : DiagGroup<"uninitialized">;
+def UnknownPragmas : DiagGroup<"unknown-pragmas">;
+def : DiagGroup<"unused-function">;
+def : DiagGroup<"unused-label">;
+def : DiagGroup<"unused-parameter">;
+def UnusedValue : DiagGroup<"unused-value">;
+def UnusedVariable : DiagGroup<"unused-variable">;
+def : DiagGroup<"variadic-macros">;
+def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
+def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
+def : DiagGroup<"write-strings">;
+
+// Aggregation warning settings.
+
+
+// Format settings.
+def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>;
+def FormatSecurity : DiagGroup<"format-security", [Format]>;
+def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
+def FormatY2K : DiagGroup<"format-y2k", [Format]>;
+def Format2 : DiagGroup<"format=2",
+ [FormatNonLiteral, FormatSecurity, FormatY2K]>;
+
+
+def Extra : DiagGroup<"extra">;
+
+def Most : DiagGroup<"most", [
+ Comment,
+ Format,
+ Implicit,
+ MismatchedTags,
+ MultiChar,
+ Switch,
+ Trigraphs,
+ Uninitialized,
+ UnknownPragmas,
+ UnusedValue,
+ UnusedVariable,
+ VectorConversions,
+ VolatileRegisterVar
+ ]>;
+
+// -Wall is -Wmost -Wparentheses
+def : DiagGroup<"all", [Most, Parentheses]>;
+
+// Aliases.
+def : DiagGroup<"", [Extra]>; // -W = -Wextra
+def : DiagGroup<"endif-labels", [ExtraTokens]>; // endif-labels = endif-tokens
+
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
new file mode 100644
index 000000000000..3d1f9320cd41
--- /dev/null
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -0,0 +1,277 @@
+//==--- DiagnosticLexKinds.td - liblex diagnostics ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Lexer Diagnostics
+//===----------------------------------------------------------------------===//
+
+let Component = "Lex" in {
+
+def null_in_string : Warning<"null character(s) preserved in string literal">;
+def null_in_char : Warning<"null character(s) preserved in character literal">;
+def null_in_file : Warning<"null character ignored">;
+def warn_nested_block_comment : Warning<"'/*' within block comment">,
+ InGroup<Comment>;
+def escaped_newline_block_comment_end : Warning<
+ "escaped newline between */ characters at block comment end">,
+ InGroup<Comment>;
+def backslash_newline_space : Warning<
+ "backslash and newline separated by space">;
+
+// Trigraphs.
+def trigraph_ignored : Warning<"trigraph ignored">, InGroup<Trigraphs>;
+def trigraph_ignored_block_comment : Warning<
+ "ignored trigraph would end block comment">, InGroup<Trigraphs>;
+def trigraph_ends_block_comment : Warning<"trigraph ends block comment">,
+ InGroup<Trigraphs>;
+def trigraph_converted : Warning<"trigraph converted to '%0' character">,
+ InGroup<Trigraphs>;
+
+def ext_multi_line_bcpl_comment : Extension<"multi-line // comment">,
+ InGroup<Comment>;
+def ext_bcpl_comment : Extension<
+ "// comments are not allowed in this language">,
+ InGroup<Comment>;
+def ext_no_newline_eof : Extension<"no newline at end of file">;
+def ext_backslash_newline_eof : Extension<"backslash-newline at end of file">;
+def ext_dollar_in_identifier : Extension<"'$' in identifier">;
+def charize_microsoft_ext : Extension<"@# is a microsoft extension">;
+
+def ext_token_used : Extension<"extension used">;
+
+def err_unterminated_string : Error<"missing terminating '\"' character">;
+def err_unterminated_char : Error<"missing terminating ' character">;
+def err_empty_character : Error<"empty character constant">;
+def err_unterminated_block_comment : Error<"unterminated /* comment">;
+def err_invalid_character_to_charify : Error<
+ "invalid argument to convert to character">;
+def ext_multichar_character_literal : ExtWarn<
+ "multi-character character constant">, InGroup<MultiChar>;
+def ext_four_char_character_literal : Extension<
+ "multi-character character constant">, InGroup<FourByteMultiChar>;
+
+
+// Literal
+def ext_nonstandard_escape : Extension<
+ "use of non-standard escape character '\\%0'">;
+def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">;
+def err_hex_escape_no_digits : Error<"\\x used with no following hex digits">;
+def err_ucn_escape_no_digits : Error<"\\u used with no following hex digits">;
+def err_ucn_escape_invalid : Error<"invalid universal character">;
+def err_ucn_escape_incomplete : Error<"incomplete universal character name">;
+def err_ucn_escape_too_big : Error<"universal character name is too long">;
+def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">;
+def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">;
+def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">;
+def err_invalid_suffix_integer_constant : Error<
+ "invalid suffix '%0' on integer constant">;
+def err_invalid_suffix_float_constant : Error<
+ "invalid suffix '%0' on floating constant">;
+def warn_extraneous_wide_char_constant : Warning<
+ "extraneous characters in wide character constant ignored">;
+def warn_char_constant_too_large : Warning<
+ "character constant too long for its type">;
+def err_exponent_has_no_digits : Error<"exponent has no digits">;
+def ext_imaginary_constant : Extension<"imaginary constants are an extension">;
+def err_hexconstant_requires_exponent : Error<
+ "hexadecimal floating constants require an exponent">;
+def ext_hexconstant_invalid : Extension<
+ "hexadecimal floating constants are a C99 feature">;
+def ext_binary_literal : Extension<
+ "binary integer literals are an extension">;
+def err_pascal_string_too_long : Error<"Pascal string is too long">;
+def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">;
+def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Diagnostics
+//===----------------------------------------------------------------------===//
+def pp_hash_warning : Warning<"#warning%0">, InGroup<DiagGroup<"#warnings">>;
+def pp_include_next_in_primary : Warning<
+ "#include_next in primary source file">;
+def pp_include_macros_out_of_predefines : Error<
+ "the #__include_macros directive is only for internal use by -imacros">;
+def pp_include_next_absolute_path : Warning<"#include_next with absolute path">;
+def ext_c99_whitespace_required_after_macro_name : ExtWarn<
+ "ISO C99 requires whitespace after the macro name">;
+def ext_missing_whitespace_after_macro_name : ExtWarn<
+ "whitespace required after macro name">;
+def warn_missing_whitespace_after_macro_name : Warning<
+ "whitespace recommended after macro name">;
+
+def pp_pragma_once_in_main_file : Warning<"#pragma once in main file">;
+def pp_pragma_sysheader_in_main_file : Warning<
+ "#pragma system_header ignored in main file">;
+def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
+def pp_out_of_date_dependency : Warning<
+ "current file is older than dependency %0">;
+def pp_undef_builtin_macro : Warning<"undefining builtin macro">;
+def pp_redef_builtin_macro : Warning<"redefining builtin macro">;
+def pp_macro_not_used : Warning<"macro is not used">, DefaultIgnore,
+ InGroup<DiagGroup<"unused-macros">>;
+def warn_pp_undef_identifier : Warning<
+ "%0 is not defined, evaluates to 0">,
+ InGroup<DiagGroup<"undef">>, DefaultIgnore;
+
+def pp_invalid_string_literal : Warning<
+ "invalid string literal, ignoring final '\\'">;
+def warn_pp_expr_overflow : Warning<
+ "integer overflow in preprocessor expression">;
+def warn_pp_convert_lhs_to_positive : Warning<
+ "left side of operator converted from negative value to unsigned: %0">;
+def warn_pp_convert_rhs_to_positive : Warning<
+ "right side of operator converted from negative value to unsigned: %0">;
+
+def ext_pp_import_directive : Extension<"#import is a language extension">;
+def ext_pp_ident_directive : Extension<"#ident is a language extension">;
+def ext_pp_include_next_directive : Extension<
+ "#include_next is a language extension">;
+def ext_pp_warning_directive : Extension<"#warning is a language extension">;
+
+def ext_pp_extra_tokens_at_eol : ExtWarn<
+ "extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
+
+def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
+def ext_pp_bad_vaargs_use : Extension<
+ "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
+def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">;
+def ext_variadic_macro : Extension<"variadic macros were introduced in C99">;
+def ext_named_variadic_macro : Extension<
+ "named variadic macros are a GNU extension">;
+def ext_embedded_directive : Extension<
+ "embedding a directive within macro arguments is not portable">;
+def ext_missing_varargs_arg : Extension<
+ "varargs argument missing, but tolerated as an extension">;
+def ext_empty_fnmacro_arg : Extension<
+ "empty macro arguments were standardized in C99">;
+
+def ext_pp_base_file : Extension<"__BASE_FILE__ is a language extension">;
+def ext_pp_include_level : Extension<
+ "__INCLUDE_LEVEL__ is a language extension">;
+def ext_pp_timestamp : Extension<"__TIMESTAMP__ is a language extension">;
+def ext_pp_counter : Extension<
+ "__COUNTER__ is a language extension">;
+
+def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
+def err_pp_hash_error : Error<"#error%0">;
+def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
+def err_pp_empty_filename : Error<"empty filename">;
+def err_pp_include_too_deep : Error<"#include nested too deeply">;
+def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;
+def err_pp_macro_not_identifier : Error<"macro names must be identifiers">;
+def err_pp_missing_macro_name : Error<"macro name missing">;
+def err_pp_missing_rparen_in_macro_def : Error<
+ "missing ')' in macro parameter list">;
+def err_pp_invalid_tok_in_arg_list : Error<
+ "invalid token in macro parameter list">;
+def err_pp_expected_ident_in_arg_list : Error<
+ "expected identifier in macro parameter list">;
+def err_pp_expected_comma_in_arg_list : Error<
+ "expected comma in macro parameter list">;
+def err_pp_duplicate_name_in_arg_list : Error<
+ "duplicate macro parameter name %0">;
+def err_pp_stringize_not_parameter : Error<
+ "'#' is not followed by a macro parameter">;
+def err_pp_malformed_ident : Error<"invalid #ident directive">;
+def err_pp_unterminated_conditional : Error<
+ "unterminated conditional directive">;
+def pp_err_else_after_else : Error<"#else after #else">;
+def pp_err_elif_after_else : Error<"#elif after #else">;
+def pp_err_else_without_if : Error<"#else without #if">;
+def pp_err_elif_without_if : Error<"#elif without #if">;
+def err_pp_endif_without_if : Error<"#endif without #if">;
+def err_pp_expected_value_in_expr : Error<"expected value in expression">;
+def err_pp_missing_val_before_operator : Error<"missing value before operator">;
+def err_pp_expected_rparen : Error<"expected ')' in preprocessor expression">;
+def err_pp_expected_eol : Error<
+ "expected end of line in preprocessor expression">;
+def err_pp_defined_requires_identifier : Error<
+ "operator 'defined' requires an identifier">;
+def err_pp_missing_rparen : Error<"missing ')' after 'defined'">;
+def err_pp_colon_without_question : Error<"':' without preceding '?'">;
+def err_pp_division_by_zero : Error<
+ "division by zero in preprocessor expression">;
+def err_pp_remainder_by_zero : Error<
+ "remainder by zero in preprocessor expression">;
+def err_pp_expr_bad_token_binop : Error<
+ "token is not a valid binary operator in a preprocessor subexpression">;
+def err_pp_expr_bad_token_start_expr : Error<
+ "invalid token at start of a preprocessor expression">;
+def err_pp_invalid_poison : Error<"can only poison identifier tokens">;
+def err_pp_used_poisoned_id : Error<"attempt to use a poisoned identifier">;
+def err__Pragma_malformed : Error<
+ "_Pragma takes a parenthesized string literal">;
+def err_pragma_comment_malformed : Error<
+ "pragma comment requires parenthesized identifier and optional string">;
+def warn_pragma_ignored : Warning<"unknown pragma ignored">,
+ InGroup<UnknownPragmas>, DefaultIgnore;
+def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
+ InGroup<UnknownPragmas>;
+def ext_stdc_pragma_syntax :
+ ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">,
+ InGroup<UnknownPragmas>;
+def ext_stdc_pragma_syntax_eom :
+ ExtWarn<"expected end of macro in STDC pragma">,
+ InGroup<UnknownPragmas>;
+def warn_stdc_fenv_access_not_supported :
+ Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_invalid :
+ ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or"
+ " 'fatal'">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_invalid_option :
+ ExtWarn<"pragma diagnostic expected option name (e.g. \"-Wundef\")">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_invalid_token :
+ ExtWarn<"unexpected token in pragma diagnostic">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_diagnostic_unknown_warning :
+ ExtWarn<"unknown warning group '%0', ignored">,
+ InGroup<UnknownPragmas>;
+
+def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
+def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
+def err_paste_at_start : Error<
+ "'##' cannot appear at start of macro expansion">;
+def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">;
+def ext_paste_comma : Extension<
+ "Use of comma pasting extension is non-portable">;
+def err_unterm_macro_invoc : Error<
+ "unterminated function-like macro invocation">;
+def err_too_many_args_in_macro_invoc : Error<
+ "too many arguments provided to function-like macro invocation">;
+def err_too_few_args_in_macro_invoc : Error<
+ "too few arguments provided to function-like macro invocation">;
+def err_pp_bad_paste : Error<
+ "pasting formed '%0', an invalid preprocessing token">;
+def err_pp_operator_used_as_macro_name : Error<
+ "C++ operator '%0' cannot be used as a macro name">;
+def err_pp_illegal_floating_literal : Error<
+ "floating point literal in preprocessor expression">;
+def err_pp_line_requires_integer : Error<
+ "#line directive requires a positive integer argument">;
+def err_pp_line_invalid_filename : Error<
+ "invalid filename for #line directive">;
+def warn_pp_line_decimal : Warning<
+ "#line directive interprets number as decimal, not octal">;
+def err_pp_line_digit_sequence : Error<
+ "#line directive requires a simple digit sequence">;
+def err_pp_linemarker_requires_integer : Error<
+ "line marker directive requires a positive integer argument">;
+def err_pp_linemarker_invalid_filename : Error<
+ "invalid filename for line marker directive">;
+def err_pp_linemarker_invalid_flag : Error<
+ "invalid flag line marker directive">;
+def err_pp_linemarker_invalid_pop : Error<
+ "invalid line marker flag '2': cannot pop empty include stack">;
+def ext_pp_line_too_big : Extension<
+ "C requires #line number to be less than %0, allowed as extension">;
+
+}
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
new file mode 100644
index 000000000000..2912344e06f8
--- /dev/null
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -0,0 +1,280 @@
+//==--- DiagnosticParseKinds.td - libparse diagnostics --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Parser Diagnostics
+//===----------------------------------------------------------------------===//
+
+let Component = "Parse" in {
+
+def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">;
+
+def ext_empty_source_file : Extension<"ISO C forbids an empty source file">;
+def ext_top_level_semi : Extension<
+ "extra ';' outside of a function">;
+def ext_extra_struct_semi : Extension<
+ "extra ';' inside a struct or union">;
+
+def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
+def ext_plain_complex : ExtWarn<
+ "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
+def ext_integer_complex : Extension<
+ "complex integer types are an extension">;
+def ext_thread_before : Extension<"'__thread' before 'static'">;
+
+def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">;
+
+def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
+def err_invalid_short_spec : Error<"'short %0' is invalid">;
+def err_invalid_long_spec : Error<"'long %0' is invalid">;
+def err_invalid_longlong_spec : Error<"'long long %0' is invalid">;
+def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
+
+def ext_ident_list_in_param : Extension<
+ "type-less parameter names in function declaration">;
+def ext_c99_variable_decl_in_for_loop : Extension<
+ "variable declaration in for loop is a C99-specific feature">;
+def ext_c99_compound_literal : Extension<
+ "compound literals are a C99-specific feature">;
+def ext_enumerator_list_comma : Extension<
+ "commas at the end of enumerator lists are a %select{C99|C++0x}0-specific feature">;
+
+def ext_gnu_indirect_goto : Extension<
+ "use of GNU indirect-goto extension">;
+def ext_gnu_address_of_label : Extension<
+ "use of GNU address-of-label extension">;
+def ext_gnu_statement_expr : Extension<
+ "use of GNU statement expression extension">;
+def ext_gnu_conditional_expr : Extension<
+ "use of GNU ?: expression extension, eliding middle term">;
+def ext_gnu_empty_initializer : Extension<
+ "use of GNU empty initializer extension">;
+def ext_gnu_array_range : Extension<"use of GNU array range extension">;
+def ext_gnu_missing_equal_designator : ExtWarn<
+ "use of GNU 'missing =' extension in designator">;
+def err_expected_equal_designator : Error<"expected '=' or another designator">;
+def ext_gnu_old_style_field_designator : ExtWarn<
+ "use of GNU old-style field designator extension">;
+def ext_gnu_case_range : Extension<"use of GNU case range extension">;
+
+// Generic errors.
+def err_parse_error : Error<"parse error">;
+def err_expected_expression : Error<"expected expression">;
+def err_expected_type : Error<"expected a type">;
+def err_expected_external_declaration : Error<"expected external declaration">;
+def err_expected_ident : Error<"expected identifier">;
+def err_expected_ident_lparen : Error<"expected identifier or '('">;
+def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
+def err_expected_lbrace : Error<"expected '{'">;
+def err_expected_lparen : Error<"expected '('">;
+def err_expected_rparen : Error<"expected ')'">;
+def err_expected_rsquare : Error<"expected ']'">;
+def err_expected_rbrace : Error<"expected '}'">;
+def err_expected_greater : Error<"expected '>'">;
+def err_expected_semi_declation : Error<
+ "expected ';' at end of declaration">;
+def err_expected_semi_decl_list : Error<
+ "expected ';' at end of declaration list">;
+def ext_expected_semi_decl_list : Extension<
+ "expected ';' at end of declaration list">;
+def err_expected_member_name_or_semi : Error<
+ "expected member name or ';' after declaration specifiers">;
+def err_function_declared_typedef : Error<
+ "function definition declared 'typedef'">;
+def err_expected_fn_body : Error<
+ "expected function body after function declarator">;
+def err_expected_method_body : Error<"expected method body">;
+def err_invalid_token_after_toplevel_declarator : Error<
+ "invalid token after top level declarator">;
+def err_expected_statement : Error<"expected statement">;
+def err_expected_lparen_after : Error<"expected '(' after '%0'">;
+def err_expected_lparen_after_id : Error<"expected '(' after %0">;
+def err_expected_less_after : Error<"expected '<' after '%0'">;
+def err_expected_comma : Error<"expected ','">;
+def err_expected_lbrace_in_compound_literal : Error<
+ "expected '{' in compound literal">;
+def err_expected_while : Error<"expected 'while' in do/while loop">;
+def err_expected_semi_after : Error<"expected ';' after %0">;
+def err_expected_semi_after_expr : Error<"expected ';' after expression">;
+def err_expected_semi_after_method_proto : Error<
+ "expected ';' after method prototype">;
+def err_expected_semi_after_static_assert : Error<
+ "expected ';' after static_assert">;
+def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
+def err_expected_colon_after : Error<"expected ':' after %0">;
+def err_label_end_of_compound_statement : Error<
+ "label at end of compound statement: expected statement">;
+def err_expected_string_literal : Error<"expected string literal">;
+def err_expected_asm_operand : Error<
+ "expected string literal or '[' for asm operand">;
+def err_expected_selector_for_method : Error<
+ "expected selector for Objective-C method">;
+
+def err_unexpected_at : Error<"unexpected '@' in program">;
+
+def err_invalid_reference_qualifier_application : Error<
+ "'%0' qualifier may not be applied to a reference">;
+def err_illegal_decl_reference_to_reference : Error<
+ "%0 declared as a reference to a reference">;
+def err_rvalue_reference : Error<
+ "rvalue references are only allowed in C++0x">;
+def err_argument_required_after_attribute : Error<
+ "argument required after attribute">;
+def err_missing_param : Error<"expected parameter declarator">;
+def err_unexpected_typedef_ident : Error<
+ "unexpected type name %0: expected identifier">;
+def err_expected_class_name : Error<"expected class name">;
+def err_unspecified_vla_size_with_static : Error<
+ "'static' may not be used with an unspecified variable length array size">;
+
+// Declarations.
+def err_typename_requires_specqual : Error<
+ "type name requires a specifier or qualifier">;
+def err_typename_invalid_storageclass : Error<
+ "type name does not allow storage class to be specified">;
+def err_typename_invalid_functionspec : Error<
+ "type name does not allow function specifier to be specified">;
+def err_invalid_decl_spec_combination : Error<
+ "cannot combine with previous '%0' declaration specifier">;
+def err_unknown_typename : Error<
+ "unknown type name %0">;
+def err_use_of_tag_name_without_tag : Error<
+ "use of tagged type %0 without '%1' tag">;
+
+
+/// Objective-C parser diagnostics
+def err_objc_no_attributes_on_category : Error<
+ "attributes may not be specified on a category">;
+def err_objc_missing_end : Error<"missing @end">;
+def warn_objc_protocol_qualifier_missing_id : Warning<
+ "protocol qualifiers without 'id' is archaic">;
+
+def err_objc_illegal_visibility_spec : Error<
+ "illegal visibility specification">;
+def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">;
+def err_objc_expected_equal : Error<
+ "setter/getter expects '=' followed by name">;
+def err_objc_property_requires_field_name : Error<
+ "property requires fields to be named">;
+def err_objc_property_bitfield : Error<"property name cannot be a bitfield">;
+def err_objc_expected_property_attr : Error<"unknown property attribute %0">;
+def err_objc_propertoes_require_objc2 : Error<
+ "properties are an Objective-C 2 feature">;
+def err_objc_unexpected_attr : Error<
+ "prefix attribute must be followed by an interface or protocol">;
+def err_objc_directive_only_in_protocol : Error<
+ "directive may only be specified in protocols only">;
+def err_missing_catch_finally : Error<
+ "@try statement without a @catch and @finally clause">;
+def err_objc_concat_string : Error<"unexpected token after Objective-C string">;
+def err_missing_sel_definition : Error<"cannot find definition of 'SEL'">;
+def err_missing_id_definition : Error<"cannot find definition of 'id'">;
+def err_missing_proto_definition : Error<
+ "cannot find definition of 'Protocol'">;
+def err_missing_class_definition : Error<"cannot find definition of 'Class'">;
+def warn_expected_implementation : Warning<
+ "@end must appear in an @implementation context">;
+def error_property_ivar_decl : Error<
+ "property synthesize requires specification of an ivar">;
+
+def err_expected_field_designator : Error<
+ "expected a field designator, such as '.field = 4'">;
+
+def err_declaration_does_not_declare_param : Error<
+ "declaration does not declare a parameter">;
+def err_no_matching_param : Error<"parameter named %0 is missing">;
+
+/// C++ parser diagnostics
+def err_expected_unqualified_id : Error<"expected unqualified-id">;
+def err_func_def_no_params : Error<
+ "function definition does not declare parameters">;
+def err_expected_lparen_after_type : Error<
+ "expected '(' for function-style cast or type construction">;
+def err_expected_equal_after_declarator : Error<
+ "expected '=' after declarator">;
+def warn_parens_disambiguated_as_function_decl : Warning<
+ "parentheses were disambiguated as a function declarator">;
+def err_expected_member_or_base_name : Error<
+ "expected class member or base class name">;
+def ext_ellipsis_exception_spec : Extension<
+ "exception specification of '...' is a Microsoft extension">;
+def err_expected_catch : Error<"expected catch">;
+def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
+
+// C++ derived classes
+def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
+
+// C++ operator overloading
+def err_operator_missing_type_specifier : Error<
+ "missing type specifier after 'operator'">;
+
+// Classes.
+def err_anon_type_definition : Error<
+ "declaration of anonymous %0 must be a definition">;
+
+
+/// C++ Templates
+def err_expected_template : Error<"expected template">;
+def err_expected_comma_greater : Error<
+ "expected ',' or '>' in template-parameter-list">;
+def err_expected_type_id_after : Error<"expected type-id after '%0'">;
+def err_expected_class_before : Error<"expected 'class' before '%0'">;
+def err_template_spec_syntax_non_template : Error<
+ "identifier followed by '<' indicates a class template specialization but "
+ "%0 %select{does not refer to a template|refers to a function "
+ "template|<unused>|refers to a template template parameter}1">;
+def err_id_after_template_in_nested_name_spec : Error<
+ "expected template name after 'template' keyword in nested name specifier">;
+def err_id_after_template_in_typename_spec : Error<
+ "expected template name after 'template' keyword in typename specifier">;
+def err_less_after_template_name_in_nested_name_spec : Error<
+ "expected '<' after 'template %0' in nested name specifier">;
+def err_two_right_angle_brackets_need_space : Error<
+ "a space is required between consecutive right angle brackets (use '> >')">;
+def warn_cxx0x_right_shift_in_template_arg : Warning<
+ "use of right-shift operator ('>>') in template argument will require "
+ "parentheses in C++0x">;
+def err_multiple_template_declarators : Error<
+ "%select{|a template declaration|an explicit template specialization|"
+ "an explicit template instantiation}0 can "
+ "only %select{|declare|declare|instantiate}0 a single entity">;
+def err_explicit_instantiation_with_definition : Error<
+ "explicit template instantiation cannot have a definition; if this "
+ "definition is meant to be an explicit specialization, add '<>' after the "
+ "'template' keyword">;
+
+def err_expected_qualified_after_typename : Error<
+ "expected a qualified name after 'typename'">;
+def err_typename_refers_to_non_type_template : Error<
+ "typename specifier refers to a non-template">;
+def err_expected_type_name_after_typename : Error<
+ "expected an identifier or template-id after '::'">;
+
+// Language specific pragmas
+// - Generic warnings
+def warn_pragma_expected_lparen : Warning<
+ "missing '(' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_rparen : Warning<
+ "missing ')' after '#pragma %0' - ignoring">;
+def warn_pragma_expected_identifier : Warning<
+ "expected identifier in '#pragma %0' - ignored">;
+// - #pragma pack
+def warn_pragma_pack_invalid_action : Warning<
+ "unknown action for '#pragma pack' - ignored">;
+def warn_pragma_pack_invalid_constant : Warning<
+ "invalid constant for '#pragma pack', expected %0 - ignored">;
+def warn_pragma_pack_malformed : Warning<
+ "expected integer or identifier in '#pragma pack' - ignored">;
+// - #pragma unused
+def warn_pragma_unused_expected_var : Warning<
+ "expected '#pragma unused' argument to be a variable name">;
+def warn_pragma_unused_expected_punc : Warning<
+ "expected ')' or ',' in '#pragma unused'">;
+
+} // end of Parser diagnostics
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
new file mode 100644
index 000000000000..672e473678dd
--- /dev/null
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -0,0 +1,1822 @@
+//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Semantic Analysis
+//===----------------------------------------------------------------------===//
+
+let Component = "Sema" in {
+
+// Constant expressions
+def err_expr_not_ice : Error<
+ "expression is not an integer constant expression">;
+def ext_expr_not_ice : Extension<
+ "expression is not integer constant expression "
+ "(but is allowed as an extension)">;
+
+def ext_null_pointer_expr_not_ice : Extension<
+ "null pointer expression is not an integer constant expression "
+ "(but is allowed as an extension)">;
+
+
+
+// Semantic analysis of string and character constant literals.
+def ext_predef_outside_function : Warning<
+ "predefined identifier is only valid inside function">;
+
+// C99 Designated Initializers
+def err_array_designator_negative : Error<
+ "array designator value '%0' is negative">;
+def err_array_designator_empty_range : Error<
+ "array designator range [%0, %1] is empty">;
+def err_array_designator_non_array : Error<
+ "array designator cannot initialize non-array type %0">;
+def err_array_designator_too_large : Error<
+ "array designator index (%0) exceeds array bounds (%1)">;
+def err_field_designator_non_aggr : Error<
+ "field designator cannot initialize a "
+ "%select{non-struct, non-union|non-class}0 type %1">;
+def err_field_designator_unknown : Error<
+ "field designator %0 does not refer to any field in type %1">;
+def err_field_designator_nonfield : Error<
+ "field designator %0 does not refer to a non-static data member">;
+def note_field_designator_found : Note<"field designator refers here">;
+def err_designator_for_scalar_init : Error<
+ "designator in initializer for scalar type %0">;
+def warn_subobject_initializer_overrides : Warning<
+ "subobject initialization overrides initialization of other fields "
+ "within its enclosing subobject">;
+def warn_initializer_overrides : Warning<
+ "initializer overrides prior initialization of this subobject">;
+def note_previous_initializer : Note<
+ "previous initialization %select{|with side effects }0is here"
+ "%select{| (side effects may not occur at run time)}0">;
+def err_designator_into_flexible_array_member : Error<
+ "designator into flexible array member subobject">;
+def note_flexible_array_member : Note<
+ "initialized flexible array member %0 is here">;
+def ext_flexible_array_init : Extension<
+ "flexible array initialization is a GNU extension">;
+
+// Declarations.
+def ext_vla : Extension<
+ "variable length arrays are a C99 feature, accepted as an extension">;
+def ext_anon_param_requires_type_specifier : Extension<
+ "type specifier required for unnamed parameter, defaults to int">;
+def err_bad_variable_name : Error<
+ "'%0' cannot be the name of a variable or data member">;
+def err_parameter_name_omitted : Error<"parameter name omitted">;
+def warn_decl_in_param_list : Warning<
+ "declaration of %0 will not be visible outside of this function">;
+
+def warn_implicit_function_decl : Warning<
+ "implicit declaration of function %0">,
+ InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
+def ext_implicit_function_decl : Extension<
+ "implicit declaration of function %0 is invalid in C99">,
+ InGroup<ImplicitFunctionDeclare>;
+
+def err_ellipsis_first_arg : Error<
+ "ISO C requires a named argument before '...'">;
+def err_declarator_need_ident : Error<"declarator requires an identifier">;
+def err_bad_language : Error<"unknown linkage language">;
+def warn_use_out_of_scope_declaration : Warning<
+ "use of out-of-scope declaration of %0">;
+def err_inline_non_function : Error<
+ "'inline' can only appear on functions">;
+
+def err_invalid_thread : Error<
+ "'__thread' is only allowed on variable declarations">;
+def err_thread_non_global : Error<
+ "'__thread' variables must have global storage">;
+def err_thread_unsupported : Error<
+ "thread-local storage is unsupported for the current target">;
+
+/// Built-in functions.
+def ext_implicit_lib_function_decl : ExtWarn<
+ "implicitly declaring C library function '%0' with type %1">;
+def note_please_include_header : Note<
+ "please include the header <%0> or explicitly provide a "
+ "declaration for '%1'">;
+def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
+def err_implicit_decl_requires_stdio : Error<
+ "implicit declaration of '%0' requires inclusion of the header <stdio.h>">;
+def warn_redecl_library_builtin : Warning<
+ "incompatible redeclaration of library function %0">;
+def err_builtin_definition : Error<"definition of builtin function %0">;
+def err_types_compatible_p_in_cplusplus : Error<
+ "__builtin_types_compatible_p is not valid in C++">;
+
+/// parser diagnostics
+def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">;
+def err_statically_allocated_object : Error<
+ "interface type cannot be statically allocated">;
+def err_object_cannot_be_passed_returned_by_value : Error<
+ "interface type %1 cannot be %select{returned|passed}0 by value">;
+def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
+def warn_pragma_pack_invalid_alignment : Warning<
+ "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">;
+// Follow the MSVC implementation.
+def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
+// FIXME: Dehardcode.
+def warn_pragma_pack_pop_identifer_and_alignment : Warning<
+ "specifying both a name and alignment to 'pop' is undefined">;
+def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
+
+def warn_pragma_unused_expected_localvar : Warning<
+ "only local variables can be arguments to '#pragma unused'">;
+
+/// Objective-C parser diagnostics
+def err_duplicate_class_def : Error<
+ "duplicate interface definition for class %0">;
+def err_undef_superclass : Error<
+ "cannot find interface declaration for %0, superclass of %1">;
+def warn_previous_alias_decl : Warning<"previously declared alias is ignored">;
+def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">;
+def warn_undef_interface : Warning<"cannot find interface declaration for %0">;
+def warn_duplicate_protocol_def : Warning<"duplicate protocol definition of %0 is ignored">;
+def err_protocol_has_circular_dependency : Error<
+ "protocol has circular dependency">;
+def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
+def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">;
+def warn_readonly_property : Warning<
+ "attribute 'readonly' of property %0 restricts attribute "
+ "'readwrite' of property inherited from %1">;
+
+def warn_property_attribute : Warning<
+ "property %0 '%1' attribute does not match the property inherited from %2">;
+def warn_property_types_are_incompatible : Warning<
+ "property type %0 is incompatible with type %1 inherited from %2">;
+def err_undef_interface : Error<"cannot find interface declaration for %0">;
+def warn_dup_category_def : Warning<
+ "duplicate definition of category %1 on interface %0">;
+def err_conflicting_super_class : Error<"conflicting super class name %0">;
+def err_dup_implementation_class : Error<"reimplementation of class %0">;
+def err_conflicting_ivar_type : Error<
+ "instance variable %0 has conflicting type: %1 vs %2">;
+def err_conflicting_ivar_bitwidth : Error<
+ "instance variable %0 has conflicting bitfield width">;
+def err_conflicting_ivar_name : Error<
+ "conflicting instance variable names: %0 vs %1">;
+def err_inconsistant_ivar_count : Error<
+ "inconsistent number of instance variables specified">;
+def warn_incomplete_impl : Warning<"incomplete implementation">;
+def warn_undef_method_impl : Warning<"method definition for %0 not found">;
+
+def warn_conflicting_ret_types : Warning<
+ "conflicting return type in implementation of %0: %1 vs %2">;
+
+def warn_conflicting_param_types : Warning<
+ "conflicting parameter types in implementation of %0: %1 vs %2">;
+
+def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
+def warn_accessor_property_type_mismatch : Warning<
+ "type of property %0 does not match type of accessor %1">;
+def note_declared_at : Note<"declared at">;
+def err_setter_type_void : Error<"type of setter must be void">;
+def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
+def err_objc_var_decl_inclass :
+ Error<"cannot declare variable inside @interface or @protocol">;
+def error_missing_method_context : Error<
+ "missing context for method declaration">;
+def err_objc_property_attr_mutually_exclusive : Error<
+ "property attributes '%0' and '%1' are mutually exclusive">;
+def err_objc_property_requires_object : Error<
+ "property with '%0' attribute must be of object type">;
+def warn_objc_property_no_assignment_attribute : Warning<
+ "no 'assign', 'retain', or 'copy' attribute is specified - "
+ "'assign' is assumed">;
+def warn_objc_property_default_assign_on_object : Warning<
+ "default property attribute 'assign' not appropriate for non-gc object">;
+def warn_property_attr_mismatch : Warning<
+ "property attribute in continuation class does not match the primary class">;
+def warn_objc_property_copy_missing_on_block : Warning<
+ "'copy' attribute must be specified for the block property "
+ "when -fobjc-gc-only is specified">;
+def err_use_continuation_class : Error<
+ "attribute of property in continuation class of %0 can only be 'readwrite'">;
+def err_continuation_class : Error<"continuation class has no primary class">;
+def err_property_type : Error<"property cannot have array or function type %0">;
+def error_missing_property_context : Error<
+ "missing context for property implementation declaration">;
+def error_bad_property_decl : Error<
+ "property implementation must have its declaration in interface %0">;
+def error_synthesize_category_decl : Error<
+ "@synthesize not allowed in a category's implementation">;
+def error_missing_property_interface : Error<
+ "property implementation in a category with no category declaration">;
+def error_bad_category_property_decl : Error<
+ "property implementation must have its declaration in the category %0">;
+def error_bad_property_context : Error<
+ "property implementation must be in a class or category implementation">;
+def error_missing_property_ivar_decl : Error<
+ "synthesized property %0 must either be named the same as a compatible"
+ " ivar or must explicitly name an ivar">;
+
+def error_synthesized_ivar_yet_not_supported : Error<
+ "instance variable synthesis not yet supported"
+ " (need to declare %0 explicitly)">;
+
+def error_property_ivar_type : Error<
+ "type of property %0 does not match type of ivar %1">;
+def error_ivar_in_superclass_use : Error<
+ "property %0 attempting to use ivar %1 declared in super class %2">;
+def error_weak_property : Error<
+ "existing ivar %1 for __weak property %0 must be __weak">;
+def error_strong_property : Error<
+ "existing ivar %1 for a __strong property %0 must be garbage collectable">;
+def error_dynamic_property_ivar_decl : Error<
+ "dynamic property can not have ivar specification">;
+def error_duplicate_ivar_use : Error<
+ "synthesized properties %0 and %1 both claim ivar %2">;
+def error_property_implemented : Error<"property %0 is already implemented">;
+def warn_objc_property_attr_mutually_exclusive : Warning<
+ "property attributes '%0' and '%1' are mutually exclusive">,
+ InGroup<DiagGroup<"readonly-setter-attrs">>, DefaultIgnore;
+
+// C++ declarations
+def err_static_assert_expression_is_not_constant : Error<
+ "static_assert expression is not an integral constant expression">;
+def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
+
+def err_friend_decl_outside_class : Error<
+ "'friend' used outside of class">;
+
+def err_abstract_type_in_decl : Error<
+ "%select{return|parameter|variable|field}1 type %0 is an abstract class">;
+def err_allocation_of_abstract_type : Error<
+ "allocation of an object of abstract type %0">;
+
+def err_type_defined_in_type_specifier : Error<
+ "%0 can not be defined in a type specifier">;
+def err_type_defined_in_result_type : Error<
+ "%0 can not be defined in the result type of a function">;
+def err_type_defined_in_param_type : Error<
+ "%0 can not be defined in a parameter type">;
+
+def note_pure_virtual_function : Note<
+ "pure virtual function %0">;
+
+def err_deleted_non_function : Error<
+ "only functions can have deleted definitions">;
+def err_deleted_decl_not_first : Error<
+ "deleted definition must be first declaration">;
+
+// C++ exception specifications
+def err_exception_spec_in_typedef : Error<
+ "exception specifications are not allowed in typedefs">;
+def err_distant_exception_spec : Error<
+ "exception specifications are not allowed beyond a single level "
+ "of indirection">;
+def err_incomplete_in_exception_spec : Error<
+ "%select{|pointer to |reference to }1incomplete type %0 is not allowed "
+ "in exception specification">;
+
+// C++ access checking
+def err_class_redeclared_with_different_access : Error<
+ "%0 redeclared with '%1' access">;
+def note_previous_access_declaration : Note<
+ "previously declared '%1' here">;
+
+// C++ name lookup
+def err_incomplete_nested_name_spec : Error<
+ "incomplete type %0 named in nested name specifier">;
+
+// C++ class members
+def err_storageclass_invalid_for_member : Error<
+ "storage class specified for a member declaration">;
+def err_mutable_function : Error<"'mutable' cannot be applied to functions">;
+def err_mutable_reference : Error<"'mutable' cannot be applied to references">;
+def err_mutable_const : Error<"'mutable' and 'const' cannot be mixed">;
+def err_mutable_nonmember : Error<
+ "'mutable' can only be applied to member variables">;
+def err_virtual_non_function : Error<
+ "'virtual' can only appear on non-static member functions">;
+def err_explicit_non_function : Error<
+ "'explicit' can only appear on non-static member functions">;
+def err_virtual_out_of_class : Error<
+ "'virtual' can only be specified inside the class definition">;
+def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
+def err_static_out_of_line : Error<
+ "'static' can only be specified inside the class definition">;
+def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">;
+def err_not_integral_type_bitfield : Error<
+ "bit-field %0 has non-integral type %1">;
+def err_not_integral_type_anon_bitfield : Error<
+ "anonymous bit-field has non-integral type %0">;
+def err_member_initialization : Error<
+ "%0 can only be initialized if it is a static const integral data member">;
+def err_member_function_initialization : Error<
+ "initializer on function does not look like a pure-specifier">;
+def err_non_virtual_pure : Error<
+ "%0 is not virtual and cannot be declared pure">;
+def err_implicit_object_parameter_init : Error<
+ "cannot initialize object parameter of type %0 with an expression "
+ "of type %1">;
+
+def err_different_return_type_for_overriding_virtual_function : Error<
+ "virtual function %0 has a different return type (%1) than the "
+ "function it overrides (which has return type %2)">;
+def note_overridden_virtual_function : Note<
+ "overridden virtual function is here">;
+
+def err_covariant_return_inaccessible_base : Error<
+ "return type of virtual function %2 is not covariant with the return type "
+ "of the function it overrides "
+ "(conversion from %0 to inaccessible base class %1)">;
+def err_covariant_return_ambiguous_derived_to_base_conv : Error<
+ "return type of virtual function %3 is not covariant with the return type of "
+ "the function it overrides (ambiguous conversion from derived class "
+ "%0 to base class %1:%2)">;
+def err_covariant_return_not_derived : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (%1 is not derived from %2)">;
+def err_covariant_return_type_different_qualifications : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (%1 has different qualifiers than %2)">;
+def err_covariant_return_type_class_type_more_qualified : Error<
+ "return type of virtual function %0 is not covariant with the return type of "
+ "the function it overrides (class type %1 is more qualified than class "
+ "type %2">;
+// C++ constructors
+def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">;
+def err_invalid_qualified_constructor : Error<
+ "'%0' qualifier is not allowed on a constructor">;
+def err_constructor_return_type : Error<
+ "constructor cannot have a return type">;
+def err_constructor_redeclared : Error<"constructor cannot be redeclared">;
+def err_constructor_byvalue_arg : Error<
+ "copy constructor must pass its first argument by reference">;
+
+// C++ destructors
+def err_destructor_not_member : Error<
+ "destructor must be a non-static member function">;
+def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">;
+def err_invalid_qualified_destructor : Error<
+ "'%0' qualifier is not allowed on a destructor">;
+def err_destructor_return_type : Error<"destructor cannot have a return type">;
+def err_destructor_redeclared : Error<"destructor cannot be redeclared">;
+def err_destructor_with_params : Error<"destructor cannot have any parameters">;
+def err_destructor_variadic : Error<"destructor cannot be variadic">;
+def err_destructor_typedef_name : Error<
+ "destructor cannot be declared using a typedef %0 of the class name">;
+
+// C++ initialization
+def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
+// FIXME: passing in an English string as %1!
+def err_not_reference_to_const_init : Error<
+ "non-const lvalue reference to type %0 cannot be initialized "
+ "with a %1 of type %2">;
+// FIXME: passing in an English string as %1!
+def err_reference_init_drops_quals : Error<
+ "initialization of reference to type %0 with a %1 of type %2 drops "
+ "qualifiers">;
+def err_reference_var_requires_init : Error<
+ "declaration of reference variable %0 requires an initializer">;
+def err_const_var_requires_init : Error<
+ "declaration of const variable '%0' requires an initializer">;
+def err_init_non_aggr_init_list : Error<
+ "initialization of non-aggregate type %0 with an initializer list">;
+def err_init_reference_member_uninitialized : Error<
+ "reference member of type %0 uninitialized">;
+def note_uninit_reference_member : Note<
+ "uninitialized reference member is here">;
+
+// Objective-C++
+def err_objc_decls_may_only_appear_in_global_scope : Error<
+ "Objective-C declarations may only appear in global scope">;
+def err_nsobject_attribute : Error<
+ "__attribute ((NSObject)) is for pointer types only">;
+
+// Attributes
+def err_attribute_can_be_applied_only_to_symbol_declaration : Error<
+ "%0 attribute can be applied only to symbol declaration">;
+def err_attributes_are_not_compatible : Error<
+ "%0 and %1 attributes are not compatible">;
+def err_attribute_wrong_number_arguments : Error<
+ "attribute requires %0 argument(s)">;
+def err_attribute_missing_parameter_name : Error<
+ "attribute requires unquoted parameter">;
+def err_attribute_invalid_vector_type : Error<"invalid vector type %0">;
+def err_attribute_argument_not_int : Error<
+ "'%0' attribute requires integer constant">;
+def err_attribute_argument_n_not_int : Error<
+ "'%0' attribute requires parameter %1 to be an integer constant">;
+def err_attribute_argument_n_not_string : Error<
+ "'%0' attribute requires parameter %1 to be a string">;
+def err_attribute_argument_out_of_bounds : Error<
+ "'%0' attribute parameter %1 is out of bounds">;
+def err_attribute_requires_objc_interface : Error<
+ "attribute may only be applied to an Objective-C interface">;
+def err_nonnull_pointers_only : Error<
+ "nonnull attribute only applies to pointer arguments">;
+def err_format_strftime_third_parameter : Error<
+ "strftime format attribute requires 3rd parameter to be 0">;
+def err_format_attribute_requires_variadic : Error<
+ "format attribute requires variadic function">;
+def err_format_attribute_not : Error<"format argument not %0">;
+def err_format_attribute_result_not : Error<"function does not return %0">;
+def err_attribute_invalid_size : Error<
+ "vector size not an integral multiple of component size">;
+def err_attribute_zero_size : Error<"zero vector size">;
+def err_typecheck_vector_not_convertable : Error<
+ "can't convert between vector values of different size (%0 and %1)">;
+def err_typecheck_ext_vector_not_typedef : Error<
+ "ext_vector_type only applies to types, not variables">;
+def err_unsupported_vector_size : Error<
+ "unsupported type %0 for vector_size attribute, please use on typedef">;
+def err_ext_vector_component_exceeds_length : Error<
+ "vector component access exceeds type %0">;
+def err_ext_vector_component_requires_even : Error<
+ "vector component access invalid for odd-sized type %0">;
+def err_ext_vector_component_name_illegal : Error<
+ "illegal vector component name '%0'">;
+def err_attribute_address_space_not_int : Error<
+ "address space attribute requires an integer constant">;
+def err_attribute_address_multiple_qualifiers : Error<
+ "multiple address spaces specified for type">;
+def err_implicit_pointer_address_space_cast : Error<
+ "illegal implicit cast between two pointers with different address spaces">;
+def err_as_qualified_auto_decl : Error<
+ "automatic variable qualified with an address space">;
+def err_attribute_annotate_no_string : Error<
+ "argument to annotate attribute was not a string literal">;
+def err_attribute_aligned_not_power_of_two : Error<
+ "requested alignment is not a power of 2">;
+def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
+ "'%0' redeclared without %1 attribute: previous %1 ignored">;
+def warn_attribute_ignored : Warning<"%0 attribute ignored">;
+def warn_attribute_weak_on_field : Warning<
+ "__weak attribute cannot be specified on a field declaration">;
+def warn_attribute_weak_on_local : Warning<
+ "__weak attribute cannot be specified on an automatic variable">;
+def warn_attribute_weak_import_invalid_on_definition : Warning<
+ "'weak_import' attribute cannot be specified on a definition">;
+def warn_attribute_wrong_decl_type : Warning<
+ "%0 attribute only applies to %select{function|union|"
+ "variable and function|function or method|parameter|parameter or Objective-C method |"
+ "function, method or block}1 types">;
+def warn_gnu_inline_attribute_requires_inline : Warning<
+ "'gnu_inline' attribute requires function to be marked 'inline',"
+ " attribute ignored">;
+
+def warn_attribute_ignored_for_field_of_type : Warning<
+ "%0 attribute ignored for field of type %1">;
+def warn_transparent_union_attribute_field_size_align : Warning<
+ "%select{alignment|size}0 of field %1 (%2 bits) does not match the "
+ "%select{alignment|size}0 of the first field in transparent union; "
+ "transparent_union attribute ignored">;
+def note_transparent_union_first_field_size_align : Note<
+ "%select{alignment|size}0 of first field is %1 bits">;
+def warn_transparent_union_attribute_not_definition : Warning<
+ "transparent_union attribute can only be applied to a union definition; "
+ "attribute ignored">;
+def warn_transparent_union_attribute_floating : Warning<
+ "first field of a transparent union cannot have floating point or vector "
+ "type; transparent_union attribute ignored">;
+def warn_transparent_union_attribute_zero_fields : Warning<
+ "transparent union definition must contain at least one field; "
+ "transparent_union attribute ignored">;
+def warn_attribute_type_not_supported : Warning<
+ "'%0' attribute argument not supported: %1">;
+def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">;
+def err_unknown_machine_mode : Error<"unknown machine mode %0">;
+def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
+def err_mode_not_primitive : Error<
+ "mode attribute only supported for integer and floating-point types">;
+def err_mode_wrong_type : Error<
+ "type of machine mode does not match type of base type">;
+def err_attr_wrong_decl : Error<
+ "'%0' attribute invalid on this declaration, requires typedef or value">;
+def warn_attribute_nonnull_no_pointers : Warning<
+ "'nonnull' attribute applied to function with no pointer arguments">;
+def warn_transparent_union_nonpointer : Warning<
+ "'transparent_union' attribute support incomplete; only supported for "
+ "pointer unions">;
+
+def warn_attribute_sentinel_named_arguments : Warning<
+ "'sentinel' attribute requires named arguments">;
+def warn_attribute_sentinel_not_variadic : Warning<
+ "'sentinel' attribute only supported for variadic %select{functions|blocks}0">;
+def err_attribute_sentinel_less_than_zero : Error<
+ "'sentinel' parameter 1 less than zero">;
+def err_attribute_sentinel_not_zero_or_one : Error<
+ "'sentinel' parameter 2 not 0 or 1">;
+def err_attribute_cleanup_arg_not_found : Error<
+ "'cleanup' argument %0 not found">;
+def err_attribute_cleanup_arg_not_function : Error<
+ "'cleanup' argument %0 is not a function">;
+def err_attribute_cleanup_func_must_take_one_arg : Error<
+ "'cleanup' function %0 must take 1 parameter">;
+def err_attribute_cleanup_func_arg_incompatible_type : Error<
+ "'cleanup' function %0 parameter has type %1 which is incompatible with "
+ "type %2">;
+def err_attribute_regparm_wrong_platform : Error<
+ "'regparm' is not valid on this platform">;
+def err_attribute_regparm_invalid_number : Error<
+ "'regparm' parameter must be between 0 and %0 inclusive">;
+
+
+// Clang-Specific Attributes
+def err_attribute_iboutlet : Error<
+ "'iboutlet' attribute can only be applied to instance variables or "
+ "properties">;
+def err_attribute_overloadable_not_function : Error<
+ "'overloadable' attribute can only be applied to a function">;
+def err_attribute_overloadable_missing : Error<
+ "%select{overloaded function|redeclaration of}0 %1 must have the "
+ "'overloadable' attribute">;
+def note_attribute_overloadable_prev_overload : Note<
+ "previous overload of function is here">;
+def err_attribute_overloadable_no_prototype : Error<
+ "'overloadable' function %0 must have a prototype">;
+def warn_ns_attribute_wrong_return_type : Warning<
+ "%0 attribute only applies to functions or methods that "
+ "return a pointer or Objective-C object">;
+
+// Function Parameter Semantic Analysis.
+def err_param_with_void_type : Error<"argument may not have 'void' type">;
+def err_void_only_param : Error<
+ "'void' must be the first and only parameter if specified">;
+def err_void_param_qualified : Error<
+ "'void' as parameter must not have type qualifiers">;
+def err_ident_list_in_fn_declaration : Error<
+ "a parameter list without types is only allowed in a function definition">;
+def ext_param_not_declared : Extension<
+ "parameter %0 was not declared, defaulting to type 'int'">;
+def err_param_typedef_of_void : Error<
+ "empty parameter list defined with a typedef of 'void' not allowed in C++">;
+def err_param_default_argument : Error<
+ "C does not support default arguments">;
+def err_param_default_argument_redefinition : Error<
+ "redefinition of default argument">;
+def err_param_default_argument_missing : Error<
+ "missing default argument on parameter">;
+def err_param_default_argument_missing_name : Error<
+ "missing default argument on parameter %0">;
+def err_param_default_argument_references_param : Error<
+ "default argument references parameter %0">;
+def err_param_default_argument_references_local : Error<
+ "default argument references local variable %0 of enclosing function">;
+def err_param_default_argument_references_this : Error<
+ "default argument references 'this'">;
+def err_param_default_argument_nonfunc : Error<
+ "default arguments can only be specified for parameters in a function "
+ "declaration">;
+
+def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
+ "promoted type %0 of K&R function parameter is not compatible with the "
+ "parameter type %1 declared in a previous prototype">;
+
+
+// C++ Overloading Semantic Analysis.
+def err_ovl_diff_return_type : Error<
+ "functions that differ only in their return type cannot be overloaded">;
+def err_ovl_static_nonstatic_member : Error<
+ "static and non-static member functions with the same parameter types "
+ "cannot be overloaded">;
+
+def err_ovl_no_viable_function_in_call : Error<
+ "no matching function for call to %0">;
+def err_ovl_no_viable_member_function_in_call : Error<
+ "no matching member function for call to %0">;
+def err_ovl_ambiguous_call : Error<
+ "call to %0 is ambiguous">;
+def err_ovl_deleted_call : Error<
+ "call to %select{unavailable|deleted}0 function %1">;
+def err_ovl_ambiguous_member_call : Error<
+ "call to member function %0 is ambiguous">;
+def err_ovl_deleted_member_call : Error<
+ "call to %select{unavailable|deleted}0 member function %1">;
+def err_ovl_candidate : Note<"candidate function">;
+def err_ovl_candidate_deleted : Note<
+ "candidate function has been explicitly %select{made unavailable|deleted}0">;
+def err_ovl_builtin_candidate : Note<"built-in candidate function %0">;
+def err_ovl_no_viable_function_in_init : Error<
+ "no matching constructor for initialization of %0">;
+def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
+def err_ovl_deleted_init : Error<
+ "call to %select{unavailable|deleted}0 constructor of %1">;
+def err_ovl_ambiguous_oper : Error<
+ "use of overloaded operator '%0' is ambiguous">;
+def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
+def err_ovl_deleted_oper : Error<
+ "overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
+
+def err_ovl_no_viable_object_call : Error<
+ "no matching function for call to object of type %0">;
+def err_ovl_ambiguous_object_call : Error<
+ "call to object of type %0 is ambiguous">;
+def err_ovl_deleted_object_call : Error<
+ "call to %select{unavailable|deleted}0 function call operator in type %1">;
+def err_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
+def err_member_call_without_object : Error<
+ "call to non-static member function without an object argument">;
+
+// C++ Template Declarations
+def err_template_param_shadow : Error<
+ "declaration of %0 shadows template parameter">;
+def note_template_param_here : Note<"template parameter is declared here">;
+def note_template_export_unsupported : Note<
+ "exported templates are unsupported">;
+def err_template_outside_namespace_or_class_scope : Error<
+ "templates can only be declared in namespace or class scope">;
+def err_template_linkage : Error<"templates must have C++ linkage">;
+def err_template_unnamed_class : Error<
+ "cannot declare a class template with no name">;
+def err_template_param_list_different_arity : Error<
+ "%select{too few|too many}0 template parameters in template "
+ "%select{|template parameter }1redeclaration">;
+def note_template_param_list_different_arity : Note<
+ "%select{too few|too many}0 template parameters in template template "
+ "argument">;
+def note_template_prev_declaration : Note<
+ "previous template %select{declaration|template parameter}0 is here">;
+def err_template_param_different_kind : Error<
+ "template parameter has a different kind in template "
+ "%select{|template parameter }0redeclaration">;
+def note_template_param_different_kind : Note<
+ "template parameter has a different kind in template argument">;
+def err_template_nontype_parm_different_type : Error<
+ "template non-type parameter has a different type %0 in template "
+ "%select{|template parameter }1redeclaration">;
+
+def note_template_nontype_parm_different_type : Note<
+ "template non-type parameter has a different type %0 in template argument">;
+def note_template_nontype_parm_prev_declaration : Note<
+ "previous non-type template parameter with type %0 is here">;
+def err_template_nontype_parm_bad_type : Error<
+ "a non-type template parameter cannot have type %0">;
+def err_template_param_default_arg_redefinition : Error<
+ "template parameter redefines default argument">;
+def note_template_param_prev_default_arg : Note<
+ "previous default template argument defined here">;
+def err_template_param_default_arg_missing : Error<
+ "template parameter missing a default argument">;
+
+// C++ Template Argument Lists
+def err_template_arg_list_different_arity : Error<
+ "%select{too few|too many}0 template arguments for "
+ "%select{class template|function template|template template parameter"
+ "|template}1 %2">;
+def note_template_decl_here : Note<"template is declared here">;
+def note_member_of_template_here : Note<"member is declared here">;
+def err_template_arg_must_be_type : Error<
+ "template argument for template type parameter must be a type">;
+def err_template_arg_must_be_expr : Error<
+ "template argument for non-type template parameter must be an expression">;
+def err_template_arg_nontype_ambig : Error<
+ "template argument for non-type template parameter is treated as type %0">;
+def err_template_arg_must_be_template : Error<
+ "template argument for template template parameter must be a template">;
+def err_template_arg_local_type : Error<"template argument uses local type %0">;
+def err_template_arg_unnamed_type : Error<
+ "template argument uses unnamed type">;
+def note_template_unnamed_type_here : Note<
+ "unnamed type used in template argument was declared here">;
+def err_template_arg_not_class_template : Error<
+ "template argument does not refer to a class template">;
+def note_template_arg_refers_here_func : Note<
+ "template argument refers to function template %0, here">;
+def err_template_arg_template_params_mismatch : Error<
+ "template template argument has different template parameters than its "
+ "corresponding template template parameter">;
+def err_template_arg_not_integral_or_enumeral : Error<
+ "non-type template argument of type %0 must have an integral or enumeration"
+ " type">;
+def err_template_arg_not_ice : Error<
+ "non-type template argument of type %0 is not an integral constant "
+ "expression">;
+def err_template_arg_not_convertible : Error<
+ "non-type template argument of type %0 cannot be converted to a value "
+ "of type %1">;
+def err_template_arg_negative : Error<
+ "non-type template argument provides negative value '%0' for unsigned "
+ "template parameter of type %1">;
+def err_template_arg_too_large : Error<
+ "non-type template argument value '%0' is too large for template "
+ "parameter of type %1">;
+def err_template_arg_no_ref_bind : Error<
+ "non-type template parameter of reference type %0 cannot bind to template "
+ "argument of type %1">;
+def err_template_arg_ref_bind_ignores_quals : Error<
+ "reference binding of non-type template parameter of type %0 to template "
+ "argument of type %1 ignores qualifiers">;
+def err_template_arg_not_object_or_func_form : Error<
+ "non-type template argument does not directly refer to an object or "
+ "function">;
+def err_template_arg_field : Error<
+ "non-type template argument refers to non-static data member %0">;
+def err_template_arg_method : Error<
+ "non-type template argument refers to non-static member function %0">;
+def err_template_arg_function_not_extern : Error<
+ "non-template argument refers to function %0 with internal linkage">;
+def err_template_arg_object_not_extern : Error<
+ "non-template argument refers to object %0 that does not have external "
+ "linkage">;
+def note_template_arg_internal_object : Note<
+ "non-template argument refers to %select{function|object}0 here">;
+def note_template_arg_refers_here : Note<"non-template argument refers here">;
+def err_template_arg_not_object_or_func : Error<
+ "non-type template argument does not refer to an object or function">;
+def err_template_arg_not_pointer_to_member_form : Error<
+ "non-type template argument is not a pointer to member constant">;
+def err_template_arg_extra_parens : Error<
+ "non-type template argument cannot be surrounded by parentheses">;
+
+// C++ class template specialization
+def err_template_spec_needs_header : Error<
+ "template specialization requires 'template<>'">;
+def err_template_spec_extra_headers : Error<
+ "template specialization must have a single 'template<>' header">;
+def unsup_template_partial_spec_ordering : Error<
+ "partial ordering of class template partial specializations is not yet "
+ "supported">;
+def err_template_spec_decl_out_of_scope_global : Error<
+ "class template specialization of %0 must occur in the global scope">;
+def err_template_spec_decl_out_of_scope : Error<
+ "class template specialization of %0 not in namespace %1">;
+def err_template_spec_decl_function_scope : Error<
+ "%select{class template specialization|explicit instantiation}0 of %1 "
+ "in function scope">;
+def err_template_spec_redecl_out_of_scope : Error<
+ "%select{class template specialization|explicit instantiation}0 of %1 "
+ "not in a namespace enclosing %2">;
+def err_template_spec_redecl_global_scope : Error<
+ "%select{class template specialization|explicit instantiation}0 of %1 must "
+ "occur at global scope">;
+
+// C++ Template Instantiation
+def err_template_recursion_depth_exceeded : Error<
+ "recursive template instantiation exceeded maximum depth of %0">,DefaultFatal;
+def note_template_recursion_depth : Note<
+ "use -ftemplate-depth-N to increase recursive template instantiation depth">;
+
+def err_template_instantiate_undefined : Error<
+ "%select{implicit|explicit}0 instantiation of undefined template %1">;
+def err_implicit_instantiate_member_undefined : Error<
+ "implicit instantiation of undefined member %0">;
+def note_template_class_instantiation_here : Note<
+ "in instantiation of template class %0 requested here">;
+def note_template_member_class_here : Note<
+ "in instantiation of member class %0 requested here">;
+def note_template_member_function_here : Note<
+ "in instantiation of member function %q0 requested here">;
+def note_default_arg_instantiation_here : Note<
+ "in instantiation of default argument for '%0' required here">;
+def err_field_instantiates_to_function : Error<
+ "data member instantiated with function type %0">;
+def err_nested_name_spec_non_tag : Error<
+ "type %0 cannot be used prior to '::' because it has no members">;
+
+// C++ Explicit Instantiation
+def err_explicit_instantiation_duplicate : Error<
+ "duplicate explicit instantiation of %0">;
+def note_previous_explicit_instantiation : Note<
+ "previous explicit instantiation is here">;
+def ext_explicit_instantiation_after_specialization : Extension<
+ "explicit instantiation of %0 that occurs after an explicit "
+ "specialization will be ignored (C++0x extension)">;
+def note_previous_template_specialization : Note<
+ "previous template specialization is here">;
+def err_explicit_instantiation_enum : Error<
+ "explicit instantiation of enumeration type %0">;
+def err_explicit_instantiation_nontemplate_type : Error<
+ "explicit instantiation of non-templated type %0">;
+def note_nontemplate_decl_here : Note<
+ "non-templated declaration is here">;
+def err_explicit_instantiation_out_of_scope : Error<
+ "explicit instantiation of %0 not in a namespace enclosing %1">;
+
+// C++ typename-specifiers
+def err_typename_nested_not_found : Error<"no type named %0 in %1">;
+def err_typename_nested_not_found_global : Error<
+ "no type named %0 in the global namespace">;
+def err_typename_nested_not_type : Error<
+ "typename specifier refers to non-type member %0">;
+def note_typename_refers_here : Note<
+ "referenced member %0 is declared here">;
+
+def err_template_kw_refers_to_non_template : Error<
+ "%0 following the 'template' keyword does not refer to a template">;
+def err_template_kw_refers_to_function_template : Error<
+ "%0 following the 'template' keyword refers to a function template">;
+
+def err_unexpected_typedef : Error<
+ "unexpected type name %0: expected expression">;
+def err_unexpected_namespace : Error<
+ "unexpected namespace name %0: expected expression">;
+def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
+def err_undeclared_use : Error<"use of undeclared '%0'">;
+def warn_deprecated : Warning<"%0 is deprecated">,
+ InGroup<DiagGroup<"deprecated-declarations">>;
+def warn_unavailable : Warning<"%0 is unavailable">;
+def note_unavailable_here : Note<
+ "function has been explicitly marked %select{unavailable|deleted}0 here">;
+def warn_not_enough_argument : Warning<
+ "not enough variable arguments in %0 declaration to fit a sentinel">;
+def warn_missing_sentinel : Warning <
+ "missing sentinel in %select{function call|method dispatch|block call}0">;
+def note_sentinel_here : Note<
+ "%select{function|method|block}0 has been explicitly marked sentinel here">;
+def warn_missing_prototype : Warning<
+ "no previous prototype for function %0">,
+ InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
+def err_redefinition : Error<"redefinition of %0">;
+
+def warn_redefinition_of_typedef : Warning<
+ "redefinition of typedef %0 is invalid in C">,
+ InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
+
+def err_static_non_static : Error<
+ "static declaration of %0 follows non-static declaration">;
+def err_non_static_static : Error<
+ "non-static declaration of %0 follows static declaration">;
+def err_non_thread_thread : Error<
+ "non-thread-local declaration of %0 follows thread-local declaration">;
+def err_thread_non_thread : Error<
+ "thread-local declaration of %0 follows non-thread-local declaration">;
+def err_redefinition_different_type : Error<
+ "redefinition of %0 with a different type">;
+def err_redefinition_different_kind : Error<
+ "redefinition of %0 as different kind of symbol">;
+def err_redefinition_different_typedef : Error<
+ "typedef redefinition with different types (%0 vs %1)">;
+def err_tag_definition_of_typedef : Error<
+ "definition of type %0 conflicts with typedef of the same name">;
+def err_conflicting_types : Error<"conflicting types for %0">;
+def err_nested_redefinition : Error<"nested redefinition of %0">;
+def err_use_with_wrong_tag : Error<
+ "use of %0 with tag type that does not match previous declaration">;
+def warn_struct_class_tag_mismatch : Warning<
+ "%select{struct|class}0 %select{|template}1 %2 was previously declared "
+ "as a %select{class|struct}0 %select{|template}1">,
+ InGroup<MismatchedTags>, DefaultIgnore;
+def ext_forward_ref_enum : Extension<
+ "ISO C forbids forward references to 'enum' types">;
+def err_forward_ref_enum : Error<
+ "ISO C++ forbids forward references to 'enum' types">;
+def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
+def err_duplicate_member : Error<"duplicate member %0">;
+def ext_enum_value_not_int : Extension<
+ "ISO C restricts enumerator values to range of 'int' (%0 is too large)">;
+def warn_enum_too_large : Warning<
+ "enumeration values exceed range of largest integer">;
+def warn_illegal_constant_array_size : Extension<
+ "size of static array must be an integer constant expression">;
+def err_vla_decl_in_file_scope : Error<
+ "variable length array declaration not allowed at file scope">;
+def err_vla_decl_has_static_storage : Error<
+ "variable length array declaration can not have 'static' storage duration">;
+def err_vla_decl_has_extern_linkage : Error<
+ "variable length array declaration can not have 'extern' linkage">;
+def err_vm_decl_in_file_scope : Error<
+ "variably modified type declaration not allowed at file scope">;
+def err_vm_decl_has_extern_linkage : Error<
+ "variably modified type declaration can not have 'extern' linkage">;
+def err_typecheck_field_variable_size : Error<
+ "fields must have a constant size: 'variable length array in structure' "
+ "extension will never be supported">;
+def err_vm_func_decl : Error<
+ "function declaration cannot have variably modified type">;
+
+def err_typecheck_negative_array_size : Error<"array size is negative">;
+def warn_typecheck_function_qualifiers : Warning<
+ "qualifier on function type %0 has unspecified behavior">;
+def err_typecheck_invalid_restrict_not_pointer : Error<
+ "restrict requires a pointer or reference (%0 is invalid)">;
+def err_typecheck_invalid_restrict_invalid_pointee : Error<
+ "pointer to function type %0 may not be 'restrict' qualified">;
+def ext_typecheck_zero_array_size : Extension<
+ "zero size arrays are an extension">;
+def err_at_least_one_initializer_needed_to_size_array : Error<
+ "at least one initializer value required to size array">;
+def err_array_size_non_int : Error<"size of array has non-integer type %0">;
+def err_init_element_not_constant : Error<
+ "initializer element is not a compile-time constant">;
+def err_block_extern_cant_init : Error<
+ "'extern' variable cannot have an initializer">;
+def warn_extern_init : Warning<"'extern' variable has an initializer">;
+def err_variable_object_no_init : Error<
+ "variable-sized object may not be initialized">;
+def err_array_init_list_required : Error<
+ "initialization with '{...}' expected for array">;
+def err_excess_initializers : Error<
+ "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
+def warn_excess_initializers : Warning<
+ "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
+def err_excess_initializers_in_char_array_initializer : Error<
+ "excess elements in char array initializer">;
+def warn_excess_initializers_in_char_array_initializer : Warning<
+ "excess elements in char array initializer">;
+def warn_initializer_string_for_char_array_too_long : Warning<
+ "initializer-string for char array is too long">;
+def warn_braces_around_scalar_init : Warning<
+ "braces around scalar initializer">;
+def err_many_braces_around_scalar_init : Error<
+ "too many braces around scalar initializer">;
+def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
+def err_illegal_initializer : Error<
+ "illegal initializer (only variables can be initialized)">;
+def err_illegal_initializer_type : Error<"illegal initializer type %0">;
+def err_implicit_empty_initializer : Error<
+ "initializer for aggregate with no elements requires explicit braces">;
+def err_bitfield_has_negative_width : Error<
+ "bit-field %0 has negative width (%1)">;
+def err_anon_bitfield_has_negative_width : Error<
+ "anonymous bit-field has negative width (%0)">;
+def err_bitfield_has_zero_width : Error<"bit-field %0 has zero width">;
+def err_bitfield_width_exceeds_type_size : Error<
+ "size of bit-field %0 exceeds size of its type (%1 bits)">;
+def err_anon_bitfield_width_exceeds_type_size : Error<
+ "size of anonymous bitfield exceeds size of its type (%0 bits)">;
+
+def err_redefinition_of_label : Error<"redefinition of label '%0'">;
+def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
+
+def err_goto_into_protected_scope : Error<"illegal goto into protected scope">;
+def err_switch_into_protected_scope : Error<
+ "illegal switch case into protected scope">;
+def err_indirect_goto_in_protected_scope : Error<
+ "illegal indirect goto in protected scope, unknown effect on scopes">;
+def err_addr_of_label_in_protected_scope : Error<
+ "address taken of label in protected scope, jump to it would have "
+ "unknown effect on scope">;
+def note_protected_by_vla_typedef : Note<
+ "jump bypasses initialization of VLA typedef">;
+def note_protected_by_vla : Note<
+ "jump bypasses initialization of variable length array">;
+def note_protected_by_cleanup : Note<
+ "jump bypasses initialization of declaration with __attribute__((cleanup))">;
+def note_protected_by_objc_try : Note<
+ "jump bypasses initialization of @try block">;
+def note_protected_by_objc_catch : Note<
+ "jump bypasses initialization of @catch block">;
+def note_protected_by_objc_finally : Note<
+ "jump bypasses initialization of @finally block">;
+def note_protected_by_objc_synchronized : Note<
+ "jump bypasses initialization of @synchronized block">;
+def note_protected_by_cxx_try : Note<
+ "jump bypasses initialization of try block">;
+def note_protected_by_cxx_catch : Note<
+ "jump bypasses initialization of catch block">;
+
+def err_func_returning_array_function : Error<
+ "function cannot return array or function type %0">;
+def err_field_declared_as_function : Error<"field %0 declared as a function">;
+def err_field_incomplete : Error<"field has incomplete type %0">;
+def ext_variable_sized_type_in_struct : ExtWarn<
+ "field %0 with variable sized type %1 not at the end of a struct or class is"
+ " a GNU extension">;
+
+def err_flexible_array_empty_struct : Error<
+ "flexible array %0 not allowed in otherwise empty struct">;
+def ext_flexible_array_in_struct : Extension<
+ "%0 may not be nested in a struct due to flexible array member">;
+def ext_flexible_array_in_array : Extension<
+ "%0 may not be used as an array element due to flexible array member">;
+def err_flexible_array_init_nonempty : Error<
+ "non-empty initialization of flexible array member inside subobject">;
+def err_flexible_array_init_needs_braces : Error<
+ "flexible array requires brace-enclosed initializer">;
+def err_illegal_decl_array_of_functions : Error<
+ "'%0' declared as array of functions">;
+def err_illegal_decl_array_incomplete_type : Error<
+ "array has incomplete element type %0">;
+def err_illegal_decl_array_of_references : Error<
+ "'%0' declared as array of references">;
+def err_array_star_outside_prototype : Error<
+ "star modifier used outside of function prototype">;
+def err_illegal_decl_pointer_to_reference : Error<
+ "'%0' declared as a pointer to a reference">;
+def err_illegal_decl_mempointer_to_void : Error<
+ "'%0' declared as a member pointer to void">;
+def err_illegal_decl_mempointer_in_nonclass : Error<
+ "'%0' does not point into a class">;
+def err_reference_to_void : Error<"cannot form a reference to 'void'">;
+def err_qualified_block_pointer_type : Error<
+ "qualifier specification on block pointer type not allowed">;
+def err_nonfunction_block_type : Error<
+ "block pointer to non-function type is invalid">;
+def err_return_block_has_expr : Error<"void block should not return a value">;
+def err_block_return_missing_expr : Error<
+ "non-void block should return a value">;
+def err_block_with_return_type_requires_args : Error<
+ "block with explicit return type requires argument list">;
+def err_func_def_incomplete_result : Error<
+ "incomplete result type %0 in function definition">;
+
+// Expressions.
+def ext_sizeof_function_type : Extension<
+ "invalid application of 'sizeof' to a function type">;
+def ext_sizeof_void_type : Extension<
+ "invalid application of '%0' to a void type">;
+// FIXME: merge with %select
+def err_sizeof_incomplete_type : Error<
+ "invalid application of 'sizeof' to an incomplete type %0">;
+def err_alignof_incomplete_type : Error<
+ "invalid application of '__alignof' to an incomplete type %0">;
+def err_sizeof_alignof_bitfield : Error<
+ "invalid application of '%select{sizeof|__alignof}0' to bitfield">;
+def err_offsetof_record_type : Error<
+ "offsetof requires struct, union, or class type, %0 invalid">;
+def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
+def ext_offsetof_extended_field_designator : Extension<
+ "using extended field designator is an extension">;
+def warn_offsetof_non_pod_type : Warning<"offset of on non-POD type %0">,
+ InGroup<InvalidOffsetof>;
+
+def warn_floatingpoint_eq : Warning<
+ "comparing floating point with == or != is unsafe">,
+ InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
+
+def err_sizeof_nonfragile_interface : Error<
+ "invalid application of '%select{alignof|sizeof}1' to interface %0 in "
+ "non-fragile ABI">;
+def err_atdef_nonfragile_interface : Error<
+ "invalid application of @defs in non-fragile ABI">;
+def err_subscript_nonfragile_interface : Error<
+ "subscript requires size of interface %0, which is not constant in "
+ "non-fragile ABI">;
+
+def err_arithmetic_nonfragile_interface : Error<
+ "arithmetic on pointer to interface %0, which is not a constant size in "
+ "non-fragile ABI">;
+
+
+def ext_subscript_non_lvalue : Extension<
+ "ISO C90 does not allow subscripting non-lvalue array">;
+def err_typecheck_subscript_value : Error<
+ "subscripted value is not an array, pointer, or vector">;
+def err_typecheck_subscript_not_integer : Error<
+ "array subscript is not an integer">;
+def err_subscript_function_type : Error<
+ "subscript of pointer to function type %0">;
+def err_subscript_incomplete_type : Error<
+ "subscript of pointer to incomplete type %0">;
+def err_typecheck_member_reference_struct_union : Error<
+ "member reference base type %0 is not a structure or union">;
+def err_typecheck_member_reference_ivar : Error<
+ "%0 does not have a member named %1">;
+def err_typecheck_member_reference_arrow : Error<
+ "member reference type %0 is not a pointer">;
+def err_typecheck_member_reference_type : Error<
+ "cannot refer to type member %0 with '%select{.|->}1'">;
+def err_typecheck_member_reference_unknown : Error<
+ "cannot refer to member %0 with '%select{.|->}1'">;
+def note_member_reference_needs_call : Note<
+ "perhaps you meant to call this function with '()'?">;
+
+def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
+def err_typecheck_no_member : Error<"no member named %0">;
+def err_member_redeclared : Error<"class member cannot be redeclared">;
+def err_member_def_does_not_match : Error<
+ "out-of-line definition does not match any declaration in %0">;
+def err_nonstatic_member_out_of_line : Error<
+ "non-static data member defined out-of-line">;
+def err_qualified_typedef_declarator : Error<
+ "typedef declarator cannot be qualified">;
+def err_qualified_param_declarator : Error<
+ "parameter declarator cannot be qualified">;
+def err_out_of_line_declaration : Error<
+ "out-of-line declaration of a member must be a definition">;
+def note_member_def_close_match : Note<"member declaration nearly matches">;
+def err_typecheck_ivar_variable_size : Error<
+ "instance variables must have a constant size">;
+// FIXME: Improve with %select
+def err_typecheck_illegal_increment_decrement : Error<
+ "cannot modify value of type %0">;
+def err_typecheck_arithmetic_incomplete_type : Error<
+ "arithmetic on pointer to incomplete type %0">;
+def err_typecheck_pointer_arith_function_type : Error<
+ "arithmetic on pointer to function type %0">;
+def err_typecheck_pointer_arith_void_type : Error<
+ "arithmetic on pointer to void type">;
+def err_typecheck_decl_incomplete_type : Error<
+ "variable has incomplete type %0">;
+def err_tentative_def_incomplete_type : Error<
+ "tentative definition has type %0 that is never completed">;
+def err_tentative_def_incomplete_type_arr : Error<
+ "tentative definition has array of type %0 that is never completed">;
+def warn_tentative_incomplete_array : Warning<
+ "tentative array definition assumed to have one element">;
+
+def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
+def err_typecheck_sclass_fscope : Error<
+ "illegal storage class on file-scoped variable">;
+def err_unsupported_global_register : Error<
+ "global register variables are not supported">;
+def err_typecheck_sclass_func : Error<"illegal storage class on function">;
+def err_static_block_func : Error<
+ "function declared in block scope cannot have 'static' storage class">;
+def err_typecheck_address_of : Error<"address of %0 requested">;
+def ext_typecheck_addrof_void : Extension<
+ "ISO C forbids taking the address of an expression of type 'void'">;
+def err_typecheck_invalid_lvalue_addrof : Error<
+ "address expression must be an lvalue or a function designator">;
+def err_typecheck_unary_expr : Error<
+ "invalid argument type %0 to unary expression">;
+def err_typecheck_indirection_requires_pointer : Error<
+ "indirection requires pointer operand (%0 invalid)">;
+def err_typecheck_invalid_operands : Error<
+ "invalid operands to binary expression (%0 and %1)">;
+def err_typecheck_sub_ptr_object : Error<
+ "subtraction of pointer %0 requires pointee to be a complete object type">;
+def err_typecheck_sub_ptr_compatible : Error<
+ "%0 and %1 are not pointers to compatible types">;
+def ext_typecheck_comparison_of_pointer_integer : Warning<
+ "comparison between pointer and integer (%0 and %1)">;
+def ext_typecheck_comparison_of_distinct_pointers : Warning<
+ "comparison of distinct pointer types (%0 and %1)">;
+def ext_typecheck_cond_incompatible_operands : Warning<
+ "incompatible operand types (%0 and %1)">;
+def err_typecheck_comparison_of_distinct_pointers : Error<
+ "comparison of distinct pointer types (%0 and %1)">;
+def err_typecheck_vector_comparison : Error<
+ "comparison of vector types (%0 and %1) not supported yet">;
+def err_typecheck_assign_const : Error<"read-only variable is not assignable">;
+def err_stmtexpr_file_scope : Error<
+ "statement expression not allowed at file scope">;
+
+def err_invalid_this_use : Error<
+ "invalid use of 'this' outside of a nonstatic member function">;
+def err_invalid_member_use_in_static_method : Error<
+ "invalid use of member %0 in static member function">;
+def err_invalid_qualified_function_type : Error<
+ "type qualifier is not allowed on this function">;
+def err_invalid_qualified_typedef_function_type_use : Error<
+ "a qualified function type cannot be used to declare a nonmember function "
+ "or a static member function">;
+
+def err_invalid_non_static_member_use : Error<
+ "invalid use of nonstatic data member %0">;
+def err_invalid_incomplete_type_use : Error<
+ "invalid use of incomplete type %0">;
+def err_builtin_func_cast_more_than_one_arg : Error<
+ "function-style cast to a builtin type can only take one argument">;
+def err_builtin_direct_init_more_than_one_arg : Error<
+ "initializer of a builtin type can only take one argument">;
+def err_value_init_for_array_type : Error<
+ "array types cannot be value-initialized">;
+def warn_printf_nonliteral_noargs : Warning<
+ "format string is not a string literal (potentially insecure)">,
+ InGroup<FormatSecurity>;
+def warn_printf_nonliteral : Warning<
+ "format string is not a string literal">,
+ InGroup<FormatNonLiteral>, DefaultIgnore;
+
+def err_unexpected_interface : Error<
+ "unexpected interface name %0: expected expression">;
+def err_property_not_found : Error<
+ "property %0 not found on object of type %1">;
+def ext_gnu_void_ptr : Extension<
+ "use of GNU void* extension">;
+def ext_gnu_ptr_func_arith : Extension<
+ "arithmetic on pointer to function type %0 is a GNU extension">;
+def error_readonly_property_assignment : Error<
+ "assigning to property with 'readonly' attribute not allowed">;
+def ext_integer_increment_complex : Extension<
+ "ISO C does not support '++'/'--' on complex integer type %0">;
+def ext_integer_complement_complex : Extension<
+ "ISO C does not support '~' for complex conjugation of %0">;
+def error_nosetter_property_assignment : Error<
+ "setter method is needed to assign to object using property" " assignment syntax">;
+
+def ext_freestanding_complex : Extension<
+ "complex numbers are an extension in a freestanding C99 implementation">;
+
+
+// Obj-c expressions
+def warn_root_inst_method_not_found : Warning<
+ "instance method %0 is being used on 'Class' which is not in the root class">;
+def warn_class_method_not_found : Warning<
+ "method %objcclass0 not found (return type defaults to 'id')">;
+def warn_inst_method_not_found : Warning<
+ "method %objcinstance0 not found (return type defaults to 'id')">;
+def error_no_super_class_message : Error<
+ "no @interface declaration found in class messaging of %0">;
+def error_no_super_class : Error<
+ "no super class declared in @interface for %0">;
+def err_invalid_receiver_to_message : Error<
+ "invalid receiver to message expression">;
+def warn_bad_receiver_type : Warning<
+ "receiver type %0 is not 'id' or interface pointer, consider "
+ "casting it to 'id'">;
+def err_bad_receiver_type : Error<"bad receiver type %0">;
+def error_objc_throw_expects_object : Error<
+ "@throw requires an Objective-C object type (%0 invalid)">;
+def error_objc_synchronized_expects_object : Error<
+ "@synchronized requires an Objective-C object type (%0 invalid)">;
+def error_rethrow_used_outside_catch : Error<
+ "@throw (rethrow) used outside of a @catch block">;
+def err_attribute_multiple_objc_gc : Error<
+ "multiple garbage collection attributes specified for type">;
+def err_catch_param_not_objc_type : Error<
+ "@catch parameter is not a pointer to an interface type">;
+def err_illegal_qualifiers_on_catch_parm : Error<
+ "illegal qualifiers on @catch parameter">;
+def err_illegal_super_cast : Error<
+ "cannot cast 'super' (it isn't an expression)">;
+def warn_setter_getter_impl_required : Warning<
+ "property %0 requires method %1 to be defined - "
+ "use @synthesize, @dynamic or provide a method implementation">;
+def note_property_impl_required : Note<
+ "implementation is here">;
+
+
+// C++ casts
+def err_bad_cxx_cast_generic : Error<"%0 from %2 to %1 is not allowed">;
+def err_bad_cxx_cast_rvalue : Error<"%0 from rvalue to reference type %1">;
+def err_bad_cxx_cast_const_away : Error<
+ "%0 from %2 to %1 casts away constness">;
+def err_bad_const_cast_dest : Error<
+ "const_cast to %0, which is not a reference, pointer-to-object, "
+ "or pointer-to-data-member">;
+
+def err_bad_reinterpret_cast_same_type : Error<
+ "source and destination type of reinterpret_cast are not distinct">;
+def ext_reinterpret_cast_fn_obj : Extension<
+ "reinterpret_cast between pointer-to-function and pointer-to-object is "
+ "an extension">;
+
+def err_bad_reinterpret_cast_small_int : Error<
+ "cast from pointer to smaller type %0 loses information">;
+def err_bad_dynamic_cast_not_ref_or_ptr : Error<
+ "%0 is not a reference or pointer">;
+def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">;
+def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">;
+def err_bad_dynamic_cast_not_ptr : Error<"%0 is not a pointer">;
+def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
+// FIXME: Display the path somehow better.
+def err_ambiguous_base_to_derived_cast : Error<
+ "ambiguous static_cast from base %0 to derived %1:%2">;
+def err_static_downcast_via_virtual : Error<
+ "cannot cast %0 to %1 via virtual base %2">;
+def err_bad_lvalue_to_rvalue_cast : Error<
+ "cannot cast from lvalue of type %0 to rvalue reference to %1; types are "
+ "not compatible">;
+
+// Other C++ expressions
+def err_need_header_before_typeid : Error<
+ "you need to include <typeinfo> before using the 'typeid' operator">;
+def err_static_illegal_in_new : Error<
+ "the 'static' modifier for the array size is not legal in new expressions">;
+def err_array_new_needs_size : Error<
+ "array size must be specified in new expressions">;
+def err_bad_new_type : Error<
+ "cannot allocate %select{function|reference}1 type %0 with new">;
+def err_new_incomplete_type : Error<
+ "allocation of incomplete type %0">;
+def err_new_array_nonconst : Error<
+ "only the first dimension of an allocated array may be non-const">;
+def err_array_size_not_integral : Error<
+ "array size expression must have integral or enumerated type, not %0">;
+def err_new_uninitialized_const : Error<
+ "must provide an initializer if the allocated object is 'const'">;
+def err_delete_operand : Error<"cannot delete expression of type %0">;
+def warn_delete_incomplete : Warning<
+ "deleting pointer to incomplete type %0 may cause undefined behaviour">;
+def err_decrement_bool : Error<"cannot decrement expression of type bool">;
+def warn_increment_bool : Warning<
+ "incrementing expression of type bool is deprecated">;
+def err_catch_incomplete_ptr : Error<
+ "cannot catch pointer to incomplete type %0">;
+def err_catch_incomplete_ref : Error<
+ "cannot catch reference to incomplete type %0">;
+def err_catch_incomplete : Error<"cannot catch incomplete type %0">;
+def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">;
+def err_qualified_catch_declarator : Error<
+ "exception declarator cannot be qualified">;
+def err_early_catch_all : Error<"catch-all handler must come last">;
+def err_bad_memptr_rhs : Error<
+ "right hand operand to %0 has non pointer-to-member type %1">;
+def err_bad_memptr_lhs : Error<
+ "left hand operand to %0 must be a %select{|pointer to }1class "
+ "compatible with the right hand operand, but is %2">;
+
+def err_conditional_void_nonvoid : Error<
+ "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
+ "is of type %0">;
+def err_conditional_ambiguous : Error<
+ "conditional expression is ambiguous; %0 can be converted to %1 "
+ "and vice versa">;
+def err_conditional_ambiguous_ovl : Error<
+ "conditional expression is ambiguous; %0 and %1 can be converted to several "
+ "common types">;
+
+def err_throw_incomplete : Error<
+ "cannot throw object of incomplete type %0">;
+def err_throw_incomplete_ptr : Error<
+ "cannot throw pointer to object of incomplete type %0">;
+def err_return_in_constructor_handler : Error<
+ "return in the catch of a function try block of a constructor is illegal">;
+
+def err_invalid_use_of_function_type : Error<
+ "a function type is not allowed here">;
+def err_invalid_use_of_array_type : Error<"an array type is not allowed here">;
+def err_type_defined_in_condition : Error<
+ "types may not be defined in conditions">;
+def err_typecheck_bool_condition : Error<
+ "value of type %0 is not contextually convertible to 'bool'">;
+def err_expected_class_or_namespace : Error<"expected a class or namespace">;
+def err_invalid_declarator_scope : Error<
+ "definition or redeclaration of %0 not in a namespace enclosing %1">;
+def err_invalid_declarator_global_scope : Error<
+ "definition or redeclaration of %0 cannot name the global scope">;
+def err_invalid_declarator_in_function : Error<
+ "definition or redeclaration of %0 not allowed inside a function">;
+def err_not_tag_in_scope : Error<
+ "%0 does not name a tag member in the specified scope">;
+
+def warn_value_always_zero : Warning<"%0 is always zero in this context">;
+def warn_value_always_false : Warning<"%0 is always false in this context">;
+
+// assignment related diagnostics (also for argument passing, returning, etc).
+// FIXME: %2 is an english string here.
+def err_typecheck_convert_incompatible : Error<
+ "incompatible type %2 %1, expected %0">;
+def err_cannot_initialize_decl_noname : Error<
+ "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 "
+ "of type %2">;
+def err_cannot_initialize_decl : Error<
+ "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">;
+def warn_incompatible_qualified_id : Warning<
+ "incompatible type %2 %1, expected %0">;
+def warn_incompatible_qualified_id_operands : Warning<
+ "invalid operands to binary expression (%0 and %1)">;
+def ext_typecheck_convert_pointer_int : ExtWarn<
+ "incompatible pointer to integer conversion %2 %1, expected %0">;
+def ext_typecheck_convert_int_pointer : ExtWarn<
+ "incompatible integer to pointer conversion %2 %1, expected %0">;
+def ext_typecheck_convert_pointer_void_func : Extension<
+ "%2 %1 converts between void* and function pointer, expected %0">;
+def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
+ "pointer types point to integer types with different sign %2 %1, expected %0">,
+ InGroup<DiagGroup<"pointer-sign">>;
+def ext_typecheck_convert_incompatible_pointer : ExtWarn<
+ "incompatible pointer types %2 %1, expected %0">;
+def ext_typecheck_convert_discards_qualifiers : ExtWarn<
+ "%2 %1 discards qualifiers, expected %0">;
+def warn_incompatible_vectors : Warning<
+ "incompatible vector types %2 %1, expected %0">,
+ InGroup<VectorConversions>, DefaultIgnore;
+def err_int_to_block_pointer : Error<
+ "invalid conversion %2 integer %1, expected block pointer %0">;
+def err_typecheck_comparison_of_distinct_blocks : Error<
+ "comparison of distinct block types (%0 and %1)">;
+def err_typecheck_convert_incompatible_block_pointer : Error<
+ "incompatible block pointer types %2 %1, expected %0">;
+
+def err_typecheck_array_not_modifiable_lvalue : Error<
+ "array type %0 is not assignable">;
+def err_typecheck_non_object_not_modifiable_lvalue : Error<
+ "non-object type %0 is not assignable">;
+def err_typecheck_expression_not_modifiable_lvalue : Error<
+ "expression is not assignable">;
+def err_typecheck_incomplete_type_not_modifiable_lvalue : Error<
+ "incomplete type %0 is not assignable">;
+def err_typecheck_lvalue_casts_not_supported : Error<
+ "assignment to cast is illegal, lvalue casts are not supported">;
+
+def err_typecheck_duplicate_vector_components_not_mlvalue : Error<
+ "vector is not assignable (contains duplicate components)">;
+def err_block_decl_ref_not_modifiable_lvalue : Error<
+ "variable is not assignable (missing __block type specifier)">;
+def err_typecheck_call_not_function : Error<
+ "called object type %0 is not a function or function pointer">;
+def err_call_incomplete_return : Error<
+ "return type of called function (%0) is incomplete">;
+def err_call_incomplete_argument : Error<
+ "argument type %0 is incomplete">;
+def err_typecheck_call_too_few_args : Error<
+ "too few arguments to %select{function|block|method}0 call">;
+def err_typecheck_call_too_many_args : Error<
+ "too many arguments to %select{function|block|method}0 call">;
+def warn_call_wrong_number_of_arguments : Warning<
+ "too %select{few|many}0 arguments in call to %1">;
+def err_atomic_builtin_must_be_pointer : Error<
+ "first argument to atomic builtin must be a pointer (%0 invalid)">;
+def err_atomic_builtin_must_be_pointer_intptr : Error<
+ "first argument to atomic builtin must be a pointer to integer or pointer"
+ " (%0 invalid)">;
+def err_atomic_builtin_pointer_size : Error<
+ "first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
+ "type (%0 invalid)">;
+
+
+def err_deleted_function_use : Error<"attempt to use a deleted function">;
+
+def err_cannot_pass_objc_interface_to_vararg : Error<
+ "cannot pass object with interface type %0 by-value through variadic "
+ "%select{function|block|method}1">;
+
+def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
+ "cannot pass object of non-POD type %0 through variadic "
+ "%select{function|block|method}1; call will abort at runtime">;
+
+def err_typecheck_closure_too_many_args : Error<
+ "too many arguments to closure call">;
+def err_typecheck_call_invalid_ordered_compare : Error<
+ "ordered compare requires two args of floating point type (%0 and %1)">;
+def err_typecheck_cond_expect_scalar : Error<
+ "used type %0 where arithmetic or pointer type is required">;
+def ext_typecheck_cond_one_void : Extension<
+ "C99 forbids conditional expressions with only one void side">;
+def ext_typecheck_cast_nonscalar : Extension<
+ "C99 forbids casting nonscalar type %0 to the same type">;
+def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">;
+def err_typecheck_cast_to_union_no_type : Error<
+ "cast to union type from type %0 not present in union">;
+def err_cast_pointer_from_non_pointer_int : Error<
+ "operand of type %0 cannot be cast to a pointer type">;
+def err_cast_pointer_to_non_pointer_int : Error<
+ "pointer cannot be cast to type %0">;
+def err_typecheck_expect_scalar_operand : Error<
+ "operand of type %0 where arithmetic or pointer type is required">;
+def err_typecheck_cond_incompatible_operands : Error<
+ "incompatible operand types (%0 and %1)">;
+def err_cast_selector_expr : Error<
+ "cannot type cast @selector expression">;
+def warn_typecheck_cond_incompatible_pointers : Warning<
+ "pointer type mismatch (%0 and %1)">;
+def warn_typecheck_cond_pointer_integer_mismatch : Warning<
+ "pointer/integer type mismatch in conditional expression (%0 and %1)">;
+def err_typecheck_choose_expr_requires_constant : Error<
+ "'__builtin_choose_expr' requires a constant expression">;
+def ext_typecheck_expression_not_constant_but_accepted : Extension<
+ "expression is not a constant, but is accepted as one by GNU extensions">;
+def warn_unused_expr : Warning<"expression result unused">,
+ InGroup<UnusedValue>;
+
+// inline asm.
+def err_asm_wide_character : Error<"wide string is invalid in 'asm'">;
+def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">;
+def err_asm_invalid_output_constraint : Error<
+ "invalid output constraint '%0' in asm">;
+def err_asm_invalid_lvalue_in_input : Error<
+ "invalid lvalue in asm input for constraint '%0'">;
+def err_asm_invalid_input_constraint : Error<
+ "invalid input constraint '%0' in asm">;
+def err_asm_invalid_type_in_input : Error<
+ "invalid type %0 in asm input for constraint '%1'">;
+def err_asm_tying_incompatible_types : Error<
+ "unsupported inline asm: input with type %0 matching output with type %1">;
+def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
+def err_invalid_asm_cast_lvalue : Error<
+ "invalid use of a cast in a inline asm context requiring an l-value: "
+ "remove the cast or build with -fheinous-gnu-extensions">;
+
+def warn_invalid_asm_cast_lvalue : Warning<
+ "invalid use of a cast in a inline asm context requiring an l-value: "
+ "accepted due to -fheinous-gnu-extensions, but clang may remove support "
+ "for this in the future">;
+
+
+
+def err_invalid_conversion_between_vectors : Error<
+ "invalid conversion between vector type %0 and %1 of different size">;
+def err_invalid_conversion_between_vector_and_integer : Error<
+ "invalid conversion between vector type %0 and integer type %1 "
+ "of different size">;
+
+def err_invalid_conversion_between_vector_and_scalar : Error<
+ "invalid conversion between vector type %0 and scalar type %1">;
+def err_overload_expr_requires_non_zero_constant : Error<
+ "overload requires a non-zero constant expression as first argument">;
+def err_overload_incorrect_fntype : Error<
+ "argument is not a function, or has wrong number of parameters">;
+
+// FIXME: PASSING TYPES AS STRING.
+def err_overload_no_match : Error<
+ "no matching overload found for arguments of type '%0'">;
+def err_overload_multiple_match : Error<
+ "more than one matching function found in __builtin_overload">;
+
+// C++ member initializers.
+def err_only_constructors_take_base_inits : Error<
+ "only constructors take base initializers">;
+
+def err_mem_init_not_member_or_class : Error<
+ "member initializer %0 does not name a non-static data member or base "
+ "class">;
+
+def err_base_init_does_not_name_class : Error<
+ "constructor initializer %0 does not name a class">;
+def err_base_init_direct_and_virtual : Error<
+ "base class initializer %0 names both a direct base class and an "
+ "inherited virtual base class">;
+
+def err_in_class_initializer_non_integral_type : Error<
+ "in-class initializer has non-integral, non-enumeration type %0">;
+def err_in_class_initializer_non_constant : Error<
+ "in-class initializer is not an integral constant expression">;
+
+// C++ anonymous unions and GNU anonymous structs/unions
+def ext_anonymous_union : Extension<
+ "anonymous unions are a GNU extension in C">;
+def ext_anonymous_struct : Extension<
+ "anonymous structs are a GNU extension">;
+def err_anonymous_union_not_static : Error<
+ "anonymous unions at namespace or global scope must be declared 'static'">;
+def err_anonymous_union_with_storage_spec : Error<
+ "anonymous union at class scope must not have a storage specifier">;
+def err_anonymous_struct_not_member : Error<
+ "anonymous %select{structs|structs and classes}0 must be "
+ "%select{struct or union|class}0 members">;
+def err_anonymous_union_member_redecl : Error<
+ "member of anonymous union redeclares %0">;
+def err_anonymous_struct_member_redecl : Error<
+ "member of anonymous struct redeclares %0">;
+def err_anonymous_record_with_type : Error<
+ "types cannot be declared in an anonymous %select{struct|union}0">;
+def err_anonymous_record_with_function : Error<
+ "functions cannot be declared in an anonymous %select{struct|union}0">;
+def err_anonymous_record_with_static : Error<
+ "static members cannot be declared in an anonymous %select{struct|union}0">;
+def err_anonymous_record_bad_member : Error<
+ "anonymous %select{struct|union}0 can only contain non-static data members">;
+def err_anonymous_record_nonpublic_member : Error<
+ "anonymous %select{struct|union}0 cannot contain a "
+ "%select{private|protected}1 data member">;
+
+// C++ derived classes
+def err_base_clause_on_union : Error<"unions cannot have base classes">;
+def err_base_must_be_class : Error<"base specifier must name a class">;
+def err_union_as_base_class : Error<"unions cannot be base classes">;
+def err_incomplete_base_class : Error<"base class has incomplete type">;
+def err_duplicate_base_class : Error<
+ "base class %0 specified more than once as a direct base class">;
+// FIXME: better way to display derivation? Pass entire thing into diagclient?
+def err_ambiguous_derived_to_base_conv : Error<
+ "ambiguous conversion from derived class %0 to base class %1:%2">;
+def err_ambiguous_memptr_conv : Error<
+ "ambiguous conversion from pointer to member of %select{base|derived}0 "
+ "class %1 to pointer to member of %select{derived|base}0 class %2:%3">;
+
+def err_memptr_conv_via_virtual : Error<
+ "conversion from pointer to member of class %0 to pointer to member "
+ "of class %1 via virtual base %2 is not allowed">;
+
+// C++ access control
+def err_conv_to_inaccessible_base : Error<
+ "conversion from %0 to inaccessible base class %1">;
+def note_inheritance_specifier_here : Note<
+ "'%0' inheritance specifier here">;
+def note_inheritance_implicitly_private_here : Note<
+ "inheritance is implicitly 'private'">;
+
+// C++ member name lookup
+def err_ambiguous_member_multiple_subobjects : Error<
+ "non-static member %0 found in multiple base-class subobjects of type %1:%2">;
+def err_ambiguous_member_multiple_subobject_types : Error<
+ "member %0 found in multiple base classes of different types">;
+def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">;
+def err_ambiguous_reference : Error<"reference to %0 is ambiguous">;
+def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">;
+
+// C++ operator overloading
+def err_operator_overload_needs_class_or_enum : Error<
+ "overloaded %0 must have at least one parameter of class "
+ "or enumeration type">;
+
+def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
+def err_operator_overload_static : Error<
+ "overloaded %0 cannot be a static member function">;
+def err_operator_overload_default_arg : Error<
+ "parameter of overloaded %0 cannot have a default argument">;
+def err_operator_overload_must_be : Error<
+ "overloaded %0 must be a %select{unary|binary|unary or binary}2 operator "
+ "(has %1 parameter%s1)">;
+
+def err_operator_overload_must_be_member : Error<
+ "overloaded %0 must be a non-static member function">;
+def err_operator_overload_post_incdec_must_be_int : Error<
+ "parameter of overloaded post-%select{increment|decrement}1 operator must "
+ "have type 'int' (not %0)">;
+
+
+// C++ conversion functions
+def err_conv_function_not_member : Error<
+ "conversion function must be a non-static member function">;
+def err_conv_function_return_type : Error<
+ "conversion function cannot have a return type">;
+def err_conv_function_with_params : Error<
+ "conversion function cannot have any parameters">;
+def err_conv_function_variadic : Error<
+ "conversion function cannot be variadic">;
+def err_conv_function_to_array : Error<
+ "conversion function cannot convert to an array type">;
+def err_conv_function_to_function : Error<
+ "conversion function cannot convert to a function type">;
+def err_conv_function_redeclared : Error<
+ "conversion function cannot be redeclared">;
+def warn_conv_to_self_not_used : Warning<
+ "conversion function converting %0 to itself will never be used">;
+def warn_conv_to_base_not_used : Warning<
+ "conversion function converting %0 to its base class %1 will never be used">;
+def warn_conv_to_void_not_used : Warning<
+ "conversion function converting %0 to %1 will never be used">;
+
+def warn_not_compound_assign : Warning<
+ "use of unary operator that may be intended as compound assignment (%0=)">;
+
+// C++0x explicit conversion operators
+def warn_explicit_conversion_functions : Warning<
+ "explicit conversion functions are a C++0x extension">;
+
+def warn_printf_write_back : Warning<
+ "use of '%%n' in format string discouraged (potentially insecure)">,
+ InGroup<FormatSecurity>;
+def warn_printf_insufficient_data_args : Warning<
+ "more '%%' conversions than data arguments">, InGroup<Format>;
+def warn_printf_too_many_data_args : Warning<
+ "more data arguments than '%%' conversions">, InGroup<FormatExtraArgs>;
+def warn_printf_invalid_conversion : Warning<
+ "invalid conversion '%0'">, InGroup<Format>;
+def warn_printf_missing_format_string : Warning<
+ "format string missing">, InGroup<Format>;
+def warn_null_arg : Warning<
+ "null passed to a callee which requires a non-null argument">,
+ InGroup<NonNull>;
+def warn_printf_empty_format_string : Warning<
+ "format string is empty">, InGroup<FormatZeroLength>;
+def warn_printf_format_string_is_wide_literal : Warning<
+ "format string should not be a wide string">, InGroup<Format>;
+def warn_printf_format_string_contains_null_char : Warning<
+ "format string contains '\\0' within the string body">, InGroup<Format>;
+def warn_printf_asterisk_width_missing_arg : Warning<
+ "'*' specified field width is missing a matching 'int' argument">;
+def warn_printf_asterisk_precision_missing_arg : Warning<
+ "'.*' specified field precision is missing a matching 'int' argument">;
+def warn_printf_asterisk_width_wrong_type : Warning<
+ "field width should have type 'int', but argument has type %0">,
+ InGroup<Format>;
+def warn_printf_asterisk_precision_wrong_type : Warning<
+ "field precision should have type 'int', but argument has type %0">,
+ InGroup<Format>;
+
+// CHECK: returning address/reference of stack memory
+def warn_ret_stack_addr : Warning<
+ "address of stack memory associated with local variable %0 returned">;
+def warn_ret_stack_ref : Warning<
+ "reference to stack memory associated with local variable %0 returned">;
+
+
+// For non-floating point, expressions of the form x == x or x != x
+// should result in a warning, since these always evaluate to a constant.
+def warn_selfcomparison : Warning<
+ "self-comparison always results in a constant value">;
+def warn_stringcompare : Warning<
+ "result of comparison against %select{a string literal|@encode}0 is "
+ "unspecified (use strcmp instead)">;
+
+
+
+// Blocks
+def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
+ " or pick a deployment target that supports them">;
+def err_expected_block_lbrace : Error<"expected '{' in block literal">;
+def err_goto_in_block : Error<
+ "goto not allowed in block literal">;
+def err_return_in_block_expression : Error<
+ "return not allowed in block expression literal">;
+def err_block_returns_array : Error<
+ "block declared as returning an array">;
+
+def err_ret_local_block : Error<
+ "returning block that lives on the local stack">;
+
+// CFString checking
+def err_cfstring_literal_not_string_constant : Error<
+ "CFString literal is not a string constant">;
+def warn_cfstring_literal_contains_nul_character : Warning<
+ "CFString literal contains NUL character">;
+
+// Statements.
+def err_continue_not_in_loop : Error<
+ "'continue' statement not in loop statement">;
+def err_break_not_in_loop_or_switch : Error<
+ "'break' statement not in loop or switch statement">;
+def err_default_not_in_switch : Error<
+ "'default' statement not in switch statement">;
+def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
+def warn_case_value_overflow : Warning<
+ "overflow converting case value to switch condition type (%0 to %1)">;
+def err_duplicate_case : Error<"duplicate case value '%0'">;
+def warn_case_empty_range : Warning<"empty case range specified">;
+def err_typecheck_statement_requires_scalar : Error<
+ "statement requires expression of scalar type (%0 invalid)">;
+def err_typecheck_statement_requires_integer : Error<
+ "statement requires expression of integer type (%0 invalid)">;
+def err_multiple_default_labels_defined : Error<
+ "multiple default labels in one switch">;
+def warn_empty_if_body : Warning<
+ "if statement has empty body">;
+def err_va_start_used_in_non_variadic_function : Error<
+ "'va_start' used in function with fixed args">;
+def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
+ "second parameter of 'va_start' not last named argument">;
+def err_first_argument_to_va_arg_not_of_type_va_list : Error<
+ "first argument to 'va_arg' is of type %0 and not 'va_list'">;
+
+def warn_return_missing_expr : Warning<
+ "non-void %select{function|method}1 %0 should return a value">,
+ InGroup<ReturnType>;
+def ext_return_missing_expr : ExtWarn<
+ "non-void %select{function|method}1 %0 should return a value">,
+ InGroup<ReturnType>;
+def ext_return_has_expr : ExtWarn<
+ "void %select{function|method}1 %0 should not return a value">,
+ InGroup<ReturnType>;
+def ext_return_has_void_expr : Extension<
+ "void %select{function|method}1 %0 should not return void expression">;
+def warn_noreturn_function_has_return_expr : Warning<
+ "function %0 declared 'noreturn' should not return">, DefaultError,
+ InGroup<DiagGroup<"invalid-noreturn">>;
+def err_noreturn_block_has_return_expr : Error<
+ "block declared 'noreturn' should not return">;
+def err_block_on_nonlocal : Error<
+ "__block attribute not allowed, only allowed on local variables">;
+def err_block_on_vm : Error<
+ "__block attribute not allowed on declaration with a variably modified type">;
+
+def err_shufflevector_non_vector : Error<
+ "first two arguments to __builtin_shufflevector must be vectors">;
+def err_shufflevector_incompatible_vector : Error<
+ "first two arguments to __builtin_shufflevector must have the same type">;
+def err_shufflevector_nonconstant_argument : Error<
+ "index for __builtin_shufflevector must be a constant integer">;
+def err_shufflevector_argument_too_large : Error<
+ "index for __builtin_shufflevector must be less than the total number "
+ "of vector elements">;
+
+
+def err_stack_const_level : Error<
+ "level argument for a stack address builtin must be constant">;
+
+def err_prefetch_invalid_argument : Error<
+ "argument to __builtin_prefetch must be a constant integer">;
+def err_argument_invalid_range : Error<
+ "argument should be a value from %0 to %1">;
+
+def err_object_size_invalid_argument : Error<
+ "argument to __builtin_object_size must be a constant integer">;
+
+def err_builtin_longjmp_invalid_val : Error<
+ "argument to __builtin_longjmp must be a constant 1">;
+
+def ext_mixed_decls_code : Extension<
+ "ISO C90 forbids mixing declarations and code">;
+def err_non_variable_decl_in_for : Error<
+ "declaration of non-local variable in 'for' loop">;
+def err_toomany_element_decls : Error<
+ "only one element declaration is allowed">;
+def err_selector_element_not_lvalue : Error<
+ "selector element is not a valid lvalue">;
+def err_selector_element_type : Error<
+ "selector element type %0 is not a valid object">;
+def err_collection_expr_type : Error<
+ "collection expression type %0 is not a valid object">;
+
+// Type
+def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
+def warn_receiver_forward_class : Warning<
+ "receiver %0 is a forward class and corresponding @interface may not exist">;
+def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
+def warn_missing_declspec : Warning<
+ "declaration specifier missing, defaulting to 'int'">;
+def warn_missing_type_specifier : Warning<
+ "type specifier missing, defaults to 'int'">,
+ InGroup<ImplicitInt>;
+def err_decimal_unsupported : Error<
+ "GNU decimal type extension not supported">;
+def err_missing_type_specifier : Error<
+ "C++ requires a type specifier for all declarations">;
+def err_missing_param_declspec : Error<
+ "parameter requires a declaration specifier">;
+def err_objc_array_of_interfaces : Error<
+ "array of interface %0 is invalid (probably should be an array of pointers)">;
+def ext_c99_array_usage : Extension<
+ "use of C99-specific array features, accepted as an extension">;
+def err_invalid_protocol_qualifiers : Error<
+ "invalid protocol qualifiers on non-ObjC type">;
+def err_qualified_class_unsupported : Error<
+ "protocol qualified 'Class' is unsupported">;
+def warn_ivar_use_hidden : Warning<
+ "local declaration of %0 hides instance variable">;
+def error_ivar_use_in_class_method : Error<
+ "instance variable %0 accessed in class method">;
+def error_private_ivar_access : Error<"instance variable %0 is private">;
+def error_protected_ivar_access : Error<"instance variable %0 is protected">;
+def warn_maynot_respond : Warning<"%0 may not respond to %1">;
+def warn_attribute_method_def : Warning<
+ "method attribute can only be specified on method declarations">;
+
+
+}
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
new file mode 100644
index 000000000000..d6a0cf34d9fa
--- /dev/null
+++ b/include/clang/Basic/FileManager.h
@@ -0,0 +1,178 @@
+//===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the FileManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FILEMANAGER_H
+#define LLVM_CLANG_FILEMANAGER_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Config/config.h" // for mode_t
+#include <map>
+#include <set>
+#include <string>
+// FIXME: Enhance libsystem to support inode and other fields in stat.
+#include <sys/types.h>
+#include <sys/stat.h>
+
+namespace clang {
+class FileManager;
+
+/// DirectoryEntry - Cached information about one directory on the disk.
+///
+class DirectoryEntry {
+ const char *Name; // Name of the directory.
+ friend class FileManager;
+public:
+ DirectoryEntry() : Name(0) {}
+ const char *getName() const { return Name; }
+};
+
+/// FileEntry - Cached information about one file on the disk.
+///
+class FileEntry {
+ const char *Name; // Name of the file.
+ off_t Size; // File size in bytes.
+ time_t ModTime; // Modification time of file.
+ const DirectoryEntry *Dir; // Directory file lives in.
+ unsigned UID; // A unique (small) ID for the file.
+ dev_t Device; // ID for the device containing the file.
+ ino_t Inode; // Inode number for the file.
+ mode_t FileMode; // The file mode as returned by 'stat'.
+ friend class FileManager;
+public:
+ FileEntry(dev_t device, ino_t inode, mode_t m)
+ : Name(0), Device(device), Inode(inode), FileMode(m) {}
+ // Add a default constructor for use with llvm::StringMap
+ FileEntry() : Name(0), Device(0), Inode(0), FileMode(0) {}
+
+ const char *getName() const { return Name; }
+ off_t getSize() const { return Size; }
+ unsigned getUID() const { return UID; }
+ ino_t getInode() const { return Inode; }
+ dev_t getDevice() const { return Device; }
+ time_t getModificationTime() const { return ModTime; }
+ mode_t getFileMode() const { return FileMode; }
+
+ /// getDir - Return the directory the file lives in.
+ ///
+ const DirectoryEntry *getDir() const { return Dir; }
+
+ bool operator<(const FileEntry& RHS) const {
+ return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
+ }
+};
+
+// FIXME: This is a lightweight shim that is used by FileManager to cache
+// 'stat' system calls. We will use it with PTH to identify if caching
+// stat calls in PTH files is a performance win.
+class StatSysCallCache {
+public:
+ virtual ~StatSysCallCache() {}
+ virtual int stat(const char *path, struct stat *buf) = 0;
+};
+
+/// \brief A stat listener that can be used by FileManager to keep
+/// track of the results of stat() calls that occur throughout the
+/// execution of the front end.
+class MemorizeStatCalls : public StatSysCallCache {
+public:
+ /// \brief The result of a stat() call.
+ ///
+ /// The first member is the result of calling stat(). If stat()
+ /// found something, the second member is a copy of the stat
+ /// structure.
+ typedef std::pair<int, struct stat> StatResult;
+
+ /// \brief The set of stat() calls that have been
+ llvm::StringMap<StatResult, llvm::BumpPtrAllocator> StatCalls;
+
+ typedef llvm::StringMap<StatResult, llvm::BumpPtrAllocator>::const_iterator
+ iterator;
+
+ iterator begin() const { return StatCalls.begin(); }
+ iterator end() const { return StatCalls.end(); }
+
+ virtual int stat(const char *path, struct stat *buf);
+};
+
+/// FileManager - Implements support for file system lookup, file system
+/// caching, and directory search management. This also handles more advanced
+/// properties, such as uniquing files based on "inode", so that a file with two
+/// names (e.g. symlinked) will be treated as a single file.
+///
+class FileManager {
+
+ class UniqueDirContainer;
+ class UniqueFileContainer;
+
+ /// UniqueDirs/UniqueFiles - Cache for existing directories/files.
+ ///
+ UniqueDirContainer &UniqueDirs;
+ UniqueFileContainer &UniqueFiles;
+
+ /// DirEntries/FileEntries - This is a cache of directory/file entries we have
+ /// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
+ ///
+ llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> DirEntries;
+ llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> FileEntries;
+
+ /// NextFileUID - Each FileEntry we create is assigned a unique ID #.
+ ///
+ unsigned NextFileUID;
+
+ // Statistics.
+ unsigned NumDirLookups, NumFileLookups;
+ unsigned NumDirCacheMisses, NumFileCacheMisses;
+
+ // Caching.
+ llvm::OwningPtr<StatSysCallCache> StatCache;
+
+ int stat_cached(const char* path, struct stat* buf) {
+ return StatCache.get() ? StatCache->stat(path, buf) : stat(path, buf);
+ }
+
+public:
+ FileManager();
+ ~FileManager();
+
+ /// setStatCache - Installs the provided StatSysCallCache object within
+ /// the FileManager. Ownership of this object is transferred to the
+ /// FileManager.
+ void setStatCache(StatSysCallCache *statCache) {
+ StatCache.reset(statCache);
+ }
+
+ /// getDirectory - Lookup, cache, and verify the specified directory. This
+ /// returns null if the directory doesn't exist.
+ ///
+ const DirectoryEntry *getDirectory(const std::string &Filename) {
+ return getDirectory(&Filename[0], &Filename[0] + Filename.size());
+ }
+ const DirectoryEntry *getDirectory(const char *FileStart,const char *FileEnd);
+
+ /// getFile - Lookup, cache, and verify the specified file. This returns null
+ /// if the file doesn't exist.
+ ///
+ const FileEntry *getFile(const std::string &Filename) {
+ return getFile(&Filename[0], &Filename[0] + Filename.size());
+ }
+ const FileEntry *getFile(const char *FilenameStart,
+ const char *FilenameEnd);
+
+ void PrintStats() const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
new file mode 100644
index 000000000000..57cd31163144
--- /dev/null
+++ b/include/clang/Basic/IdentifierTable.h
@@ -0,0 +1,561 @@
+//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the IdentifierInfo, IdentifierTable, and Selector
+// interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
+#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
+
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <string>
+#include <cassert>
+
+namespace llvm {
+ template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+ class LangOptions;
+ class IdentifierInfo;
+ class IdentifierTable;
+ class SourceLocation;
+ class MultiKeywordSelector; // private class used by Selector
+ class DeclarationName; // AST class that stores declaration names
+
+ /// IdentifierLocPair - A simple pair of identifier info and location.
+ typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
+
+
+/// IdentifierInfo - One of these records is kept for each identifier that
+/// is lexed. This contains information about whether the token was #define'd,
+/// is a language keyword, or if it is a front-end token of some sort (e.g. a
+/// variable or function name). The preprocessor keeps this information in a
+/// set, and all tok::identifier tokens have a pointer to one of these.
+class IdentifierInfo {
+ // Note: DON'T make TokenID a 'tok::TokenKind'; MSVC will treat it as a
+ // signed char and TokenKinds > 127 won't be handled correctly.
+ unsigned TokenID : 8; // Front-end token ID or tok::identifier.
+ // Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
+ // First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
+ // are for builtins.
+ unsigned ObjCOrBuiltinID :10;
+ bool HasMacro : 1; // True if there is a #define for this.
+ bool IsExtension : 1; // True if identifier is a lang extension.
+ bool IsPoisoned : 1; // True if identifier is poisoned.
+ bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
+ bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
+ // 9 bits left in 32-bit word.
+ void *FETokenInfo; // Managed by the language front-end.
+ llvm::StringMapEntry<IdentifierInfo*> *Entry;
+
+ IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE.
+ void operator=(const IdentifierInfo&); // NONASSIGNABLE.
+
+ friend class IdentifierTable;
+
+public:
+ IdentifierInfo();
+
+
+ /// isStr - Return true if this is the identifier for the specified string.
+ /// This is intended to be used for string literals only: II->isStr("foo").
+ template <std::size_t StrLen>
+ bool isStr(const char (&Str)[StrLen]) const {
+ return getLength() == StrLen-1 && !memcmp(getName(), Str, StrLen-1);
+ }
+
+ /// getName - Return the actual string for this identifier. The returned
+ /// string is properly null terminated.
+ ///
+ const char *getName() const {
+ if (Entry) return Entry->getKeyData();
+ // FIXME: This is gross. It would be best not to embed specific details
+ // of the PTH file format here.
+ // The 'this' pointer really points to a
+ // std::pair<IdentifierInfo, const char*>, where internal pointer
+ // points to the external string data.
+ return ((std::pair<IdentifierInfo, const char*>*) this)->second;
+ }
+
+ /// getLength - Efficiently return the length of this identifier info.
+ ///
+ unsigned getLength() const {
+ if (Entry) return Entry->getKeyLength();
+ // FIXME: This is gross. It would be best not to embed specific details
+ // of the PTH file format here.
+ // The 'this' pointer really points to a
+ // std::pair<IdentifierInfo, const char*>, where internal pointer
+ // points to the external string data.
+ const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second-2;
+ return (((unsigned) p[0])
+ | (((unsigned) p[1]) << 8)) - 1;
+ }
+
+ /// hasMacroDefinition - Return true if this identifier is #defined to some
+ /// other value.
+ bool hasMacroDefinition() const {
+ return HasMacro;
+ }
+ void setHasMacroDefinition(bool Val) {
+ if (HasMacro == Val) return;
+
+ HasMacro = Val;
+ if (Val)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+
+ /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
+ /// can be used to cause the lexer to map identifiers to source-language
+ /// tokens.
+ tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
+ void setTokenID(tok::TokenKind ID) { TokenID = ID; }
+
+ /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
+ /// For example, "define" will return tok::pp_define.
+ tok::PPKeywordKind getPPKeywordID() const;
+
+ /// getObjCKeywordID - Return the Objective-C keyword ID for the this
+ /// identifier. For example, 'class' will return tok::objc_class if ObjC is
+ /// enabled.
+ tok::ObjCKeywordKind getObjCKeywordID() const {
+ if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS)
+ return tok::ObjCKeywordKind(ObjCOrBuiltinID);
+ else
+ return tok::objc_not_keyword;
+ }
+ void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
+
+ /// getBuiltinID - Return a value indicating whether this is a builtin
+ /// function. 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
+ /// 2+ are specific builtin functions.
+ unsigned getBuiltinID() const {
+ if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS)
+ return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS;
+ else
+ return 0;
+ }
+ void setBuiltinID(unsigned ID) {
+ ObjCOrBuiltinID = ID + tok::NUM_OBJC_KEYWORDS;
+ assert(ObjCOrBuiltinID - unsigned(tok::NUM_OBJC_KEYWORDS) == ID
+ && "ID too large for field!");
+ }
+
+ unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; }
+ void setObjCOrBuiltinID(unsigned ID) { ObjCOrBuiltinID = ID; }
+
+ /// get/setExtension - Initialize information about whether or not this
+ /// language token is an extension. This controls extension warnings, and is
+ /// only valid if a custom token ID is set.
+ bool isExtensionToken() const { return IsExtension; }
+ void setIsExtensionToken(bool Val) {
+ IsExtension = Val;
+ if (Val)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+
+ /// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the
+ /// Preprocessor will emit an error every time this token is used.
+ void setIsPoisoned(bool Value = true) {
+ IsPoisoned = Value;
+ if (Value)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+
+ /// isPoisoned - Return true if this token has been poisoned.
+ bool isPoisoned() const { return IsPoisoned; }
+
+ /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
+ /// this identifier is a C++ alternate representation of an operator.
+ void setIsCPlusPlusOperatorKeyword(bool Val = true) {
+ IsCPPOperatorKeyword = Val;
+ if (Val)
+ NeedsHandleIdentifier = 1;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+ bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
+
+ /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
+ /// associate arbitrary metadata with this token.
+ template<typename T>
+ T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
+ void setFETokenInfo(void *T) { FETokenInfo = T; }
+
+ /// isHandleIdentifierCase - Return true if the Preprocessor::HandleIdentifier
+ /// must be called on a token of this identifier. If this returns false, we
+ /// know that HandleIdentifier will not affect the token.
+ bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
+
+private:
+ /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
+ /// several special (but rare) things to identifiers of various sorts. For
+ /// example, it changes the "for" keyword token from tok::identifier to
+ /// tok::for.
+ ///
+ /// This method is very tied to the definition of HandleIdentifier. Any
+ /// change to it should be reflected here.
+ void RecomputeNeedsHandleIdentifier() {
+ NeedsHandleIdentifier =
+ (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
+ isExtensionToken());
+ }
+};
+
+/// IdentifierInfoLookup - An abstract class used by IdentifierTable that
+/// provides an interface for performing lookups from strings
+/// (const char *) to IdentiferInfo objects.
+class IdentifierInfoLookup {
+public:
+ virtual ~IdentifierInfoLookup();
+
+ /// get - Return the identifier token info for the specified named identifier.
+ /// Unlike the version in IdentifierTable, this returns a pointer instead
+ /// of a reference. If the pointer is NULL then the IdentifierInfo cannot
+ /// be found.
+ virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd) = 0;
+};
+
+/// \brief An abstract class used to resolve numerical identifier
+/// references (meaningful only to some external source) into
+/// IdentifierInfo pointers.
+class ExternalIdentifierLookup {
+public:
+ virtual ~ExternalIdentifierLookup();
+
+ /// \brief Return the identifier associated with the given ID number.
+ ///
+ /// The ID 0 is associated with the NULL identifier.
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
+};
+
+/// IdentifierTable - This table implements an efficient mapping from strings to
+/// IdentifierInfo nodes. It has no other purpose, but this is an
+/// extremely performance-critical piece of the code, as each occurrance of
+/// every identifier goes through here when lexed.
+class IdentifierTable {
+ // Shark shows that using MallocAllocator is *much* slower than using this
+ // BumpPtrAllocator!
+ typedef llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator> HashTableTy;
+ HashTableTy HashTable;
+
+ IdentifierInfoLookup* ExternalLookup;
+
+public:
+ /// IdentifierTable ctor - Create the identifier table, populating it with
+ /// info about the language keywords for the language specified by LangOpts.
+ IdentifierTable(const LangOptions &LangOpts,
+ IdentifierInfoLookup* externalLookup = 0);
+
+ /// \brief Set the external identifier lookup mechanism.
+ void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) {
+ ExternalLookup = IILookup;
+ }
+
+ llvm::BumpPtrAllocator& getAllocator() {
+ return HashTable.getAllocator();
+ }
+
+ /// get - Return the identifier token info for the specified named identifier.
+ ///
+ IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
+ llvm::StringMapEntry<IdentifierInfo*> &Entry =
+ HashTable.GetOrCreateValue(NameStart, NameEnd);
+
+ IdentifierInfo *II = Entry.getValue();
+ if (II) return *II;
+
+ // No entry; if we have an external lookup, look there first.
+ if (ExternalLookup) {
+ II = ExternalLookup->get(NameStart, NameEnd);
+ if (II) {
+ // Cache in the StringMap for subsequent lookups.
+ Entry.setValue(II);
+ return *II;
+ }
+ }
+
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ Entry.setValue(II);
+
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+
+ return *II;
+ }
+
+ /// \brief Creates a new IdentifierInfo from the given string.
+ ///
+ /// This is a lower-level version of get() that requires that this
+ /// identifier not be known previously and that does not consult an
+ /// external source for identifiers. In particular, external
+ /// identifier sources can use this routine to build IdentifierInfo
+ /// nodes and then introduce additional information about those
+ /// identifiers.
+ IdentifierInfo &CreateIdentifierInfo(const char *NameStart,
+ const char *NameEnd) {
+ llvm::StringMapEntry<IdentifierInfo*> &Entry =
+ HashTable.GetOrCreateValue(NameStart, NameEnd);
+
+ IdentifierInfo *II = Entry.getValue();
+ assert(!II && "IdentifierInfo already exists");
+
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ Entry.setValue(II);
+
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+
+ return *II;
+ }
+
+ IdentifierInfo &get(const char *Name) {
+ return get(Name, Name+strlen(Name));
+ }
+ IdentifierInfo &get(const std::string &Name) {
+ // Don't use c_str() here: no need to be null terminated.
+ const char *NameBytes = Name.data();
+ return get(NameBytes, NameBytes+Name.size());
+ }
+
+ typedef HashTableTy::const_iterator iterator;
+ typedef HashTableTy::const_iterator const_iterator;
+
+ iterator begin() const { return HashTable.begin(); }
+ iterator end() const { return HashTable.end(); }
+ unsigned size() const { return HashTable.size(); }
+
+ /// PrintStats - Print some statistics to stderr that indicate how well the
+ /// hashing is doing.
+ void PrintStats() const;
+
+ void AddKeywords(const LangOptions &LangOpts);
+};
+
+/// Selector - This smart pointer class efficiently represents Objective-C
+/// method names. This class will either point to an IdentifierInfo or a
+/// MultiKeywordSelector (which is private). This enables us to optimize
+/// selectors that take no arguments and selectors that take 1 argument, which
+/// accounts for 78% of all selectors in Cocoa.h.
+class Selector {
+ friend class DiagnosticInfo;
+
+ enum IdentifierInfoFlag {
+ // MultiKeywordSelector = 0.
+ ZeroArg = 0x1,
+ OneArg = 0x2,
+ ArgFlags = ZeroArg|OneArg
+ };
+ uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
+
+ Selector(IdentifierInfo *II, unsigned nArgs) {
+ InfoPtr = reinterpret_cast<uintptr_t>(II);
+ assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
+ assert(nArgs < 2 && "nArgs not equal to 0/1");
+ InfoPtr |= nArgs+1;
+ }
+ Selector(MultiKeywordSelector *SI) {
+ InfoPtr = reinterpret_cast<uintptr_t>(SI);
+ assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
+ }
+
+ IdentifierInfo *getAsIdentifierInfo() const {
+ if (getIdentifierInfoFlag())
+ return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
+ return 0;
+ }
+ unsigned getIdentifierInfoFlag() const {
+ return InfoPtr & ArgFlags;
+ }
+
+public:
+ friend class SelectorTable; // only the SelectorTable can create these
+ friend class DeclarationName; // and the AST's DeclarationName.
+
+ /// The default ctor should only be used when creating data structures that
+ /// will contain selectors.
+ Selector() : InfoPtr(0) {}
+ Selector(uintptr_t V) : InfoPtr(V) {}
+
+ /// operator==/!= - Indicate whether the specified selectors are identical.
+ bool operator==(Selector RHS) const {
+ return InfoPtr == RHS.InfoPtr;
+ }
+ bool operator!=(Selector RHS) const {
+ return InfoPtr != RHS.InfoPtr;
+ }
+ void *getAsOpaquePtr() const {
+ return reinterpret_cast<void*>(InfoPtr);
+ }
+
+ /// \brief Determine whether this is the empty selector.
+ bool isNull() const { return InfoPtr == 0; }
+
+ // Predicates to identify the selector type.
+ bool isKeywordSelector() const {
+ return getIdentifierInfoFlag() != ZeroArg;
+ }
+ bool isUnarySelector() const {
+ return getIdentifierInfoFlag() == ZeroArg;
+ }
+ unsigned getNumArgs() const;
+ IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
+
+ /// getAsString - Derive the full selector name (e.g. "foo:bar:") and return
+ /// it as an std::string.
+ std::string getAsString() const;
+
+ static Selector getEmptyMarker() {
+ return Selector(uintptr_t(-1));
+ }
+ static Selector getTombstoneMarker() {
+ return Selector(uintptr_t(-2));
+ }
+};
+
+/// SelectorTable - This table allows us to fully hide how we implement
+/// multi-keyword caching.
+class SelectorTable {
+ void *Impl; // Actually a SelectorTableImpl
+ SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
+ void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
+public:
+ SelectorTable();
+ ~SelectorTable();
+
+ /// getSelector - This can create any sort of selector. NumArgs indicates
+ /// whether this is a no argument selector "foo", a single argument selector
+ /// "foo:" or multi-argument "foo:bar:".
+ Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
+
+ Selector getUnarySelector(IdentifierInfo *ID) {
+ return Selector(ID, 1);
+ }
+ Selector getNullarySelector(IdentifierInfo *ID) {
+ return Selector(ID, 0);
+ }
+
+ /// constructSetterName - Return the setter name for the given
+ /// identifier, i.e. "set" + Name where the initial character of Name
+ /// has been capitalized.
+ static Selector constructSetterName(IdentifierTable &Idents,
+ SelectorTable &SelTable,
+ const IdentifierInfo *Name) {
+ llvm::SmallString<100> SelectorName;
+ SelectorName = "set";
+ SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
+ SelectorName[3] = toupper(SelectorName[3]);
+ IdentifierInfo *SetterName =
+ &Idents.get(SelectorName.data(),
+ SelectorName.data() + SelectorName.size());
+ return SelTable.getUnarySelector(SetterName);
+ }
+};
+
+/// DeclarationNameExtra - Common base of the MultiKeywordSelector,
+/// CXXSpecialName, and CXXOperatorIdName classes, all of which are
+/// private classes that describe different kinds of names.
+class DeclarationNameExtra {
+public:
+ /// ExtraKind - The kind of "extra" information stored in the
+ /// DeclarationName. See @c ExtraKindOrNumArgs for an explanation of
+ /// how these enumerator values are used.
+ enum ExtraKind {
+ CXXConstructor = 0,
+ CXXDestructor,
+ CXXConversionFunction,
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ CXXOperator##Name,
+#include "clang/Basic/OperatorKinds.def"
+ CXXUsingDirective,
+ NUM_EXTRA_KINDS
+ };
+
+ /// ExtraKindOrNumArgs - Either the kind of C++ special name or
+ /// operator-id (if the value is one of the CXX* enumerators of
+ /// ExtraKind), in which case the DeclarationNameExtra is also a
+ /// CXXSpecialName (for CXXConstructor, CXXDestructor, or
+ /// CXXConversionFunction) or CXXOperatorIdName, it may be also
+ /// name common to C++ using-directives (CXXUsingDirective), otherwise
+ /// it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of
+ /// arguments in the Objective-C selector, in which case the
+ /// DeclarationNameExtra is also a MultiKeywordSelector.
+ unsigned ExtraKindOrNumArgs;
+};
+
+} // end namespace clang
+
+namespace llvm {
+/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
+/// DenseSets.
+template <>
+struct DenseMapInfo<clang::Selector> {
+ static inline clang::Selector getEmptyKey() {
+ return clang::Selector::getEmptyMarker();
+ }
+ static inline clang::Selector getTombstoneKey() {
+ return clang::Selector::getTombstoneMarker();
+ }
+
+ static unsigned getHashValue(clang::Selector S);
+
+ static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
+ return LHS == RHS;
+ }
+
+ static bool isPod() { return true; }
+};
+
+// Provide PointerLikeTypeTraits for IdentifierInfo pointers, which
+// are not guaranteed to be 8-byte aligned.
+template<>
+class PointerLikeTypeTraits<clang::IdentifierInfo*> {
+public:
+ static inline void *getAsVoidPointer(clang::IdentifierInfo* P) {
+ return P;
+ }
+ static inline clang::IdentifierInfo *getFromVoidPointer(void *P) {
+ return static_cast<clang::IdentifierInfo*>(P);
+ }
+ enum { NumLowBitsAvailable = 1 };
+};
+
+template<>
+class PointerLikeTypeTraits<const clang::IdentifierInfo*> {
+public:
+ static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) {
+ return P;
+ }
+ static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) {
+ return static_cast<const clang::IdentifierInfo*>(P);
+ }
+ enum { NumLowBitsAvailable = 1 };
+};
+
+} // end namespace llvm
+#endif
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
new file mode 100644
index 000000000000..92370cdd9efc
--- /dev/null
+++ b/include/clang/Basic/LangOptions.h
@@ -0,0 +1,157 @@
+//===--- LangOptions.h - C Language Family Language Options -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LangOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LANGOPTIONS_H
+#define LLVM_CLANG_LANGOPTIONS_H
+
+namespace clang {
+
+/// LangOptions - This class keeps track of the various options that can be
+/// enabled, which controls the dialect of C that is accepted.
+class LangOptions {
+public:
+ unsigned Trigraphs : 1; // Trigraphs in source files.
+ unsigned BCPLComment : 1; // BCPL-style '//' comments.
+ unsigned DollarIdents : 1; // '$' allowed in identifiers.
+ unsigned AsmPreprocessor : 1; // Preprocessor in asm mode.
+ unsigned GNUMode : 1; // True in gnu99 mode false in c99 mode (etc)
+ unsigned ImplicitInt : 1; // C89 implicit 'int'.
+ unsigned Digraphs : 1; // C94, C99 and C++
+ unsigned HexFloats : 1; // C99 Hexadecimal float constants.
+ unsigned C99 : 1; // C99 Support
+ unsigned Microsoft : 1; // Microsoft extensions.
+ unsigned CPlusPlus : 1; // C++ Support
+ unsigned CPlusPlus0x : 1; // C++0x Support
+ unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords.
+
+ unsigned ObjC1 : 1; // Objective-C 1 support enabled.
+ unsigned ObjC2 : 1; // Objective-C 2 support enabled.
+ unsigned ObjCSenderDispatch: 1; // Objective-C 2 three-dimensional dispatch
+ // enabled.
+ unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled
+
+ unsigned PascalStrings : 1; // Allow Pascal strings
+ unsigned WritableStrings : 1; // Allow writable strings
+ unsigned LaxVectorConversions : 1;
+ unsigned Exceptions : 1; // Support exception handling.
+
+ unsigned NeXTRuntime : 1; // Use NeXT runtime.
+ unsigned Freestanding : 1; // Freestanding implementation
+ unsigned NoBuiltin : 1; // Do not use builtin functions (-fno-builtin)
+
+ unsigned ThreadsafeStatics : 1; // Whether static initializers are protected
+ // by locks.
+ unsigned Blocks : 1; // block extension to C
+ unsigned EmitAllDecls : 1; // Emit all declarations, even if
+ // they are unused.
+ unsigned MathErrno : 1; // Math functions must respect errno
+ // (modulo the platform support).
+
+ unsigned OverflowChecking : 1; // Extension to call a handler function when
+ // signed integer arithmetic overflows.
+
+ unsigned HeinousExtensions : 1; // Extensions that we really don't like and
+ // may be ripped out at any time.
+
+ unsigned Optimize : 1; // Whether __OPTIMIZE__ should be defined.
+ unsigned OptimizeSize : 1; // Whether __OPTIMIZE_SIZE__ should be
+ // defined.
+ unsigned Static : 1; // Should __STATIC__ be defined (as
+ // opposed to __DYNAMIC__).
+ unsigned PICLevel : 2; // The value for __PIC__, if non-zero.
+
+ unsigned GNUInline : 1; // Should GNU inline semantics be
+ // used (instead of C99 semantics).
+ unsigned NoInline : 1; // Should __NO_INLINE__ be defined.
+
+ unsigned ObjCGCBitmapPrint : 1; // Enable printing of gc's bitmap layout
+ // for __weak/__strong ivars.
+
+ unsigned AccessControl : 1; // Whether C++ access control should
+ // be enabled.
+private:
+ unsigned GC : 2; // Objective-C Garbage Collection modes. We declare
+ // this enum as unsigned because MSVC insists on making enums
+ // signed. Set/Query this value using accessors.
+ unsigned SymbolVisibility : 3; // Symbol's visibility.
+
+ /// The user provided name for the "main file", if non-null. This is
+ /// useful in situations where the input file name does not match
+ /// the original input file, for example with -save-temps.
+ const char *MainFileName;
+
+public:
+ unsigned InstantiationDepth; // Maximum template instantiation depth.
+
+ enum GCMode { NonGC, GCOnly, HybridGC };
+ enum VisibilityMode {
+ Default,
+ Protected,
+ Hidden
+ };
+
+ LangOptions() {
+ Trigraphs = BCPLComment = DollarIdents = AsmPreprocessor = 0;
+ GNUMode = ImplicitInt = Digraphs = 0;
+ HexFloats = 0;
+ GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0;
+ C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
+ CXXOperatorNames = PascalStrings = WritableStrings = 0;
+ Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0;
+ LaxVectorConversions = 1;
+ HeinousExtensions = 0;
+
+ SymbolVisibility = (unsigned) Default;
+
+ // FIXME: The default should be 1.
+ ThreadsafeStatics = 0;
+ Blocks = 0;
+ EmitAllDecls = 0;
+ MathErrno = 1;
+
+ // FIXME: The default should be 1.
+ AccessControl = 0;
+
+ OverflowChecking = 0;
+ ObjCGCBitmapPrint = 0;
+ ObjCSenderDispatch = 0;
+
+ InstantiationDepth = 99;
+
+ Optimize = 0;
+ OptimizeSize = 0;
+
+ Static = 0;
+ PICLevel = 0;
+
+ GNUInline = 0;
+ NoInline = 0;
+
+ MainFileName = 0;
+ }
+
+ GCMode getGCMode() const { return (GCMode) GC; }
+ void setGCMode(GCMode m) { GC = (unsigned) m; }
+
+ const char *getMainFileName() const { return MainFileName; }
+ void setMainFileName(const char *Name) { MainFileName = Name; }
+
+ VisibilityMode getVisibilityMode() const {
+ return (VisibilityMode) SymbolVisibility;
+ }
+ void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
new file mode 100644
index 000000000000..b08d61457b75
--- /dev/null
+++ b/include/clang/Basic/Makefile
@@ -0,0 +1,22 @@
+LEVEL = ../../../../..
+BUILT_SOURCES = DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \
+ DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \
+ DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \
+ DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \
+ DiagnosticGroups.inc
+
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(LEVEL)/Makefile.common
+
+$(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td DiagnosticGroups.td Diagnostic%Kinds.td $(TBLGEN)
+ $(Echo) "Building Clang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen"
+ $(Verb) -$(MKDIR) $(@D)
+ $(Verb) $(TableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $<
+
+$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td $(wildcard Diagnostic*.td) $(TBLGEN)
+ $(Echo) "Building Clang diagnostic groups with tblgen"
+ $(Verb) -$(MKDIR) $(@D)
+ $(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $<
+
+
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
new file mode 100644
index 000000000000..f54d67042c47
--- /dev/null
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -0,0 +1,362 @@
+//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines facilities for reading and writing on-disk hash
+// tables.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
+#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Host.h"
+#include <cassert>
+#include <cstdlib>
+
+namespace clang {
+
+// Bernstein hash function:
+// This is basically copy-and-paste from StringMap. This likely won't
+// stay here, which is why I didn't both to expose this function from
+// String Map.
+inline unsigned BernsteinHash(const char* x) {
+ unsigned int R = 0;
+ for ( ; *x != '\0' ; ++x) R = R * 33 + *x;
+ return R + (R >> 5);
+}
+
+inline unsigned BernsteinHash(const char* x, unsigned n) {
+ unsigned int R = 0;
+ for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x;
+ return R + (R >> 5);
+}
+
+inline unsigned BernsteinHashPartial(const char* x, unsigned n, unsigned R) {
+ for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x;
+ return R + (R >> 5);
+}
+
+namespace io {
+
+typedef uint32_t Offset;
+
+inline void Emit8(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+}
+
+inline void Emit16(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ assert((V >> 16) == 0);
+}
+
+inline void Emit32(llvm::raw_ostream& Out, uint32_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ Out << (unsigned char)(V >> 16);
+ Out << (unsigned char)(V >> 24);
+}
+
+inline void Emit64(llvm::raw_ostream& Out, uint64_t V) {
+ Out << (unsigned char)(V);
+ Out << (unsigned char)(V >> 8);
+ Out << (unsigned char)(V >> 16);
+ Out << (unsigned char)(V >> 24);
+ Out << (unsigned char)(V >> 32);
+ Out << (unsigned char)(V >> 40);
+ Out << (unsigned char)(V >> 48);
+ Out << (unsigned char)(V >> 56);
+}
+
+inline void Pad(llvm::raw_ostream& Out, unsigned A) {
+ Offset off = (Offset) Out.tell();
+ uint32_t n = ((uintptr_t)(off+A-1) & ~(uintptr_t)(A-1)) - off;
+ for (; n ; --n)
+ Emit8(Out, 0);
+}
+
+inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) {
+ uint16_t V = ((uint16_t)Data[0]) |
+ ((uint16_t)Data[1] << 8);
+ Data += 2;
+ return V;
+}
+
+inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) {
+ uint32_t V = ((uint32_t)Data[0]) |
+ ((uint32_t)Data[1] << 8) |
+ ((uint32_t)Data[2] << 16) |
+ ((uint32_t)Data[3] << 24);
+ Data += 4;
+ return V;
+}
+
+inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) {
+ uint64_t V = ((uint64_t)Data[0]) |
+ ((uint64_t)Data[1] << 8) |
+ ((uint64_t)Data[2] << 16) |
+ ((uint64_t)Data[3] << 24) |
+ ((uint64_t)Data[4] << 32) |
+ ((uint64_t)Data[5] << 40) |
+ ((uint64_t)Data[6] << 48) |
+ ((uint64_t)Data[7] << 56);
+ Data += 8;
+ return V;
+}
+
+inline uint32_t ReadLE32(const unsigned char *&Data) {
+ // Hosts that directly support little-endian 32-bit loads can just
+ // use them. Big-endian hosts need a bswap.
+ uint32_t V = *((uint32_t*)Data);
+ if (llvm::sys::isBigEndianHost())
+ V = llvm::ByteSwap_32(V);
+ Data += 4;
+ return V;
+}
+
+} // end namespace io
+
+template<typename Info>
+class OnDiskChainedHashTableGenerator {
+ unsigned NumBuckets;
+ unsigned NumEntries;
+ llvm::BumpPtrAllocator BA;
+
+ class Item {
+ public:
+ typename Info::key_type key;
+ typename Info::data_type data;
+ Item *next;
+ const uint32_t hash;
+
+ Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
+ : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
+ };
+
+ class Bucket {
+ public:
+ io::Offset off;
+ Item* head;
+ unsigned length;
+
+ Bucket() {}
+ };
+
+ Bucket* Buckets;
+
+private:
+ void insert(Bucket* b, size_t size, Item* E) {
+ unsigned idx = E->hash & (size - 1);
+ Bucket& B = b[idx];
+ E->next = B.head;
+ ++B.length;
+ B.head = E;
+ }
+
+ void resize(size_t newsize) {
+ Bucket* newBuckets = (Bucket*) std::calloc(newsize, sizeof(Bucket));
+ // Populate newBuckets with the old entries.
+ for (unsigned i = 0; i < NumBuckets; ++i)
+ for (Item* E = Buckets[i].head; E ; ) {
+ Item* N = E->next;
+ E->next = 0;
+ insert(newBuckets, newsize, E);
+ E = N;
+ }
+
+ free(Buckets);
+ NumBuckets = newsize;
+ Buckets = newBuckets;
+ }
+
+public:
+
+ void insert(typename Info::key_type_ref key,
+ typename Info::data_type_ref data) {
+
+ ++NumEntries;
+ if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
+ insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data));
+ }
+
+ io::Offset Emit(llvm::raw_ostream &out) {
+ Info InfoObj;
+ return Emit(out, InfoObj);
+ }
+
+ io::Offset Emit(llvm::raw_ostream &out, Info &InfoObj) {
+ using namespace clang::io;
+
+ // Emit the payload of the table.
+ for (unsigned i = 0; i < NumBuckets; ++i) {
+ Bucket& B = Buckets[i];
+ if (!B.head) continue;
+
+ // Store the offset for the data of this bucket.
+ B.off = out.tell();
+ assert(B.off && "Cannot write a bucket at offset 0. Please add padding.");
+
+ // Write out the number of items in the bucket.
+ Emit16(out, B.length);
+
+ // Write out the entries in the bucket.
+ for (Item *I = B.head; I ; I = I->next) {
+ Emit32(out, I->hash);
+ const std::pair<unsigned, unsigned>& Len =
+ InfoObj.EmitKeyDataLength(out, I->key, I->data);
+ InfoObj.EmitKey(out, I->key, Len.first);
+ InfoObj.EmitData(out, I->key, I->data, Len.second);
+ }
+ }
+
+ // Emit the hashtable itself.
+ Pad(out, 4);
+ io::Offset TableOff = out.tell();
+ Emit32(out, NumBuckets);
+ Emit32(out, NumEntries);
+ for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off);
+
+ return TableOff;
+ }
+
+ OnDiskChainedHashTableGenerator() {
+ NumEntries = 0;
+ NumBuckets = 64;
+ // Note that we do not need to run the constructors of the individual
+ // Bucket objects since 'calloc' returns bytes that are all 0.
+ Buckets = (Bucket*) std::calloc(NumBuckets, sizeof(Bucket));
+ }
+
+ ~OnDiskChainedHashTableGenerator() {
+ std::free(Buckets);
+ }
+};
+
+template<typename Info>
+class OnDiskChainedHashTable {
+ const unsigned NumBuckets;
+ const unsigned NumEntries;
+ const unsigned char* const Buckets;
+ const unsigned char* const Base;
+ Info InfoObj;
+
+public:
+ typedef typename Info::internal_key_type internal_key_type;
+ typedef typename Info::external_key_type external_key_type;
+ typedef typename Info::data_type data_type;
+
+ OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries,
+ const unsigned char* buckets,
+ const unsigned char* base,
+ const Info &InfoObj = Info())
+ : NumBuckets(numBuckets), NumEntries(numEntries),
+ Buckets(buckets), Base(base), InfoObj(InfoObj) {
+ assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
+ "'buckets' must have a 4-byte alignment");
+ }
+
+ unsigned getNumBuckets() const { return NumBuckets; }
+ unsigned getNumEntries() const { return NumEntries; }
+ const unsigned char* getBase() const { return Base; }
+ const unsigned char* getBuckets() const { return Buckets; }
+
+ bool isEmpty() const { return NumEntries == 0; }
+
+ class iterator {
+ internal_key_type key;
+ const unsigned char* const data;
+ const unsigned len;
+ Info *InfoObj;
+ public:
+ iterator() : data(0), len(0) {}
+ iterator(const internal_key_type k, const unsigned char* d, unsigned l,
+ Info *InfoObj)
+ : key(k), data(d), len(l), InfoObj(InfoObj) {}
+
+ data_type operator*() const { return InfoObj->ReadData(key, data, len); }
+ bool operator==(const iterator& X) const { return X.data == data; }
+ bool operator!=(const iterator& X) const { return X.data != data; }
+ };
+
+ iterator find(const external_key_type& eKey, Info *InfoPtr = 0) {
+ if (!InfoPtr)
+ InfoPtr = &InfoObj;
+
+ using namespace io;
+ const internal_key_type& iKey = Info::GetInternalKey(eKey);
+ unsigned key_hash = Info::ComputeHash(iKey);
+
+ // Each bucket is just a 32-bit offset into the hash table file.
+ unsigned idx = key_hash & (NumBuckets - 1);
+ const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx;
+
+ unsigned offset = ReadLE32(Bucket);
+ if (offset == 0) return iterator(); // Empty bucket.
+ const unsigned char* Items = Base + offset;
+
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ unsigned len = ReadUnalignedLE16(Items);
+
+ for (unsigned i = 0; i < len; ++i) {
+ // Read the hash.
+ uint32_t item_hash = ReadUnalignedLE32(Items);
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items);
+ unsigned item_len = L.first + L.second;
+
+ // Compare the hashes. If they are not the same, skip the entry entirely.
+ if (item_hash != key_hash) {
+ Items += item_len;
+ continue;
+ }
+
+ // Read the key.
+ const internal_key_type& X =
+ InfoPtr->ReadKey((const unsigned char* const) Items, L.first);
+
+ // If the key doesn't match just skip reading the value.
+ if (!Info::EqualKey(X, iKey)) {
+ Items += item_len;
+ continue;
+ }
+
+ // The key matches!
+ return iterator(X, Items + L.first, L.second, InfoPtr);
+ }
+
+ return iterator();
+ }
+
+ iterator end() const { return iterator(); }
+
+
+ static OnDiskChainedHashTable* Create(const unsigned char* buckets,
+ const unsigned char* const base,
+ const Info &InfoObj = Info()) {
+ using namespace io;
+ assert(buckets > base);
+ assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
+ "buckets should be 4-byte aligned.");
+
+ unsigned numBuckets = ReadLE32(buckets);
+ unsigned numEntries = ReadLE32(buckets);
+ return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets,
+ base, InfoObj);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/OperatorKinds.def b/include/clang/Basic/OperatorKinds.def
new file mode 100644
index 000000000000..d011e9d39ff8
--- /dev/null
+++ b/include/clang/Basic/OperatorKinds.def
@@ -0,0 +1,106 @@
+//===--- OperatorKinds.def - C++ Overloaded Operator Database ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the OverloadedOperator database, which includes
+// all of the overloadable C++ operators.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file OperatorKinds.def
+///
+/// In this file, each of the overloadable C++ operators is enumerated
+/// with either the OVERLOADED_OPERATOR or OVERLOADED_OPERATOR_MULTI
+/// macro, each of which can be specified by the code including this
+/// file. OVERLOADED_OPERATOR is used for single-token operators
+/// (e.g., "+"), and has six arguments:
+///
+/// Name: The name of the token. OO_Name will be the name of the
+/// corresponding enumerator in OverloadedOperatorKind in
+/// OperatorKinds.h.
+///
+/// Spelling: A string that provides a canonical spelling for the
+/// operator, e.g., "operator+".
+///
+/// Token: The name of the token that specifies the operator, e.g.,
+/// "plus" for operator+ or "greatergreaterequal" for
+/// "operator>>=". With a "kw_" prefix, the token name can be used as
+/// an enumerator into the TokenKind enumeration.
+///
+/// Unary: True if the operator can be declared as a unary operator.
+///
+/// Binary: True if the operator can be declared as a binary
+/// operator. Note that some operators (e.g., "operator+" and
+/// "operator*") can be both unary and binary.
+///
+/// MemberOnly: True if this operator can only be declared as a
+/// non-static member function. False if the operator can be both a
+/// non-member function and a non-static member function.
+///
+/// OVERLOADED_OPERATOR_MULTI is used to enumerate the multi-token
+/// overloaded operator names, e.g., "operator delete []". The macro
+/// has all of the parameters of OVERLOADED_OPERATOR except Token,
+/// which is omitted.
+
+#ifndef OVERLOADED_OPERATOR
+# define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)
+#endif
+
+#ifndef OVERLOADED_OPERATOR_MULTI
+# define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) \
+ OVERLOADED_OPERATOR(Name,Spelling,unknown,Unary,Binary,MemberOnly)
+#endif
+
+OVERLOADED_OPERATOR_MULTI(New , "new" , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Delete , "delete" , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_New , "new[]" , true , true , false)
+OVERLOADED_OPERATOR_MULTI(Array_Delete , "delete[]" , true , true , false)
+OVERLOADED_OPERATOR(Plus , "+" , plus , true , true , false)
+OVERLOADED_OPERATOR(Minus , "-" , minus , true , true , false)
+OVERLOADED_OPERATOR(Star , "*" , star , true , true , false)
+OVERLOADED_OPERATOR(Slash , "/" , slash , false, true , false)
+OVERLOADED_OPERATOR(Percent , "%" , percent , false, true , false)
+OVERLOADED_OPERATOR(Caret , "^" , caret , false, true , false)
+OVERLOADED_OPERATOR(Amp , "&" , amp , true , true , false)
+OVERLOADED_OPERATOR(Pipe , "|" , pipe , false, true , false)
+OVERLOADED_OPERATOR(Tilde , "~" , tilde , true , false, false)
+OVERLOADED_OPERATOR(Exclaim , "!" , exclaim , true , false, false)
+OVERLOADED_OPERATOR(Equal , "=" , equal , false, true , true)
+OVERLOADED_OPERATOR(Less , "<" , less , false, true , false)
+OVERLOADED_OPERATOR(Greater , ">" , greater , false, true , false)
+OVERLOADED_OPERATOR(PlusEqual , "+=" , plusequal , false, true , false)
+OVERLOADED_OPERATOR(MinusEqual , "-=" , minusequal , false, true , false)
+OVERLOADED_OPERATOR(StarEqual , "*=" , starequal , false, true , false)
+OVERLOADED_OPERATOR(SlashEqual , "/=" , slashequal , false, true , false)
+OVERLOADED_OPERATOR(PercentEqual , "%=" , percentequal , false, true , false)
+OVERLOADED_OPERATOR(CaretEqual , "^=" , caretequal , false, true , false)
+OVERLOADED_OPERATOR(AmpEqual , "&=" , ampequal , false, true , false)
+OVERLOADED_OPERATOR(PipeEqual , "|=" , pipeequal , false, true , false)
+OVERLOADED_OPERATOR(LessLess , "<<" , lessless , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreater , ">>" , greatergreater , false, true , false)
+OVERLOADED_OPERATOR(LessLessEqual , "<<=" , lesslessequal , false, true , false)
+OVERLOADED_OPERATOR(GreaterGreaterEqual , ">>=" , greatergreaterequal, false, true , false)
+OVERLOADED_OPERATOR(EqualEqual , "==" , equalequal , false, true , false)
+OVERLOADED_OPERATOR(ExclaimEqual , "!=" , exclaimequal , false, true , false)
+OVERLOADED_OPERATOR(LessEqual , "<=" , lessequal , false, true , false)
+OVERLOADED_OPERATOR(GreaterEqual , ">=" , greaterequal , false, true , false)
+OVERLOADED_OPERATOR(AmpAmp , "&&" , ampamp , false, true , false)
+OVERLOADED_OPERATOR(PipePipe , "||" , pipepipe , false, true , false)
+OVERLOADED_OPERATOR(PlusPlus , "++" , plusplus , true , true , false)
+OVERLOADED_OPERATOR(MinusMinus , "--" , minusminus , true , true , false)
+OVERLOADED_OPERATOR(Comma , "," , comma , false, true , false)
+OVERLOADED_OPERATOR(ArrowStar , "->*" , arrowstar , false, true , false)
+OVERLOADED_OPERATOR(Arrow , "->" , arrow , true , false, true)
+OVERLOADED_OPERATOR_MULTI(Call , "()" , true , true , true)
+OVERLOADED_OPERATOR_MULTI(Subscript , "[]" , false, true , true)
+// ?: can *not* be overloaded, but we need the overload
+// resolution machinery for it.
+OVERLOADED_OPERATOR_MULTI(Conditional , "?" , false, true , false)
+
+#undef OVERLOADED_OPERATOR_MULTI
+#undef OVERLOADED_OPERATOR
diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
new file mode 100644
index 000000000000..790b75ba3af3
--- /dev/null
+++ b/include/clang/Basic/OperatorKinds.h
@@ -0,0 +1,32 @@
+//===--- OperatorKinds.h - C++ Overloaded Operators -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines C++ overloaded operators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H
+#define LLVM_CLANG_BASIC_OPERATOR_KINDS_H
+
+namespace clang {
+
+/// OverloadedOperatorKind - Enumeration specifying the different kinds of
+/// C++ overloaded operators.
+enum OverloadedOperatorKind {
+ OO_None, //< Not an overloaded operator
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+ OO_##Name,
+#include "clang/Basic/OperatorKinds.def"
+ NUM_OVERLOADED_OPERATORS
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h
new file mode 100644
index 000000000000..5a5d55192b69
--- /dev/null
+++ b/include/clang/Basic/PrettyStackTrace.h
@@ -0,0 +1,37 @@
+//===- clang/Basic/PrettyStackTrace.h - Pretty Crash Handling --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PrettyStackTraceEntry class, which is used to make
+// crashes give more contextual information about what the program was doing
+// when it crashed.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_BASIC_PRETTYSTACKTRACE_H
+#define CLANG_BASIC_PRETTYSTACKTRACE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+
+ /// PrettyStackTraceLoc - If a crash happens while one of these objects are
+ /// live, the message is printed out along with the specified source location.
+ class PrettyStackTraceLoc : public llvm::PrettyStackTraceEntry {
+ SourceManager &SM;
+ SourceLocation Loc;
+ const char *Message;
+ public:
+ PrettyStackTraceLoc(SourceManager &sm, SourceLocation L, const char *Msg)
+ : SM(sm), Loc(L), Message(Msg) {}
+ virtual void print(llvm::raw_ostream &OS) const;
+ };
+}
+
+#endif
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
new file mode 100644
index 000000000000..2405c2fe7db7
--- /dev/null
+++ b/include/clang/Basic/SourceLocation.h
@@ -0,0 +1,305 @@
+//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SourceLocation class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SOURCELOCATION_H
+#define LLVM_CLANG_SOURCELOCATION_H
+
+#include <utility>
+#include <cassert>
+
+namespace llvm {
+ class MemoryBuffer;
+ class raw_ostream;
+ template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+
+class SourceManager;
+class FileEntry;
+
+/// FileID - This is an opaque identifier used by SourceManager which refers to
+/// a source file (MemoryBuffer) along with its #include path and #line data.
+///
+class FileID {
+ /// ID - Opaque identifier, 0 is "invalid".
+ unsigned ID;
+public:
+ FileID() : ID(0) {}
+
+ bool isInvalid() const { return ID == 0; }
+
+ bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
+ bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
+ bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
+ bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
+ bool operator>(const FileID &RHS) const { return RHS < *this; }
+ bool operator>=(const FileID &RHS) const { return RHS <= *this; }
+
+ static FileID getSentinel() { return get(~0U); }
+ unsigned getHashValue() const { return ID; }
+
+private:
+ friend class SourceManager;
+ static FileID get(unsigned V) {
+ FileID F;
+ F.ID = V;
+ return F;
+ }
+ unsigned getOpaqueValue() const { return ID; }
+};
+
+
+/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
+/// a full include stack, line and column number information for a position in
+/// an input translation unit.
+class SourceLocation {
+ unsigned ID;
+ friend class SourceManager;
+ enum {
+ MacroIDBit = 1U << 31
+ };
+public:
+
+ SourceLocation() : ID(0) {} // 0 is an invalid FileID.
+
+ bool isFileID() const { return (ID & MacroIDBit) == 0; }
+ bool isMacroID() const { return (ID & MacroIDBit) != 0; }
+
+ /// isValid - Return true if this is a valid SourceLocation object. Invalid
+ /// SourceLocations are often used when events have no corresponding location
+ /// in the source (e.g. a diagnostic is required for a command line option).
+ ///
+ bool isValid() const { return ID != 0; }
+ bool isInvalid() const { return ID == 0; }
+
+private:
+ /// getOffset - Return the index for SourceManager's SLocEntryTable table,
+ /// note that this is not an index *into* it though.
+ unsigned getOffset() const {
+ return ID & ~MacroIDBit;
+ }
+
+ static SourceLocation getFileLoc(unsigned ID) {
+ assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
+ SourceLocation L;
+ L.ID = ID;
+ return L;
+ }
+
+ static SourceLocation getMacroLoc(unsigned ID) {
+ assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
+ SourceLocation L;
+ L.ID = MacroIDBit | ID;
+ return L;
+ }
+public:
+
+ /// getFileLocWithOffset - Return a source location with the specified offset
+ /// from this file SourceLocation.
+ SourceLocation getFileLocWithOffset(int Offset) const {
+ assert(((getOffset()+Offset) & MacroIDBit) == 0 && "invalid location");
+ SourceLocation L;
+ L.ID = ID+Offset;
+ return L;
+ }
+
+ /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
+ /// an (opaque) 32-bit integer encoding for it. This should only be passed
+ /// to SourceLocation::getFromRawEncoding, it should not be inspected
+ /// directly.
+ unsigned getRawEncoding() const { return ID; }
+
+
+ /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
+ /// a real SourceLocation.
+ static SourceLocation getFromRawEncoding(unsigned Encoding) {
+ SourceLocation X;
+ X.ID = Encoding;
+ return X;
+ }
+
+ void print(llvm::raw_ostream &OS, const SourceManager &SM) const;
+ void dump(const SourceManager &SM) const;
+};
+
+inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return LHS.getRawEncoding() == RHS.getRawEncoding();
+}
+
+inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return !(LHS == RHS);
+}
+
+inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return LHS.getRawEncoding() < RHS.getRawEncoding();
+}
+
+/// SourceRange - a trival tuple used to represent a source range.
+class SourceRange {
+ SourceLocation B;
+ SourceLocation E;
+public:
+ SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
+ SourceRange(SourceLocation loc) : B(loc), E(loc) {}
+ SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
+
+ SourceLocation getBegin() const { return B; }
+ SourceLocation getEnd() const { return E; }
+
+ void setBegin(SourceLocation b) { B = b; }
+ void setEnd(SourceLocation e) { E = e; }
+
+ bool isValid() const { return B.isValid() && E.isValid(); }
+
+ bool operator==(const SourceRange &X) const {
+ return B == X.B && E == X.E;
+ }
+
+ bool operator!=(const SourceRange &X) const {
+ return B != X.B || E != X.E;
+ }
+};
+
+/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful
+/// for argument passing to functions that expect both objects.
+class FullSourceLoc : public SourceLocation {
+ SourceManager* SrcMgr;
+public:
+ /// Creates a FullSourceLoc where isValid() returns false.
+ explicit FullSourceLoc() : SrcMgr((SourceManager*) 0) {}
+
+ explicit FullSourceLoc(SourceLocation Loc, SourceManager &SM)
+ : SourceLocation(Loc), SrcMgr(&SM) {}
+
+ SourceManager &getManager() {
+ assert(SrcMgr && "SourceManager is NULL.");
+ return *SrcMgr;
+ }
+
+ const SourceManager &getManager() const {
+ assert(SrcMgr && "SourceManager is NULL.");
+ return *SrcMgr;
+ }
+
+ FileID getFileID() const;
+
+ FullSourceLoc getInstantiationLoc() const;
+ FullSourceLoc getSpellingLoc() const;
+
+ unsigned getInstantiationLineNumber() const;
+ unsigned getInstantiationColumnNumber() const;
+
+ unsigned getSpellingLineNumber() const;
+ unsigned getSpellingColumnNumber() const;
+
+ const char *getCharacterData() const;
+
+ const llvm::MemoryBuffer* getBuffer() const;
+
+ /// getBufferData - Return a pointer to the start and end of the source buffer
+ /// data for the specified FileID.
+ std::pair<const char*, const char*> getBufferData() const;
+
+ /// getDecomposedLoc - Decompose the specified location into a raw FileID +
+ /// Offset pair. The first element is the FileID, the second is the
+ /// offset from the start of the buffer of the location.
+ std::pair<FileID, unsigned> getDecomposedLoc() const;
+
+ bool isInSystemHeader() const;
+
+ /// Prints information about this FullSourceLoc to stderr. Useful for
+ /// debugging.
+ void dump() const { SourceLocation::dump(*SrcMgr); }
+
+ friend inline bool
+ operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
+ return LHS.getRawEncoding() == RHS.getRawEncoding() &&
+ LHS.SrcMgr == RHS.SrcMgr;
+ }
+
+ friend inline bool
+ operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
+ return !(LHS == RHS);
+ }
+
+};
+
+/// PresumedLoc - This class represents an unpacked "presumed" location which
+/// can be presented to the user. A 'presumed' location can be modified by
+/// #line and GNU line marker directives and is always the instantiation point
+/// of a normal location.
+///
+/// You can get a PresumedLoc from a SourceLocation with SourceManager.
+class PresumedLoc {
+ const char *Filename;
+ unsigned Line, Col;
+ SourceLocation IncludeLoc;
+public:
+ PresumedLoc() : Filename(0) {}
+ PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
+ : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
+ }
+
+ /// isInvalid - Return true if this object is invalid or uninitialized. This
+ /// occurs when created with invalid source locations or when walking off
+ /// the top of a #include stack.
+ bool isInvalid() const { return Filename == 0; }
+ bool isValid() const { return Filename != 0; }
+
+ /// getFilename - Return the presumed filename of this location. This can be
+ /// affected by #line etc.
+ const char *getFilename() const { return Filename; }
+
+ /// getLine - Return the presumed line number of this location. This can be
+ /// affected by #line etc.
+ unsigned getLine() const { return Line; }
+
+ /// getColumn - Return the presumed column number of this location. This can
+ /// not be affected by #line, but is packaged here for convenience.
+ unsigned getColumn() const { return Col; }
+
+ /// getIncludeLoc - Return the presumed include location of this location.
+ /// This can be affected by GNU linemarker directives.
+ SourceLocation getIncludeLoc() const { return IncludeLoc; }
+};
+
+
+} // end namespace clang
+
+namespace llvm {
+ /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
+ /// DenseSets.
+ template <>
+ struct DenseMapInfo<clang::FileID> {
+ static inline clang::FileID getEmptyKey() {
+ return clang::FileID();
+ }
+ static inline clang::FileID getTombstoneKey() {
+ return clang::FileID::getSentinel();
+ }
+
+ static unsigned getHashValue(clang::FileID S) {
+ return S.getHashValue();
+ }
+
+ static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
+ return LHS == RHS;
+ }
+
+ static bool isPod() { return true; }
+ };
+
+} // end namespace llvm
+
+#endif
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
new file mode 100644
index 000000000000..43369829387d
--- /dev/null
+++ b/include/clang/Basic/SourceManager.h
@@ -0,0 +1,714 @@
+//===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SourceManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SOURCEMANAGER_H
+#define LLVM_CLANG_SOURCEMANAGER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+#include <cassert>
+
+namespace llvm {
+class MemoryBuffer;
+}
+
+namespace clang {
+
+class SourceManager;
+class FileManager;
+class FileEntry;
+class IdentifierTokenInfo;
+class LineTableInfo;
+
+/// SrcMgr - Public enums and private classes that are part of the
+/// SourceManager implementation.
+///
+namespace SrcMgr {
+ /// CharacteristicKind - This is used to represent whether a file or directory
+ /// holds normal user code, system code, or system code which is implicitly
+ /// 'extern "C"' in C++ mode. Entire directories can be tagged with this
+ /// (this is maintained by DirectoryLookup and friends) as can specific
+ /// FileIDInfos when a #pragma system_header is seen or various other cases.
+ ///
+ enum CharacteristicKind {
+ C_User, C_System, C_ExternCSystem
+ };
+
+ /// ContentCache - Once instance of this struct is kept for every file
+ /// loaded or used. This object owns the MemoryBuffer object.
+ class ContentCache {
+ /// Buffer - The actual buffer containing the characters from the input
+ /// file. This is owned by the ContentCache object.
+ mutable const llvm::MemoryBuffer *Buffer;
+
+ public:
+ /// Reference to the file entry. This reference does not own
+ /// the FileEntry object. It is possible for this to be NULL if
+ /// the ContentCache encapsulates an imaginary text buffer.
+ const FileEntry *Entry;
+
+ /// SourceLineCache - A bump pointer allocated array of offsets for each
+ /// source line. This is lazily computed. This is owned by the
+ /// SourceManager BumpPointerAllocator object.
+ unsigned *SourceLineCache;
+
+ /// NumLines - The number of lines in this ContentCache. This is only valid
+ /// if SourceLineCache is non-null.
+ unsigned NumLines;
+
+ /// getBuffer - Returns the memory buffer for the associated content.
+ const llvm::MemoryBuffer *getBuffer() const;
+
+ /// getSize - Returns the size of the content encapsulated by this
+ /// ContentCache. This can be the size of the source file or the size of an
+ /// arbitrary scratch buffer. If the ContentCache encapsulates a source
+ /// file this size is retrieved from the file's FileEntry.
+ unsigned getSize() const;
+
+ /// getSizeBytesMapped - Returns the number of bytes actually mapped for
+ /// this ContentCache. This can be 0 if the MemBuffer was not actually
+ /// instantiated.
+ unsigned getSizeBytesMapped() const;
+
+ void setBuffer(const llvm::MemoryBuffer *B) {
+ assert(!Buffer && "MemoryBuffer already set.");
+ Buffer = B;
+ }
+
+ ContentCache(const FileEntry *Ent = 0)
+ : Buffer(0), Entry(Ent), SourceLineCache(0), NumLines(0) {}
+
+ ~ContentCache();
+
+ /// The copy ctor does not allow copies where source object has either
+ /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
+ /// is not transfered, so this is a logical error.
+ ContentCache(const ContentCache &RHS) : Buffer(0), SourceLineCache(0) {
+ Entry = RHS.Entry;
+
+ assert (RHS.Buffer == 0 && RHS.SourceLineCache == 0
+ && "Passed ContentCache object cannot own a buffer.");
+
+ NumLines = RHS.NumLines;
+ }
+
+ private:
+ // Disable assignments.
+ ContentCache &operator=(const ContentCache& RHS);
+ };
+
+ /// FileInfo - Information about a FileID, basically just the logical file
+ /// that it represents and include stack information.
+ ///
+ /// Each FileInfo has include stack information, indicating where it came
+ /// from. This information encodes the #include chain that a token was
+ /// instantiated from. The main include file has an invalid IncludeLoc.
+ ///
+ /// FileInfos contain a "ContentCache *", with the contents of the file.
+ ///
+ class FileInfo {
+ /// IncludeLoc - The location of the #include that brought in this file.
+ /// This is an invalid SLOC for the main file (top of the #include chain).
+ unsigned IncludeLoc; // Really a SourceLocation
+
+ /// Data - This contains the ContentCache* and the bits indicating the
+ /// characteristic of the file and whether it has #line info, all bitmangled
+ /// together.
+ uintptr_t Data;
+ public:
+ /// get - Return a FileInfo object.
+ static FileInfo get(SourceLocation IL, const ContentCache *Con,
+ CharacteristicKind FileCharacter) {
+ FileInfo X;
+ X.IncludeLoc = IL.getRawEncoding();
+ X.Data = (uintptr_t)Con;
+ assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned");
+ assert((unsigned)FileCharacter < 4 && "invalid file character");
+ X.Data |= (unsigned)FileCharacter;
+ return X;
+ }
+
+ SourceLocation getIncludeLoc() const {
+ return SourceLocation::getFromRawEncoding(IncludeLoc);
+ }
+ const ContentCache* getContentCache() const {
+ return reinterpret_cast<const ContentCache*>(Data & ~7UL);
+ }
+
+ /// getCharacteristic - Return whether this is a system header or not.
+ CharacteristicKind getFileCharacteristic() const {
+ return (CharacteristicKind)(Data & 3);
+ }
+
+ /// hasLineDirectives - Return true if this FileID has #line directives in
+ /// it.
+ bool hasLineDirectives() const { return (Data & 4) != 0; }
+
+ /// setHasLineDirectives - Set the flag that indicates that this FileID has
+ /// line table entries associated with it.
+ void setHasLineDirectives() {
+ Data |= 4;
+ }
+ };
+
+ /// InstantiationInfo - Each InstantiationInfo encodes the Instantiation
+ /// location - where the token was ultimately instantiated, and the
+ /// SpellingLoc - where the actual character data for the token came from.
+ class InstantiationInfo {
+ // Really these are all SourceLocations.
+
+ /// SpellingLoc - Where the spelling for the token can be found.
+ unsigned SpellingLoc;
+
+ /// InstantiationLocStart/InstantiationLocEnd - In a macro expansion, these
+ /// indicate the start and end of the instantiation. In object-like macros,
+ /// these will be the same. In a function-like macro instantiation, the
+ /// start will be the identifier and the end will be the ')'.
+ unsigned InstantiationLocStart, InstantiationLocEnd;
+ public:
+ SourceLocation getSpellingLoc() const {
+ return SourceLocation::getFromRawEncoding(SpellingLoc);
+ }
+ SourceLocation getInstantiationLocStart() const {
+ return SourceLocation::getFromRawEncoding(InstantiationLocStart);
+ }
+ SourceLocation getInstantiationLocEnd() const {
+ return SourceLocation::getFromRawEncoding(InstantiationLocEnd);
+ }
+
+ std::pair<SourceLocation,SourceLocation> getInstantiationLocRange() const {
+ return std::make_pair(getInstantiationLocStart(),
+ getInstantiationLocEnd());
+ }
+
+ /// get - Return a InstantiationInfo for an expansion. IL specifies
+ /// the instantiation location (where the macro is expanded), and SL
+ /// specifies the spelling location (where the characters from the token
+ /// come from). IL and PL can both refer to normal File SLocs or
+ /// instantiation locations.
+ static InstantiationInfo get(SourceLocation ILStart, SourceLocation ILEnd,
+ SourceLocation SL) {
+ InstantiationInfo X;
+ X.SpellingLoc = SL.getRawEncoding();
+ X.InstantiationLocStart = ILStart.getRawEncoding();
+ X.InstantiationLocEnd = ILEnd.getRawEncoding();
+ return X;
+ }
+ };
+
+ /// SLocEntry - This is a discriminated union of FileInfo and
+ /// InstantiationInfo. SourceManager keeps an array of these objects, and
+ /// they are uniquely identified by the FileID datatype.
+ class SLocEntry {
+ unsigned Offset; // low bit is set for instantiation info.
+ union {
+ FileInfo File;
+ InstantiationInfo Instantiation;
+ };
+ public:
+ unsigned getOffset() const { return Offset >> 1; }
+
+ bool isInstantiation() const { return Offset & 1; }
+ bool isFile() const { return !isInstantiation(); }
+
+ const FileInfo &getFile() const {
+ assert(isFile() && "Not a file SLocEntry!");
+ return File;
+ }
+
+ const InstantiationInfo &getInstantiation() const {
+ assert(isInstantiation() && "Not an instantiation SLocEntry!");
+ return Instantiation;
+ }
+
+ static SLocEntry get(unsigned Offset, const FileInfo &FI) {
+ SLocEntry E;
+ E.Offset = Offset << 1;
+ E.File = FI;
+ return E;
+ }
+
+ static SLocEntry get(unsigned Offset, const InstantiationInfo &II) {
+ SLocEntry E;
+ E.Offset = (Offset << 1) | 1;
+ E.Instantiation = II;
+ return E;
+ }
+ };
+} // end SrcMgr namespace.
+
+/// \brief External source of source location entries.
+class ExternalSLocEntrySource {
+public:
+ virtual ~ExternalSLocEntrySource();
+
+ /// \brief Read the source location entry with index ID.
+ virtual void ReadSLocEntry(unsigned ID) = 0;
+};
+
+/// SourceManager - This file handles loading and caching of source files into
+/// memory. This object owns the MemoryBuffer objects for all of the loaded
+/// files and assigns unique FileID's for each unique #include chain.
+///
+/// The SourceManager can be queried for information about SourceLocation
+/// objects, turning them into either spelling or instantiation locations.
+/// Spelling locations represent where the bytes corresponding to a token came
+/// from and instantiation locations represent where the location is in the
+/// user's view. In the case of a macro expansion, for example, the spelling
+/// location indicates where the expanded token came from and the instantiation
+/// location specifies where it was expanded.
+class SourceManager {
+ mutable llvm::BumpPtrAllocator ContentCacheAlloc;
+
+ /// FileInfos - Memoized information about all of the files tracked by this
+ /// SourceManager. This set allows us to merge ContentCache entries based
+ /// on their FileEntry*. All ContentCache objects will thus have unique,
+ /// non-null, FileEntry pointers.
+ llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
+
+ /// MemBufferInfos - Information about various memory buffers that we have
+ /// read in. All FileEntry* within the stored ContentCache objects are NULL,
+ /// as they do not refer to a file.
+ std::vector<SrcMgr::ContentCache*> MemBufferInfos;
+
+ /// SLocEntryTable - This is an array of SLocEntry's that we have created.
+ /// FileID is an index into this vector. This array is sorted by the offset.
+ std::vector<SrcMgr::SLocEntry> SLocEntryTable;
+ /// NextOffset - This is the next available offset that a new SLocEntry can
+ /// start at. It is SLocEntryTable.back().getOffset()+size of back() entry.
+ unsigned NextOffset;
+
+ /// \brief If source location entries are being lazily loaded from
+ /// an external source, this vector indicates whether the Ith source
+ /// location entry has already been loaded from the external storage.
+ std::vector<bool> SLocEntryLoaded;
+
+ /// \brief An external source for source location entries.
+ ExternalSLocEntrySource *ExternalSLocEntries;
+
+ /// LastFileIDLookup - This is a one-entry cache to speed up getFileID.
+ /// LastFileIDLookup records the last FileID looked up or created, because it
+ /// is very common to look up many tokens from the same file.
+ mutable FileID LastFileIDLookup;
+
+ /// LineTable - This holds information for #line directives. It is referenced
+ /// by indices from SLocEntryTable.
+ LineTableInfo *LineTable;
+
+ /// LastLineNo - These ivars serve as a cache used in the getLineNumber
+ /// method which is used to speedup getLineNumber calls to nearby locations.
+ mutable FileID LastLineNoFileIDQuery;
+ mutable SrcMgr::ContentCache *LastLineNoContentCache;
+ mutable unsigned LastLineNoFilePos;
+ mutable unsigned LastLineNoResult;
+
+ /// MainFileID - The file ID for the main source file of the translation unit.
+ FileID MainFileID;
+
+ // Statistics for -print-stats.
+ mutable unsigned NumLinearScans, NumBinaryProbes;
+
+ // SourceManager doesn't support copy construction.
+ explicit SourceManager(const SourceManager&);
+ void operator=(const SourceManager&);
+public:
+ SourceManager()
+ : ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
+ NumBinaryProbes(0) {
+ clearIDTables();
+ }
+ ~SourceManager();
+
+ void clearIDTables();
+
+ //===--------------------------------------------------------------------===//
+ // MainFileID creation and querying methods.
+ //===--------------------------------------------------------------------===//
+
+ /// getMainFileID - Returns the FileID of the main source file.
+ FileID getMainFileID() const { return MainFileID; }
+
+ /// createMainFileID - Create the FileID for the main source file.
+ FileID createMainFileID(const FileEntry *SourceFile,
+ SourceLocation IncludePos) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User);
+ return MainFileID;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Methods to create new FileID's and instantiations.
+ //===--------------------------------------------------------------------===//
+
+ /// createFileID - Create a new FileID that represents the specified file
+ /// being #included from the specified IncludePosition. This returns 0 on
+ /// error and translates NULL into standard input.
+ /// PreallocateID should be non-zero to specify which a pre-allocated,
+ /// lazily computed source location is being filled in by this operation.
+ FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0) {
+ const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
+ if (IR == 0) return FileID(); // Error opening file?
+ return createFileID(IR, IncludePos, FileCharacter, PreallocatedID, Offset);
+ }
+
+ /// createFileIDForMemBuffer - Create a new FileID that represents the
+ /// specified memory buffer. This does no caching of the buffer and takes
+ /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
+ FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0) {
+ return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
+ SrcMgr::C_User, PreallocatedID, Offset);
+ }
+
+ /// createMainFileIDForMembuffer - Create the FileID for a memory buffer
+ /// that will represent the FileID for the main source. One example
+ /// of when this would be used is when the main source is read from STDIN.
+ FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = createFileIDForMemBuffer(Buffer);
+ return MainFileID;
+ }
+
+ /// createInstantiationLoc - Return a new SourceLocation that encodes the fact
+ /// that a token at Loc should actually be referenced from InstantiationLoc.
+ /// TokLength is the length of the token being instantiated.
+ SourceLocation createInstantiationLoc(SourceLocation Loc,
+ SourceLocation InstantiationLocStart,
+ SourceLocation InstantiationLocEnd,
+ unsigned TokLength,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0);
+
+ //===--------------------------------------------------------------------===//
+ // FileID manipulation methods.
+ //===--------------------------------------------------------------------===//
+
+ /// getBuffer - Return the buffer for the specified FileID.
+ ///
+ const llvm::MemoryBuffer *getBuffer(FileID FID) const {
+ return getSLocEntry(FID).getFile().getContentCache()->getBuffer();
+ }
+
+ /// getFileEntryForID - Returns the FileEntry record for the provided FileID.
+ const FileEntry *getFileEntryForID(FileID FID) const {
+ return getSLocEntry(FID).getFile().getContentCache()->Entry;
+ }
+
+ /// getBufferData - Return a pointer to the start and end of the source buffer
+ /// data for the specified FileID.
+ std::pair<const char*, const char*> getBufferData(FileID FID) const;
+
+
+ //===--------------------------------------------------------------------===//
+ // SourceLocation manipulation methods.
+ //===--------------------------------------------------------------------===//
+
+ /// getFileID - Return the FileID for a SourceLocation. This is a very
+ /// hot method that is used for all SourceManager queries that start with a
+ /// SourceLocation object. It is responsible for finding the entry in
+ /// SLocEntryTable which contains the specified location.
+ ///
+ FileID getFileID(SourceLocation SpellingLoc) const {
+ unsigned SLocOffset = SpellingLoc.getOffset();
+
+ // If our one-entry cache covers this offset, just return it.
+ if (isOffsetInFileID(LastFileIDLookup, SLocOffset))
+ return LastFileIDLookup;
+
+ return getFileIDSlow(SLocOffset);
+ }
+
+ /// getLocForStartOfFile - Return the source location corresponding to the
+ /// first byte of the specified file.
+ SourceLocation getLocForStartOfFile(FileID FID) const {
+ assert(FID.ID < SLocEntryTable.size() && "FileID out of range");
+ assert(getSLocEntry(FID).isFile() && "FileID is not a file");
+ unsigned FileOffset = getSLocEntry(FID).getOffset();
+ return SourceLocation::getFileLoc(FileOffset);
+ }
+
+ /// getInstantiationLoc - Given a SourceLocation object, return the
+ /// instantiation location referenced by the ID.
+ SourceLocation getInstantiationLoc(SourceLocation Loc) const {
+ // Handle the non-mapped case inline, defer to out of line code to handle
+ // instantiations.
+ if (Loc.isFileID()) return Loc;
+ return getInstantiationLocSlowCase(Loc);
+ }
+
+ /// getImmediateInstantiationRange - Loc is required to be an instantiation
+ /// location. Return the start/end of the instantiation information.
+ std::pair<SourceLocation,SourceLocation>
+ getImmediateInstantiationRange(SourceLocation Loc) const;
+
+ /// getInstantiationRange - Given a SourceLocation object, return the
+ /// range of tokens covered by the instantiation in the ultimate file.
+ std::pair<SourceLocation,SourceLocation>
+ getInstantiationRange(SourceLocation Loc) const;
+
+
+ /// getSpellingLoc - Given a SourceLocation object, return the spelling
+ /// location referenced by the ID. This is the place where the characters
+ /// that make up the lexed token can be found.
+ SourceLocation getSpellingLoc(SourceLocation Loc) const {
+ // Handle the non-mapped case inline, defer to out of line code to handle
+ // instantiations.
+ if (Loc.isFileID()) return Loc;
+ return getSpellingLocSlowCase(Loc);
+ }
+
+ /// getImmediateSpellingLoc - Given a SourceLocation object, return the
+ /// spelling location referenced by the ID. This is the first level down
+ /// towards the place where the characters that make up the lexed token can be
+ /// found. This should not generally be used by clients.
+ SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;
+
+ /// getDecomposedLoc - Decompose the specified location into a raw FileID +
+ /// Offset pair. The first element is the FileID, the second is the
+ /// offset from the start of the buffer of the location.
+ std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset());
+ }
+
+ /// getDecomposedInstantiationLoc - Decompose the specified location into a
+ /// raw FileID + Offset pair. If the location is an instantiation record,
+ /// walk through it until we find the final location instantiated.
+ std::pair<FileID, unsigned>
+ getDecomposedInstantiationLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
+
+ unsigned Offset = Loc.getOffset()-E->getOffset();
+ if (Loc.isFileID())
+ return std::make_pair(FID, Offset);
+
+ return getDecomposedInstantiationLocSlowCase(E, Offset);
+ }
+
+ /// getDecomposedSpellingLoc - Decompose the specified location into a raw
+ /// FileID + Offset pair. If the location is an instantiation record, walk
+ /// through it until we find its spelling record.
+ std::pair<FileID, unsigned>
+ getDecomposedSpellingLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
+
+ unsigned Offset = Loc.getOffset()-E->getOffset();
+ if (Loc.isFileID())
+ return std::make_pair(FID, Offset);
+ return getDecomposedSpellingLocSlowCase(E, Offset);
+ }
+
+ /// getFileOffset - This method returns the offset from the start
+ /// of the file that the specified SourceLocation represents. This is not very
+ /// meaningful for a macro ID.
+ unsigned getFileOffset(SourceLocation SpellingLoc) const {
+ return getDecomposedLoc(SpellingLoc).second;
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Queries about the code at a SourceLocation.
+ //===--------------------------------------------------------------------===//
+
+ /// getCharacterData - Return a pointer to the start of the specified location
+ /// in the appropriate spelling MemoryBuffer.
+ const char *getCharacterData(SourceLocation SL) const;
+
+ /// getColumnNumber - Return the column # for the specified file position.
+ /// This is significantly cheaper to compute than the line number. This
+ /// returns zero if the column number isn't known. This may only be called on
+ /// a file sloc, so you must choose a spelling or instantiation location
+ /// before calling this method.
+ unsigned getColumnNumber(FileID FID, unsigned FilePos) const;
+ unsigned getSpellingColumnNumber(SourceLocation Loc) const;
+ unsigned getInstantiationColumnNumber(SourceLocation Loc) const;
+
+
+ /// getLineNumber - Given a SourceLocation, return the spelling line number
+ /// for the position indicated. This requires building and caching a table of
+ /// line offsets for the MemoryBuffer, so this is not cheap: use only when
+ /// about to emit a diagnostic.
+ unsigned getLineNumber(FileID FID, unsigned FilePos) const;
+
+ unsigned getInstantiationLineNumber(SourceLocation Loc) const;
+ unsigned getSpellingLineNumber(SourceLocation Loc) const;
+
+ /// Return the filename or buffer identifier of the buffer the location is in.
+ /// Note that this name does not respect #line directives. Use getPresumedLoc
+ /// for normal clients.
+ const char *getBufferName(SourceLocation Loc) const;
+
+ /// getFileCharacteristic - return the file characteristic of the specified
+ /// source location, indicating whether this is a normal file, a system
+ /// header, or an "implicit extern C" system header.
+ ///
+ /// This state can be modified with flags on GNU linemarker directives like:
+ /// # 4 "foo.h" 3
+ /// which changes all source locations in the current file after that to be
+ /// considered to be from a system header.
+ SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;
+
+ /// getPresumedLoc - This method returns the "presumed" location of a
+ /// SourceLocation specifies. A "presumed location" can be modified by #line
+ /// or GNU line marker directives. This provides a view on the data that a
+ /// user should see in diagnostics, for example.
+ ///
+ /// Note that a presumed location is always given as the instantiation point
+ /// of an instantiation location, not at the spelling location.
+ PresumedLoc getPresumedLoc(SourceLocation Loc) const;
+
+ /// isFromSameFile - Returns true if both SourceLocations correspond to
+ /// the same file.
+ bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
+ return getFileID(Loc1) == getFileID(Loc2);
+ }
+
+ /// isFromMainFile - Returns true if the file of provided SourceLocation is
+ /// the main file.
+ bool isFromMainFile(SourceLocation Loc) const {
+ return getFileID(Loc) == getMainFileID();
+ }
+
+ /// isInSystemHeader - Returns if a SourceLocation is in a system header.
+ bool isInSystemHeader(SourceLocation Loc) const {
+ return getFileCharacteristic(Loc) != SrcMgr::C_User;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Line Table Manipulation Routines
+ //===--------------------------------------------------------------------===//
+
+ /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+ ///
+ unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+
+ /// AddLineNote - Add a line note to the line table for the FileID and offset
+ /// specified by Loc. If FilenameID is -1, it is considered to be
+ /// unspecified.
+ void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID);
+ void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
+ bool IsFileEntry, bool IsFileExit,
+ bool IsSystemHeader, bool IsExternCHeader);
+
+ /// \brief Determine if the source manager has a line table.
+ bool hasLineTable() const { return LineTable != 0; }
+
+ /// \brief Retrieve the stored line table.
+ LineTableInfo &getLineTable();
+
+ //===--------------------------------------------------------------------===//
+ // Other miscellaneous methods.
+ //===--------------------------------------------------------------------===//
+
+ // Iterators over FileInfos.
+ typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
+ ::const_iterator fileinfo_iterator;
+ fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
+ fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
+
+ /// PrintStats - Print statistics to stderr.
+ ///
+ void PrintStats() const;
+
+ // Iteration over the source location entry table.
+ typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator;
+
+ sloc_entry_iterator sloc_entry_begin() const {
+ return SLocEntryTable.begin();
+ }
+
+ sloc_entry_iterator sloc_entry_end() const {
+ return SLocEntryTable.end();
+ }
+
+ unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
+
+ const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {
+ assert(FID.ID < SLocEntryTable.size() && "Invalid id");
+ if (ExternalSLocEntries &&
+ FID.ID < SLocEntryLoaded.size() &&
+ !SLocEntryLoaded[FID.ID])
+ ExternalSLocEntries->ReadSLocEntry(FID.ID);
+ return SLocEntryTable[FID.ID];
+ }
+
+ unsigned getNextOffset() const { return NextOffset; }
+
+ /// \brief Preallocate some number of source location entries, which
+ /// will be loaded as needed from the given external source.
+ void PreallocateSLocEntries(ExternalSLocEntrySource *Source,
+ unsigned NumSLocEntries,
+ unsigned NextOffset);
+
+ /// \brief Clear out any preallocated source location entries that
+ /// haven't already been loaded.
+ void ClearPreallocatedSLocEntries();
+
+private:
+ /// isOffsetInFileID - Return true if the specified FileID contains the
+ /// specified SourceLocation offset. This is a very hot method.
+ inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const {
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
+ // If the entry is after the offset, it can't contain it.
+ if (SLocOffset < Entry.getOffset()) return false;
+
+ // If this is the last entry than it does. Otherwise, the entry after it
+ // has to not include it.
+ if (FID.ID+1 == SLocEntryTable.size()) return true;
+
+ return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset();
+ }
+
+ /// createFileID - Create a new fileID for the specified ContentCache and
+ /// include position. This works regardless of whether the ContentCache
+ /// corresponds to a file or some other input source.
+ FileID createFileID(const SrcMgr::ContentCache* File,
+ SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind DirCharacter,
+ unsigned PreallocatedID = 0,
+ unsigned Offset = 0);
+
+ const SrcMgr::ContentCache *
+ getOrCreateContentCache(const FileEntry *SourceFile);
+
+ /// createMemBufferContentCache - Create a new ContentCache for the specified
+ /// memory buffer.
+ const SrcMgr::ContentCache*
+ createMemBufferContentCache(const llvm::MemoryBuffer *Buf);
+
+ FileID getFileIDSlow(unsigned SLocOffset) const;
+
+ SourceLocation getInstantiationLocSlowCase(SourceLocation Loc) const;
+ SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const;
+
+ std::pair<FileID, unsigned>
+ getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const;
+ std::pair<FileID, unsigned>
+ getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const;
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h
new file mode 100644
index 000000000000..0bcb68e4601d
--- /dev/null
+++ b/include/clang/Basic/SourceManagerInternals.h
@@ -0,0 +1,130 @@
+//===--- SourceManagerInternals.h - SourceManager Internals -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the implementation details of the SourceManager
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
+#define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringMap.h"
+#include <map>
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// Line Table Implementation
+//===----------------------------------------------------------------------===//
+
+struct LineEntry {
+ /// FileOffset - The offset in this file that the line entry occurs at.
+ unsigned FileOffset;
+
+ /// LineNo - The presumed line number of this line entry: #line 4.
+ unsigned LineNo;
+
+ /// FilenameID - The ID of the filename identified by this line entry:
+ /// #line 4 "foo.c". This is -1 if not specified.
+ int FilenameID;
+
+ /// Flags - Set the 0 if no flags, 1 if a system header,
+ SrcMgr::CharacteristicKind FileKind;
+
+ /// IncludeOffset - This is the offset of the virtual include stack location,
+ /// which is manipulated by GNU linemarker directives. If this is 0 then
+ /// there is no virtual #includer.
+ unsigned IncludeOffset;
+
+ static LineEntry get(unsigned Offs, unsigned Line, int Filename,
+ SrcMgr::CharacteristicKind FileKind,
+ unsigned IncludeOffset) {
+ LineEntry E;
+ E.FileOffset = Offs;
+ E.LineNo = Line;
+ E.FilenameID = Filename;
+ E.FileKind = FileKind;
+ E.IncludeOffset = IncludeOffset;
+ return E;
+ }
+};
+
+// needed for FindNearestLineEntry (upper_bound of LineEntry)
+inline bool operator<(const LineEntry &lhs, const LineEntry &rhs) {
+ // FIXME: should check the other field?
+ return lhs.FileOffset < rhs.FileOffset;
+}
+
+inline bool operator<(const LineEntry &E, unsigned Offset) {
+ return E.FileOffset < Offset;
+}
+
+inline bool operator<(unsigned Offset, const LineEntry &E) {
+ return Offset < E.FileOffset;
+}
+
+/// LineTableInfo - This class is used to hold and unique data used to
+/// represent #line information.
+class LineTableInfo {
+ /// FilenameIDs - This map is used to assign unique IDs to filenames in
+ /// #line directives. This allows us to unique the filenames that
+ /// frequently reoccur and reference them with indices. FilenameIDs holds
+ /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
+ /// to string.
+ llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
+ std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
+
+ /// LineEntries - This is a map from FileIDs to a list of line entries (sorted
+ /// by the offset they occur in the file.
+ std::map<unsigned, std::vector<LineEntry> > LineEntries;
+public:
+ LineTableInfo() {
+ }
+
+ void clear() {
+ FilenameIDs.clear();
+ FilenamesByID.clear();
+ LineEntries.clear();
+ }
+
+ ~LineTableInfo() {}
+
+ unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+ const char *getFilename(unsigned ID) const {
+ assert(ID < FilenamesByID.size() && "Invalid FilenameID");
+ return FilenamesByID[ID]->getKeyData();
+ }
+ unsigned getNumFilenames() const { return FilenamesByID.size(); }
+
+ void AddLineNote(unsigned FID, unsigned Offset,
+ unsigned LineNo, int FilenameID);
+ void AddLineNote(unsigned FID, unsigned Offset,
+ unsigned LineNo, int FilenameID,
+ unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);
+
+
+ /// FindNearestLineEntry - Find the line entry nearest to FID that is before
+ /// it. If there is no line entry before Offset in FID, return null.
+ const LineEntry *FindNearestLineEntry(unsigned FID, unsigned Offset);
+
+ // Low-level access
+ typedef std::map<unsigned, std::vector<LineEntry> >::iterator iterator;
+ iterator begin() { return LineEntries.begin(); }
+ iterator end() { return LineEntries.end(); }
+
+ /// \brief Add a new line entry that has already been encoded into
+ /// the internal representation of the line table.
+ void AddEntry(unsigned FID, const std::vector<LineEntry> &Entries);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
new file mode 100644
index 000000000000..f577d6b32287
--- /dev/null
+++ b/include/clang/Basic/TargetInfo.h
@@ -0,0 +1,391 @@
+//===--- TargetInfo.h - Expose information about the target -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TargetInfo interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
+#define LLVM_CLANG_BASIC_TARGETINFO_H
+
+// FIXME: Daniel isn't smart enough to use a prototype for this.
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <vector>
+#include <string>
+
+namespace llvm { struct fltSemantics; }
+
+namespace clang {
+
+class Diagnostic;
+class SourceManager;
+class LangOptions;
+
+namespace Builtin { struct Info; }
+
+/// TargetInfo - This class exposes information about the current target.
+///
+class TargetInfo {
+ std::string Triple;
+protected:
+ // Target values set by the ctor of the actual target implementation. Default
+ // values are specified by the TargetInfo constructor.
+ bool CharIsSigned;
+ bool TLSSupported;
+ unsigned char PointerWidth, PointerAlign;
+ unsigned char WCharWidth, WCharAlign;
+ unsigned char IntWidth, IntAlign;
+ unsigned char FloatWidth, FloatAlign;
+ unsigned char DoubleWidth, DoubleAlign;
+ unsigned char LongDoubleWidth, LongDoubleAlign;
+ unsigned char LongWidth, LongAlign;
+ unsigned char LongLongWidth, LongLongAlign;
+ unsigned char IntMaxTWidth;
+ const char *DescriptionString;
+ const char *UserLabelPrefix;
+ const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
+ unsigned char RegParmMax, SSERegParmMax;
+
+ // TargetInfo Constructor. Default initializes all fields.
+ TargetInfo(const std::string &T);
+
+public:
+ /// CreateTargetInfo - Return the target info object for the specified target
+ /// triple.
+ static TargetInfo* CreateTargetInfo(const std::string &Triple);
+
+ virtual ~TargetInfo();
+
+ ///===---- Target Data Type Query Methods -------------------------------===//
+ enum IntType {
+ NoInt = 0,
+ SignedShort,
+ UnsignedShort,
+ SignedInt,
+ UnsignedInt,
+ SignedLong,
+ UnsignedLong,
+ SignedLongLong,
+ UnsignedLongLong
+ };
+protected:
+ IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType;
+public:
+ IntType getSizeType() const { return SizeType; }
+ IntType getIntMaxType() const { return IntMaxType; }
+ IntType getUIntMaxType() const { return UIntMaxType; }
+ IntType getPtrDiffType(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace);
+ }
+ IntType getIntPtrType() const { return IntPtrType; }
+ IntType getWCharType() const { return WCharType; }
+
+ /// isCharSigned - Return true if 'char' is 'signed char' or false if it is
+ /// treated as 'unsigned char'. This is implementation defined according to
+ /// C99 6.2.5p15. In our implementation, this is target-specific.
+ bool isCharSigned() const { return CharIsSigned; }
+
+ /// getPointerWidth - Return the width of pointers on this target, for the
+ /// specified address space.
+ uint64_t getPointerWidth(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace);
+ }
+ uint64_t getPointerAlign(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
+ }
+
+ /// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this
+ /// target, in bits.
+ unsigned getBoolWidth(bool isWide = false) const { return 8; } // FIXME
+ unsigned getBoolAlign(bool isWide = false) const { return 8; } // FIXME
+
+ unsigned getCharWidth(bool isWide = false) const {
+ return isWide ? getWCharWidth() : 8; // FIXME
+ }
+ unsigned getCharAlign(bool isWide = false) const {
+ return isWide ? getWCharAlign() : 8; // FIXME
+ }
+
+ /// getShortWidth/Align - Return the size of 'signed short' and
+ /// 'unsigned short' for this target, in bits.
+ unsigned getShortWidth() const { return 16; } // FIXME
+ unsigned getShortAlign() const { return 16; } // FIXME
+
+ /// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for
+ /// this target, in bits.
+ unsigned getIntWidth() const { return IntWidth; }
+ unsigned getIntAlign() const { return IntAlign; }
+
+ /// getLongWidth/Align - Return the size of 'signed long' and 'unsigned long'
+ /// for this target, in bits.
+ unsigned getLongWidth() const { return LongWidth; }
+ unsigned getLongAlign() const { return LongAlign; }
+
+ /// getLongLongWidth/Align - Return the size of 'signed long long' and
+ /// 'unsigned long long' for this target, in bits.
+ unsigned getLongLongWidth() const { return LongLongWidth; }
+ unsigned getLongLongAlign() const { return LongLongAlign; }
+
+ /// getWcharWidth/Align - Return the size of 'wchar_t' for this target, in
+ /// bits.
+ unsigned getWCharWidth() const { return WCharWidth; }
+ unsigned getWCharAlign() const { return WCharAlign; }
+
+ /// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
+ unsigned getFloatWidth() const { return FloatWidth; }
+ unsigned getFloatAlign() const { return FloatAlign; }
+ const llvm::fltSemantics &getFloatFormat() const { return *FloatFormat; }
+
+ /// getDoubleWidth/Align/Format - Return the size/align/format of 'double'.
+ unsigned getDoubleWidth() const { return DoubleWidth; }
+ unsigned getDoubleAlign() const { return DoubleAlign; }
+ const llvm::fltSemantics &getDoubleFormat() const { return *DoubleFormat; }
+
+ /// getLongDoubleWidth/Align/Format - Return the size/align/format of 'long
+ /// double'.
+ unsigned getLongDoubleWidth() const { return LongDoubleWidth; }
+ unsigned getLongDoubleAlign() const { return LongDoubleAlign; }
+ const llvm::fltSemantics &getLongDoubleFormat() const {
+ return *LongDoubleFormat;
+ }
+
+ /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
+ /// target, in bits.
+ unsigned getIntMaxTWidth() const {
+ return IntMaxTWidth;
+ }
+
+ /// getUserLabelPrefix - This returns the default value of the
+ /// __USER_LABEL_PREFIX__ macro, which is the prefix given to user symbols by
+ /// default. On most platforms this is "_", but it is "" on some, and "." on
+ /// others.
+ const char *getUserLabelPrefix() const {
+ return UserLabelPrefix;
+ }
+
+ /// getTypeName - Return the user string for the specified integer type enum.
+ /// For example, SignedShort -> "short".
+ static const char *getTypeName(IntType T);
+
+ ///===---- Other target property query methods --------------------------===//
+
+ /// getTargetDefines - Appends the target-specific #define values for this
+ /// target set to the specified buffer.
+ virtual void getTargetDefines(const LangOptions &Opts,
+ std::vector<char> &DefineBuffer) const = 0;
+
+ /// getTargetBuiltins - Return information about target-specific builtins for
+ /// the current primary target, and info about which builtins are non-portable
+ /// across the current set of primary and secondary targets.
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const = 0;
+
+ /// getVAListDeclaration - Return the declaration to use for
+ /// __builtin_va_list, which is target-specific.
+ virtual const char *getVAListDeclaration() const = 0;
+
+ /// isValidGCCRegisterName - Returns whether the passed in string
+ /// is a valid register name according to GCC. This is used by Sema for
+ /// inline asm statements.
+ bool isValidGCCRegisterName(const char *Name) const;
+
+ // getNormalizedGCCRegisterName - Returns the "normalized" GCC register name.
+ // For example, on x86 it will return "ax" when "eax" is passed in.
+ const char *getNormalizedGCCRegisterName(const char *Name) const;
+
+ struct ConstraintInfo {
+ enum {
+ CI_None = 0x00,
+ CI_AllowsMemory = 0x01,
+ CI_AllowsRegister = 0x02,
+ CI_ReadWrite = 0x04, // "+r" output constraint (read and write).
+ CI_HasMatchingInput = 0x08 // This output operand has a matching input.
+ };
+ unsigned Flags;
+ int TiedOperand;
+
+ std::string ConstraintStr; // constraint: "=rm"
+ std::string Name; // Operand name: [foo] with no []'s.
+ public:
+ ConstraintInfo(const char *str, unsigned strlen, const std::string &name)
+ : Flags(0), TiedOperand(-1), ConstraintStr(str, str+strlen), Name(name) {}
+ explicit ConstraintInfo(const std::string &Str, const std::string &name)
+ : Flags(0), TiedOperand(-1), ConstraintStr(Str), Name(name) {}
+
+ const std::string &getConstraintStr() const { return ConstraintStr; }
+ const std::string &getName() const { return Name; }
+ bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; }
+ bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
+ bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
+
+ /// hasMatchingInput - Return true if this output operand has a matching
+ /// (tied) input operand.
+ bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; }
+
+ /// hasTiedOperand() - Return true if this input operand is a matching
+ /// constraint that ties it to an output operand. If this returns true,
+ /// then getTiedOperand will indicate which output operand this is tied to.
+ bool hasTiedOperand() const { return TiedOperand != -1; }
+ unsigned getTiedOperand() const {
+ assert(hasTiedOperand() && "Has no tied operand!");
+ return (unsigned)TiedOperand;
+ }
+
+ void setIsReadWrite() { Flags |= CI_ReadWrite; }
+ void setAllowsMemory() { Flags |= CI_AllowsMemory; }
+ void setAllowsRegister() { Flags |= CI_AllowsRegister; }
+ void setHasMatchingInput() { Flags |= CI_HasMatchingInput; }
+
+ /// setTiedOperand - Indicate that this is an input operand that is tied to
+ /// the specified output operand. Copy over the various constraint
+ /// information from the output.
+ void setTiedOperand(unsigned N, ConstraintInfo &Output) {
+ Output.setHasMatchingInput();
+ Flags = Output.Flags;
+ TiedOperand = N;
+ // Don't copy Name or constraint string.
+ }
+ };
+
+ // validateOutputConstraint, validateInputConstraint - Checks that
+ // a constraint is valid and provides information about it.
+ // FIXME: These should return a real error instead of just true/false.
+ bool validateOutputConstraint(ConstraintInfo &Info) const;
+ bool validateInputConstraint(ConstraintInfo *OutputConstraints,
+ unsigned NumOutputs,
+ ConstraintInfo &info) const;
+ bool resolveSymbolicName(const char *&Name,
+ ConstraintInfo *OutputConstraints,
+ unsigned NumOutputs, unsigned &Index) const;
+
+ virtual std::string convertConstraint(const char Constraint) const {
+ return std::string(1, Constraint);
+ }
+
+ // Returns a string of target-specific clobbers, in LLVM format.
+ virtual const char *getClobbers() const = 0;
+
+
+ /// getTargetPrefix - Return the target prefix used for identifying
+ /// llvm intrinsics.
+ virtual const char *getTargetPrefix() const = 0;
+
+ /// getTargetTriple - Return the target triple of the primary target.
+ const char *getTargetTriple() const {
+ return Triple.c_str();
+ }
+
+ const char *getTargetDescription() const {
+ return DescriptionString;
+ }
+
+ struct GCCRegAlias {
+ const char * const Aliases[5];
+ const char * const Register;
+ };
+
+ virtual bool useGlobalsForAutomaticVariables() const { return false; }
+
+ /// getStringSymbolPrefix - Get the default symbol prefix to
+ /// use for string literals.
+ virtual const char *getStringSymbolPrefix(bool IsConstant) const {
+ return ".str";
+ }
+
+ /// getCFStringSymbolPrefix - Get the default symbol prefix
+ /// to use for CFString literals.
+ virtual const char *getCFStringSymbolPrefix() const {
+ return "";
+ }
+
+ /// getUnicodeStringSymbolPrefix - Get the default symbol prefix to
+ /// use for string literals.
+ virtual const char *getUnicodeStringSymbolPrefix() const {
+ return ".str";
+ }
+
+ /// getUnicodeStringSection - Return the section to use for unicode
+ /// string literals, or 0 if no special section is used.
+ virtual const char *getUnicodeStringSection() const {
+ return 0;
+ }
+
+ /// getCFStringSection - Return the section to use for CFString
+ /// literals, or 0 if no special section is used.
+ virtual const char *getCFStringSection() const {
+ return "__DATA,__cfstring";
+ }
+
+ /// getCFStringDataSection - Return the section to use for the
+ /// constant string data associated with a CFString literal, or 0 if
+ /// no special section is used.
+ virtual const char *getCFStringDataSection() const {
+ return "__TEXT,__cstring,cstring_literals";
+ }
+
+ /// getDefaultLangOptions - Allow the target to specify default settings for
+ /// various language options. These may be overridden by command line
+ /// options.
+ virtual void getDefaultLangOptions(LangOptions &Opts) {}
+
+ /// getDefaultFeatures - Get the default set of target features for
+ /// the \args CPU; this should include all legal feature strings on
+ /// the target.
+ virtual void getDefaultFeatures(const std::string &CPU,
+ llvm::StringMap<bool> &Features) const {
+ }
+
+ /// setFeatureEnabled - Enable or disable a specific target feature,
+ /// the feature name must be valid.
+ ///
+ /// \return - False on error (invalid feature name).
+ virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
+ const std::string &Name,
+ bool Enabled) const {
+ return false;
+ }
+
+ /// HandleTargetOptions - Perform initialization based on the user
+ /// configured set of features.
+ virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features) {
+ }
+
+ // getRegParmMax - Returns maximal number of args passed in registers.
+ unsigned getRegParmMax() const {
+ return RegParmMax;
+ }
+
+ // isTLSSupported - Whether the target supports thread-local storage
+ unsigned isTLSSupported() const {
+ return TLSSupported;
+ }
+
+protected:
+ virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
+ return PointerWidth;
+ }
+ virtual uint64_t getPointerAlignV(unsigned AddrSpace) const {
+ return PointerAlign;
+ }
+ virtual enum IntType getPtrDiffTypeV(unsigned AddrSpace) const {
+ return PtrDiffType;
+ }
+ virtual void getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const = 0;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const = 0;
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const= 0;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h
new file mode 100644
index 000000000000..c6ea05bb1396
--- /dev/null
+++ b/include/clang/Basic/TemplateKinds.h
@@ -0,0 +1,39 @@
+//===--- TemplateKinds.h - Enum values for C++ Template Kinds ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TemplateNameKind enum.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TEMPLATEKINDS_H
+#define LLVM_CLANG_TEMPLATEKINDS_H
+
+namespace clang {
+
+/// \brief Specifies the kind of template name that an identifier refers to.
+enum TemplateNameKind {
+ /// The name does not refer to a template.
+ TNK_Non_template = 0,
+ /// The name refers to a function template or a set of overloaded
+ /// functions that includes at least one function template.
+ TNK_Function_template,
+ /// The name refers to a template whose specialization produces a
+ /// type. The template itself could be a class template, template
+ /// template parameter, or C++0x template alias.
+ TNK_Type_template,
+ /// The name refers to a dependent template name. Whether the
+ /// template name is assumed to refer to a type template or a
+ /// function template depends on the context in which the template
+ /// name occurs.
+ TNK_Dependent_template_name
+};
+
+}
+#endif
+
+
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
new file mode 100644
index 000000000000..9b65288f68e1
--- /dev/null
+++ b/include/clang/Basic/TokenKinds.def
@@ -0,0 +1,413 @@
+//===--- TokenKinds.def - C Family Token Kind Database ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenKind database. This includes normal tokens like
+// tok::ampamp (corresponding to the && token) as well as keywords for various
+// languages. Users of this file must optionally #define the TOK, KEYWORD,
+// ALIAS, or PPKEYWORD macros to make use of this file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TOK
+#define TOK(X)
+#endif
+#ifndef KEYWORD
+#define KEYWORD(X,Y) TOK(kw_ ## X)
+#endif
+#ifndef ALIAS
+#define ALIAS(X,Y,Z)
+#endif
+#ifndef PPKEYWORD
+#define PPKEYWORD(X)
+#endif
+#ifndef CXX_KEYWORD_OPERATOR
+#define CXX_KEYWORD_OPERATOR(X,Y)
+#endif
+#ifndef OBJC1_AT_KEYWORD
+#define OBJC1_AT_KEYWORD(X)
+#endif
+#ifndef OBJC2_AT_KEYWORD
+#define OBJC2_AT_KEYWORD(X)
+#endif
+#ifndef ANNOTATION
+#define ANNOTATION(X) TOK(annot_ ## X)
+#endif
+
+//===----------------------------------------------------------------------===//
+// Preprocessor keywords.
+//===----------------------------------------------------------------------===//
+
+// These have meaning after a '#' at the start of a line. These define enums in
+// the tok::pp_* namespace. Note that IdentifierInfo::getPPKeywordID must be
+// manually updated if something is added here.
+PPKEYWORD(not_keyword)
+
+// C99 6.10.1 - Conditional Inclusion.
+PPKEYWORD(if)
+PPKEYWORD(ifdef)
+PPKEYWORD(ifndef)
+PPKEYWORD(elif)
+PPKEYWORD(else)
+PPKEYWORD(endif)
+PPKEYWORD(defined)
+
+// C99 6.10.2 - Source File Inclusion.
+PPKEYWORD(include)
+PPKEYWORD(__include_macros)
+
+// C99 6.10.3 - Macro Replacement.
+PPKEYWORD(define)
+PPKEYWORD(undef)
+
+// C99 6.10.4 - Line Control.
+PPKEYWORD(line)
+
+// C99 6.10.5 - Error Directive.
+PPKEYWORD(error)
+
+// C99 6.10.6 - Pragma Directive.
+PPKEYWORD(pragma)
+
+// GNU Extensions.
+PPKEYWORD(import)
+PPKEYWORD(include_next)
+PPKEYWORD(warning)
+PPKEYWORD(ident)
+PPKEYWORD(sccs)
+PPKEYWORD(assert)
+PPKEYWORD(unassert)
+
+//===----------------------------------------------------------------------===//
+// Language keywords.
+//===----------------------------------------------------------------------===//
+
+// These define members of the tok::* namespace.
+
+TOK(unknown) // Not a token.
+TOK(eof) // End of file.
+TOK(eom) // End of macro (end of line inside a macro).
+
+// C99 6.4.9: Comments.
+TOK(comment) // Comment (only in -E -C[C] mode)
+
+// C99 6.4.2: Identifiers.
+TOK(identifier) // abcde123
+
+// C99 6.4.4.1: Integer Constants
+// C99 6.4.4.2: Floating Constants
+TOK(numeric_constant) // 0x123
+
+// C99 6.4.4: Character Constants
+TOK(char_constant) // 'a' L'b'
+
+// C99 6.4.5: String Literals.
+TOK(string_literal) // "foo"
+TOK(wide_string_literal) // L"foo"
+TOK(angle_string_literal)// <foo>
+
+// C99 6.4.6: Punctuators.
+TOK(l_square) // [
+TOK(r_square) // ]
+TOK(l_paren) // (
+TOK(r_paren) // )
+TOK(l_brace) // {
+TOK(r_brace) // }
+TOK(period) // .
+TOK(ellipsis) // ...
+TOK(amp) // &
+TOK(ampamp) // &&
+TOK(ampequal) // &=
+TOK(star) // *
+TOK(starequal) // *=
+TOK(plus) // +
+TOK(plusplus) // ++
+TOK(plusequal) // +=
+TOK(minus) // -
+TOK(arrow) // ->
+TOK(minusminus) // --
+TOK(minusequal) // -=
+TOK(tilde) // ~
+TOK(exclaim) // !
+TOK(exclaimequal) // !=
+TOK(slash) // /
+TOK(slashequal) // /=
+TOK(percent) // %
+TOK(percentequal) // %=
+TOK(less) // <
+TOK(lessless) // <<
+TOK(lessequal) // <=
+TOK(lesslessequal) // <<=
+TOK(greater) // >
+TOK(greatergreater) // >>
+TOK(greaterequal) // >=
+TOK(greatergreaterequal) // >>=
+TOK(caret) // ^
+TOK(caretequal) // ^=
+TOK(pipe) // |
+TOK(pipepipe) // ||
+TOK(pipeequal) // |=
+TOK(question) // ?
+TOK(colon) // :
+TOK(semi) // ;
+TOK(equal) // =
+TOK(equalequal) // ==
+TOK(comma) // ,
+TOK(hash) // #
+TOK(hashhash) // ##
+TOK(hashat) // #@
+
+// C++ Support
+TOK(periodstar) // .*
+TOK(arrowstar) // ->*
+TOK(coloncolon) // ::
+
+// Objective C support.
+TOK(at) // @
+
+
+// C99 6.4.1: Keywords. These turn into kw_* tokens.
+// Flags allowed:
+// KEYALL - This is a keyword in all variants of C and C++, or it
+// is a keyword in the implementation namespace that should
+// always be treated as a keyword
+// KEYC99 - This is a keyword introduced to C in C99
+// KEYCXX - This is a C++ keyword, or a C++-specific keyword in the
+// implementation namespace
+// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
+// KEYGNU - This is a keyword if GNU extensions are enabled
+// KEYMS - This is a keyword if Microsoft extensions are enabled
+//
+KEYWORD(auto , KEYALL)
+KEYWORD(break , KEYALL)
+KEYWORD(case , KEYALL)
+KEYWORD(char , KEYALL)
+KEYWORD(const , KEYALL)
+KEYWORD(continue , KEYALL)
+KEYWORD(default , KEYALL)
+KEYWORD(do , KEYALL)
+KEYWORD(double , KEYALL)
+KEYWORD(else , KEYALL)
+KEYWORD(enum , KEYALL)
+KEYWORD(extern , KEYALL)
+KEYWORD(float , KEYALL)
+KEYWORD(for , KEYALL)
+KEYWORD(goto , KEYALL)
+KEYWORD(if , KEYALL)
+KEYWORD(inline , KEYC99|KEYCXX|KEYGNU)
+KEYWORD(int , KEYALL)
+KEYWORD(long , KEYALL)
+KEYWORD(register , KEYALL)
+KEYWORD(restrict , KEYC99)
+KEYWORD(return , KEYALL)
+KEYWORD(short , KEYALL)
+KEYWORD(signed , KEYALL)
+KEYWORD(sizeof , KEYALL)
+KEYWORD(static , KEYALL)
+KEYWORD(struct , KEYALL)
+KEYWORD(switch , KEYALL)
+KEYWORD(typedef , KEYALL)
+KEYWORD(union , KEYALL)
+KEYWORD(unsigned , KEYALL)
+KEYWORD(void , KEYALL)
+KEYWORD(volatile , KEYALL)
+KEYWORD(while , KEYALL)
+KEYWORD(_Bool , KEYALL)
+KEYWORD(_Complex , KEYALL)
+KEYWORD(_Imaginary , KEYALL)
+KEYWORD(__func__ , KEYALL)
+
+// C++ 2.11p1: Keywords.
+KEYWORD(asm , KEYCXX|KEYGNU)
+KEYWORD(bool , KEYCXX)
+KEYWORD(catch , KEYCXX)
+KEYWORD(class , KEYCXX)
+KEYWORD(const_cast , KEYCXX)
+KEYWORD(delete , KEYCXX)
+KEYWORD(dynamic_cast , KEYCXX)
+KEYWORD(explicit , KEYCXX)
+KEYWORD(export , KEYCXX)
+KEYWORD(false , KEYCXX)
+KEYWORD(friend , KEYCXX)
+KEYWORD(mutable , KEYCXX)
+KEYWORD(namespace , KEYCXX)
+KEYWORD(new , KEYCXX)
+KEYWORD(operator , KEYCXX)
+KEYWORD(private , KEYCXX)
+KEYWORD(protected , KEYCXX)
+KEYWORD(public , KEYCXX)
+KEYWORD(reinterpret_cast , KEYCXX)
+KEYWORD(static_cast , KEYCXX)
+KEYWORD(template , KEYCXX)
+KEYWORD(this , KEYCXX)
+KEYWORD(throw , KEYCXX)
+KEYWORD(true , KEYCXX)
+KEYWORD(try , KEYCXX)
+KEYWORD(typename , KEYCXX)
+KEYWORD(typeid , KEYCXX)
+KEYWORD(using , KEYCXX)
+KEYWORD(virtual , KEYCXX)
+KEYWORD(wchar_t , KEYCXX)
+
+// C++ 2.5p2: Alternative Representations.
+CXX_KEYWORD_OPERATOR(and , ampamp)
+CXX_KEYWORD_OPERATOR(and_eq , ampequal)
+CXX_KEYWORD_OPERATOR(bitand , amp)
+CXX_KEYWORD_OPERATOR(bitor , pipe)
+CXX_KEYWORD_OPERATOR(compl , tilde)
+CXX_KEYWORD_OPERATOR(not , exclaim)
+CXX_KEYWORD_OPERATOR(not_eq , exclaimequal)
+CXX_KEYWORD_OPERATOR(or , pipepipe)
+CXX_KEYWORD_OPERATOR(or_eq , pipeequal)
+CXX_KEYWORD_OPERATOR(xor , caret)
+CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
+
+// C++0x keywords
+KEYWORD(alignof , KEYCXX0X)
+KEYWORD(axiom , KEYCXX0X)
+KEYWORD(char16_t , KEYCXX0X)
+KEYWORD(char32_t , KEYCXX0X)
+KEYWORD(concept , KEYCXX0X)
+KEYWORD(concept_map , KEYCXX0X)
+KEYWORD(constexpr , KEYCXX0X)
+KEYWORD(decltype , KEYCXX0X)
+KEYWORD(late_check , KEYCXX0X)
+KEYWORD(nullptr , KEYCXX0X)
+KEYWORD(requires , KEYCXX0X)
+KEYWORD(static_assert , KEYCXX0X)
+KEYWORD(thread_local , KEYCXX0X)
+
+// GNU Extensions (in impl-reserved namespace)
+KEYWORD(_Decimal32 , KEYALL)
+KEYWORD(_Decimal64 , KEYALL)
+KEYWORD(_Decimal128 , KEYALL)
+KEYWORD(__null , KEYCXX)
+KEYWORD(__alignof , KEYALL)
+KEYWORD(__attribute , KEYALL)
+KEYWORD(__builtin_choose_expr , KEYALL)
+KEYWORD(__builtin_offsetof , KEYALL)
+KEYWORD(__builtin_types_compatible_p, KEYALL)
+KEYWORD(__builtin_va_arg , KEYALL)
+KEYWORD(__extension__ , KEYALL)
+KEYWORD(__imag , KEYALL)
+KEYWORD(__label__ , KEYALL)
+KEYWORD(__real , KEYALL)
+KEYWORD(__thread , KEYALL)
+KEYWORD(__FUNCTION__ , KEYALL)
+KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
+
+// GNU Extensions (outside impl-reserved namespace)
+KEYWORD(typeof , KEYGNU)
+
+// GNU and MS Type Traits
+KEYWORD(__has_nothrow_assign , KEYCXX)
+KEYWORD(__has_nothrow_copy , KEYCXX)
+KEYWORD(__has_nothrow_constructor , KEYCXX)
+KEYWORD(__has_trivial_assign , KEYCXX)
+KEYWORD(__has_trivial_copy , KEYCXX)
+KEYWORD(__has_trivial_constructor , KEYCXX)
+KEYWORD(__has_trivial_destructor , KEYCXX)
+KEYWORD(__has_virtual_destructor , KEYCXX)
+KEYWORD(__is_abstract , KEYCXX)
+KEYWORD(__is_base_of , KEYCXX)
+KEYWORD(__is_class , KEYCXX)
+KEYWORD(__is_empty , KEYCXX)
+KEYWORD(__is_enum , KEYCXX)
+KEYWORD(__is_pod , KEYCXX)
+KEYWORD(__is_polymorphic , KEYCXX)
+KEYWORD(__is_union , KEYCXX)
+// FIXME: Add MS's traits, too.
+
+// Apple Extension.
+KEYWORD(__private_extern__ , KEYALL)
+
+// Microsoft Extension.
+KEYWORD(__declspec , KEYALL)
+KEYWORD(__cdecl , KEYALL)
+KEYWORD(__stdcall , KEYALL)
+KEYWORD(__fastcall , KEYALL)
+KEYWORD(__ptr64 , KEYALL)
+KEYWORD(__w64 , KEYALL)
+KEYWORD(__forceinline , KEYALL)
+
+// Alternate spelling for various tokens. There are GCC extensions in all
+// languages, but should not be disabled in strict conformance mode.
+ALIAS("__attribute__", __attribute, KEYALL)
+ALIAS("__const" , const , KEYALL)
+ALIAS("__const__" , const , KEYALL)
+ALIAS("__alignof__" , __alignof , KEYALL)
+ALIAS("_asm" , asm , KEYMS)
+ALIAS("__asm" , asm , KEYALL)
+ALIAS("__asm__" , asm , KEYALL)
+ALIAS("__complex" , _Complex , KEYALL)
+ALIAS("__complex__" , _Complex , KEYALL)
+ALIAS("__imag__" , __imag , KEYALL)
+ALIAS("__inline" , inline , KEYALL)
+ALIAS("__inline__" , inline , KEYALL)
+ALIAS("__real__" , __real , KEYALL)
+ALIAS("__restrict" , restrict , KEYALL)
+ALIAS("__restrict__" , restrict , KEYALL)
+ALIAS("__signed" , signed , KEYALL)
+ALIAS("__signed__" , signed , KEYALL)
+ALIAS("__typeof" , typeof , KEYALL)
+ALIAS("__typeof__" , typeof , KEYALL)
+ALIAS("__volatile" , volatile , KEYALL)
+ALIAS("__volatile__" , volatile , KEYALL)
+
+
+//===----------------------------------------------------------------------===//
+// Objective-C @-preceeded keywords.
+//===----------------------------------------------------------------------===//
+
+// These have meaning after an '@' in Objective-C mode. These define enums in
+// the tok::objc_* namespace.
+
+OBJC1_AT_KEYWORD(not_keyword)
+OBJC1_AT_KEYWORD(class)
+OBJC1_AT_KEYWORD(compatibility_alias)
+OBJC1_AT_KEYWORD(defs)
+OBJC1_AT_KEYWORD(encode)
+OBJC1_AT_KEYWORD(end)
+OBJC1_AT_KEYWORD(implementation)
+OBJC1_AT_KEYWORD(interface)
+OBJC1_AT_KEYWORD(private)
+OBJC1_AT_KEYWORD(protected)
+OBJC1_AT_KEYWORD(protocol)
+OBJC1_AT_KEYWORD(public)
+OBJC1_AT_KEYWORD(selector)
+OBJC1_AT_KEYWORD(throw)
+OBJC1_AT_KEYWORD(try)
+OBJC1_AT_KEYWORD(catch)
+OBJC1_AT_KEYWORD(finally)
+OBJC1_AT_KEYWORD(synchronized)
+
+OBJC2_AT_KEYWORD(property)
+OBJC2_AT_KEYWORD(package)
+OBJC2_AT_KEYWORD(required)
+OBJC2_AT_KEYWORD(optional)
+OBJC2_AT_KEYWORD(synthesize)
+OBJC2_AT_KEYWORD(dynamic)
+
+// TODO: What to do about context-sensitive keywords like:
+// bycopy/byref/in/inout/oneway/out?
+
+ANNOTATION(cxxscope) // annotation for a C++ scope spec, e.g. "::foo::bar::"
+ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly
+ // qualified) typename, e.g. "foo::MyClass", or
+ // template-id that names a type ("std::vector<int>")
+ANNOTATION(template_id) // annotation for a C++ template-id that names a
+ // function template specialization (not a type),
+ // e.g., "std::swap<int>"
+#undef ANNOTATION
+#undef OBJC2_AT_KEYWORD
+#undef OBJC1_AT_KEYWORD
+#undef CXX_KEYWORD_OPERATOR
+#undef PPKEYWORD
+#undef ALIAS
+#undef KEYWORD
+#undef TOK
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
new file mode 100644
index 000000000000..62a9e428bf21
--- /dev/null
+++ b/include/clang/Basic/TokenKinds.h
@@ -0,0 +1,64 @@
+//===--- TokenKinds.h - Enum values for C Token Kinds -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenKind enum and support functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKENKINDS_H
+#define LLVM_CLANG_TOKENKINDS_H
+
+namespace clang {
+
+namespace tok {
+
+/// TokenKind - This provides a simple uniform namespace for tokens from all C
+/// languages.
+enum TokenKind {
+#define TOK(X) X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_TOKENS
+};
+
+/// PPKeywordKind - This provides a namespace for preprocessor keywords which
+/// start with a '#' at the beginning of the line.
+enum PPKeywordKind {
+#define PPKEYWORD(X) pp_##X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_PP_KEYWORDS
+};
+
+/// ObjCKeywordKind - This provides a namespace for Objective-C keywords which
+/// start with an '@'.
+enum ObjCKeywordKind {
+#define OBJC1_AT_KEYWORD(X) objc_##X,
+#define OBJC2_AT_KEYWORD(X) objc_##X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_OBJC_KEYWORDS
+};
+
+/// \brief Determines the name of a token as used within the front end.
+///
+/// The name of a token will be an internal name (such as "l_square")
+/// and should not be used as part of diagnostic messages.
+const char *getTokenName(enum TokenKind Kind);
+
+/// \brief Determines the spelling of simple punctuation tokens like
+/// '!' or '%', and returns NULL for literal and annotation tokens.
+///
+/// This routine only retrieves the "simple" spelling of the token,
+/// and will not produce any alternative spellings (e.g., a
+/// digraph). For the actual spelling of a given Token, use
+/// Preprocessor::getSpelling().
+const char *getTokenSimpleSpelling(enum TokenKind Kind);
+
+} // end namespace tok
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
new file mode 100644
index 000000000000..2a2eacc4caac
--- /dev/null
+++ b/include/clang/Basic/TypeTraits.h
@@ -0,0 +1,40 @@
+//===--- TypeTraits.h - C++ Type Traits Support Enumerations ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines enumerations for the type traits support.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TYPETRAITS_H
+#define LLVM_CLANG_TYPETRAITS_H
+
+namespace clang {
+
+ /// UnaryTypeTrait - Names for the unary type traits.
+ enum UnaryTypeTrait {
+ UTT_HasNothrowAssign,
+ UTT_HasNothrowCopy,
+ UTT_HasNothrowConstructor,
+ UTT_HasTrivialAssign,
+ UTT_HasTrivialCopy,
+ UTT_HasTrivialConstructor,
+ UTT_HasTrivialDestructor,
+ UTT_HasVirtualDestructor,
+ UTT_IsAbstract,
+ UTT_IsClass,
+ UTT_IsEmpty,
+ UTT_IsEnum,
+ UTT_IsPOD,
+ UTT_IsPolymorphic,
+ UTT_IsUnion
+ };
+
+}
+
+#endif
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
new file mode 100644
index 000000000000..f0e1aa7db233
--- /dev/null
+++ b/include/clang/Basic/Version.h
@@ -0,0 +1,35 @@
+//===- Version.h - Clang Version Number -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines version macros for Clang.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_VERSION_H
+#define LLVM_CLANG_BASIC_VERSION_H
+
+/// \brief Clang major version
+#define CLANG_VERSION_MAJOR 1
+
+/// \brief Clang minor version
+#define CLANG_VERSION_MINOR 0
+
+/// \brief Helper macro for CLANG_VERSION_STRING.
+#define CLANG_MAKE_VERSION_STRING2(X) #X
+
+/// \brief Helper macro for CLANG_VERSION_STRING.
+#define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y)
+
+/// \brief A string that describes the Clang version number, e.g.,
+/// "1.0".
+#define CLANG_VERSION_STRING \
+ CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR)
+
+
+#endif // LLVM_CLANG_BASIC_VERSION_H
diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt
new file mode 100644
index 000000000000..39e3698a1655
--- /dev/null
+++ b/include/clang/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Basic)
diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h
new file mode 100644
index 000000000000..5812da1b562e
--- /dev/null
+++ b/include/clang/CodeGen/ModuleBuilder.h
@@ -0,0 +1,40 @@
+//===--- CodeGen/ModuleBuilder.h - Build LLVM from ASTs ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ModuleBuilder interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H
+#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
+
+#include "clang/AST/ASTConsumer.h"
+#include <string>
+
+namespace llvm {
+ class Module;
+}
+
+namespace clang {
+ class Diagnostic;
+ class LangOptions;
+ class CompileOptions;
+
+ class CodeGenerator : public ASTConsumer {
+ public:
+ virtual llvm::Module* GetModule() = 0;
+ virtual llvm::Module* ReleaseModule() = 0;
+ };
+
+ CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags,
+ const std::string &ModuleName,
+ const CompileOptions &CO);
+}
+
+#endif
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
new file mode 100644
index 000000000000..b9bf671db2bd
--- /dev/null
+++ b/include/clang/Driver/Action.h
@@ -0,0 +1,209 @@
+//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_ACTION_H_
+#define CLANG_DRIVER_ACTION_H_
+
+#include "llvm/ADT/SmallVector.h"
+
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+namespace driver {
+ class Arg;
+
+/// Action - Represent an abstract compilation step to perform.
+///
+/// An action represents an edge in the compilation graph; typically
+/// it is a job to transform an input using some tool.
+///
+/// The current driver is hard wired to expect actions which produce a
+/// single primary output, at least in terms of controlling the
+/// compilation. Actions can produce auxiliary files, but can only
+/// produce a single output to feed into subsequent actions.
+class Action {
+public:
+ typedef ActionList::size_type size_type;
+ typedef ActionList::iterator iterator;
+ typedef ActionList::const_iterator const_iterator;
+
+ enum ActionClass {
+ InputClass = 0,
+ BindArchClass,
+ PreprocessJobClass,
+ PrecompileJobClass,
+ AnalyzeJobClass,
+ CompileJobClass,
+ AssembleJobClass,
+ LinkJobClass,
+ LipoJobClass,
+
+ JobClassFirst=PreprocessJobClass,
+ JobClassLast=LipoJobClass
+ };
+
+ static const char *getClassName(ActionClass AC);
+
+private:
+ ActionClass Kind;
+
+ /// The output type of this action.
+ types::ID Type;
+
+ ActionList Inputs;
+
+protected:
+ Action(ActionClass _Kind, types::ID _Type) : Kind(_Kind), Type(_Type) {}
+ Action(ActionClass _Kind, Action *Input, types::ID _Type)
+ : Kind(_Kind), Type(_Type), Inputs(&Input, &Input + 1) {}
+ Action(ActionClass _Kind, const ActionList &_Inputs, types::ID _Type)
+ : Kind(_Kind), Type(_Type), Inputs(_Inputs) {}
+public:
+ virtual ~Action();
+
+ ActionClass getKind() const { return Kind; }
+ types::ID getType() const { return Type; }
+
+ ActionList &getInputs() { return Inputs; }
+ const ActionList &getInputs() const { return Inputs; }
+
+ size_type size() const { return Inputs.size(); }
+
+ iterator begin() { return Inputs.begin(); }
+ iterator end() { return Inputs.end(); }
+ const_iterator begin() const { return Inputs.begin(); }
+ const_iterator end() const { return Inputs.end(); }
+
+ static bool classof(const Action *) { return true; }
+};
+
+class InputAction : public Action {
+ const Arg &Input;
+public:
+ InputAction(const Arg &_Input, types::ID _Type);
+
+ const Arg &getInputArg() const { return Input; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == InputClass;
+ }
+ static bool classof(const InputAction *) { return true; }
+};
+
+class BindArchAction : public Action {
+ /// The architecture to bind, or 0 if the default architecture
+ /// should be bound.
+ const char *ArchName;
+
+public:
+ BindArchAction(Action *Input, const char *_ArchName);
+
+ const char *getArchName() const { return ArchName; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == BindArchClass;
+ }
+ static bool classof(const BindArchAction *) { return true; }
+};
+
+class JobAction : public Action {
+protected:
+ JobAction(ActionClass Kind, Action *Input, types::ID Type);
+ JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
+
+public:
+ static bool classof(const Action *A) {
+ return (A->getKind() >= JobClassFirst &&
+ A->getKind() <= JobClassLast);
+ }
+ static bool classof(const JobAction *) { return true; }
+};
+
+class PreprocessJobAction : public JobAction {
+public:
+ PreprocessJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == PreprocessJobClass;
+ }
+ static bool classof(const PreprocessJobAction *) { return true; }
+};
+
+class PrecompileJobAction : public JobAction {
+public:
+ PrecompileJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == PrecompileJobClass;
+ }
+ static bool classof(const PrecompileJobAction *) { return true; }
+};
+
+class AnalyzeJobAction : public JobAction {
+public:
+ AnalyzeJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == AnalyzeJobClass;
+ }
+ static bool classof(const AnalyzeJobAction *) { return true; }
+};
+
+class CompileJobAction : public JobAction {
+public:
+ CompileJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == CompileJobClass;
+ }
+ static bool classof(const CompileJobAction *) { return true; }
+};
+
+class AssembleJobAction : public JobAction {
+public:
+ AssembleJobAction(Action *Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == AssembleJobClass;
+ }
+ static bool classof(const AssembleJobAction *) { return true; }
+};
+
+class LinkJobAction : public JobAction {
+public:
+ LinkJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == LinkJobClass;
+ }
+ static bool classof(const LinkJobAction *) { return true; }
+};
+
+class LipoJobAction : public JobAction {
+public:
+ LipoJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == LipoJobClass;
+ }
+ static bool classof(const LipoJobAction *) { return true; }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h
new file mode 100644
index 000000000000..6bed2b8cbdef
--- /dev/null
+++ b/include/clang/Driver/Arg.h
@@ -0,0 +1,230 @@
+//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_ARG_H_
+#define CLANG_DRIVER_ARG_H_
+
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+#include "Util.h"
+#include <vector>
+#include <string>
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Option;
+
+ /// Arg - A concrete instance of a particular driver option.
+ ///
+ /// The Arg class encodes just enough information to be able to
+ /// derive the argument values efficiently. In addition, Arg
+ /// instances have an intrusive double linked list which is used by
+ /// ArgList to provide efficient iteration over all instances of a
+ /// particular option.
+ class Arg {
+ public:
+ enum ArgClass {
+ FlagClass = 0,
+ PositionalClass,
+ JoinedClass,
+ SeparateClass,
+ CommaJoinedClass,
+ JoinedAndSeparateClass
+ };
+
+ private:
+ ArgClass Kind;
+
+ /// The option this argument is an instance of.
+ const Option *Opt;
+
+ /// The argument this argument was derived from (during tool chain
+ /// argument translation), if any.
+ const Arg *BaseArg;
+
+ /// The index at which this argument appears in the containing
+ /// ArgList.
+ unsigned Index;
+
+ /// Flag indicating whether this argument was used to effect
+ /// compilation; used for generating "argument unused"
+ /// diagnostics.
+ mutable bool Claimed;
+
+ protected:
+ Arg(ArgClass Kind, const Option *Opt, unsigned Index,
+ const Arg *BaseArg = 0);
+
+ public:
+ Arg(const Arg &);
+ virtual ~Arg();
+
+ ArgClass getKind() const { return Kind; }
+ const Option &getOption() const { return *Opt; }
+ unsigned getIndex() const { return Index; }
+
+ /// getBaseArg - Return the base argument which generated this
+ /// arg; this is either the argument itself or the argument it was
+ /// derived from during tool chain specific argument translation.
+ const Arg &getBaseArg() const {
+ return BaseArg ? *BaseArg : *this;
+ }
+ void setBaseArg(const Arg *_BaseArg) {
+ BaseArg = _BaseArg;
+ }
+
+ bool isClaimed() const { return getBaseArg().Claimed; }
+
+ /// claim - Set the Arg claimed bit.
+
+ // FIXME: We need to deal with derived arguments and set the bit
+ // in the original argument; not the derived one.
+ void claim() const { getBaseArg().Claimed = true; }
+
+ virtual unsigned getNumValues() const = 0;
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const = 0;
+
+ /// render - Append the argument onto the given array as strings.
+ virtual void render(const ArgList &Args, ArgStringList &Output) const = 0;
+
+ /// renderAsInput - Append the argument, render as an input, onto
+ /// the given array as strings. The distinction is that some
+ /// options only render their values when rendered as a input
+ /// (e.g., Xlinker).
+ void renderAsInput(const ArgList &Args, ArgStringList &Output) const;
+
+ static bool classof(const Arg *) { return true; }
+
+ void dump() const;
+
+ /// getAsString - Return a formatted version of the argument and
+ /// its values, for debugging and diagnostics.
+ std::string getAsString(const ArgList &Args) const;
+ };
+
+ /// FlagArg - An argument with no value.
+ class FlagArg : public Arg {
+ public:
+ FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0);
+
+ virtual void render(const ArgList &Args, ArgStringList &Output) const;
+
+ virtual unsigned getNumValues() const { return 0; }
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const;
+
+ static bool classof(const Arg *A) {
+ return A->getKind() == Arg::FlagClass;
+ }
+ static bool classof(const FlagArg *) { return true; }
+ };
+
+ /// PositionalArg - A simple positional argument.
+ class PositionalArg : public Arg {
+ public:
+ PositionalArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0);
+
+ virtual void render(const ArgList &Args, ArgStringList &Output) const;
+
+ virtual unsigned getNumValues() const { return 1; }
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const;
+
+ static bool classof(const Arg *A) {
+ return A->getKind() == Arg::PositionalClass;
+ }
+ static bool classof(const PositionalArg *) { return true; }
+ };
+
+ /// JoinedArg - A single value argument where the value is joined
+ /// (suffixed) to the option.
+ class JoinedArg : public Arg {
+ public:
+ JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0);
+
+ virtual void render(const ArgList &Args, ArgStringList &Output) const;
+
+ virtual unsigned getNumValues() const { return 1; }
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const;
+
+ static bool classof(const Arg *A) {
+ return A->getKind() == Arg::JoinedClass;
+ }
+ static bool classof(const JoinedArg *) { return true; }
+ };
+
+ /// SeparateArg - An argument where one or more values follow the
+ /// option specifier immediately in the argument vector.
+ class SeparateArg : public Arg {
+ unsigned NumValues;
+
+ public:
+ SeparateArg(const Option *Opt, unsigned Index, unsigned NumValues,
+ const Arg *BaseArg = 0);
+
+ virtual void render(const ArgList &Args, ArgStringList &Output) const;
+
+ virtual unsigned getNumValues() const { return NumValues; }
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const;
+
+ static bool classof(const Arg *A) {
+ return A->getKind() == Arg::SeparateClass;
+ }
+ static bool classof(const SeparateArg *) { return true; }
+ };
+
+ /// CommaJoinedArg - An argument with multiple values joined by
+ /// commas and joined (suffixed) to the option specifier.
+ ///
+ /// The key point of this arg is that it renders its values into
+ /// separate arguments, which allows it to be used as a generic
+ /// mechanism for passing arguments through to tools.
+ class CommaJoinedArg : public Arg {
+ std::vector<std::string> Values;
+
+ public:
+ CommaJoinedArg(const Option *Opt, unsigned Index, const char *Str,
+ const Arg *BaseArg = 0);
+
+ virtual void render(const ArgList &Args, ArgStringList &Output) const;
+
+ virtual unsigned getNumValues() const { return Values.size(); }
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const;
+
+ static bool classof(const Arg *A) {
+ return A->getKind() == Arg::CommaJoinedClass;
+ }
+ static bool classof(const CommaJoinedArg *) { return true; }
+ };
+
+ /// JoinedAndSeparateArg - An argument with both joined and separate
+ /// values.
+ class JoinedAndSeparateArg : public Arg {
+ public:
+ JoinedAndSeparateArg(const Option *Opt, unsigned Index,
+ const Arg *BaseArg = 0);
+
+ virtual void render(const ArgList &Args, ArgStringList &Output) const;
+
+ virtual unsigned getNumValues() const { return 2; }
+ virtual const char *getValue(const ArgList &Args, unsigned N=0) const;
+
+ static bool classof(const Arg *A) {
+ return A->getKind() == Arg::JoinedAndSeparateClass;
+ }
+ static bool classof(const JoinedAndSeparateArg *) { return true; }
+ };
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h
new file mode 100644
index 000000000000..84e0329a375e
--- /dev/null
+++ b/include/clang/Driver/ArgList.h
@@ -0,0 +1,245 @@
+//===--- ArgList.h - Argument List Management ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_ARGLIST_H_
+#define CLANG_DRIVER_ARGLIST_H_
+
+#include "clang/Driver/Options.h"
+
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include <list>
+
+namespace clang {
+namespace driver {
+ class Arg;
+
+ /// ArgList - Ordered collection of driver arguments.
+ ///
+ /// The ArgList class manages a list of Arg instances as well as
+ /// auxiliary data and convenience methods to allow Tools to quickly
+ /// check for the presence of Arg instances for a particular Option
+ /// and to iterate over groups of arguments.
+ class ArgList {
+ public:
+ typedef llvm::SmallVector<Arg*, 16> arglist_type;
+ typedef arglist_type::iterator iterator;
+ typedef arglist_type::const_iterator const_iterator;
+ typedef arglist_type::reverse_iterator reverse_iterator;
+ typedef arglist_type::const_reverse_iterator const_reverse_iterator;
+
+ private:
+ /// The full list of arguments.
+ arglist_type &Args;
+
+ protected:
+ ArgList(arglist_type &Args);
+
+ public:
+ virtual ~ArgList();
+
+ /// @name Arg Access
+ /// @{
+
+ /// append - Append \arg A to the arg list.
+ void append(Arg *A);
+
+ arglist_type &getArgs() { return Args; }
+ const arglist_type &getArgs() const { return Args; }
+
+ unsigned size() const { return Args.size(); }
+
+ iterator begin() { return Args.begin(); }
+ iterator end() { return Args.end(); }
+
+ reverse_iterator rbegin() { return Args.rbegin(); }
+ reverse_iterator rend() { return Args.rend(); }
+
+ const_iterator begin() const { return Args.begin(); }
+ const_iterator end() const { return Args.end(); }
+
+ const_reverse_iterator rbegin() const { return Args.rbegin(); }
+ const_reverse_iterator rend() const { return Args.rend(); }
+
+ /// hasArg - Does the arg list contain any option matching \arg Id.
+ ///
+ /// \arg Claim Whether the argument should be claimed, if it exists.
+ bool hasArg(options::ID Id, bool Claim=true) const {
+ return getLastArg(Id, Claim) != 0;
+ }
+ bool hasArg(options::ID Id0, options::ID Id1, bool Claim=true) const {
+ return getLastArg(Id0, Id1, Claim) != 0;
+ }
+
+ /// getLastArg - Return the last argument matching \arg Id, or null.
+ ///
+ /// \arg Claim Whether the argument should be claimed, if it exists.
+ Arg *getLastArg(options::ID Id, bool Claim=true) const;
+ Arg *getLastArg(options::ID Id0, options::ID Id1, bool Claim=true) const;
+
+ /// getArgString - Return the input argument string at \arg Index.
+ virtual const char *getArgString(unsigned Index) const = 0;
+ /// @name Translation Utilities
+ /// @{
+
+ /// hasFlag - Given an option \arg Pos and its negative form \arg
+ /// Neg, return true if the option is present, false if the
+ /// negation is present, and \arg Default if neither option is
+ /// given. If both the option and its negation are present, the
+ /// last one wins.
+ bool hasFlag(options::ID Pos, options::ID Neg, bool Default=true) const;
+
+ /// AddLastArg - Render only the last argument match \arg Id0, if
+ /// present.
+ void AddLastArg(ArgStringList &Output, options::ID Id0) const;
+
+ /// AddAllArgs - Render all arguments matching the given ids.
+ void AddAllArgs(ArgStringList &Output, options::ID Id0) const;
+ void AddAllArgs(ArgStringList &Output, options::ID Id0,
+ options::ID Id1) const;
+ void AddAllArgs(ArgStringList &Output, options::ID Id0, options::ID Id1,
+ options::ID Id2) const;
+
+ /// AddAllArgValues - Render the argument values of all arguments
+ /// matching the given ids.
+ void AddAllArgValues(ArgStringList &Output, options::ID Id0) const;
+ void AddAllArgValues(ArgStringList &Output, options::ID Id0,
+ options::ID Id1) const;
+
+ /// AddAllArgsTranslated - Render all the arguments matching the
+ /// given ids, but forced to separate args and using the provided
+ /// name instead of the first option value.
+ ///
+ /// \param Joined - If true, render the argument as joined with
+ /// the option specifier.
+ void AddAllArgsTranslated(ArgStringList &Output, options::ID Id0,
+ const char *Translation,
+ bool Joined = false) const;
+
+ /// ClaimAllArgs - Claim all arguments which match the given
+ /// option id.
+ void ClaimAllArgs(options::ID Id0) const;
+
+ /// @}
+ /// @name Arg Synthesis
+ /// @{
+
+ /// MakeArgString - Construct a constant string pointer whose
+ /// lifetime will match that of the ArgList.
+ virtual const char *MakeArgString(const char *Str) const = 0;
+
+ /// @}
+ };
+
+ class InputArgList : public ArgList {
+ private:
+ /// The internal list of arguments.
+ arglist_type ActualArgs;
+
+ /// List of argument strings used by the contained Args.
+ ///
+ /// This is mutable since we treat the ArgList as being the list
+ /// of Args, and allow routines to add new strings (to have a
+ /// convenient place to store the memory) via MakeIndex.
+ mutable ArgStringList ArgStrings;
+
+ /// Strings for synthesized arguments.
+ ///
+ /// This is mutable since we treat the ArgList as being the list
+ /// of Args, and allow routines to add new strings (to have a
+ /// convenient place to store the memory) via MakeIndex.
+ mutable std::list<std::string> SynthesizedStrings;
+
+ /// The number of original input argument strings.
+ unsigned NumInputArgStrings;
+
+ public:
+ InputArgList(const char **ArgBegin, const char **ArgEnd);
+ InputArgList(const ArgList &);
+ ~InputArgList();
+
+ virtual const char *getArgString(unsigned Index) const {
+ return ArgStrings[Index];
+ }
+
+ /// getNumInputArgStrings - Return the number of original input
+ /// argument strings.
+ unsigned getNumInputArgStrings() const { return NumInputArgStrings; }
+
+ /// @name Arg Synthesis
+ /// @{
+
+ public:
+ /// MakeIndex - Get an index for the given string(s).
+ unsigned MakeIndex(const char *String0) const;
+ unsigned MakeIndex(const char *String0, const char *String1) const;
+
+ virtual const char *MakeArgString(const char *Str) const;
+
+ /// @}
+ };
+
+ /// DerivedArgList - An ordered collection of driver arguments,
+ /// whose storage may be in another argument list.
+ class DerivedArgList : public ArgList {
+ InputArgList &BaseArgs;
+
+ /// The internal list of arguments.
+ arglist_type ActualArgs;
+
+ /// The list of arguments we synthesized.
+ arglist_type SynthesizedArgs;
+
+ /// Is this only a proxy for the base ArgList?
+ bool OnlyProxy;
+
+ public:
+ /// Construct a new derived arg list from \arg BaseArgs.
+ ///
+ /// \param OnlyProxy - If true, this is only a proxy for the base
+ /// list (to adapt the type), and it's Args list is unused.
+ DerivedArgList(InputArgList &BaseArgs, bool OnlyProxy);
+ ~DerivedArgList();
+
+ virtual const char *getArgString(unsigned Index) const {
+ return BaseArgs.getArgString(Index);
+ }
+
+ /// @name Arg Synthesis
+ /// @{
+
+ virtual const char *MakeArgString(const char *Str) const;
+
+ /// MakeFlagArg - Construct a new FlagArg for the given option
+ /// \arg Id.
+ Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const;
+
+ /// MakePositionalArg - Construct a new Positional arg for the
+ /// given option \arg Id, with the provided \arg Value.
+ Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt,
+ const char *Value) const;
+
+ /// MakeSeparateArg - Construct a new Positional arg for the
+ /// given option \arg Id, with the provided \arg Value.
+ Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
+ const char *Value) const;
+
+ /// MakeJoinedArg - Construct a new Positional arg for the
+ /// given option \arg Id, with the provided \arg Value.
+ Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
+ const char *Value) const;
+
+ /// @}
+ };
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
new file mode 100644
index 000000000000..4985f30ad553
--- /dev/null
+++ b/include/clang/Driver/Compilation.h
@@ -0,0 +1,127 @@
+//===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_COMPILATION_H_
+#define CLANG_DRIVER_COMPILATION_H_
+
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+namespace driver {
+ class DerivedArgList;
+ class Driver;
+ class InputArgList;
+ class JobList;
+ class ToolChain;
+
+/// Compilation - A set of tasks to perform for a single driver
+/// invocation.
+class Compilation {
+ /// The driver we were created by.
+ Driver &TheDriver;
+
+ /// The default tool chain.
+ ToolChain &DefaultToolChain;
+
+ /// The original (untranslated) input argument list.
+ InputArgList *Args;
+
+ /// The list of actions.
+ ActionList Actions;
+
+ /// The root list of jobs.
+ JobList Jobs;
+
+ /// Cache of translated arguments for a particular tool chain.
+ llvm::DenseMap<const ToolChain*, DerivedArgList*> TCArgs;
+
+ /// Temporary files which should be removed on exit.
+ ArgStringList TempFiles;
+
+ /// Result files which should be removed on failure.
+ ArgStringList ResultFiles;
+
+public:
+ Compilation(Driver &D, ToolChain &DefaultToolChain, InputArgList *Args);
+ ~Compilation();
+
+ const Driver &getDriver() const { return TheDriver; }
+
+ const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
+
+ const InputArgList &getArgs() const { return *Args; }
+
+ ActionList &getActions() { return Actions; }
+ const ActionList &getActions() const { return Actions; }
+
+ JobList &getJobs() { return Jobs; }
+
+ /// getArgsForToolChain - Return the derived argument list for the
+ /// tool chain \arg TC (or the default tool chain, if TC is not
+ /// specified).
+ const DerivedArgList &getArgsForToolChain(const ToolChain *TC = 0);
+
+ /// addTempFile - Add a file to remove on exit, and returns its
+ /// argument.
+ const char *addTempFile(const char *Name) {
+ TempFiles.push_back(Name);
+ return Name;
+ }
+
+ /// addResultFile - Add a file to remove on failure, and returns its
+ /// argument.
+ const char *addResultFile(const char *Name) {
+ ResultFiles.push_back(Name);
+ return Name;
+ }
+
+ /// Execute - Execute the compilation jobs and return an
+ /// appropriate exit code.
+ int Execute() const;
+
+private:
+ /// CleanupFileList - Remove the files in the given list.
+ ///
+ /// \param IssueErrors - Report failures as errors.
+ /// \return Whether all files were removed successfully.
+ bool CleanupFileList(const ArgStringList &Files,
+ bool IssueErrors=false) const;
+
+ /// PrintJob - Print one job in -### format.
+ ///
+ /// OS - The stream to print on.
+ /// J - The job to print.
+ /// Terminator - A string to print at the end of the line.
+ /// Quote - Should separate arguments be quoted.
+ void PrintJob(llvm::raw_ostream &OS, const Job &J,
+ const char *Terminator, bool Quote) const;
+
+ /// ExecuteCommand - Execute an actual command.
+ ///
+ /// \return The result code of the subprocess.
+ int ExecuteCommand(const Command &C) const;
+
+ /// ExecuteJob - Execute a single job.
+ ///
+ /// \return The accumulated result code of the job.
+ int ExecuteJob(const Job &J) const;
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
new file mode 100644
index 000000000000..66e3b9787594
--- /dev/null
+++ b/include/clang/Driver/Driver.h
@@ -0,0 +1,271 @@
+//===--- Driver.h - Clang GCC Compatible Driver -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_DRIVER_H_
+#define CLANG_DRIVER_DRIVER_H_
+
+#include "clang/Basic/Diagnostic.h"
+
+#include "clang/Driver/Phases.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/System/Path.h" // FIXME: Kill when CompilationInfo
+ // lands.
+#include <list>
+#include <set>
+#include <string>
+
+namespace clang {
+namespace driver {
+ class Action;
+ class ArgList;
+ class Compilation;
+ class HostInfo;
+ class InputArgList;
+ class InputInfo;
+ class JobAction;
+ class OptTable;
+ class PipedJob;
+ class ToolChain;
+
+/// Driver - Encapsulate logic for constructing compilation processes
+/// from a set of gcc-driver-like command line arguments.
+class Driver {
+ OptTable *Opts;
+
+ Diagnostic &Diags;
+
+public:
+ // Diag - Forwarding function for diagnostics.
+ DiagnosticBuilder Diag(unsigned DiagID) const {
+ return Diags.Report(FullSourceLoc(), DiagID);
+ }
+
+ // FIXME: Privatize once interface is stable.
+public:
+ /// The name the driver was invoked as.
+ std::string Name;
+
+ /// The path the driver executable was in, as invoked from the
+ /// command line.
+ std::string Dir;
+
+ /// Default host triple.
+ std::string DefaultHostTriple;
+
+ /// Default name for linked images (e.g., "a.out").
+ std::string DefaultImageName;
+
+ /// Host information for the platform the driver is running as. This
+ /// will generally be the actual host platform, but not always.
+ const HostInfo *Host;
+
+ /// Information about the host which can be overriden by the user.
+ std::string HostBits, HostMachine, HostSystem, HostRelease;
+
+ /// Whether the driver should follow g++ like behavior.
+ bool CCCIsCXX : 1;
+
+ /// Echo commands while executing (in -v style).
+ bool CCCEcho : 1;
+
+ /// Only print tool bindings, don't build any jobs.
+ bool CCCPrintBindings : 1;
+
+ /// Name to use when calling the generic gcc.
+ std::string CCCGenericGCCName;
+
+private:
+ /// Use the clang compiler where possible.
+ bool CCCUseClang : 1;
+
+ /// Use clang for handling C++ and Objective-C++ inputs.
+ bool CCCUseClangCXX : 1;
+
+ /// Use clang as a preprocessor (clang's preprocessor will still be
+ /// used where an integrated CPP would).
+ bool CCCUseClangCPP : 1;
+
+public:
+ /// Use lazy precompiled headers for PCH support.
+ bool CCCUsePCH;
+
+private:
+ /// Only use clang for the given architectures (only used when
+ /// non-empty).
+ std::set<std::string> CCCClangArchs;
+
+ /// Certain options suppress the 'no input files' warning.
+ bool SuppressMissingInputWarning : 1;
+
+ std::list<std::string> TempFiles;
+ std::list<std::string> ResultFiles;
+
+public:
+ Driver(const char *_Name, const char *_Dir,
+ const char *_DefaultHostTriple,
+ const char *_DefaultImageName,
+ Diagnostic &_Diags);
+ ~Driver();
+
+ /// @name Accessors
+ /// @{
+
+ const OptTable &getOpts() const { return *Opts; }
+
+ const Diagnostic &getDiags() const { return Diags; }
+
+ /// @}
+ /// @name Primary Functionality
+ /// @{
+
+ /// BuildCompilation - Construct a compilation object for a command
+ /// line argument vector.
+ ///
+ /// \return A compilation, or 0 if none was built for the given
+ /// argument vector. A null return value does not necessarily
+ /// indicate an error condition, the diagnostics should be queried
+ /// to determine if an error occurred.
+ Compilation *BuildCompilation(int argc, const char **argv);
+
+ /// @name Driver Steps
+ /// @{
+
+ /// ParseArgStrings - Parse the given list of strings into an
+ /// ArgList.
+ InputArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd);
+
+ /// BuildActions - Construct the list of actions to perform for the
+ /// given arguments, which are only done for a single architecture.
+ ///
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildActions(const ArgList &Args, ActionList &Actions) const;
+
+ /// BuildUniversalActions - Construct the list of actions to perform
+ /// for the given arguments, which may require a universal build.
+ ///
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildUniversalActions(const ArgList &Args, ActionList &Actions) const;
+
+ /// BuildJobs - Bind actions to concrete tools and translate
+ /// arguments to form the list of jobs to run.
+ ///
+ /// \arg C - The compilation that is being built.
+ void BuildJobs(Compilation &C) const;
+
+ /// @}
+ /// @name Helper Methods
+ /// @{
+
+ /// PrintActions - Print the list of actions.
+ void PrintActions(const Compilation &C) const;
+
+ /// PrintHelp - Print the help text.
+ ///
+ /// \param ShowHidden - Show hidden options.
+ void PrintHelp(bool ShowHidden) const;
+
+ /// PrintOptions - Print the list of arguments.
+ void PrintOptions(const ArgList &Args) const;
+
+ /// PrintVersion - Print the driver version.
+ void PrintVersion(const Compilation &C) const;
+
+ /// GetFilePath - Lookup \arg Name in the list of file search paths.
+ ///
+ /// \arg TC - The tool chain for additional information on
+ /// directories to search.
+ // FIXME: This should be in CompilationInfo.
+ llvm::sys::Path GetFilePath(const char *Name, const ToolChain &TC) const;
+
+ /// GetProgramPath - Lookup \arg Name in the list of program search
+ /// paths.
+ ///
+ /// \arg TC - The provided tool chain for additional information on
+ /// directories to search.
+ ///
+ /// \arg WantFile - False when searching for an executable file, otherwise
+ /// true. Defaults to false.
+ // FIXME: This should be in CompilationInfo.
+ llvm::sys::Path GetProgramPath(const char *Name, const ToolChain &TC,
+ bool WantFile = false) const;
+
+ /// HandleImmediateArgs - Handle any arguments which should be
+ /// treated before building actions or binding tools.
+ ///
+ /// \return Whether any compilation should be built for this
+ /// invocation.
+ bool HandleImmediateArgs(const Compilation &C);
+
+ /// ConstructAction - Construct the appropriate action to do for
+ /// \arg Phase on the \arg Input, taking in to account arguments
+ /// like -fsyntax-only or --analyze.
+ Action *ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+ Action *Input) const;
+
+
+ /// BuildJobsForAction - Construct the jobs to perform for the
+ /// action \arg A.
+ void BuildJobsForAction(Compilation &C,
+ const Action *A,
+ const ToolChain *TC,
+ bool CanAcceptPipe,
+ bool AtTopLevel,
+ const char *LinkingOutput,
+ InputInfo &Result) const;
+
+ /// GetNamedOutputPath - Return the name to use for the output of
+ /// the action \arg JA. The result is appended to the compilation's
+ /// list of temporary or result files, as appropriate.
+ ///
+ /// \param C - The compilation.
+ /// \param JA - The action of interest.
+ /// \param BaseInput - The original input file that this action was
+ /// triggered by.
+ /// \param AtTopLevel - Whether this is a "top-level" action.
+ const char *GetNamedOutputPath(Compilation &C,
+ const JobAction &JA,
+ const char *BaseInput,
+ bool AtTopLevel) const;
+
+ /// GetTemporaryPath - Return the pathname of a temporary file to
+ /// use as part of compilation; the file will have the given suffix.
+ ///
+ /// GCC goes to extra lengths here to be a bit more robust.
+ std::string GetTemporaryPath(const char *Suffix) const;
+
+ /// GetHostInfo - Construct a new host info object for the given
+ /// host triple.
+ const HostInfo *GetHostInfo(const char *HostTriple) const;
+
+ /// ShouldUseClangCompilar - Should the clang compiler be used to
+ /// handle this action.
+ bool ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
+ const std::string &ArchName) const;
+
+ /// @}
+
+ /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
+ /// return the grouped values as integers. Numbers which are not
+ /// provided are set to 0.
+ ///
+ /// \return True if the entire string was parsed (9.2), or all
+ /// groups were parsed (10.3.5extrastuff). HadExtra is true if all
+ /// groups were parsed but extra characters remain at the end.
+ static bool GetReleaseVersion(const char *Str, unsigned &Major,
+ unsigned &Minor, unsigned &Micro,
+ bool &HadExtra);
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h
new file mode 100644
index 000000000000..2a4413c24e07
--- /dev/null
+++ b/include/clang/Driver/DriverDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticDriver.h - Diagnostics for libdriver ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DRIVERDIAGNOSTIC_H
+#define LLVM_CLANG_DRIVERDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define DRIVERSTART
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_DRIVER_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h
new file mode 100644
index 000000000000..020bb3ab5a82
--- /dev/null
+++ b/include/clang/Driver/HostInfo.h
@@ -0,0 +1,84 @@
+//===--- HostInfo.h - Host specific information -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_HOSTINFO_H_
+#define CLANG_DRIVER_HOSTINFO_H_
+
+#include "clang/Driver/Types.h"
+#include "llvm/ADT/Triple.h"
+#include <string>
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Driver;
+ class ToolChain;
+
+/// HostInfo - Config information about a particular host which may
+/// interact with driver behavior.
+///
+/// The host information is used for controlling the parts of the
+/// driver which interact with the platform the driver is ostensibly
+/// being run from. For testing purposes, the HostInfo used by the
+/// driver may differ from the actual host.
+class HostInfo {
+ const Driver &TheDriver;
+ const llvm::Triple Triple;
+
+protected:
+ HostInfo(const Driver &D, const llvm::Triple &_Triple);
+
+public:
+ virtual ~HostInfo();
+
+ const Driver &getDriver() const { return TheDriver; }
+
+ const llvm::Triple& getTriple() const { return Triple; }
+ std::string getArchName() const { return Triple.getArchName(); }
+ std::string getPlatformName() const { return Triple.getVendorName(); }
+ std::string getOSName() const { return Triple.getOSName(); }
+
+ /// useDriverDriver - Whether the driver should act as a driver
+ /// driver for this host and support -arch, -Xarch, etc.
+ virtual bool useDriverDriver() const = 0;
+
+ /// lookupTypeForExtension - Return the default language type to use
+ /// for the given extension.
+ virtual types::ID lookupTypeForExtension(const char *Ext) const = 0;
+
+ /// getToolChain - Construct the toolchain to use for this host.
+ ///
+ /// \param Args - The argument list, which may be used to alter the
+ /// default toolchain, for example in the presence of -m32 or -m64.
+ ///
+ /// \param ArchName - The architecture to return a toolchain for, or
+ /// 0 if unspecified. This will only ever be non-zero for hosts
+ /// which support a driver driver.
+
+ // FIXME: Pin down exactly what the HostInfo is allowed to use Args
+ // for here. Currently this is for -m32 / -m64 defaulting.
+ virtual ToolChain *getToolChain(const ArgList &Args,
+ const char *ArchName=0) const = 0;
+};
+
+const HostInfo *createDarwinHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createFreeBSDHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createDragonFlyHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createLinuxHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+const HostInfo *createUnknownHostInfo(const Driver &D,
+ const llvm::Triple& Triple);
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
new file mode 100644
index 000000000000..f60f5146414c
--- /dev/null
+++ b/include/clang/Driver/Job.h
@@ -0,0 +1,138 @@
+//===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_JOB_H_
+#define CLANG_DRIVER_JOB_H_
+
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+namespace driver {
+ class Command;
+
+class Job {
+public:
+ enum JobClass {
+ CommandClass,
+ PipedJobClass,
+ JobListClass
+ };
+
+private:
+ JobClass Kind;
+
+protected:
+ Job(JobClass _Kind) : Kind(_Kind) {}
+public:
+ virtual ~Job();
+
+ JobClass getKind() const { return Kind; }
+
+ /// addCommand - Append a command to the current job, which must be
+ /// either a piped job or a job list.
+ void addCommand(Command *C);
+
+ static bool classof(const Job *) { return true; }
+};
+
+ /// Command - An executable path/name and argument vector to
+ /// execute.
+class Command : public Job {
+ /// The executable to run.
+ const char *Executable;
+
+ /// The list of program arguments (not including the implicit first
+ /// argument, which will be the executable).
+ ArgStringList Arguments;
+
+public:
+ Command(const char *_Executable, const ArgStringList &_Arguments);
+
+ const char *getExecutable() const { return Executable; }
+ const ArgStringList &getArguments() const { return Arguments; }
+
+ static bool classof(const Job *J) {
+ return J->getKind() == CommandClass;
+ }
+ static bool classof(const Command *) { return true; }
+};
+
+ /// PipedJob - A list of Commands which should be executed together
+ /// with their standard inputs and outputs connected.
+class PipedJob : public Job {
+public:
+ typedef llvm::SmallVector<Command*, 4> list_type;
+ typedef list_type::size_type size_type;
+ typedef list_type::iterator iterator;
+ typedef list_type::const_iterator const_iterator;
+
+private:
+ list_type Commands;
+
+public:
+ PipedJob();
+
+ void addCommand(Command *C) { Commands.push_back(C); }
+
+ const list_type &getCommands() const { return Commands; }
+
+ size_type size() const { return Commands.size(); }
+ iterator begin() { return Commands.begin(); }
+ const_iterator begin() const { return Commands.begin(); }
+ iterator end() { return Commands.end(); }
+ const_iterator end() const { return Commands.end(); }
+
+ static bool classof(const Job *J) {
+ return J->getKind() == PipedJobClass;
+ }
+ static bool classof(const PipedJob *) { return true; }
+};
+
+ /// JobList - A sequence of jobs to perform.
+class JobList : public Job {
+public:
+ typedef llvm::SmallVector<Job*, 4> list_type;
+ typedef list_type::size_type size_type;
+ typedef list_type::iterator iterator;
+ typedef list_type::const_iterator const_iterator;
+
+private:
+ list_type Jobs;
+
+public:
+ JobList();
+
+ void addJob(Job *J) { Jobs.push_back(J); }
+
+ const list_type &getJobs() const { return Jobs; }
+
+ size_type size() const { return Jobs.size(); }
+ iterator begin() { return Jobs.begin(); }
+ const_iterator begin() const { return Jobs.begin(); }
+ iterator end() { return Jobs.end(); }
+ const_iterator end() const { return Jobs.end(); }
+
+ static bool classof(const Job *J) {
+ return J->getKind() == JobListClass;
+ }
+ static bool classof(const JobList *) { return true; }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h
new file mode 100644
index 000000000000..c59faef897ae
--- /dev/null
+++ b/include/clang/Driver/Option.h
@@ -0,0 +1,308 @@
+//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTION_H_
+#define CLANG_DRIVER_OPTION_H_
+
+#include "Options.h"
+
+#include "llvm/Support/Casting.h"
+using llvm::isa;
+using llvm::cast;
+using llvm::cast_or_null;
+using llvm::dyn_cast;
+using llvm::dyn_cast_or_null;
+
+namespace clang {
+namespace driver {
+ class Arg;
+ class InputArgList;
+ class OptionGroup;
+
+ /// Option - Abstract representation for a single form of driver
+ /// argument.
+ ///
+ /// An Option class represents a form of option that the driver
+ /// takes, for example how many arguments the option has and how
+ /// they can be provided. Individual option instances store
+ /// additional information about what group the option is a member
+ /// of (if any), if the option is an alias, and a number of
+ /// flags. At runtime the driver parses the command line into
+ /// concrete Arg instances, each of which corresponds to a
+ /// particular Option instance.
+ class Option {
+ public:
+ enum OptionClass {
+ GroupClass = 0,
+ InputClass,
+ UnknownClass,
+ FlagClass,
+ JoinedClass,
+ SeparateClass,
+ CommaJoinedClass,
+ MultiArgClass,
+ JoinedOrSeparateClass,
+ JoinedAndSeparateClass
+ };
+
+ private:
+ OptionClass Kind;
+
+ options::ID ID;
+
+ /// The option name.
+ const char *Name;
+
+ /// Group this option is a member of, if any.
+ const OptionGroup *Group;
+
+ /// Option that this is an alias for, if any.
+ const Option *Alias;
+
+ /// Unsupported options will not be rejected.
+ bool Unsupported : 1;
+
+ /// Treat this option like a linker input?
+ bool LinkerInput : 1;
+
+ /// When rendering as an input, don't render the option.
+
+ // FIXME: We should ditch the render/renderAsInput distinction.
+ bool NoOptAsInput : 1;
+
+ /// Always render this option as separate form its value.
+ bool ForceSeparateRender : 1;
+
+ /// Always render this option joined with its value.
+ bool ForceJoinedRender : 1;
+
+ /// This option is only consumed by the driver.
+ bool DriverOption : 1;
+
+ /// This option should not report argument unused errors.
+ bool NoArgumentUnused : 1;
+
+ protected:
+ Option(OptionClass Kind, options::ID ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+ public:
+ virtual ~Option();
+
+ options::ID getId() const { return ID; }
+ OptionClass getKind() const { return Kind; }
+ const char *getName() const { return Name; }
+ const OptionGroup *getGroup() const { return Group; }
+ const Option *getAlias() const { return Alias; }
+
+ bool isUnsupported() const { return Unsupported; }
+ void setUnsupported(bool Value) { Unsupported = Value; }
+
+ bool isLinkerInput() const { return LinkerInput; }
+ void setLinkerInput(bool Value) { LinkerInput = Value; }
+
+ bool hasNoOptAsInput() const { return NoOptAsInput; }
+ void setNoOptAsInput(bool Value) { NoOptAsInput = Value; }
+
+ bool hasForceSeparateRender() const { return ForceSeparateRender; }
+ void setForceSeparateRender(bool Value) { ForceSeparateRender = Value; }
+
+ bool hasForceJoinedRender() const { return ForceJoinedRender; }
+ void setForceJoinedRender(bool Value) { ForceJoinedRender = Value; }
+
+ bool isDriverOption() const { return DriverOption; }
+ void setDriverOption(bool Value) { DriverOption = Value; }
+
+ bool hasNoArgumentUnused() const { return NoArgumentUnused; }
+ void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; }
+
+ bool hasForwardToGCC() const { return !DriverOption && !LinkerInput; }
+
+ /// getUnaliasedOption - Return the final option this option
+ /// aliases (itself, if the option has no alias).
+ const Option *getUnaliasedOption() const {
+ if (Alias) return Alias->getUnaliasedOption();
+ return this;
+ }
+
+ /// getRenderName - Return the name to use when rendering this
+ /// option.
+ const char *getRenderName() const {
+ return getUnaliasedOption()->getName();
+ }
+
+ /// matches - Predicate for whether this option is part of the
+ /// given option (which may be a group).
+ bool matches(const Option *Opt) const;
+ bool matches(options::ID Id) const;
+
+ /// accept - Potentially accept the current argument, returning a
+ /// new Arg instance, or 0 if the option does not accept this
+ /// argument (or the argument is missing values).
+ ///
+ /// If the option accepts the current argument, accept() sets
+ /// Index to the position where argument parsing should resume
+ /// (even if the argument is missing values).
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const = 0;
+
+ void dump() const;
+
+ static bool classof(const Option *) { return true; }
+ };
+
+ /// OptionGroup - A set of options which are can be handled uniformly
+ /// by the driver.
+ class OptionGroup : public Option {
+ public:
+ OptionGroup(options::ID ID, const char *Name, const OptionGroup *Group);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::GroupClass;
+ }
+ static bool classof(const OptionGroup *) { return true; }
+ };
+
+ // Dummy option classes.
+
+ /// InputOption - Dummy option class for representing driver inputs.
+ class InputOption : public Option {
+ public:
+ InputOption();
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::InputClass;
+ }
+ static bool classof(const InputOption *) { return true; }
+ };
+
+ /// UnknownOption - Dummy option class for represent unknown arguments.
+ class UnknownOption : public Option {
+ public:
+ UnknownOption();
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::UnknownClass;
+ }
+ static bool classof(const UnknownOption *) { return true; }
+ };
+
+ // Normal options.
+
+ class FlagOption : public Option {
+ public:
+ FlagOption(options::ID ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::FlagClass;
+ }
+ static bool classof(const FlagOption *) { return true; }
+ };
+
+ class JoinedOption : public Option {
+ public:
+ JoinedOption(options::ID ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedClass;
+ }
+ static bool classof(const JoinedOption *) { return true; }
+ };
+
+ class SeparateOption : public Option {
+ public:
+ SeparateOption(options::ID ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::SeparateClass;
+ }
+ static bool classof(const SeparateOption *) { return true; }
+ };
+
+ class CommaJoinedOption : public Option {
+ public:
+ CommaJoinedOption(options::ID ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::CommaJoinedClass;
+ }
+ static bool classof(const CommaJoinedOption *) { return true; }
+ };
+
+ // FIXME: Fold MultiArgOption into SeparateOption?
+
+ /// MultiArgOption - An option which takes multiple arguments (these
+ /// are always separate arguments).
+ class MultiArgOption : public Option {
+ unsigned NumArgs;
+
+ public:
+ MultiArgOption(options::ID ID, const char *Name, const OptionGroup *Group,
+ const Option *Alias, unsigned NumArgs);
+
+ unsigned getNumArgs() const { return NumArgs; }
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::MultiArgClass;
+ }
+ static bool classof(const MultiArgOption *) { return true; }
+ };
+
+ /// JoinedOrSeparateOption - An option which either literally
+ /// prefixes its (non-empty) value, or is follwed by a value.
+ class JoinedOrSeparateOption : public Option {
+ public:
+ JoinedOrSeparateOption(options::ID ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedOrSeparateClass;
+ }
+ static bool classof(const JoinedOrSeparateOption *) { return true; }
+ };
+
+ /// JoinedAndSeparateOption - An option which literally prefixes its
+ /// value and is followed by another value.
+ class JoinedAndSeparateOption : public Option {
+ public:
+ JoinedAndSeparateOption(options::ID ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias);
+
+ virtual Arg *accept(const InputArgList &Args, unsigned &Index) const;
+
+ static bool classof(const Option *O) {
+ return O->getKind() == Option::JoinedAndSeparateClass;
+ }
+ static bool classof(const JoinedAndSeparateOption *) { return true; }
+ };
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
new file mode 100644
index 000000000000..c2981b934fc9
--- /dev/null
+++ b/include/clang/Driver/Options.def
@@ -0,0 +1,624 @@
+//===--- Options.def - Driver option info -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the driver option information. Users of this file
+// must define the OPTION macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPTION
+#error "Define OPTION prior to including this file!"
+#endif
+
+// OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM,
+// HELPTEXT, METAVARNAME)
+
+// The NAME value is the option name as a string.
+
+// The ID is the internal option id, which must be a valid
+// C++ identifier, and results in a clang::driver::options::OPT_XX
+// enum constant for XX.
+//
+// We want to unambiguously be able to refer to options from the
+// driver source code, for this reason the option name is mangled into
+// an id. This mangling isn't guaranteed to have an inverse, but for
+// practical purposes it does.
+//
+// The mangling scheme is to ignore the leading '-', and perform the
+// following substitutions:
+// _ => __
+// - => _
+// # => _HASH
+// , => _COMMA
+// = => _EQ
+// C++ => CXX
+
+// The KIND value is the option type, one of Group, Flag, Joined,
+// Separate, CommaJoined, JoinedOrSeparate, JoinedAndSeparate.
+
+// The GROUP value is the internal name of the option group, or
+// INVALID if the option is not part of a group.
+
+// The ALIAS value is the internal name of an aliased option, or
+// INVALID if the option is not an alias.
+
+// The PARAM value is a string containing option flags. Valid values:
+// d: The option is a "driver" option, and should not be forwarded to
+// gcc.
+//
+// i: The option should not render the name when rendered as an
+// input (i.e., the option is rendered as values).
+//
+// l: The option is a linker input.
+//
+// q: Don't report argument unused warnings for this option; this is
+// useful for options like -static or -dynamic which a user may
+// always end up passing, even if the platform defaults to (or
+// only supports) that option.
+//
+// u: The option is unsupported, and the driver will reject command
+// lines that use it.
+//
+// S: The option should be rendered separately, even if joined (only
+// sensible on joined options).
+//
+// J: The option should be rendered joined, even if separate (only
+// sensible on single value separate options).
+
+// The PARAM value is an arbitrary integer parameter; currently
+// this is only used for specifying the number of arguments for
+// Separate options.
+
+// The HELPTEXT value is the string to print for this option in
+// --help, or 0 if undocumented.
+
+// The METAVAR value is the name to use for this values arguments (if
+// any) in the help text. This must be defined if the help text is
+// specified and this option takes extra arguments.
+
+//
+
+// For now (pre-TableGen, that is) Options must be in order. The
+// ordering is *almost* lexicographic, with two exceptions. First,
+// '\0' comes at the end of the alphabet instead of the beginning
+// (thus options preceed any other options which prefix them). Second,
+// for options with the same name, the less permissive version should
+// come first; a Flag option should preceed a Joined option, for
+// example.
+
+/////////
+// Groups
+
+OPTION("<I group>", I_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<M group>", M_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<T group>", T_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<O group>", O_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<W group>", W_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<X group>", X_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<a group>", a_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<d group>", d_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<f group>", f_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<g group>", g_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<i group>", i_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<clang i group>", clang_i_Group, Group, i_Group, INVALID, "", 0, 0, 0)
+OPTION("<m group>", m_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<m x86 features group>", m_x86_Features_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<u group>", u_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+
+OPTION("<pedantic group>", pedantic_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+
+// Temporary groups for clang options which we know we don't support,
+// but don't want to verbosely warn the user about.
+OPTION("<clang ignored f group>", clang_ignored_f_Group, Group, f_Group,
+ INVALID, "", 0, 0, 0)
+OPTION("<clang ignored m group>", clang_ignored_m_Group, Group, m_Group,
+ INVALID, "", 0, 0, 0)
+
+//////////
+// Options
+
+OPTION("-###", _HASH_HASH_HASH, Flag, INVALID, INVALID, "d", 0,
+ "Print the commands to run for this compilation", 0)
+OPTION("--CLASSPATH=", _CLASSPATH_EQ, Joined, INVALID, fclasspath_EQ, "", 0, 0, 0)
+OPTION("--CLASSPATH", _CLASSPATH, Separate, INVALID, fclasspath_EQ, "J", 0, 0, 0)
+OPTION("--all-warnings", _all_warnings, Flag, INVALID, Wall, "", 0, 0, 0)
+OPTION("--analyze-auto", _analyze_auto, Flag, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("--analyzer-no-default-checks", _analyzer_no_default_checks, Flag, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("--analyzer-output", _analyzer_output, JoinedOrSeparate, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("--analyze", _analyze, Flag, INVALID, INVALID, "d", 0,
+ "Run the static analyzer", 0)
+OPTION("--ansi", _ansi, Flag, INVALID, ansi, "", 0, 0, 0)
+OPTION("--assemble", _assemble, Flag, INVALID, S, "", 0, 0, 0)
+OPTION("--assert=", _assert_EQ, Joined, INVALID, A, "S", 0, 0, 0)
+OPTION("--assert", _assert, Separate, INVALID, A, "", 0, 0, 0)
+OPTION("--bootclasspath=", _bootclasspath_EQ, Joined, INVALID, fbootclasspath_EQ, "", 0, 0, 0)
+OPTION("--bootclasspath", _bootclasspath, Separate, INVALID, fbootclasspath_EQ, "J", 0, 0, 0)
+OPTION("--classpath=", _classpath_EQ, Joined, INVALID, fclasspath_EQ, "", 0, 0, 0)
+OPTION("--classpath", _classpath, Separate, INVALID, fclasspath_EQ, "J", 0, 0, 0)
+OPTION("--combine", _combine, Flag, INVALID, combine, "u", 0, 0, 0)
+OPTION("--comments-in-macros", _comments_in_macros, Flag, INVALID, CC, "", 0, 0, 0)
+OPTION("--comments", _comments, Flag, INVALID, C, "", 0, 0, 0)
+OPTION("--compile", _compile, Flag, INVALID, c, "", 0, 0, 0)
+OPTION("--constant-cfstrings", _constant_cfstrings, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("--coverage", _coverage, Flag, INVALID, coverage, "", 0, 0, 0)
+OPTION("--debug=", _debug_EQ, Joined, INVALID, g_Flag, "u", 0, 0, 0)
+OPTION("--debug", _debug, Flag, INVALID, g_Flag, "u", 0, 0, 0)
+OPTION("--define-macro=", _define_macro_EQ, Joined, INVALID, D, "", 0, 0, 0)
+OPTION("--define-macro", _define_macro, Separate, INVALID, D, "J", 0, 0, 0)
+OPTION("--dependencies", _dependencies, Flag, INVALID, M, "", 0, 0, 0)
+OPTION("--encoding=", _encoding_EQ, Joined, INVALID, fencoding_EQ, "", 0, 0, 0)
+OPTION("--encoding", _encoding, Separate, INVALID, fencoding_EQ, "J", 0, 0, 0)
+OPTION("--entry", _entry, Flag, INVALID, e, "", 0, 0, 0)
+OPTION("--extdirs=", _extdirs_EQ, Joined, INVALID, fextdirs_EQ, "", 0, 0, 0)
+OPTION("--extdirs", _extdirs, Separate, INVALID, fextdirs_EQ, "J", 0, 0, 0)
+OPTION("--extra-warnings", _extra_warnings, Flag, INVALID, W_Joined, "", 0, 0, 0)
+OPTION("--for-linker=", _for_linker_EQ, Joined, INVALID, Xlinker, "liS", 0, 0, 0)
+OPTION("--for-linker", _for_linker, Separate, INVALID, Xlinker, "li", 0, 0, 0)
+OPTION("--force-link=", _force_link_EQ, Joined, INVALID, u, "S", 0, 0, 0)
+OPTION("--force-link", _force_link, Separate, INVALID, u, "", 0, 0, 0)
+OPTION("--help-hidden", _help_hidden, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("--help", _help, Flag, INVALID, INVALID, "", 0,
+ "Display available options", 0)
+OPTION("--imacros=", _imacros_EQ, Joined, INVALID, imacros, "S", 0, 0, 0)
+OPTION("--imacros", _imacros, Separate, INVALID, imacros, "", 0, 0, 0)
+OPTION("--include-barrier", _include_barrier, Flag, INVALID, I_, "", 0, 0, 0)
+OPTION("--include-directory-after=", _include_directory_after_EQ, Joined, INVALID, idirafter, "S", 0, 0, 0)
+OPTION("--include-directory-after", _include_directory_after, Separate, INVALID, idirafter, "", 0, 0, 0)
+OPTION("--include-directory=", _include_directory_EQ, Joined, INVALID, I, "", 0, 0, 0)
+OPTION("--include-directory", _include_directory, Separate, INVALID, I, "J", 0, 0, 0)
+OPTION("--include-prefix=", _include_prefix_EQ, Joined, INVALID, iprefix, "S", 0, 0, 0)
+OPTION("--include-prefix", _include_prefix, Separate, INVALID, iprefix, "", 0, 0, 0)
+OPTION("--include-with-prefix-after=", _include_with_prefix_after_EQ, Joined, INVALID, iwithprefix, "S", 0, 0, 0)
+OPTION("--include-with-prefix-after", _include_with_prefix_after, Separate, INVALID, iwithprefix, "", 0, 0, 0)
+OPTION("--include-with-prefix-before=", _include_with_prefix_before_EQ, Joined, INVALID, iwithprefixbefore, "S", 0, 0, 0)
+OPTION("--include-with-prefix-before", _include_with_prefix_before, Separate, INVALID, iwithprefixbefore, "", 0, 0, 0)
+OPTION("--include-with-prefix=", _include_with_prefix_EQ, Joined, INVALID, iwithprefix, "S", 0, 0, 0)
+OPTION("--include-with-prefix", _include_with_prefix, Separate, INVALID, iwithprefix, "", 0, 0, 0)
+OPTION("--include=", _include_EQ, Joined, INVALID, include, "S", 0, 0, 0)
+OPTION("--include", _include, Separate, INVALID, include, "", 0, 0, 0)
+OPTION("--language=", _language_EQ, Joined, INVALID, x, "S", 0, 0, 0)
+OPTION("--language", _language, Separate, INVALID, x, "", 0, 0, 0)
+OPTION("--library-directory=", _library_directory_EQ, Joined, INVALID, L, "S", 0, 0, 0)
+OPTION("--library-directory", _library_directory, Separate, INVALID, L, "", 0, 0, 0)
+OPTION("--machine-=", _machine__EQ, Joined, INVALID, m_Joined, "u", 0, 0, 0)
+OPTION("--machine-", _machine_, Joined, INVALID, m_Joined, "u", 0, 0, 0)
+OPTION("--machine=", _machine_EQ, Joined, INVALID, m_Joined, "", 0, 0, 0)
+OPTION("--machine", _machine, Separate, INVALID, m_Joined, "J", 0, 0, 0)
+OPTION("--no-integrated-cpp", _no_integrated_cpp, Flag, INVALID, no_integrated_cpp, "", 0, 0, 0)
+OPTION("--no-line-commands", _no_line_commands, Flag, INVALID, P, "", 0, 0, 0)
+OPTION("--no-standard-includes", _no_standard_includes, Flag, INVALID, nostdinc, "", 0, 0, 0)
+OPTION("--no-standard-libraries", _no_standard_libraries, Flag, INVALID, nostdlib, "", 0, 0, 0)
+OPTION("--no-warnings", _no_warnings, Flag, INVALID, w, "", 0, 0, 0)
+OPTION("--optimize=", _optimize_EQ, Joined, INVALID, O, "u", 0, 0, 0)
+OPTION("--optimize", _optimize, Flag, INVALID, O, "u", 0, 0, 0)
+OPTION("--output-class-directory=", _output_class_directory_EQ, Joined, INVALID, foutput_class_dir_EQ, "", 0, 0, 0)
+OPTION("--output-class-directory", _output_class_directory, Separate, INVALID, foutput_class_dir_EQ, "J", 0, 0, 0)
+OPTION("--output=", _output_EQ, Joined, INVALID, o, "S", 0, 0, 0)
+OPTION("--output", _output, Separate, INVALID, o, "", 0, 0, 0)
+OPTION("--param=", _param_EQ, Joined, INVALID, _param, "S", 0, 0, 0)
+OPTION("--param", _param, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("--pass-exit-codes", _pass_exit_codes, Flag, INVALID, pass_exit_codes, "", 0, 0, 0)
+OPTION("--pedantic-errors", _pedantic_errors, Flag, INVALID, pedantic_errors, "", 0, 0, 0)
+OPTION("--pedantic", _pedantic, Flag, INVALID, pedantic, "", 0, 0, 0)
+OPTION("--pipe", _pipe, Flag, INVALID, pipe, "d", 0, 0, 0)
+OPTION("--prefix=", _prefix_EQ, Joined, INVALID, B, "S", 0, 0, 0)
+OPTION("--prefix", _prefix, Separate, INVALID, B, "", 0, 0, 0)
+OPTION("--preprocess", _preprocess, Flag, INVALID, E, "", 0, 0, 0)
+OPTION("--print-file-name=", _print_file_name_EQ, Joined, INVALID, print_file_name_EQ, "", 0, 0, 0)
+OPTION("--print-file-name", _print_file_name, Separate, INVALID, print_file_name_EQ, "", 0, 0, 0)
+OPTION("--print-libgcc-file-name", _print_libgcc_file_name, Flag, INVALID, print_libgcc_file_name, "", 0, 0, 0)
+OPTION("--print-missing-file-dependencies", _print_missing_file_dependencies, Flag, INVALID, MG, "", 0, 0, 0)
+OPTION("--print-multi-directory", _print_multi_directory, Flag, INVALID, print_multi_directory, "", 0, 0, 0)
+OPTION("--print-multi-lib", _print_multi_lib, Flag, INVALID, print_multi_lib, "", 0, 0, 0)
+OPTION("--print-multi-os-directory", _print_multi_os_directory, Flag, INVALID, print_multi_os_directory, "", 0, 0, 0)
+OPTION("--print-prog-name=", _print_prog_name_EQ, Joined, INVALID, print_prog_name_EQ, "", 0, 0, 0)
+OPTION("--print-prog-name", _print_prog_name, Separate, INVALID, print_prog_name_EQ, "", 0, 0, 0)
+OPTION("--print-search-dirs", _print_search_dirs, Flag, INVALID, print_search_dirs, "", 0, 0, 0)
+OPTION("--profile-blocks", _profile_blocks, Flag, INVALID, a, "", 0, 0, 0)
+OPTION("--profile", _profile, Flag, INVALID, p, "", 0, 0, 0)
+OPTION("--resource=", _resource_EQ, Joined, INVALID, fcompile_resource_EQ, "", 0, 0, 0)
+OPTION("--resource", _resource, Separate, INVALID, fcompile_resource_EQ, "J", 0, 0, 0)
+OPTION("--save-temps", _save_temps, Flag, INVALID, save_temps, "", 0, 0, 0)
+OPTION("--shared", _shared, Flag, INVALID, shared, "", 0, 0, 0)
+OPTION("--specs=", _specs_EQ, Joined, INVALID, specs_EQ, "u", 0, 0, 0)
+OPTION("--specs", _specs, Separate, INVALID, specs_EQ, "uJ", 0, 0, 0)
+OPTION("--static", _static, Flag, INVALID, static, "", 0, 0, 0)
+OPTION("--std=", _std_EQ, Joined, INVALID, std_EQ, "", 0, 0, 0)
+OPTION("--std", _std, Separate, INVALID, std_EQ, "J", 0, 0, 0)
+OPTION("--sysroot=", _sysroot_EQ, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("--sysroot", _sysroot, Separate, INVALID, _sysroot_EQ, "J", 0, 0, 0)
+OPTION("--target-help", _target_help, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("--trace-includes", _trace_includes, Flag, INVALID, H, "", 0, 0, 0)
+OPTION("--traditional-cpp", _traditional_cpp, Flag, INVALID, traditional_cpp, "", 0, 0, 0)
+OPTION("--traditional", _traditional, Flag, INVALID, traditional, "", 0, 0, 0)
+OPTION("--trigraphs", _trigraphs, Flag, INVALID, trigraphs, "", 0, 0, 0)
+OPTION("--undefine-macro=", _undefine_macro_EQ, Joined, INVALID, U, "", 0, 0, 0)
+OPTION("--undefine-macro", _undefine_macro, Separate, INVALID, U, "J", 0, 0, 0)
+OPTION("--user-dependencies", _user_dependencies, Flag, INVALID, MM, "", 0, 0, 0)
+OPTION("--verbose", _verbose, Flag, INVALID, v, "", 0, 0, 0)
+OPTION("--version", _version, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("--warn-=", _warn__EQ, Joined, INVALID, W_Joined, "u", 0, 0, 0)
+OPTION("--warn-", _warn_, Joined, INVALID, W_Joined, "u", 0, 0, 0)
+OPTION("--write-dependencies", _write_dependencies, Flag, INVALID, MD, "", 0, 0, 0)
+OPTION("--write-user-dependencies", _write_user_dependencies, Flag, INVALID, MMD, "", 0, 0, 0)
+OPTION("--", _, Joined, INVALID, f, "u", 0, 0, 0)
+OPTION("-A", A, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-B", B, JoinedOrSeparate, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-CC", CC, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-C", C, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-D", D, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-E", E, Flag, INVALID, INVALID, "d", 0,
+ "Only run the preprocessor", 0)
+OPTION("-F", F, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-H", H, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-I-", I_, Flag, I_Group, INVALID, "", 0, 0, 0)
+OPTION("-I", I, JoinedOrSeparate, I_Group, INVALID, "", 0, 0, 0)
+OPTION("-L", L, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-MD", MD, Flag, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MF", MF, JoinedOrSeparate, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MG", MG, Flag, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MMD", MMD, Flag, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MM", MM, Flag, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MP", MP, Flag, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MQ", MQ, JoinedOrSeparate, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-MT", MT, JoinedOrSeparate, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-Mach", Mach, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-M", M, Flag, M_Group, INVALID, "", 0, 0, 0)
+OPTION("-O4", O4, Joined, O_Group, INVALID, "", 0, 0, 0)
+OPTION("-ObjC++", ObjCXX, Flag, INVALID, INVALID, "d", 0,
+ "Treat source input files as Objective-C++ inputs", 0)
+OPTION("-ObjC", ObjC, Flag, INVALID, INVALID, "d", 0,
+ "Treat source input files as Objective-C inputs", 0)
+OPTION("-O", O, Joined, O_Group, INVALID, "", 0, 0, 0)
+OPTION("-P", P, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-Qn", Qn, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-Qunused-arguments", Qunused_arguments, Flag, INVALID, INVALID, "d", 0,
+ "Don't emit warning for unused driver arguments", 0)
+OPTION("-Q", Q, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-R", R, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-S", S, Flag, INVALID, INVALID, "d", 0,
+ "Only run preprocess and compilation steps", 0)
+OPTION("-Tbss", Tbss, JoinedOrSeparate, T_Group, INVALID, "", 0, 0, 0)
+OPTION("-Tdata", Tdata, JoinedOrSeparate, T_Group, INVALID, "", 0, 0, 0)
+OPTION("-Ttext", Ttext, JoinedOrSeparate, T_Group, INVALID, "", 0, 0, 0)
+OPTION("-T", T, JoinedOrSeparate, T_Group, INVALID, "", 0, 0, 0)
+OPTION("-U", U, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-V", V, JoinedOrSeparate, INVALID, INVALID, "du", 0, 0, 0)
+OPTION("-Wa,", Wa_COMMA, CommaJoined, INVALID, INVALID, "", 0,
+ "Pass the comma separated arguments in <arg> to the assembler", "<arg>")
+OPTION("-Wall", Wall, Flag, W_Group, INVALID, "", 0, 0, 0)
+OPTION("-Wextra", Wextra, Flag, W_Group, INVALID, "", 0, 0, 0)
+OPTION("-Wl,", Wl_COMMA, CommaJoined, INVALID, INVALID, "li", 0,
+ "Pass the comma separated arguments in <arg> to the linker", "<arg>")
+OPTION("-Wno-nonportable-cfstrings", Wno_nonportable_cfstrings, Joined, W_Group, INVALID, "", 0, 0, 0)
+OPTION("-Wnonportable-cfstrings", Wnonportable_cfstrings, Joined, W_Group, INVALID, "", 0, 0, 0)
+OPTION("-Wp,", Wp_COMMA, CommaJoined, INVALID, INVALID, "", 0,
+ "Pass the comma separated arguments in <arg> to the preprocessor", "<arg>")
+OPTION("-W", W_Joined, Joined, W_Group, INVALID, "", 0, 0, 0)
+OPTION("-Xanalyzer", Xanalyzer, Separate, INVALID, INVALID, "", 0,
+ "Pass <arg> to the static analyzer", "<arg>")
+OPTION("-Xarch_", Xarch__, JoinedAndSeparate, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("-Xassembler", Xassembler, Separate, INVALID, INVALID, "", 0,
+ "Pass <arg> to the assembler", "<arg>")
+OPTION("-Xclang", Xclang, Separate, INVALID, INVALID, "", 0,
+ "Pass <arg> to the clang compiler", "<arg>")
+OPTION("-Xlinker", Xlinker, Separate, INVALID, INVALID, "li", 0,
+ "Pass <arg> to the linker", "<arg>")
+OPTION("-Xpreprocessor", Xpreprocessor, Separate, INVALID, INVALID, "", 0,
+ "Pass <arg> to the preprocessor", "<arg>")
+OPTION("-X", X_Flag, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-X", X_Joined, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-Z", Z_Flag, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-Z", Z_Joined, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-all_load", all__load, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-allowable_client", allowable__client, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-ansi", ansi, Flag, a_Group, INVALID, "", 0, 0, 0)
+OPTION("-arch", arch, Separate, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("-a", a, Joined, a_Group, INVALID, "", 0, 0, 0)
+OPTION("-bind_at_load", bind__at__load, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-bundle_loader", bundle__loader, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-bundle", bundle, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-b", b, JoinedOrSeparate, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-client_name", client__name, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-combine", combine, Flag, INVALID, INVALID, "du", 0, 0, 0)
+OPTION("-compatibility_version", compatibility__version, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-coverage", coverage, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-cpp-precomp", cpp_precomp, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-current_version", current__version, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-c", c, Flag, INVALID, INVALID, "d", 0,
+ "Only run preprocess, compile, and assemble steps", 0)
+OPTION("-dA", dA, Flag, d_Group, INVALID, "", 0, 0, 0)
+OPTION("-dD", dD, Flag, d_Group, INVALID, "", 0, 0, 0)
+OPTION("-dM", dM, Flag, d_Group, INVALID, "", 0, 0, 0)
+OPTION("-dead_strip", dead__strip, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dependency-file", dependency_file, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dumpmachine", dumpmachine, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-dumpspecs", dumpspecs, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-dumpversion", dumpversion, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dylib_file", dylib__file, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dylinker_install_name", dylinker__install__name, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dylinker", dylinker, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dynamiclib", dynamiclib, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-dynamic", dynamic, Flag, INVALID, INVALID, "q", 0, 0, 0)
+OPTION("-d", d_Flag, Flag, d_Group, INVALID, "", 0, 0, 0)
+OPTION("-d", d_Joined, Joined, d_Group, INVALID, "", 0, 0, 0)
+OPTION("-emit-llvm", emit_llvm, Flag, INVALID, INVALID, "", 0,
+ "Use the LLVM representation for assembler and object files", 0)
+OPTION("-exported_symbols_list", exported__symbols__list, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-e", e, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-fPIC", fPIC, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fPIE", fPIE, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fapple-kext", fapple_kext, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fasm-blocks", fasm_blocks, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fastcp", fastcp, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fastf", fastf, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fast", fast, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fasynchronous-unwind-tables", fasynchronous_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fblocks", fblocks, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fbootclasspath=", fbootclasspath_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fbuiltin", fbuiltin, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fclasspath=", fclasspath_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fcommon", fcommon, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fcompile-resource=", fcompile_resource_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fconstant-cfstrings", fconstant_cfstrings, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fcreate-profile", fcreate_profile, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fdebug-pass-arguments", fdebug_pass_arguments, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fdebug-pass-structure", fdebug_pass_structure, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fdiagnostics-fixit-info", fdiagnostics_fixit_info, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fdiagnostics-print-source-range-info", fdiagnostics_print_source_range_info, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fdiagnostics-show-option", fdiagnostics_show_option, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fdollars-in-identifiers", fdollars_in_identifiers, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-feliminate-unused-debug-symbols", feliminate_unused_debug_symbols, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-femit-all-decls", femit_all_decls, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fencoding=", fencoding_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fexceptions", fexceptions, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fextdirs=", fextdirs_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-ffreestanding", ffreestanding, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fgnu-runtime", fgnu_runtime, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fheinous-gnu-extensions", fheinous_gnu_extensions, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-filelist", filelist, Separate, INVALID, INVALID, "l", 0, 0, 0)
+OPTION("-findirect-virtual-calls", findirect_virtual_calls, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-finline-functions", finline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-finline", finline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fkeep-inline-functions", fkeep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-flat_namespace", flat__namespace, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-flax-vector-conversions", flax_vector_conversions, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-flimited-precision=", flimited_precision_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-flto", flto, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fmath-errno", fmath_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fmessage-length=", fmessage_length_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fms-extensions", fms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fmudflapth", fmudflapth, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fmudflap", fmudflap, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fnested-functions", fnested_functions, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fnext-runtime", fnext_runtime, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-asynchronous-unwind-tables", fno_asynchronous_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-blocks", fno_blocks, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-builtin", fno_builtin, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-caret-diagnostics", fno_caret_diagnostics, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-common", fno_common, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-constant-cfstrings", fno_constant_cfstrings, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-diagnostics-fixit-info", fno_diagnostics_fixit_info, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-diagnostics-show-option", fno_diagnostics_show_option, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-dollars-in-identifiers", fno_dollars_in_identifiers, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-eliminate-unused-debug-symbols", fno_eliminate_unused_debug_symbols, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-inline-functions", fno_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-show-column", fno_show_column, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-stack-protector", fno_stack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-strict-aliasing", fno_strict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-unit-at-a-time", fno_unit_at_a_time, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-unwind-tables", fno_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-working-directory", fno_working_directory, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fno-zero-initialized-in-bss", fno_zero_initialized_in_bss, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-atdefs", fobjc_atdefs, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-call-cxx-cdtors", fobjc_call_cxx_cdtors, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-gc-only", fobjc_gc_only, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-gc", fobjc_gc, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-new-property", fobjc_new_property, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-nonfragile-abi", fobjc_nonfragile_abi, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-sender-dependent-dispatch", fobjc_sender_dependent_dispatch, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-tight-layout", fobjc_tight_layout, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc", fobjc, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fomit-frame-pointer", fomit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fopenmp", fopenmp, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-force_cpusubtype_ALL", force__cpusubtype__ALL, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-force_flat_namespace", force__flat__namespace, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-foutput-class-dir=", foutput_class_dir_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fpascal-strings", fpascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fpch-preprocess", fpch_preprocess, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fpic", fpic, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fpie", fpie, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fprofile-arcs", fprofile_arcs, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fprofile-generate", fprofile_generate, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
+OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fstack-protector", fstack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fstrict-aliasing", fstrict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fsyntax-only", fsyntax_only, Flag, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("-ftemplate-depth-", ftemplate_depth_, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fterminated-vtables", fterminated_vtables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-ftime-report", ftime_report, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-ftraditional", ftraditional, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-ftrapv", ftrapv, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-funit-at-a-time", funit_at_a_time, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-funsigned-bitfields", funsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-funwind-tables", funwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fverbose-asm", fverbose_asm, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fvisibility=", fvisibility_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fwritable-strings", fwritable_strings, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fzero-initialized-in-bss", fzero_initialized_in_bss, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-f", f, Joined, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-g0", g0, Joined, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-g3", g3, Joined, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-gfull", gfull, Joined, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-gstabs", gstabs, Joined, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-gused", gused, Joined, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-g", g_Flag, Flag, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-g", g_Joined, Joined, g_Group, INVALID, "", 0, 0, 0)
+OPTION("-headerpad_max_install_names", headerpad__max__install__names, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-idirafter", idirafter, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-iframework", iframework, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-imacros", imacros, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-image_base", image__base, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-include", include, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-init", init, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-install_name", install__name, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-iprefix", iprefix, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-iquote", iquote, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-isysroot", isysroot, JoinedOrSeparate, i_Group, INVALID, "", 0, 0, 0)
+OPTION("-isystem", isystem, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-iwithprefixbefore", iwithprefixbefore, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-iwithprefix", iwithprefix, JoinedOrSeparate, clang_i_Group, INVALID, "", 0, 0, 0)
+OPTION("-iwithsysroot", iwithsysroot, JoinedOrSeparate, i_Group, INVALID, "", 0, 0, 0)
+OPTION("-i", i, Joined, i_Group, INVALID, "", 0, 0, 0)
+OPTION("-keep_private_externs", keep__private__externs, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-l", l, JoinedOrSeparate, INVALID, INVALID, "l", 0, 0, 0)
+OPTION("-m32", m32, Flag, m_Group, INVALID, "d", 0, 0, 0)
+OPTION("-m3dnowa", m3dnowa, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-m3dnow", m3dnow, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-m64", m64, Flag, m_Group, INVALID, "d", 0, 0, 0)
+OPTION("-march=", march_EQ, Joined, m_Group, INVALID, "d", 0, 0, 0)
+OPTION("-mconstant-cfstrings", mconstant_cfstrings, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mdynamic-no-pic", mdynamic_no_pic, Joined, m_Group, INVALID, "q", 0, 0, 0)
+OPTION("-mfix-and-continue", mfix_and_continue, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0)
+OPTION("-miphoneos-version-min=", miphoneos_version_min_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mkernel", mkernel, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mmacosx-version-min=", mmacosx_version_min_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mmmx", mmmx, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-3dnowa", mno_3dnowa, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-3dnow", mno_3dnow, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-constant-cfstrings", mno_constant_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-mmx", mno_mmx, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-pascal-strings", mno_pascal_strings, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-red-zone", mno_red_zone, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-soft-float", mno_soft_float, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse2", mno_sse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse3", mno_sse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse4a", mno_sse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse4", mno_sse4, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse", mno_sse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-ssse3", mno_ssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-warn-nonportable-cfstrings", mno_warn_nonportable_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mpascal-strings", mpascal_strings, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mred-zone", mred_zone, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-msoft-float", msoft_float, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse2", msse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse3", msse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse4a", msse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse4", msse4, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse", msse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mssse3", mssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mtune=", mtune_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-multi_module", multi__module, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-multiply_defined_unused", multiply__defined__unused, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-multiply_defined", multiply__defined, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-mwarn-nonportable-cfstrings", mwarn_nonportable_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-m", m_Separate, Separate, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-m", m_Joined, Joined, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-no-cpp-precomp", no_cpp_precomp, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-no-integrated-cpp", no_integrated_cpp, Flag, INVALID, INVALID, "d", 0, 0, 0)
+OPTION("-no_dead_strip_inits_and_terms", no__dead__strip__inits__and__terms, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nodefaultlibs", nodefaultlibs, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nofixprebinding", nofixprebinding, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nolibc", nolibc, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nomultidefs", nomultidefs, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-noprebind", noprebind, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-noseglinkedit", noseglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nostartfiles", nostartfiles, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nostdinc", nostdinc, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-nostdlib", nostdlib, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-object", object, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-o", o, JoinedOrSeparate, INVALID, INVALID, "di", 0,
+ "Write output to <file>", "<file>")
+OPTION("-pagezero_size", pagezero__size, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-pass-exit-codes", pass_exit_codes, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-pedantic-errors", pedantic_errors, Flag, pedantic_Group, INVALID, "", 0, 0, 0)
+OPTION("-pedantic", pedantic, Flag, pedantic_Group, INVALID, "", 0, 0, 0)
+OPTION("-pg", pg, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-pipe", pipe, Flag, INVALID, INVALID, "", 0,
+ "Use pipes between commands, when possible", 0)
+OPTION("-prebind_all_twolevel_modules", prebind__all__twolevel__modules, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-prebind", prebind, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-preload", preload, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-print-file-name=", print_file_name_EQ, Joined, INVALID, INVALID, "", 0,
+ "Print the full library path of <file>", "<file>")
+OPTION("-print-ivar-layout", print_ivar_layout, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-print-libgcc-file-name", print_libgcc_file_name, Flag, INVALID, INVALID, "", 0,
+ "Print the library path for \"libgcc.a\"", 0)
+OPTION("-print-multi-directory", print_multi_directory, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-print-multi-lib", print_multi_lib, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-print-multi-os-directory", print_multi_os_directory, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-print-prog-name=", print_prog_name_EQ, Joined, INVALID, INVALID, "", 0,
+ "Print the full program path of <name>", "<name>")
+OPTION("-print-search-dirs", print_search_dirs, Flag, INVALID, INVALID, "", 0,
+ "Print the paths used for finding libraries and programs", 0)
+OPTION("-private_bundle", private__bundle, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-pthreads", pthreads, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-pthread", pthread, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-p", p, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-read_only_relocs", read__only__relocs, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-remap", remap, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-r", r, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-save-temps", save_temps, Flag, INVALID, INVALID, "d", 0,
+ "Save intermediate compilation results", 0)
+OPTION("-sectalign", sectalign, MultiArg, INVALID, INVALID, "", 3, 0, 0)
+OPTION("-sectcreate", sectcreate, MultiArg, INVALID, INVALID, "", 3, 0, 0)
+OPTION("-sectobjectsymbols", sectobjectsymbols, MultiArg, INVALID, INVALID, "", 2, 0, 0)
+OPTION("-sectorder", sectorder, MultiArg, INVALID, INVALID, "", 3, 0, 0)
+OPTION("-seg1addr", seg1addr, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-seg_addr_table_filename", seg__addr__table__filename, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-seg_addr_table", seg__addr__table, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-segaddr", segaddr, MultiArg, INVALID, INVALID, "", 2, 0, 0)
+OPTION("-segcreate", segcreate, MultiArg, INVALID, INVALID, "", 3, 0, 0)
+OPTION("-seglinkedit", seglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-segprot", segprot, MultiArg, INVALID, INVALID, "", 3, 0, 0)
+OPTION("-segs_read_only_addr", segs__read__only__addr, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-segs_read_write_addr", segs__read__write__addr, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-segs_read_", segs__read__, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-shared-libgcc", shared_libgcc, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-shared", shared, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-single_module", single__module, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-specs=", specs_EQ, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-specs", specs, Separate, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-static-libgcc", static_libgcc, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-static", static, Flag, INVALID, INVALID, "q", 0, 0, 0)
+OPTION("-std-default=", std_default_EQ, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-std=", std_EQ, Joined, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-sub_library", sub__library, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-sub_umbrella", sub__umbrella, JoinedOrSeparate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-s", s, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-time", time, Flag, INVALID, INVALID, "", 0,
+ "Time individual commands", 0)
+OPTION("-traditional-cpp", traditional_cpp, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-traditional", traditional, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-trigraphs", trigraphs, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-twolevel_namespace_hints", twolevel__namespace__hints, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-twolevel_namespace", twolevel__namespace, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-t", t, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-umbrella", umbrella, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-undefined", undefined, JoinedOrSeparate, u_Group, INVALID, "", 0, 0, 0)
+OPTION("-undef", undef, Flag, u_Group, INVALID, "", 0, 0, 0)
+OPTION("-unexported_symbols_list", unexported__symbols__list, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-u", u, JoinedOrSeparate, u_Group, INVALID, "", 0, 0, 0)
+OPTION("-v", v, Flag, INVALID, INVALID, "", 0,
+ "Show commands to run and use verbose output", 0)
+OPTION("-weak-l", weak_l, Joined, INVALID, INVALID, "l", 0, 0, 0)
+OPTION("-weak_framework", weak__framework, Separate, INVALID, INVALID, "l", 0, 0, 0)
+OPTION("-weak_library", weak__library, Separate, INVALID, INVALID, "l", 0, 0, 0)
+OPTION("-weak_reference_mismatches", weak__reference__mismatches, Separate, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-whatsloaded", whatsloaded, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-whyload", whyload, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-w", w, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-x", x, JoinedOrSeparate, INVALID, INVALID, "d", 0,
+ "Treat subsequent input files as having type <language>", "<language>")
+OPTION("-y", y, Joined, INVALID, INVALID, "", 0, 0, 0)
diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h
new file mode 100644
index 000000000000..8b959d369c0e
--- /dev/null
+++ b/include/clang/Driver/Options.h
@@ -0,0 +1,90 @@
+//===--- Options.h - Option info & table ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_OPTIONS_H_
+#define CLANG_DRIVER_OPTIONS_H_
+
+namespace clang {
+namespace driver {
+namespace options {
+ enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+ OPT_INPUT, // Reserved ID for input option.
+ OPT_UNKNOWN, // Reserved ID for unknown option.
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "clang/Driver/Options.def"
+ LastOption
+#undef OPTION
+ };
+}
+
+ class Arg;
+ class InputArgList;
+ class Option;
+
+ /// OptTable - Provide access to the Option info table.
+ ///
+ /// The OptTable class provides a layer of indirection which allows
+ /// Option instance to be created lazily. In the common case, only a
+ /// few options will be needed at runtime; the OptTable class
+ /// maintains enough information to parse command lines without
+ /// instantiating Options, while letting other parts of the driver
+ /// still use Option instances where convient.
+ class OptTable {
+ /// The table of options which have been constructed, indexed by
+ /// option::ID - 1.
+ mutable Option **Options;
+
+ /// The index of the first option which can be parsed (i.e., is
+ /// not a special option like 'input' or 'unknown', and is not an
+ /// option group).
+ unsigned FirstSearchableOption;
+
+ Option *constructOption(options::ID id) const;
+
+ public:
+ OptTable();
+ ~OptTable();
+
+ unsigned getNumOptions() const;
+
+ const char *getOptionName(options::ID id) const;
+
+ /// getOption - Get the given \arg id's Option instance, lazily
+ /// creating it if necessary.
+ const Option *getOption(options::ID id) const;
+
+ /// getOptionKind - Get the kind of the given option.
+ unsigned getOptionKind(options::ID id) const;
+
+ /// getOptionHelpText - Get the help text to use to describe this
+ /// option.
+ const char *getOptionHelpText(options::ID id) const;
+
+ /// getOptionMetaVar - Get the meta-variable name to use when
+ /// describing this options values in the help text.
+ const char *getOptionMetaVar(options::ID id) const;
+
+ /// parseOneArg - Parse a single argument; returning the new
+ /// argument and updating Index.
+ ///
+ /// \param [in] [out] Index - The current parsing position in the
+ /// argument string list; on return this will be the index of the
+ /// next argument string to parse.
+ ///
+ /// \return - The parsed argument, or 0 if the argument is missing
+ /// values (in which case Index still points at the conceptual
+ /// next argument string to parse).
+ Arg *ParseOneArg(const InputArgList &Args, unsigned &Index) const;
+ };
+}
+}
+
+#endif
diff --git a/include/clang/Driver/Phases.h b/include/clang/Driver/Phases.h
new file mode 100644
index 000000000000..a0c42ea17362
--- /dev/null
+++ b/include/clang/Driver/Phases.h
@@ -0,0 +1,32 @@
+//===--- Phases.h - Transformations on Driver Types -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_PHASES_H_
+#define CLANG_DRIVER_PHASES_H_
+
+namespace clang {
+namespace driver {
+namespace phases {
+ /// ID - Ordered values for successive stages in the
+ /// compilation process which interact with user options.
+ enum ID {
+ Preprocess,
+ Precompile,
+ Compile,
+ Assemble,
+ Link
+ };
+
+ const char *getPhaseName(ID Id);
+
+} // end namespace phases
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h
new file mode 100644
index 000000000000..d8b37e9ead88
--- /dev/null
+++ b/include/clang/Driver/Tool.h
@@ -0,0 +1,69 @@
+//===--- Tool.h - Compilation Tools -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_TOOL_H_
+#define CLANG_DRIVER_TOOL_H_
+
+namespace llvm {
+ template<typename T, unsigned N> class SmallVector;
+}
+
+namespace clang {
+namespace driver {
+ class ArgList;
+ class Compilation;
+ class InputInfo;
+ class Job;
+ class JobAction;
+ class ToolChain;
+
+ typedef llvm::SmallVector<InputInfo, 4> InputInfoList;
+
+/// Tool - Information on a specific compilation tool.
+class Tool {
+ /// The tool name (for debugging).
+ const char *Name;
+
+ /// The tool chain this tool is a part of.
+ const ToolChain &TheToolChain;
+
+public:
+ Tool(const char *Name, const ToolChain &TC);
+
+public:
+ virtual ~Tool();
+
+ const char *getName() const { return Name; }
+
+ const ToolChain &getToolChain() const { return TheToolChain; }
+
+ virtual bool acceptsPipedInput() const = 0;
+ virtual bool canPipeOutput() const = 0;
+ virtual bool hasIntegratedCPP() const = 0;
+
+ /// ConstructJob - Construct jobs to perform the action \arg JA,
+ /// writing to \arg Output and with \arg Inputs.
+ ///
+ /// \param Dest - Where to put the resulting commands.
+ /// \param TCArgs - The argument list for this toolchain, with any
+ /// tool chain specific translations applied.
+ /// \param LinkingOutput - If this output will eventually feed the
+ /// linker, then this is the final output name of the linked image.
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const = 0;
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
new file mode 100644
index 000000000000..6196c130266d
--- /dev/null
+++ b/include/clang/Driver/ToolChain.h
@@ -0,0 +1,105 @@
+//===--- ToolChain.h - Collections of tools for one platform ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_TOOLCHAIN_H_
+#define CLANG_DRIVER_TOOLCHAIN_H_
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/System/Path.h"
+#include <string>
+
+namespace clang {
+namespace driver {
+ class Compilation;
+ class DerivedArgList;
+ class HostInfo;
+ class InputArgList;
+ class JobAction;
+ class Tool;
+
+/// ToolChain - Access to tools for a single platform.
+class ToolChain {
+public:
+ typedef llvm::SmallVector<std::string, 4> path_list;
+
+private:
+ const HostInfo &Host;
+ const llvm::Triple Triple;
+
+ /// The list of toolchain specific path prefixes to search for
+ /// files.
+ path_list FilePaths;
+
+ /// The list of toolchain specific path prefixes to search for
+ /// programs.
+ path_list ProgramPaths;
+
+protected:
+ ToolChain(const HostInfo &Host, const llvm::Triple &_Triple);
+
+public:
+ virtual ~ToolChain();
+
+ // Accessors
+
+ const HostInfo &getHost() const { return Host; }
+ std::string getArchName() const { return Triple.getArchName(); }
+ std::string getPlatform() const { return Triple.getVendorName(); }
+ std::string getOS() const { return Triple.getOSName(); }
+
+ std::string getTripleString() const {
+ return Triple.getTriple();
+ }
+
+ path_list &getFilePaths() { return FilePaths; }
+ const path_list &getFilePaths() const { return FilePaths; }
+
+ path_list &getProgramPaths() { return ProgramPaths; }
+ const path_list &getProgramPaths() const { return ProgramPaths; }
+
+ // Tool access.
+
+ /// TranslateArgs - Create a new derived argument list for any
+ /// argument translations this ToolChain may wish to perform.
+ virtual DerivedArgList *TranslateArgs(InputArgList &Args) const = 0;
+
+ /// SelectTool - Choose a tool to use to handle the action \arg JA.
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const = 0;
+
+ // Helper methods
+
+ llvm::sys::Path GetFilePath(const Compilation &C, const char *Name) const;
+ llvm::sys::Path GetProgramPath(const Compilation &C, const char *Name,
+ bool WantFile = false) const;
+
+ // Platform defaults information
+
+ /// IsMathErrnoDefault - Does this tool chain set -fmath-errno by
+ /// default.
+ virtual bool IsMathErrnoDefault() const = 0;
+
+ /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
+ /// by default.
+ virtual bool IsUnwindTablesDefault() const = 0;
+
+ /// GetDefaultRelocationModel - Return the LLVM name of the default
+ /// relocation model for this tool chain.
+ virtual const char *GetDefaultRelocationModel() const = 0;
+
+ /// GetForcedPicModel - Return the LLVM name of the forced PIC model
+ /// for this tool chain, or 0 if this tool chain does not force a
+ /// particular PIC mode.
+ virtual const char *GetForcedPicModel() const = 0;
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
new file mode 100644
index 000000000000..8d24e5013fb0
--- /dev/null
+++ b/include/clang/Driver/Types.def
@@ -0,0 +1,78 @@
+//===--- Types.def - Driver Type info ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the driver type information. Users of this file
+// must define the TYPE macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPE
+#error "Define TYPE prior to including this file!"
+#endif
+
+// TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS)
+
+// The first value is the type name as a string; for types which can
+// be user specified this should be the equivalent -x option.
+
+// The second value is the type id, which will result in a
+// clang::driver::types::TY_XX enum constant.
+
+// The third value is that id of the type for preprocessed inputs of
+// this type, or INVALID if this type is not preprocessed.
+
+// The fourth value is the suffix to use when creating temporary files
+// of this type, or null if unspecified.
+
+// The fifth value is a string containt option flags. Valid values:
+// a - The type should only be assembled.
+// p - The type should only be precompiled.
+// u - The type can be user specified (with -x).
+// A - The type's temporary suffix should be appended when generating
+// outputs of this type.
+
+
+// C family source language (with and without preprocessing).
+TYPE("cpp-output", PP_C, INVALID, "i", "u")
+TYPE("c", C, PP_C, 0, "u")
+TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
+TYPE("objective-c", ObjC, PP_ObjC, 0, "u")
+TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
+TYPE("c++", CXX, PP_CXX, 0, "u")
+TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u")
+TYPE("objective-c++", ObjCXX, PP_ObjCXX, 0, "u")
+
+// C family input files to precompile.
+TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p")
+TYPE("c-header", CHeader, PP_CHeader, 0, "pu")
+TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p")
+TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, 0, "pu")
+TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
+TYPE("c++-header", CXXHeader, PP_CXXHeader, 0, "pu")
+TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
+TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, 0, "pu")
+
+// Other languages.
+TYPE("ada", Ada, INVALID, 0, "u")
+TYPE("assembler", PP_Asm, INVALID, "s", "au")
+TYPE("assembler-with-cpp", Asm, PP_Asm, 0, "au")
+TYPE("f95", PP_Fortran, INVALID, 0, "u")
+TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u")
+TYPE("java", Java, INVALID, 0, "u")
+
+// Misc.
+TYPE("llvm-asm", LLVMAsm, INVALID, "s", "")
+TYPE("llvm-bc", LLVMBC, INVALID, "o", "")
+TYPE("plist", Plist, INVALID, "plist", "")
+TYPE("precompiled-header", PCH, INVALID, "gch", "A")
+TYPE("object", Object, INVALID, "o", "")
+TYPE("treelang", Treelang, INVALID, 0, "u")
+TYPE("image", Image, INVALID, "out", "")
+TYPE("dependencies", Dependencies, INVALID, "d", "")
+TYPE("none", Nothing, INVALID, 0, "u")
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
new file mode 100644
index 000000000000..92520a77b33b
--- /dev/null
+++ b/include/clang/Driver/Types.h
@@ -0,0 +1,85 @@
+//===--- Types.h - Input & Temporary Driver Types ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_TYPES_H_
+#define CLANG_DRIVER_TYPES_H_
+
+#include "clang/Driver/Phases.h"
+
+namespace clang {
+namespace driver {
+namespace types {
+ enum ID {
+ TY_INVALID,
+#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) TY_##ID,
+#include "clang/Driver/Types.def"
+#undef TYPE
+ TY_LAST
+ };
+
+ /// getTypeName - Return the name of the type for \arg Id.
+ const char *getTypeName(ID Id);
+
+ /// getPreprocessedType - Get the ID of the type for this input when
+ /// it has been preprocessed, or INVALID if this input is not
+ /// preprocessed.
+ ID getPreprocessedType(ID Id);
+
+ /// getTypeTempSuffix - Return the suffix to use when creating a
+ /// temp file of this type, or null if unspecified.
+ const char *getTypeTempSuffix(ID Id);
+
+ /// onlyAssembleType - Should this type only be assembled.
+ bool onlyAssembleType(ID Id);
+
+ /// onlyPrecompileType - Should this type only be precompiled.
+ bool onlyPrecompileType(ID Id);
+
+ /// canTypeBeUserSpecified - Can this type be specified on the
+ /// command line (by the type name); this is used when forwarding
+ /// commands to gcc.
+ bool canTypeBeUserSpecified(ID Id);
+
+ /// appendSuffixForType - When generating outputs of this type,
+ /// should the suffix be appended (instead of replacing the existing
+ /// suffix).
+ bool appendSuffixForType(ID Id);
+
+ /// canLipoType - Is this type acceptable as the output of a
+ /// universal build (currently, just the Nothing, Image, and Object
+ /// types).
+ bool canLipoType(ID Id);
+
+ /// isAcceptedByClang - Can clang handle this input type.
+ bool isAcceptedByClang(ID Id);
+
+ /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
+ bool isCXX(ID Id);
+
+ /// lookupTypeForExtension - Lookup the type to use for the file
+ /// extension \arg Ext.
+ ID lookupTypeForExtension(const char *Ext);
+
+ /// lookupTypeForTypSpecifier - Lookup the type to use for a user
+ /// specified type name.
+ ID lookupTypeForTypeSpecifier(const char *Name);
+
+ /// getNumCompilationPhases - Return the complete number of phases
+ /// to be done for this type.
+ unsigned getNumCompilationPhases(ID Id);
+
+ /// getCompilationPhase - Return the \args N th compilation phase to
+ /// be done for this type.
+ phases::ID getCompilationPhase(ID Id, unsigned N);
+
+} // end namespace types
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Util.h b/include/clang/Driver/Util.h
new file mode 100644
index 000000000000..52f268d182a8
--- /dev/null
+++ b/include/clang/Driver/Util.h
@@ -0,0 +1,30 @@
+//===--- Util.h - Common Driver Utilities -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_UTIL_H_
+#define CLANG_DRIVER_UTIL_H_
+
+namespace llvm {
+ template<typename T, unsigned N> class SmallVector;
+}
+
+namespace clang {
+namespace driver {
+ class Action;
+
+ /// ArgStringList - Type used for constructing argv lists for subprocesses.
+ typedef llvm::SmallVector<const char*, 16> ArgStringList;
+
+ /// ActionList - Type used for lists of actions.
+ typedef llvm::SmallVector<Action*, 3> ActionList;
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
new file mode 100644
index 000000000000..04365d7c78d8
--- /dev/null
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -0,0 +1,107 @@
+//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// AST Consumers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DRIVER_ASTCONSUMERS_H
+#define DRIVER_ASTCONSUMERS_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <iosfwd>
+
+namespace llvm {
+ class Module;
+ namespace sys { class Path; }
+}
+namespace clang {
+
+class ASTConsumer;
+class Diagnostic;
+class FileManager;
+class Preprocessor;
+class PreprocessorFactory;
+struct CompileOptions;
+class LangOptions;
+
+// AST pretty-printer: prints out the AST in a format that is close to the
+// original C code. The output is intended to be in a format such that
+// clang could re-parse the output back into the same AST, but the
+// implementation is still incomplete.
+ASTConsumer *CreateASTPrinter(llvm::raw_ostream* OS);
+
+// AST XML-printer: prints out the AST in a XML format
+// The output is intended to be in a format such that
+// clang or any other tool could re-parse the output back into the same AST,
+// but the implementation is still incomplete.
+ASTConsumer *CreateASTPrinterXML(llvm::raw_ostream* OS);
+
+// AST dumper: dumps the raw AST in human-readable form to stderr; this is
+// intended for debugging.
+ASTConsumer *CreateASTDumper();
+
+// Graphical AST viewer: for each function definition, creates a graph of
+// the AST and displays it with the graph viewer "dotty". Also outputs
+// function declarations to stderr.
+ASTConsumer *CreateASTViewer();
+
+// DeclContext printer: prints out the DeclContext tree in human-readable form
+// to stderr; this is intended for debugging.
+ASTConsumer *CreateDeclContextPrinter();
+
+// ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code.
+// This is considered experimental, and only works with Apple's ObjC runtime.
+ASTConsumer *CreateObjCRewriter(const std::string& InFile,
+ llvm::raw_ostream* OS,
+ Diagnostic &Diags,
+ const LangOptions &LOpts,
+ bool SilenceRewriteMacroWarning);
+
+// LLVM code generator: uses the code generation backend to generate LLVM
+// assembly. This runs optimizations depending on the CompileOptions
+// parameter. The output depends on the Action parameter.
+enum BackendAction {
+ Backend_EmitAssembly, // Emit native assembly
+ Backend_EmitBC, // Emit LLVM bitcode file
+ Backend_EmitLL, // Emit human-readable LLVM assembly
+ Backend_EmitNothing // Don't emit anything (benchmarking mode)
+};
+ASTConsumer *CreateBackendConsumer(BackendAction Action,
+ Diagnostic &Diags,
+ const LangOptions &Features,
+ const CompileOptions &CompileOpts,
+ const std::string &ModuleID,
+ llvm::raw_ostream *OS);
+
+// HTML printer: uses the rewriter to convert source code to HTML with
+// syntax highlighting suitable for viewing in a web-browser.
+ASTConsumer* CreateHTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D,
+ Preprocessor *PP, PreprocessorFactory *PPF);
+
+// PCH generator: generates a precompiled header file; this file can be
+// used later with the PCHReader (clang-cc option -include-pch)
+// to speed up compile times.
+ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
+ llvm::raw_ostream *OS);
+
+// Block rewriter: rewrites code using the Apple blocks extension to pure
+// C code. Output is always sent to stdout.
+ASTConsumer *CreateBlockRewriter(const std::string &InFile,
+ Diagnostic &Diags,
+ const LangOptions &LangOpts);
+
+// Inheritance viewer: for C++ code, creates a graph of the inheritance
+// tree for the given class and displays it with "dotty".
+ASTConsumer *CreateInheritanceViewer(const std::string& clsname);
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def
new file mode 100644
index 000000000000..3492d09c10aa
--- /dev/null
+++ b/include/clang/Frontend/Analyses.def
@@ -0,0 +1,77 @@
+//===-- Analyses.def - Metadata about Static Analyses -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the set of static analyses used by AnalysisConsumer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ANALYSIS
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
+#endif
+
+ANALYSIS(CFGDump, "cfg-dump",
+ "Display Control-Flow Graphs", Code)
+
+ANALYSIS(CFGView, "cfg-view",
+ "View Control-Flow Graphs using GraphViz", Code)
+
+ANALYSIS(DisplayLiveVariables, "dump-live-variables",
+ "Print results of live variable analysis", Code)
+
+ANALYSIS(WarnDeadStores, "warn-dead-stores",
+ "Warn about stores to dead variables", Code)
+
+ANALYSIS(WarnUninitVals, "warn-uninit-values",
+ "Warn about uses of uninitialized variables", Code)
+
+ANALYSIS(WarnObjCMethSigs, "warn-objc-methodsigs",
+ "Warn about Objective-C method signatures with type incompatibilities",
+ ObjCImplementation)
+
+ANALYSIS(WarnObjCDealloc, "warn-objc-missing-dealloc",
+ "Warn about Objective-C classes that lack a correct implementation of -dealloc",
+ ObjCImplementation)
+
+ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars",
+ "Warn about private ivars that are never used", ObjCImplementation)
+
+ANALYSIS(CheckerSimple, "checker-simple",
+ "Perform simple path-sensitive checks.", Code)
+
+ANALYSIS(CheckerCFRef, "checker-cfref",
+ "Run the [Core] Foundation reference count checker", Code)
+
+
+#ifndef ANALYSIS_STORE
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
+#endif
+
+ANALYSIS_STORE(BasicStore, "basic", "Use basic analyzer store", CreateBasicStoreManager)
+ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager)
+
+#ifndef ANALYSIS_CONSTRAINTS
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)
+#endif
+
+ANALYSIS_CONSTRAINTS(BasicConstraints, "basic", "Use basic constraint tracking", CreateBasicConstraintManager)
+ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
+
+#ifndef ANALYSIS_DIAGNOSTICS
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
+#endif
+
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", CreateHTMLDiagnosticClient, false)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", CreatePlistDiagnosticClient, true)
+
+#undef ANALYSIS
+#undef ANALYSIS_STORE
+#undef ANALYSIS_CONSTRAINTS
+#undef ANALYSIS_DIAGNOSTICS
+#undef ANALYSIS_STORE
+
diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h
new file mode 100644
index 000000000000..0e4b09bd2a12
--- /dev/null
+++ b/include/clang/Frontend/AnalysisConsumer.h
@@ -0,0 +1,78 @@
+//===--- AnalysisConsumer.h - Front-end hooks for the analysis engine------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains the functions necessary for a front-end to run various
+// analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+namespace clang {
+class ASTConsumer;
+class Diagnostic;
+class Preprocessor;
+class PreprocessorFactory;
+class LangOptions;
+
+/// Analysis - Set of available source code analyses.
+enum Analyses {
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME,
+#include "clang/Frontend/Analyses.def"
+NumAnalyses
+};
+
+/// AnalysisStores - Set of available analysis store models.
+enum AnalysisStores {
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
+#include "clang/Frontend/Analyses.def"
+NumStores
+};
+
+/// AnalysisConstraints - Set of available constraint models.
+enum AnalysisConstraints {
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
+#include "clang/Frontend/Analyses.def"
+NumConstraints
+};
+
+/// AnalysisDiagClients - Set of available diagnostic clients for rendering
+/// analysis results.
+enum AnalysisDiagClients {
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME,
+#include "clang/Frontend/Analyses.def"
+NUM_ANALYSIS_DIAG_CLIENTS
+};
+
+struct AnalyzerOptions {
+ std::vector<Analyses> AnalysisList;
+ AnalysisStores AnalysisStoreOpt;
+ AnalysisConstraints AnalysisConstraintsOpt;
+ AnalysisDiagClients AnalysisDiagOpt;
+ bool VisualizeEGDot;
+ bool VisualizeEGUbi;
+ bool AnalyzeAll;
+ bool AnalyzerDisplayProgress;
+ bool PurgeDead;
+ bool EagerlyAssume;
+ std::string AnalyzeSpecificFunction;
+ bool TrimGraph;
+};
+
+/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
+/// analysis passes. (The set of analyses run is controlled by command-line
+/// options.)
+ASTConsumer* CreateAnalysisConsumer(Diagnostic &diags, Preprocessor *pp,
+ PreprocessorFactory *ppf,
+ const LangOptions &lopts,
+ const std::string &output,
+ const AnalyzerOptions& Opts);
+
+}
diff --git a/include/clang/Frontend/CompileOptions.h b/include/clang/Frontend/CompileOptions.h
new file mode 100644
index 000000000000..1af5e48ea119
--- /dev/null
+++ b/include/clang/Frontend/CompileOptions.h
@@ -0,0 +1,62 @@
+//===--- CompileOptions.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CompileOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_COMPILEOPTIONS_H
+#define LLVM_CLANG_FRONTEND_COMPILEOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// CompileOptions - Track various options which control how the code
+/// is optimized and passed to the backend.
+class CompileOptions {
+public:
+ unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
+ unsigned OptimizeSize : 1; /// If -Os is specified.
+ unsigned DebugInfo : 1; /// Should generate deubg info (-g).
+ unsigned UnitAtATime : 1; /// Unused. For mirroring GCC
+ /// optimization selection.
+ unsigned InlineFunctions : 1; /// Should functions be inlined?
+ unsigned SimplifyLibCalls : 1; /// Should standard library calls be
+ /// treated specially.
+ unsigned UnrollLoops : 1; /// Control whether loops are unrolled.
+ unsigned VerifyModule : 1; /// Control whether the module
+ /// should be run through the LLVM Verifier.
+ unsigned TimePasses : 1; /// Set when -ftime-report is enabled.
+ unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
+
+ /// CPU - An optional CPU to target.
+ std::string CPU;
+
+ /// Features - A list of subtarget features to pass to the code
+ /// generator.
+ std::vector<std::string> Features;
+
+public:
+ CompileOptions() {
+ OptimizationLevel = 0;
+ OptimizeSize = 0;
+ DebugInfo = 0;
+ UnitAtATime = 1;
+ InlineFunctions = SimplifyLibCalls = UnrollLoops = 0;
+ VerifyModule = 1;
+ TimePasses = 0;
+ NoCommon = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h
new file mode 100644
index 000000000000..99db717190dd
--- /dev/null
+++ b/include/clang/Frontend/DocumentXML.h
@@ -0,0 +1,128 @@
+//===--- DocumentXML.h - XML document for ASTs ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DOCUMENTXML_H
+#define LLVM_CLANG_FRONTEND_DOCUMENTXML_H
+
+#include <string>
+#include <map>
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class DeclContext;
+class Decl;
+class NamedDecl;
+class FunctionDecl;
+class ASTContext;
+
+//---------------------------------------------------------
+namespace XML
+{
+ // id maps:
+ template<class T>
+ struct IdMap : llvm::DenseMap<T, unsigned> {};
+
+ template<>
+ struct IdMap<QualType> : std::map<QualType, unsigned, QualTypeOrdering> {};
+
+ template<>
+ struct IdMap<std::string> : std::map<std::string, unsigned> {};
+}
+
+//---------------------------------------------------------
+class DocumentXML
+{
+public:
+ DocumentXML(const std::string& rootName, llvm::raw_ostream& out);
+ ~DocumentXML();
+
+ void initialize(ASTContext &Context);
+ void PrintDecl(Decl *D);
+ void PrintStmt(const Stmt *S); // defined in StmtXML.cpp
+
+ void finalize();
+
+
+ DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this
+ DocumentXML& toParent(); // returns *this
+
+ template<class T>
+ void addAttribute(const char* pName, const T& value);
+
+ void addTypeAttribute(const QualType& pType);
+ void addRefAttribute(const NamedDecl* D);
+
+ enum tContextUsage { CONTEXT_AS_CONTEXT, CONTEXT_AS_ID };
+ void addContextAttribute(const DeclContext *DC, tContextUsage usage = CONTEXT_AS_CONTEXT);
+ void addSourceFileAttribute(const std::string& fileName);
+
+ PresumedLoc addLocation(const SourceLocation& Loc);
+ void addLocationRange(const SourceRange& R);
+
+ static std::string escapeString(const char* pStr, std::string::size_type len);
+
+private:
+ DocumentXML(const DocumentXML&); // not defined
+ DocumentXML& operator=(const DocumentXML&); // not defined
+
+ struct NodeXML;
+
+ NodeXML* Root;
+ NodeXML* CurrentNode; // always after Root
+ llvm::raw_ostream& Out;
+ ASTContext *Ctx;
+ int CurrentIndent;
+ bool HasCurrentNodeSubNodes;
+
+
+ XML::IdMap<QualType> Types;
+ XML::IdMap<const DeclContext*> Contexts;
+ XML::IdMap<const Type*> BasicTypes;
+ XML::IdMap<std::string> SourceFiles;
+ XML::IdMap<const NamedDecl*> Decls;
+
+ void addContextsRecursively(const DeclContext *DC);
+ void addBasicTypeRecursively(const Type* pType);
+ void addTypeRecursively(const QualType& pType);
+
+ void PrintFunctionDecl(FunctionDecl *FD);
+ void addDeclIdAttribute(const NamedDecl* D);
+ void addTypeIdAttribute(const Type* pType);
+ void Indent();
+};
+
+//--------------------------------------------------------- inlines
+
+inline void DocumentXML::initialize(ASTContext &Context)
+{
+ Ctx = &Context;
+}
+
+//---------------------------------------------------------
+template<class T>
+inline void DocumentXML::addAttribute(const char* pName, const T& value)
+{
+ Out << ' ' << pName << "=\"" << value << "\"";
+}
+
+//---------------------------------------------------------
+
+} //namespace clang
+
+#endif //LLVM_CLANG_DOCUMENTXML_H
diff --git a/include/clang/Frontend/FixItRewriter.h b/include/clang/Frontend/FixItRewriter.h
new file mode 100644
index 000000000000..7fcd682bf66c
--- /dev/null
+++ b/include/clang/Frontend/FixItRewriter.h
@@ -0,0 +1,95 @@
+//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a diagnostic client adaptor that performs rewrites as
+// suggested by code modification hints attached to diagnostics. It
+// then forwards any diagnostics to the adapted diagnostic client.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H
+#define LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class SourceManager;
+class FileEntry;
+
+/// \brief Stores a source location in the form that it shows up on
+/// the Clang command line, e.g., file:line:column.
+///
+/// FIXME: Would prefer to use real SourceLocations, but I don't see a
+/// good way to resolve them during parsing.
+struct RequestedSourceLocation {
+ const FileEntry *File;
+ unsigned Line;
+ unsigned Column;
+};
+
+class FixItRewriter : public DiagnosticClient {
+ /// \brief The diagnostics machinery.
+ Diagnostic &Diags;
+
+ /// \brief The rewriter used to perform the various code
+ /// modifications.
+ Rewriter Rewrite;
+
+ /// \brief The diagnostic client that performs the actual formatting
+ /// of error messages.
+ DiagnosticClient *Client;
+
+ /// \brief The number of rewriter failures.
+ unsigned NumFailures;
+
+ /// \brief Locations at which we should perform fix-its.
+ ///
+ /// When empty, perform fix-it modifications everywhere.
+ llvm::SmallVector<RequestedSourceLocation, 4> FixItLocations;
+
+public:
+ /// \brief Initialize a new fix-it rewriter.
+ FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
+ const LangOptions &LangOpts);
+
+ /// \brief Destroy the fix-it rewriter.
+ ~FixItRewriter();
+
+ /// \brief Add a location where fix-it modifications should be
+ /// performed.
+ void addFixItLocation(RequestedSourceLocation Loc) {
+ FixItLocations.push_back(Loc);
+ }
+
+ /// \brief Write the modified source file.
+ ///
+ /// \returns true if there was an error, false otherwise.
+ bool WriteFixedFile(const std::string &InFileName,
+ const std::string &OutFileName = std::string());
+
+ /// IncludeInDiagnosticCounts - This method (whose default implementation
+ /// returns true) indicates whether the diagnostics handled by this
+ /// DiagnosticClient should be included in the number of diagnostics
+ /// reported by Diagnostic.
+ virtual bool IncludeInDiagnosticCounts() const;
+
+ /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+ /// capturing it to a log as needed.
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+
+ /// \brief Emit a diagnostic via the adapted diagnostic client.
+ void Diag(FullSourceLoc Loc, unsigned DiagID);
+};
+
+}
+
+#endif // LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H
diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h
new file mode 100644
index 000000000000..02432ca3a55c
--- /dev/null
+++ b/include/clang/Frontend/FrontendDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticFrontend.h - Diagnostics for frontend --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTENDDIAGNOSTIC_H
+#define LLVM_CLANG_FRONTENDDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define FRONTENDSTART
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_FRONTEND_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/InitHeaderSearch.h b/include/clang/Frontend/InitHeaderSearch.h
new file mode 100644
index 000000000000..51516661c99e
--- /dev/null
+++ b/include/clang/Frontend/InitHeaderSearch.h
@@ -0,0 +1,74 @@
+//===--- InitHeaderSearch.h - Initialize header search paths ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the InitHeaderSearch class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_INIT_HEADER_SEARCH_H_
+#define LLVM_CLANG_FRONTEND_INIT_HEADER_SEARCH_H_
+
+#include <string>
+#include <vector>
+
+#include "clang/Lex/DirectoryLookup.h"
+
+namespace clang {
+
+class HeaderSearch;
+class LangOptions;
+
+/// InitHeaderSearch - This class makes it easier to set the search paths of
+/// a HeaderSearch object. InitHeaderSearch stores several search path lists
+/// internally, which can be sent to a HeaderSearch object in one swoop.
+class InitHeaderSearch {
+ std::vector<DirectoryLookup> IncludeGroup[4];
+ HeaderSearch& Headers;
+ bool Verbose;
+ std::string isysroot;
+
+public:
+ /// InitHeaderSearch::IncludeDirGroup - Identifies the several search path
+ /// lists stored internally.
+ enum IncludeDirGroup {
+ Quoted = 0, //< `#include ""` paths. Thing `gcc -iquote`.
+ Angled, //< Paths for both `#include ""` and `#include <>`. (`-I`)
+ System, //< Like Angled, but marks system directories.
+ After //< Like System, but searched after the system directories.
+ };
+
+ InitHeaderSearch(HeaderSearch &HS,
+ bool verbose = false, const std::string &iSysroot = "")
+ : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
+
+ /// AddPath - Add the specified path to the specified group list.
+ void AddPath(const std::string &Path, IncludeDirGroup Group,
+ bool isCXXAware, bool isUserSupplied,
+ bool isFramework, bool IgnoreSysRoot = false);
+
+ /// AddEnvVarPaths - Add a list of paths from an environment variable to a
+ /// header search list.
+ void AddEnvVarPaths(const char *Name);
+
+ /// AddDefaultEnvVarPaths - Adds list of paths from default environment
+ /// variables such as CPATH.
+ void AddDefaultEnvVarPaths(const LangOptions &Lang);
+
+ /// AddDefaultSystemIncludePaths - Adds the default system include paths so
+ /// that e.g. stdio.h is found.
+ void AddDefaultSystemIncludePaths(const LangOptions &Lang);
+
+ /// Realize - Merges all search path lists into one list and send it to
+ /// HeaderSearch.
+ void Realize();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/InitPreprocessor.h b/include/clang/Frontend/InitPreprocessor.h
new file mode 100644
index 000000000000..eb03602dc57b
--- /dev/null
+++ b/include/clang/Frontend/InitPreprocessor.h
@@ -0,0 +1,70 @@
+//===--- InitPreprocessor.h - InitializePreprocessor function. --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the clang::InitializePreprocessor function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_INIT_PREPROCESSOR_H_
+#define LLVM_CLANG_FRONTEND_INIT_PREPROCESSOR_H_
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class LangOptions;
+
+/// PreprocessorInitOptions - This class is used for passing the various
+/// options used in preprocessor initialization to InitializePreprocessor().
+class PreprocessorInitOptions {
+ std::vector<std::pair<std::string, bool/*isUndef*/> > Macros;
+ std::vector<std::pair<std::string, bool/*isPTH*/> > Includes;
+ std::vector<std::string> MacroIncludes;
+
+public:
+
+ void addMacroDef(const std::string &Name) {
+ Macros.push_back(std::make_pair(Name, false));
+ }
+ void addMacroUndef(const std::string &Name) {
+ Macros.push_back(std::make_pair(Name, true));
+ }
+ void addInclude(const std::string &Name, bool isPTH = false) {
+ Includes.push_back(std::make_pair(Name, isPTH));
+ }
+ void addMacroInclude(const std::string &Name) {
+ MacroIncludes.push_back(Name);
+ }
+
+ typedef std::vector<std::pair<std::string,
+ bool> >::const_iterator macro_iterator;
+ macro_iterator macro_begin() const { return Macros.begin(); }
+ macro_iterator macro_end() const { return Macros.end(); }
+
+ typedef std::vector<std::pair<std::string,
+ bool> >::const_iterator include_iterator;
+ include_iterator include_begin() const { return Includes.begin(); }
+ include_iterator include_end() const { return Includes.end(); }
+
+ typedef std::vector<std::string>::const_iterator imacro_iterator;
+ imacro_iterator imacro_begin() const { return MacroIncludes.begin(); }
+ imacro_iterator imacro_end() const { return MacroIncludes.end(); }
+};
+
+/// InitializePreprocessor - Initialize the preprocessor getting it and the
+/// environment ready to process a single file. This returns true on error.
+///
+bool InitializePreprocessor(Preprocessor &PP,
+ const PreprocessorInitOptions& InitOptions);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/ManagerRegistry.h b/include/clang/Frontend/ManagerRegistry.h
new file mode 100644
index 000000000000..ecab67a3b676
--- /dev/null
+++ b/include/clang/Frontend/ManagerRegistry.h
@@ -0,0 +1,53 @@
+//===-- ManagerRegistry.h - Pluggable analyzer module registry --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ManagerRegistry and Register* classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_MANAGER_REGISTRY_H
+#define LLVM_CLANG_FRONTEND_MANAGER_REGISTRY_H
+
+#include "clang/Analysis/PathSensitive/GRState.h"
+
+namespace clang {
+
+/// ManagerRegistry - This class records manager creators registered at
+/// runtime. The information is communicated to AnalysisManager through static
+/// members. Better design is expected.
+
+class ManagerRegistry {
+public:
+ static StoreManagerCreator StoreMgrCreator;
+ static ConstraintManagerCreator ConstraintMgrCreator;
+};
+
+/// RegisterConstraintManager - This class is used to setup the constraint
+/// manager of the static analyzer. The constructor takes a creator function
+/// pointer for creating the constraint manager.
+///
+/// It is used like this:
+///
+/// class MyConstraintManager {};
+/// ConstraintManager* CreateMyConstraintManager(GRStateManager& statemgr) {
+/// return new MyConstraintManager(statemgr);
+/// }
+/// RegisterConstraintManager X(CreateMyConstraintManager);
+
+class RegisterConstraintManager {
+public:
+ RegisterConstraintManager(ConstraintManagerCreator CMC) {
+ assert(ManagerRegistry::ConstraintMgrCreator == 0
+ && "ConstraintMgrCreator already set!");
+ ManagerRegistry::ConstraintMgrCreator = CMC;
+ }
+};
+
+}
+#endif
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
new file mode 100644
index 000000000000..0862cd6390f4
--- /dev/null
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -0,0 +1,660 @@
+//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines Bitcode enum values for Clang precompiled header files.
+//
+// The enum values defined in this file should be considered permanent. If
+// new features are added, they should have values added at the end of the
+// respective lists.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
+#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
+
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+ namespace pch {
+ /// \brief PCH major version number supported by this version of
+ /// Clang.
+ ///
+ /// Whenever the PCH format changes in a way that makes it
+ /// incompatible with previous versions (such that a reader
+ /// designed for the previous version could not support reading
+ /// the new version), this number should be increased.
+ const unsigned VERSION_MAJOR = 1;
+
+ /// \brief PCH minor version number supported by this version of
+ /// Clang.
+ ///
+ /// Whenever the PCH format changes in a way that is still
+ /// compatible with previous versions (such that a reader designed
+ /// for the previous version could still support reading the new
+ /// version by ignoring new kinds of subblocks), this number
+ /// should be increased.
+ const unsigned VERSION_MINOR = 0;
+
+ /// \brief An ID number that refers to a declaration in a PCH file.
+ ///
+ /// The ID numbers of types are consecutive (in order of
+ /// discovery) and start at 2. 0 is reserved for NULL, and 1 is
+ /// reserved for the translation unit declaration.
+ typedef uint32_t DeclID;
+
+ /// \brief An ID number that refers to a type in a PCH file.
+ ///
+ /// The ID of a type is partitioned into two parts: the lower
+ /// three bits are used to store the const/volatile/restrict
+ /// qualifiers (as with QualType) and the upper bits provide a
+ /// type index. The type index values are partitioned into two
+ /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
+ /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
+ /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
+ /// other types that have serialized representations.
+ typedef uint32_t TypeID;
+
+ /// \brief An ID number that refers to an identifier in a PCH
+ /// file.
+ typedef uint32_t IdentID;
+
+ typedef uint32_t SelectorID;
+
+ /// \brief Describes the various kinds of blocks that occur within
+ /// a PCH file.
+ enum BlockIDs {
+ /// \brief The PCH block, which acts as a container around the
+ /// full PCH block.
+ PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+
+ /// \brief The block containing information about the source
+ /// manager.
+ SOURCE_MANAGER_BLOCK_ID,
+
+ /// \brief The block containing information about the
+ /// preprocessor.
+ PREPROCESSOR_BLOCK_ID,
+
+ /// \brief The block containing the definitions of all of the
+ /// types used within the PCH file.
+ TYPES_BLOCK_ID,
+
+ /// \brief The block containing the definitions of all of the
+ /// declarations stored in the PCH file.
+ DECLS_BLOCK_ID
+ };
+
+ /// \brief Record types that occur within the PCH block itself.
+ enum PCHRecordTypes {
+ /// \brief Offset of each type within the types block.
+ ///
+ /// The TYPE_OFFSET constant describes the record that occurs
+ /// within the block identified by TYPE_OFFSETS_BLOCK_ID within
+ /// the PCH file. The record itself is an array of offsets that
+ /// point into the types block (identified by TYPES_BLOCK_ID in
+ /// the PCH file). The index into the array is based on the ID
+ /// of a type. For a given type ID @c T, the lower three bits of
+ /// @c T are its qualifiers (const, volatile, restrict), as in
+ /// the QualType class. The upper bits, after being shifted and
+ /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
+ /// TYPE_OFFSET block to determine the offset of that type's
+ /// corresponding record within the TYPES_BLOCK_ID block.
+ TYPE_OFFSET = 1,
+
+ /// \brief Record code for the offsets of each decl.
+ ///
+ /// The DECL_OFFSET constant describes the record that occurs
+ /// within the block identifier by DECL_OFFSETS_BLOCK_ID within
+ /// the PCH file. The record itself is an array of offsets that
+ /// point into the declarations block (identified by
+ /// DECLS_BLOCK_ID). The declaration ID is an index into this
+ /// record, after subtracting one to account for the use of
+ /// declaration ID 0 for a NULL declaration pointer. Index 0 is
+ /// reserved for the translation unit declaration.
+ DECL_OFFSET = 2,
+
+ /// \brief Record code for the language options table.
+ ///
+ /// The record with this code contains the contents of the
+ /// LangOptions structure. We serialize the entire contents of
+ /// the structure, and let the reader decide which options are
+ /// actually important to check.
+ LANGUAGE_OPTIONS = 3,
+
+ /// \brief PCH metadata, including the PCH file version number
+ /// and the target triple used to build the PCH file.
+ METADATA = 4,
+
+ /// \brief Record code for the table of offsets of each
+ /// identifier ID.
+ ///
+ /// The offset table contains offsets into the blob stored in
+ /// the IDENTIFIER_TABLE record. Each offset points to the
+ /// NULL-terminated string that corresponds to that identifier.
+ IDENTIFIER_OFFSET = 5,
+
+ /// \brief Record code for the identifier table.
+ ///
+ /// The identifier table is a simple blob that contains
+ /// NULL-terminated strings for all of the identifiers
+ /// referenced by the PCH file. The IDENTIFIER_OFFSET table
+ /// contains the mapping from identifier IDs to the characters
+ /// in this blob. Note that the starting offsets of all of the
+ /// identifiers are odd, so that, when the identifier offset
+ /// table is loaded in, we can use the low bit to distinguish
+ /// between offsets (for unresolved identifier IDs) and
+ /// IdentifierInfo pointers (for already-resolved identifier
+ /// IDs).
+ IDENTIFIER_TABLE = 6,
+
+ /// \brief Record code for the array of external definitions.
+ ///
+ /// The PCH file contains a list of all of the unnamed external
+ /// definitions present within the parsed headers, stored as an
+ /// array of declaration IDs. These external definitions will be
+ /// reported to the AST consumer after the PCH file has been
+ /// read, since their presence can affect the semantics of the
+ /// program (e.g., for code generation).
+ EXTERNAL_DEFINITIONS = 7,
+
+ /// \brief Record code for the set of non-builtin, special
+ /// types.
+ ///
+ /// This record contains the type IDs for the various type nodes
+ /// that are constructed during semantic analysis (e.g.,
+ /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
+ /// offsets into this record.
+ SPECIAL_TYPES = 8,
+
+ /// \brief Record code for the extra statistics we gather while
+ /// generating a PCH file.
+ STATISTICS = 9,
+
+ /// \brief Record code for the array of tentative definitions.
+ TENTATIVE_DEFINITIONS = 10,
+
+ /// \brief Record code for the array of locally-scoped external
+ /// declarations.
+ LOCALLY_SCOPED_EXTERNAL_DECLS = 11,
+
+ /// \brief Record code for the table of offsets into the
+ /// Objective-C method pool.
+ SELECTOR_OFFSETS = 12,
+
+ /// \brief Record code for the Objective-C method pool,
+ METHOD_POOL = 13,
+
+ /// \brief The value of the next __COUNTER__ to dispense.
+ /// [PP_COUNTER_VALUE, Val]
+ PP_COUNTER_VALUE = 14,
+
+ /// \brief Record code for the table of offsets into the block
+ /// of source-location information.
+ SOURCE_LOCATION_OFFSETS = 15,
+
+ /// \brief Record code for the set of source location entries
+ /// that need to be preloaded by the PCH reader.
+ ///
+ /// This set contains the source location entry for the
+ /// predefines buffer and for any file entries that need to be
+ /// preloaded.
+ SOURCE_LOCATION_PRELOADS = 16,
+
+ /// \brief Record code for the stat() cache.
+ STAT_CACHE = 17,
+
+ /// \brief Record code for the set of ext_vector type names.
+ EXT_VECTOR_DECLS = 18,
+
+ /// \brief Record code for the set of Objective-C category
+ /// implementations.
+ OBJC_CATEGORY_IMPLEMENTATIONS = 19,
+
+ /// \brief Record code for the original file that was used to
+ /// generate the precompiled header.
+ ORIGINAL_FILE_NAME = 20
+ };
+
+ /// \brief Record types used within a source manager block.
+ enum SourceManagerRecordTypes {
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// file.
+ SM_SLOC_FILE_ENTRY = 1,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// buffer.
+ SM_SLOC_BUFFER_ENTRY = 2,
+ /// \brief Describes a blob that contains the data for a buffer
+ /// entry. This kind of record always directly follows a
+ /// SM_SLOC_BUFFER_ENTRY record.
+ SM_SLOC_BUFFER_BLOB = 3,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// macro instantiation.
+ SM_SLOC_INSTANTIATION_ENTRY = 4,
+ /// \brief Describes the SourceManager's line table, with
+ /// information about #line directives.
+ SM_LINE_TABLE = 5,
+ /// \brief Describes one header file info [isImport, DirInfo, NumIncludes]
+ /// ControllingMacro is optional.
+ SM_HEADER_FILE_INFO = 6
+ };
+
+ /// \brief Record types used within a preprocessor block.
+ enum PreprocessorRecordTypes {
+ // The macros in the PP section are a PP_MACRO_* instance followed by a
+ // list of PP_TOKEN instances for each token in the definition.
+
+ /// \brief An object-like macro definition.
+ /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
+ PP_MACRO_OBJECT_LIKE = 1,
+
+ /// \brief A function-like macro definition.
+ /// [PP_MACRO_FUNCTION_LIKE, <ObjectLikeStuff>, IsC99Varargs, IsGNUVarars,
+ /// NumArgs, ArgIdentInfoID* ]
+ PP_MACRO_FUNCTION_LIKE = 2,
+
+ /// \brief Describes one token.
+ /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
+ PP_TOKEN = 3
+ };
+
+ /// \defgroup PCHAST Precompiled header AST constants
+ ///
+ /// The constants in this group describe various components of the
+ /// abstract syntax tree within a precompiled header.
+ ///
+ /// @{
+
+ /// \brief Predefined type IDs.
+ ///
+ /// These type IDs correspond to predefined types in the AST
+ /// context, such as built-in types (int) and special place-holder
+ /// types (the <overload> and <dependent> type markers). Such
+ /// types are never actually serialized, since they will be built
+ /// by the AST context when it is created.
+ enum PredefinedTypeIDs {
+ /// \brief The NULL type.
+ PREDEF_TYPE_NULL_ID = 0,
+ /// \brief The void type.
+ PREDEF_TYPE_VOID_ID = 1,
+ /// \brief The 'bool' or '_Bool' type.
+ PREDEF_TYPE_BOOL_ID = 2,
+ /// \brief The 'char' type, when it is unsigned.
+ PREDEF_TYPE_CHAR_U_ID = 3,
+ /// \brief The 'unsigned char' type.
+ PREDEF_TYPE_UCHAR_ID = 4,
+ /// \brief The 'unsigned short' type.
+ PREDEF_TYPE_USHORT_ID = 5,
+ /// \brief The 'unsigned int' type.
+ PREDEF_TYPE_UINT_ID = 6,
+ /// \brief The 'unsigned long' type.
+ PREDEF_TYPE_ULONG_ID = 7,
+ /// \brief The 'unsigned long long' type.
+ PREDEF_TYPE_ULONGLONG_ID = 8,
+ /// \brief The 'char' type, when it is signed.
+ PREDEF_TYPE_CHAR_S_ID = 9,
+ /// \brief The 'signed char' type.
+ PREDEF_TYPE_SCHAR_ID = 10,
+ /// \brief The C++ 'wchar_t' type.
+ PREDEF_TYPE_WCHAR_ID = 11,
+ /// \brief The (signed) 'short' type.
+ PREDEF_TYPE_SHORT_ID = 12,
+ /// \brief The (signed) 'int' type.
+ PREDEF_TYPE_INT_ID = 13,
+ /// \brief The (signed) 'long' type.
+ PREDEF_TYPE_LONG_ID = 14,
+ /// \brief The (signed) 'long long' type.
+ PREDEF_TYPE_LONGLONG_ID = 15,
+ /// \brief The 'float' type.
+ PREDEF_TYPE_FLOAT_ID = 16,
+ /// \brief The 'double' type.
+ PREDEF_TYPE_DOUBLE_ID = 17,
+ /// \brief The 'long double' type.
+ PREDEF_TYPE_LONGDOUBLE_ID = 18,
+ /// \brief The placeholder type for overloaded function sets.
+ PREDEF_TYPE_OVERLOAD_ID = 19,
+ /// \brief The placeholder type for dependent types.
+ PREDEF_TYPE_DEPENDENT_ID = 20,
+ /// \brief The '__uint128_t' type.
+ PREDEF_TYPE_UINT128_ID = 21,
+ /// \brief The '__int128_t' type.
+ PREDEF_TYPE_INT128_ID = 22,
+ /// \brief The type of 'nullptr'.
+ PREDEF_TYPE_NULLPTR_ID = 23
+ };
+
+ /// \brief The number of predefined type IDs that are reserved for
+ /// the PREDEF_TYPE_* constants.
+ ///
+ /// Type IDs for non-predefined types will start at
+ /// NUM_PREDEF_TYPE_IDs.
+ const unsigned NUM_PREDEF_TYPE_IDS = 100;
+
+ /// \brief Record codes for each kind of type.
+ ///
+ /// These constants describe the records that can occur within a
+ /// block identified by TYPES_BLOCK_ID in the PCH file. Each
+ /// constant describes a record for a specific type class in the
+ /// AST.
+ enum TypeCode {
+ /// \brief An ExtQualType record.
+ TYPE_EXT_QUAL = 1,
+ /// \brief A FixedWidthIntType record.
+ TYPE_FIXED_WIDTH_INT = 2,
+ /// \brief A ComplexType record.
+ TYPE_COMPLEX = 3,
+ /// \brief A PointerType record.
+ TYPE_POINTER = 4,
+ /// \brief A BlockPointerType record.
+ TYPE_BLOCK_POINTER = 5,
+ /// \brief An LValueReferenceType record.
+ TYPE_LVALUE_REFERENCE = 6,
+ /// \brief An RValueReferenceType record.
+ TYPE_RVALUE_REFERENCE = 7,
+ /// \brief A MemberPointerType record.
+ TYPE_MEMBER_POINTER = 8,
+ /// \brief A ConstantArrayType record.
+ TYPE_CONSTANT_ARRAY = 9,
+ /// \brief An IncompleteArrayType record.
+ TYPE_INCOMPLETE_ARRAY = 10,
+ /// \brief A VariableArrayType record.
+ TYPE_VARIABLE_ARRAY = 11,
+ /// \brief A VectorType record.
+ TYPE_VECTOR = 12,
+ /// \brief An ExtVectorType record.
+ TYPE_EXT_VECTOR = 13,
+ /// \brief A FunctionNoProtoType record.
+ TYPE_FUNCTION_NO_PROTO = 14,
+ /// \brief A FunctionProtoType record.
+ TYPE_FUNCTION_PROTO = 15,
+ /// \brief A TypedefType record.
+ TYPE_TYPEDEF = 16,
+ /// \brief A TypeOfExprType record.
+ TYPE_TYPEOF_EXPR = 17,
+ /// \brief A TypeOfType record.
+ TYPE_TYPEOF = 18,
+ /// \brief A RecordType record.
+ TYPE_RECORD = 19,
+ /// \brief An EnumType record.
+ TYPE_ENUM = 20,
+ /// \brief An ObjCInterfaceType record.
+ TYPE_OBJC_INTERFACE = 21,
+ /// \brief An ObjCQualifiedInterfaceType record.
+ TYPE_OBJC_QUALIFIED_INTERFACE = 22,
+ /// \brief An ObjCQualifiedIdType record.
+ TYPE_OBJC_QUALIFIED_ID = 23
+ };
+
+ /// \brief The type IDs for special types constructed by semantic
+ /// analysis.
+ ///
+ /// The constants in this enumeration are indices into the
+ /// SPECIAL_TYPES record.
+ enum SpecialTypeIDs {
+ /// \brief __builtin_va_list
+ SPECIAL_TYPE_BUILTIN_VA_LIST = 0,
+ /// \brief Objective-C "id" type
+ SPECIAL_TYPE_OBJC_ID = 1,
+ /// \brief Objective-C selector type
+ SPECIAL_TYPE_OBJC_SELECTOR = 2,
+ /// \brief Objective-C Protocol type
+ SPECIAL_TYPE_OBJC_PROTOCOL = 3,
+ /// \brief Objective-C Class type
+ SPECIAL_TYPE_OBJC_CLASS = 4,
+ /// \brief CFConstantString type
+ SPECIAL_TYPE_CF_CONSTANT_STRING = 5,
+ /// \brief Objective-C fast enumeration state type
+ SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE = 6
+ };
+
+ /// \brief Record codes for each kind of declaration.
+ ///
+ /// These constants describe the records that can occur within a
+ /// declarations block (identified by DECLS_BLOCK_ID). Each
+ /// constant describes a record for a specific declaration class
+ /// in the AST.
+ enum DeclCode {
+ /// \brief Attributes attached to a declaration.
+ DECL_ATTR = 1,
+ /// \brief A TranslationUnitDecl record.
+ DECL_TRANSLATION_UNIT,
+ /// \brief A TypedefDecl record.
+ DECL_TYPEDEF,
+ /// \brief An EnumDecl record.
+ DECL_ENUM,
+ /// \brief A RecordDecl record.
+ DECL_RECORD,
+ /// \brief An EnumConstantDecl record.
+ DECL_ENUM_CONSTANT,
+ /// \brief A FunctionDecl record.
+ DECL_FUNCTION,
+ /// \brief A ObjCMethodDecl record.
+ DECL_OBJC_METHOD,
+ /// \brief A ObjCInterfaceDecl record.
+ DECL_OBJC_INTERFACE,
+ /// \brief A ObjCProtocolDecl record.
+ DECL_OBJC_PROTOCOL,
+ /// \brief A ObjCIvarDecl record.
+ DECL_OBJC_IVAR,
+ /// \brief A ObjCAtDefsFieldDecl record.
+ DECL_OBJC_AT_DEFS_FIELD,
+ /// \brief A ObjCClassDecl record.
+ DECL_OBJC_CLASS,
+ /// \brief A ObjCForwardProtocolDecl record.
+ DECL_OBJC_FORWARD_PROTOCOL,
+ /// \brief A ObjCCategoryDecl record.
+ DECL_OBJC_CATEGORY,
+ /// \brief A ObjCCategoryImplDecl record.
+ DECL_OBJC_CATEGORY_IMPL,
+ /// \brief A ObjCImplementationDecl record.
+ DECL_OBJC_IMPLEMENTATION,
+ /// \brief A ObjCCompatibleAliasDecl record.
+ DECL_OBJC_COMPATIBLE_ALIAS,
+ /// \brief A ObjCPropertyDecl record.
+ DECL_OBJC_PROPERTY,
+ /// \brief A ObjCPropertyImplDecl record.
+ DECL_OBJC_PROPERTY_IMPL,
+ /// \brief A FieldDecl record.
+ DECL_FIELD,
+ /// \brief A VarDecl record.
+ DECL_VAR,
+ /// \brief An ImplicitParamDecl record.
+ DECL_IMPLICIT_PARAM,
+ /// \brief A ParmVarDecl record.
+ DECL_PARM_VAR,
+ /// \brief An OriginalParmVarDecl record.
+ DECL_ORIGINAL_PARM_VAR,
+ /// \brief A FileScopeAsmDecl record.
+ DECL_FILE_SCOPE_ASM,
+ /// \brief A BlockDecl record.
+ DECL_BLOCK,
+ /// \brief A record that stores the set of declarations that are
+ /// lexically stored within a given DeclContext.
+ ///
+ /// The record itself is an array of declaration IDs, in the
+ /// order in which those declarations were added to the
+ /// declaration context. This data is used when iterating over
+ /// the contents of a DeclContext, e.g., via
+ /// DeclContext::decls_begin()/DeclContext::decls_end().
+ DECL_CONTEXT_LEXICAL,
+ /// \brief A record that stores the set of declarations that are
+ /// visible from a given DeclContext.
+ ///
+ /// The record itself stores a set of mappings, each of which
+ /// associates a declaration name with one or more declaration
+ /// IDs. This data is used when performing qualified name lookup
+ /// into a DeclContext via DeclContext::lookup.
+ DECL_CONTEXT_VISIBLE
+ };
+
+ /// \brief Record codes for each kind of statement or expression.
+ ///
+ /// These constants describe the records that describe statements
+ /// or expressions. These records can occur within either the type
+ /// or declaration blocks, so they begin with record values of
+ /// 50. Each constant describes a record for a specific
+ /// statement or expression class in the AST.
+ enum StmtCode {
+ /// \brief A marker record that indicates that we are at the end
+ /// of an expression.
+ STMT_STOP = 50,
+ /// \brief A NULL expression.
+ STMT_NULL_PTR,
+ /// \brief A NullStmt record.
+ STMT_NULL,
+ /// \brief A CompoundStmt record.
+ STMT_COMPOUND,
+ /// \brief A CaseStmt record.
+ STMT_CASE,
+ /// \brief A DefaultStmt record.
+ STMT_DEFAULT,
+ /// \brief A LabelStmt record.
+ STMT_LABEL,
+ /// \brief An IfStmt record.
+ STMT_IF,
+ /// \brief A SwitchStmt record.
+ STMT_SWITCH,
+ /// \brief A WhileStmt record.
+ STMT_WHILE,
+ /// \brief A DoStmt record.
+ STMT_DO,
+ /// \brief A ForStmt record.
+ STMT_FOR,
+ /// \brief A GotoStmt record.
+ STMT_GOTO,
+ /// \brief An IndirectGotoStmt record.
+ STMT_INDIRECT_GOTO,
+ /// \brief A ContinueStmt record.
+ STMT_CONTINUE,
+ /// \brief A BreakStmt record.
+ STMT_BREAK,
+ /// \brief A ReturnStmt record.
+ STMT_RETURN,
+ /// \brief A DeclStmt record.
+ STMT_DECL,
+ /// \brief An AsmStmt record.
+ STMT_ASM,
+ /// \brief A PredefinedExpr record.
+ EXPR_PREDEFINED,
+ /// \brief A DeclRefExpr record.
+ EXPR_DECL_REF,
+ /// \brief An IntegerLiteral record.
+ EXPR_INTEGER_LITERAL,
+ /// \brief A FloatingLiteral record.
+ EXPR_FLOATING_LITERAL,
+ /// \brief An ImaginaryLiteral record.
+ EXPR_IMAGINARY_LITERAL,
+ /// \brief A StringLiteral record.
+ EXPR_STRING_LITERAL,
+ /// \brief A CharacterLiteral record.
+ EXPR_CHARACTER_LITERAL,
+ /// \brief A ParenExpr record.
+ EXPR_PAREN,
+ /// \brief A UnaryOperator record.
+ EXPR_UNARY_OPERATOR,
+ /// \brief A SizefAlignOfExpr record.
+ EXPR_SIZEOF_ALIGN_OF,
+ /// \brief An ArraySubscriptExpr record.
+ EXPR_ARRAY_SUBSCRIPT,
+ /// \brief A CallExpr record.
+ EXPR_CALL,
+ /// \brief A MemberExpr record.
+ EXPR_MEMBER,
+ /// \brief A BinaryOperator record.
+ EXPR_BINARY_OPERATOR,
+ /// \brief A CompoundAssignOperator record.
+ EXPR_COMPOUND_ASSIGN_OPERATOR,
+ /// \brief A ConditionOperator record.
+ EXPR_CONDITIONAL_OPERATOR,
+ /// \brief An ImplicitCastExpr record.
+ EXPR_IMPLICIT_CAST,
+ /// \brief A CStyleCastExpr record.
+ EXPR_CSTYLE_CAST,
+ /// \brief A CompoundLiteralExpr record.
+ EXPR_COMPOUND_LITERAL,
+ /// \brief An ExtVectorElementExpr record.
+ EXPR_EXT_VECTOR_ELEMENT,
+ /// \brief An InitListExpr record.
+ EXPR_INIT_LIST,
+ /// \brief A DesignatedInitExpr record.
+ EXPR_DESIGNATED_INIT,
+ /// \brief An ImplicitValueInitExpr record.
+ EXPR_IMPLICIT_VALUE_INIT,
+ /// \brief A VAArgExpr record.
+ EXPR_VA_ARG,
+ /// \brief An AddrLabelExpr record.
+ EXPR_ADDR_LABEL,
+ /// \brief A StmtExpr record.
+ EXPR_STMT,
+ /// \brief A TypesCompatibleExpr record.
+ EXPR_TYPES_COMPATIBLE,
+ /// \brief A ChooseExpr record.
+ EXPR_CHOOSE,
+ /// \brief A GNUNullExpr record.
+ EXPR_GNU_NULL,
+ /// \brief A ShuffleVectorExpr record.
+ EXPR_SHUFFLE_VECTOR,
+ /// \brief BlockExpr
+ EXPR_BLOCK,
+ /// \brief A BlockDeclRef record.
+ EXPR_BLOCK_DECL_REF,
+
+ // Objective-C
+
+ /// \brief An ObjCStringLiteral record.
+ EXPR_OBJC_STRING_LITERAL,
+ /// \brief An ObjCEncodeExpr record.
+ EXPR_OBJC_ENCODE,
+ /// \brief An ObjCSelectorExpr record.
+ EXPR_OBJC_SELECTOR_EXPR,
+ /// \brief An ObjCProtocolExpr record.
+ EXPR_OBJC_PROTOCOL_EXPR,
+ /// \brief An ObjCIvarRefExpr record.
+ EXPR_OBJC_IVAR_REF_EXPR,
+ /// \brief An ObjCPropertyRefExpr record.
+ EXPR_OBJC_PROPERTY_REF_EXPR,
+ /// \brief An ObjCKVCRefExpr record.
+ EXPR_OBJC_KVC_REF_EXPR,
+ /// \brief An ObjCMessageExpr record.
+ EXPR_OBJC_MESSAGE_EXPR,
+ /// \brief An ObjCSuperExpr record.
+ EXPR_OBJC_SUPER_EXPR,
+
+ /// \brief An ObjCForCollectionStmt record.
+ STMT_OBJC_FOR_COLLECTION,
+ /// \brief An ObjCAtCatchStmt record.
+ STMT_OBJC_CATCH,
+ /// \brief An ObjCAtFinallyStmt record.
+ STMT_OBJC_FINALLY,
+ /// \brief An ObjCAtTryStmt record.
+ STMT_OBJC_AT_TRY,
+ /// \brief An ObjCAtSynchronizedStmt record.
+ STMT_OBJC_AT_SYNCHRONIZED,
+ /// \brief An ObjCAtThrowStmt record.
+ STMT_OBJC_AT_THROW
+ };
+
+ /// \brief The kinds of designators that can occur in a
+ /// DesignatedInitExpr.
+ enum DesignatorTypes {
+ /// \brief Field designator where only the field name is known.
+ DESIG_FIELD_NAME = 0,
+ /// \brief Field designator where the field has been resolved to
+ /// a declaration.
+ DESIG_FIELD_DECL = 1,
+ /// \brief Array designator.
+ DESIG_ARRAY = 2,
+ /// \brief GNU array range designator.
+ DESIG_ARRAY_RANGE = 3
+ };
+
+ /// @}
+ }
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
new file mode 100644
index 000000000000..1e00ae34137d
--- /dev/null
+++ b/include/clang/Frontend/PCHReader.h
@@ -0,0 +1,567 @@
+//===--- PCHReader.h - Precompiled Headers Reader ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PCHReader class, which reads a precompiled header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H
+#define LLVM_CLANG_FRONTEND_PCH_READER_H
+
+#include "clang/Frontend/PCHBitCodes.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/DataTypes.h"
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class AddrLabelExpr;
+class ASTConsumer;
+class ASTContext;
+class Attr;
+class Decl;
+class DeclContext;
+class GotoStmt;
+class LabelStmt;
+class NamedDecl;
+class Preprocessor;
+class Sema;
+class SwitchCase;
+
+/// \brief Reads a precompiled head containing the contents of a
+/// translation unit.
+///
+/// The PCHReader class reads a bitstream (produced by the PCHWriter
+/// class) containing the serialized representation of a given
+/// abstract syntax tree and its supporting data structures. An
+/// instance of the PCHReader can be attached to an ASTContext object,
+/// which will provide access to the contents of the PCH file.
+///
+/// The PCH reader provides lazy de-serialization of declarations, as
+/// required when traversing the AST. Only those AST nodes that are
+/// actually required will be de-serialized.
+class PCHReader
+ : public ExternalSemaSource,
+ public IdentifierInfoLookup,
+ public ExternalIdentifierLookup,
+ public ExternalSLocEntrySource {
+public:
+ enum PCHReadResult { Success, Failure, IgnorePCH };
+
+private:
+ /// \brief The semantic analysis object that will be processing the
+ /// PCH file and the translation unit that uses it.
+ Sema *SemaObj;
+
+ /// \brief The preprocessor that will be loading the source file.
+ Preprocessor &PP;
+
+ /// \brief The AST context into which we'll read the PCH file.
+ ASTContext *Context;
+
+ /// \brief The AST consumer.
+ ASTConsumer *Consumer;
+
+ /// \brief The bitstream reader from which we'll read the PCH file.
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+
+ /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
+ /// has read all the abbreviations at the start of the block and is ready to
+ /// jump around with these in context.
+ llvm::BitstreamCursor DeclsCursor;
+
+ /// \brief The file name of the PCH file.
+ std::string FileName;
+
+ /// \brief The memory buffer that stores the data associated with
+ /// this PCH file.
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+
+ /// \brief Offset type for all of the source location entries in the
+ /// PCH file.
+ const uint32_t *SLocOffsets;
+
+ /// \brief The number of source location entries in the PCH file.
+ unsigned TotalNumSLocEntries;
+
+ /// \brief Cursor used to read source location entries.
+ llvm::BitstreamCursor SLocEntryCursor;
+
+ /// \brief Offset of each type within the bitstream, indexed by the
+ /// type ID, or the representation of a Type*.
+ const uint32_t *TypeOffsets;
+
+ /// \brief Types that have already been loaded from the PCH file.
+ ///
+ /// When the pointer at index I is non-NULL, the type with
+ /// ID = (I + 1) << 3 has already been loaded from the PCH file.
+ std::vector<Type *> TypesLoaded;
+
+ /// \brief Offset of each declaration within the bitstream, indexed
+ /// by the declaration ID (-1).
+ const uint32_t *DeclOffsets;
+
+ /// \brief Declarations that have already been loaded from the PCH file.
+ ///
+ /// When the pointer at index I is non-NULL, the declaration with ID
+ /// = I + 1 has already been loaded.
+ std::vector<Decl *> DeclsLoaded;
+
+ typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> >
+ DeclContextOffsetsMap;
+
+ /// \brief Offsets of the lexical and visible declarations for each
+ /// DeclContext.
+ DeclContextOffsetsMap DeclContextOffsets;
+
+ /// \brief Actual data for the on-disk hash table.
+ ///
+ // This pointer points into a memory buffer, where the on-disk hash
+ // table for identifiers actually lives.
+ const char *IdentifierTableData;
+
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// IdentifierHashTable.
+ void *IdentifierLookupTable;
+
+ /// \brief Offsets into the identifier table data.
+ ///
+ /// This array is indexed by the identifier ID (-1), and provides
+ /// the offset into IdentifierTableData where the string data is
+ /// stored.
+ const uint32_t *IdentifierOffsets;
+
+ /// \brief A vector containing identifiers that have already been
+ /// loaded.
+ ///
+ /// If the pointer at index I is non-NULL, then it refers to the
+ /// IdentifierInfo for the identifier with ID=I+1 that has already
+ /// been loaded.
+ std::vector<IdentifierInfo *> IdentifiersLoaded;
+
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// PCHMethodPoolLookupTable.
+ ///
+ /// This hash table provides the instance and factory methods
+ /// associated with every selector known in the PCH file.
+ void *MethodPoolLookupTable;
+
+ /// \brief A pointer to the character data that comprises the method
+ /// pool.
+ ///
+ /// The SelectorOffsets table refers into this memory.
+ const unsigned char *MethodPoolLookupTableData;
+
+ /// \brief The number of selectors stored in the method pool itself.
+ unsigned TotalSelectorsInMethodPool;
+
+ /// \brief Offsets into the method pool lookup table's data array
+ /// where each selector resides.
+ const uint32_t *SelectorOffsets;
+
+ /// \brief The total number of selectors stored in the PCH file.
+ unsigned TotalNumSelectors;
+
+ /// \brief A vector containing selectors that have already been loaded.
+ ///
+ /// This vector is indexed by the Selector ID (-1). NULL selector
+ /// entries indicate that the particular selector ID has not yet
+ /// been loaded.
+ llvm::SmallVector<Selector, 16> SelectorsLoaded;
+
+ /// \brief The set of external definitions stored in the the PCH
+ /// file.
+ llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
+
+ /// \brief The set of tentative definitions stored in the the PCH
+ /// file.
+ llvm::SmallVector<uint64_t, 16> TentativeDefinitions;
+
+ /// \brief The set of locally-scoped external declarations stored in
+ /// the the PCH file.
+ llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
+
+ /// \brief The set of ext_vector type declarations stored in the the
+ /// PCH file.
+ llvm::SmallVector<uint64_t, 4> ExtVectorDecls;
+
+ /// \brief The set of Objective-C category definitions stored in the
+ /// the PCH file.
+ llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
+
+ /// \brief The original file name that was used to build the PCH
+ /// file.
+ std::string OriginalFileName;
+
+ /// \brief Mapping from switch-case IDs in the PCH file to
+ /// switch-case statements.
+ std::map<unsigned, SwitchCase *> SwitchCaseStmts;
+
+ /// \brief Mapping from label statement IDs in the PCH file to label
+ /// statements.
+ std::map<unsigned, LabelStmt *> LabelStmts;
+
+ /// \brief Mapping from label IDs to the set of "goto" statements
+ /// that point to that label before the label itself has been
+ /// de-serialized.
+ std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts;
+
+ /// \brief Mapping from label IDs to the set of address label
+ /// expressions that point to that label before the label itself has
+ /// been de-serialized.
+ std::multimap<unsigned, AddrLabelExpr *> UnresolvedAddrLabelExprs;
+
+ /// \brief The number of stat() calls that hit/missed the stat
+ /// cache.
+ unsigned NumStatHits, NumStatMisses;
+
+ /// \brief The number of source location entries de-serialized from
+ /// the PCH file.
+ unsigned NumSLocEntriesRead;
+
+ /// \brief The number of statements (and expressions) de-serialized
+ /// from the PCH file.
+ unsigned NumStatementsRead;
+
+ /// \brief The total number of statements (and expressions) stored
+ /// in the PCH file.
+ unsigned TotalNumStatements;
+
+ /// \brief The number of macros de-serialized from the PCH file.
+ unsigned NumMacrosRead;
+
+ /// \brief The number of method pool entries that have been read.
+ unsigned NumMethodPoolSelectorsRead;
+
+ /// \brief The number of times we have looked into the global method
+ /// pool and not found anything.
+ unsigned NumMethodPoolMisses;
+
+ /// \brief The total number of macros stored in the PCH file.
+ unsigned TotalNumMacros;
+
+ /// Number of lexical decl contexts read/total.
+ unsigned NumLexicalDeclContextsRead, TotalLexicalDeclContexts;
+
+ /// Number of visible decl contexts read/total.
+ unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts;
+
+ /// \brief FIXME: document!
+ llvm::SmallVector<uint64_t, 4> SpecialTypes;
+
+ /// \brief Contains declarations and definitions that will be
+ /// "interesting" to the ASTConsumer, when we get that AST consumer.
+ ///
+ /// "Interesting" declarations are those that have data that may
+ /// need to be emitted, such as inline function definitions or
+ /// Objective-C protocols.
+ llvm::SmallVector<Decl *, 16> InterestingDecls;
+
+ /// \brief The file ID for the predefines buffer in the PCH file.
+ FileID PCHPredefinesBufferID;
+
+ /// \brief Pointer to the beginning of the predefines buffer in the
+ /// PCH file.
+ const char *PCHPredefines;
+
+ /// \brief Length of the predefines buffer in the PCH file.
+ unsigned PCHPredefinesLen;
+
+ /// \brief Suggested contents of the predefines buffer, after this
+ /// PCH file has been processed.
+ ///
+ /// In most cases, this string will be empty, because the predefines
+ /// buffer computed to build the PCH file will be identical to the
+ /// predefines buffer computed from the command line. However, when
+ /// there are differences that the PCH reader can work around, this
+ /// predefines buffer may contain additional definitions.
+ std::string SuggestedPredefines;
+
+ PCHReadResult ReadPCHBlock();
+ bool CheckPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID);
+ PCHReadResult ReadSourceManagerBlock();
+ PCHReadResult ReadSLocEntryRecord(unsigned ID);
+
+ bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
+ QualType ReadTypeRecord(uint64_t Offset);
+ void LoadedDecl(unsigned Index, Decl *D);
+ Decl *ReadDeclRecord(uint64_t Offset, unsigned Index);
+
+ /// \brief Produce an error diagnostic and return true.
+ ///
+ /// This routine should only be used for fatal errors that have to
+ /// do with non-routine failures (e.g., corrupted PCH file).
+ bool Error(const char *Msg);
+
+ PCHReader(const PCHReader&); // do not implement
+ PCHReader &operator=(const PCHReader &); // do not implement
+
+public:
+ typedef llvm::SmallVector<uint64_t, 64> RecordData;
+
+ explicit PCHReader(Preprocessor &PP, ASTContext *Context);
+ ~PCHReader();
+
+ /// \brief Load the precompiled header designated by the given file
+ /// name.
+ PCHReadResult ReadPCH(const std::string &FileName);
+
+ /// \brief Retrieve the name of the original source file name
+ const std::string &getOriginalSourceFile() { return OriginalFileName; }
+
+ /// \brief Retrieve the name of the original source file name
+ /// directly from the PCH file, without actually loading the PCH
+ /// file.
+ static std::string getOriginalSourceFile(const std::string &PCHFileName);
+
+ /// \brief Returns the suggested contents of the predefines buffer,
+ /// which contains a (typically-empty) subset of the predefines
+ /// build prior to including the precompiled header.
+ const std::string &getSuggestedPredefines() { return SuggestedPredefines; }
+
+ /// \brief Resolve a type ID into a type, potentially building a new
+ /// type.
+ virtual QualType GetType(pch::TypeID ID);
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ virtual Decl *GetDecl(pch::DeclID ID);
+
+ /// \brief Resolve the offset of a statement into a statement.
+ ///
+ /// This operation will read a new statement from the external
+ /// source each time it is called, and is meant to be used via a
+ /// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
+ virtual Stmt *GetDeclStmt(uint64_t Offset);
+
+ /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
+ /// specified cursor. Read the abbreviations that are at the top of the block
+ /// and then leave the cursor pointing into the block.
+ bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID);
+
+ /// \brief Read all of the declarations lexically stored in a
+ /// declaration context.
+ ///
+ /// \param DC The declaration context whose declarations will be
+ /// read.
+ ///
+ /// \param Decls Vector that will contain the declarations loaded
+ /// from the external source. The caller is responsible for merging
+ /// these declarations with any declarations already stored in the
+ /// declaration context.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ virtual bool ReadDeclsLexicallyInContext(DeclContext *DC,
+ llvm::SmallVectorImpl<pch::DeclID> &Decls);
+
+ /// \brief Read all of the declarations visible from a declaration
+ /// context.
+ ///
+ /// \param DC The declaration context whose visible declarations
+ /// will be read.
+ ///
+ /// \param Decls A vector of visible declaration structures,
+ /// providing the mapping from each name visible in the declaration
+ /// context to the declaration IDs of declarations with that name.
+ ///
+ /// \returns true if there was an error while reading the
+ /// declarations for this declaration context.
+ ///
+ /// FIXME: Using this intermediate data structure results in an
+ /// extraneous copying of the data. Could we pass in a reference to
+ /// the StoredDeclsMap instead?
+ virtual bool ReadDeclsVisibleInContext(DeclContext *DC,
+ llvm::SmallVectorImpl<VisibleDeclaration> & Decls);
+
+ /// \brief Function that will be invoked when we begin parsing a new
+ /// translation unit involving this external AST source.
+ ///
+ /// This function will provide all of the external definitions to
+ /// the ASTConsumer.
+ virtual void StartTranslationUnit(ASTConsumer *Consumer);
+
+ /// \brief Print some statistics about PCH usage.
+ virtual void PrintStats();
+
+ /// \brief Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S);
+
+ /// \brief Retrieve the IdentifierInfo for the named identifier.
+ ///
+ /// This routine builds a new IdentifierInfo for the given
+ /// identifier. If any declarations with this name are visible from
+ /// translation unit scope, their declarations will be deserialized
+ /// and introduced into the declaration chain of the
+ /// identifier. FIXME: if this identifier names a macro, deserialize
+ /// the macro.
+ virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd);
+
+ /// \brief Load the contents of the global method pool for a given
+ /// selector.
+ ///
+ /// \returns a pair of Objective-C methods lists containing the
+ /// instance and factory methods, respectively, with this selector.
+ virtual std::pair<ObjCMethodList, ObjCMethodList>
+ ReadMethodPool(Selector Sel);
+
+ void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
+
+ /// \brief Report a diagnostic.
+ DiagnosticBuilder Diag(unsigned DiagID);
+
+ /// \brief Report a diagnostic.
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
+ IdentifierInfo *DecodeIdentifierInfo(unsigned Idx);
+
+ IdentifierInfo *GetIdentifierInfo(const RecordData &Record, unsigned &Idx) {
+ return DecodeIdentifierInfo(Record[Idx++]);
+ }
+
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) {
+ return DecodeIdentifierInfo(ID);
+ }
+
+ /// \brief Read the source location entry with index ID.
+ virtual void ReadSLocEntry(unsigned ID);
+
+ Selector DecodeSelector(unsigned Idx);
+
+ Selector GetSelector(const RecordData &Record, unsigned &Idx) {
+ return DecodeSelector(Record[Idx++]);
+ }
+ DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read an integral value
+ llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a signed integral value
+ llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a floating-point value
+ llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx);
+
+ // \brief Read a string
+ std::string ReadString(const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads attributes from the current stream position.
+ Attr *ReadAttributes();
+
+ /// \brief ReadDeclExpr - Reads an expression from the current decl cursor.
+ Expr *ReadDeclExpr();
+
+ /// \brief ReadTypeExpr - Reads an expression from the current type cursor.
+ Expr *ReadTypeExpr();
+
+ /// \brief Reads a statement from the specified cursor.
+ Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
+
+ /// \brief Read a statement from the current DeclCursor.
+ Stmt *ReadDeclStmt() {
+ return ReadStmt(DeclsCursor);
+ }
+
+ /// \brief Reads the macro record located at the given offset.
+ void ReadMacroRecord(uint64_t Offset);
+
+ /// \brief Retrieve the AST context that this PCH reader
+ /// supplements.
+ ASTContext *getContext() { return Context; }
+
+ // \brief Contains declarations that were loaded before we have
+ // access to a Sema object.
+ llvm::SmallVector<NamedDecl *, 16> PreloadedDecls;
+
+ /// \brief Retrieve the semantic analysis object used to analyze the
+ /// translation unit in which the precompiled header is being
+ /// imported.
+ Sema *getSema() { return SemaObj; }
+
+ /// \brief Retrieve the stream that this PCH reader is reading from.
+ llvm::BitstreamCursor &getStream() { return Stream; }
+ llvm::BitstreamCursor &getDeclsCursor() { return DeclsCursor; }
+
+ /// \brief Retrieve the identifier table associated with the
+ /// preprocessor.
+ IdentifierTable &getIdentifierTable();
+
+ /// \brief Record that the given ID maps to the given switch-case
+ /// statement.
+ void RecordSwitchCaseID(SwitchCase *SC, unsigned ID);
+
+ /// \brief Retrieve the switch-case statement with the given ID.
+ SwitchCase *getSwitchCaseWithID(unsigned ID);
+
+ /// \brief Record that the given label statement has been
+ /// deserialized and has the given ID.
+ void RecordLabelStmt(LabelStmt *S, unsigned ID);
+
+ /// \brief Set the label of the given statement to the label
+ /// identified by ID.
+ ///
+ /// Depending on the order in which the label and other statements
+ /// referencing that label occur, this operation may complete
+ /// immediately (updating the statement) or it may queue the
+ /// statement to be back-patched later.
+ void SetLabelOf(GotoStmt *S, unsigned ID);
+
+ /// \brief Set the label of the given expression to the label
+ /// identified by ID.
+ ///
+ /// Depending on the order in which the label and other statements
+ /// referencing that label occur, this operation may complete
+ /// immediately (updating the statement) or it may queue the
+ /// statement to be back-patched later.
+ void SetLabelOf(AddrLabelExpr *S, unsigned ID);
+};
+
+/// \brief Helper class that saves the current stream position and
+/// then restores it when destroyed.
+struct SavedStreamPosition {
+ explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor)
+ : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) { }
+
+ ~SavedStreamPosition() {
+ Cursor.JumpToBit(Offset);
+ }
+
+private:
+ llvm::BitstreamCursor &Cursor;
+ uint64_t Offset;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h
new file mode 100644
index 000000000000..5cb939547f2c
--- /dev/null
+++ b/include/clang/Frontend/PCHWriter.h
@@ -0,0 +1,278 @@
+//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PCHWriter class, which writes a precompiled
+// header containing a serialized representation of a translation
+// unit.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_PCH_WRITER_H
+#define LLVM_CLANG_FRONTEND_PCH_WRITER_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Frontend/PCHBitCodes.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include <map>
+#include <queue>
+
+namespace llvm {
+ class APFloat;
+ class APInt;
+ class BitstreamWriter;
+}
+
+namespace clang {
+
+class ASTContext;
+class LabelStmt;
+class MemorizeStatCalls;
+class Preprocessor;
+class Sema;
+class SourceManager;
+class SwitchCase;
+class TargetInfo;
+
+/// \brief Writes a precompiled header containing the contents of a
+/// translation unit.
+///
+/// The PCHWriter class produces a bitstream containing the serialized
+/// representation of a given abstract syntax tree and its supporting
+/// data structures. This bitstream can be de-serialized via an
+/// instance of the PCHReader class.
+class PCHWriter {
+public:
+ typedef llvm::SmallVector<uint64_t, 64> RecordData;
+
+private:
+ /// \brief The bitstream writer used to emit this precompiled header.
+ llvm::BitstreamWriter &Stream;
+
+ /// \brief Map that provides the ID numbers of each declaration within
+ /// the output stream.
+ ///
+ /// The ID numbers of declarations are consecutive (in order of
+ /// discovery) and start at 2. 1 is reserved for the translation
+ /// unit, while 0 is reserved for NULL.
+ llvm::DenseMap<const Decl *, pch::DeclID> DeclIDs;
+
+ /// \brief Offset of each declaration in the bitstream, indexed by
+ /// the declaration's ID.
+ std::vector<uint32_t> DeclOffsets;
+
+ /// \brief Queue containing the declarations that we still need to
+ /// emit.
+ std::queue<Decl *> DeclsToEmit;
+
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 3 bits to
+ /// allow for the const/volatile/restrict qualifiers.
+ llvm::DenseMap<const Type *, pch::TypeID> TypeIDs;
+
+ /// \brief Offset of each type in the bitstream, indexed by
+ /// the type's ID.
+ std::vector<uint32_t> TypeOffsets;
+
+ /// \brief The type ID that will be assigned to the next new type.
+ pch::TypeID NextTypeID;
+
+ /// \brief Queue containing the types that we still need to
+ /// emit.
+ std::queue<const Type *> TypesToEmit;
+
+ /// \brief Map that provides the ID numbers of each identifier in
+ /// the output stream.
+ ///
+ /// The ID numbers for identifiers are consecutive (in order of
+ /// discovery), starting at 1. An ID of zero refers to a NULL
+ /// IdentifierInfo.
+ llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs;
+
+ /// \brief Offsets of each of the identifier IDs into the identifier
+ /// table.
+ std::vector<uint32_t> IdentifierOffsets;
+
+ /// \brief Map that provides the ID numbers of each Selector.
+ llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs;
+
+ /// \brief Offset of each selector within the method pool/selector
+ /// table, indexed by the Selector ID (-1).
+ std::vector<uint32_t> SelectorOffsets;
+
+ /// \brief A vector of all Selectors (ordered by ID).
+ std::vector<Selector> SelVector;
+
+ /// \brief Offsets of each of the macro identifiers into the
+ /// bitstream.
+ ///
+ /// For each identifier that is associated with a macro, this map
+ /// provides the offset into the bitstream where that macro is
+ /// defined.
+ llvm::DenseMap<const IdentifierInfo *, uint64_t> MacroOffsets;
+
+ /// \brief Declarations encountered that might be external
+ /// definitions.
+ ///
+ /// We keep track of external definitions (as well as tentative
+ /// definitions) as we are emitting declarations to the PCH
+ /// file. The PCH file contains a separate record for these external
+ /// definitions, which are provided to the AST consumer by the PCH
+ /// reader. This is behavior is required to properly cope with,
+ /// e.g., tentative variable definitions that occur within
+ /// headers. The declarations themselves are stored as declaration
+ /// IDs, since they will be written out to an EXTERNAL_DEFINITIONS
+ /// record.
+ llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
+
+ /// \brief Statements that we've encountered while serializing a
+ /// declaration or type.
+ llvm::SmallVector<Stmt *, 8> StmtsToEmit;
+
+ /// \brief Mapping from SwitchCase statements to IDs.
+ std::map<SwitchCase *, unsigned> SwitchCaseIDs;
+
+ /// \brief Mapping from LabelStmt statements to IDs.
+ std::map<LabelStmt *, unsigned> LabelIDs;
+
+ /// \brief The number of statements written to the PCH file.
+ unsigned NumStatements;
+
+ /// \brief The number of macros written to the PCH file.
+ unsigned NumMacros;
+
+ /// \brief The number of lexical declcontexts written to the PCH
+ /// file.
+ unsigned NumLexicalDeclContexts;
+
+ /// \brief The number of visible declcontexts written to the PCH
+ /// file.
+ unsigned NumVisibleDeclContexts;
+
+ void WriteBlockInfoBlock();
+ void WriteMetadata(ASTContext &Context);
+ void WriteLanguageOptions(const LangOptions &LangOpts);
+ void WriteStatCache(MemorizeStatCalls &StatCalls);
+ void WriteSourceManagerBlock(SourceManager &SourceMgr,
+ const Preprocessor &PP);
+ void WritePreprocessor(const Preprocessor &PP);
+ void WriteType(const Type *T);
+ void WriteTypesBlock(ASTContext &Context);
+ uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
+ uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
+
+ void WriteDeclsBlock(ASTContext &Context);
+ void WriteMethodPool(Sema &SemaRef);
+ void WriteIdentifierTable(Preprocessor &PP);
+ void WriteAttributeRecord(const Attr *Attr);
+
+ unsigned ParmVarDeclAbbrev;
+ void WriteDeclsBlockAbbrevs();
+
+public:
+ /// \brief Create a new precompiled header writer that outputs to
+ /// the given bitstream.
+ PCHWriter(llvm::BitstreamWriter &Stream);
+
+ /// \brief Write a precompiled header for the given semantic analysis.
+ void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls);
+
+ /// \brief Emit a source location.
+ void AddSourceLocation(SourceLocation Loc, RecordData &Record);
+
+ /// \brief Emit an integral value.
+ void AddAPInt(const llvm::APInt &Value, RecordData &Record);
+
+ /// \brief Emit a signed integral value.
+ void AddAPSInt(const llvm::APSInt &Value, RecordData &Record);
+
+ /// \brief Emit a floating-point value.
+ void AddAPFloat(const llvm::APFloat &Value, RecordData &Record);
+
+ /// \brief Emit a reference to an identifier
+ void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record);
+
+ /// \brief Emit a Selector (which is a smart pointer reference)
+ void AddSelectorRef(const Selector, RecordData &Record);
+
+ /// \brief Get the unique number used to refer to the given
+ /// identifier.
+ pch::IdentID getIdentifierRef(const IdentifierInfo *II);
+
+ /// \brief Retrieve the offset of the macro definition for the given
+ /// identifier.
+ ///
+ /// The identifier must refer to a macro.
+ uint64_t getMacroOffset(const IdentifierInfo *II) {
+ assert(MacroOffsets.find(II) != MacroOffsets.end() &&
+ "Identifier does not name a macro");
+ return MacroOffsets[II];
+ }
+
+ /// \brief Emit a reference to a type.
+ void AddTypeRef(QualType T, RecordData &Record);
+
+ /// \brief Emit a reference to a declaration.
+ void AddDeclRef(const Decl *D, RecordData &Record);
+
+ /// \brief Determine the declaration ID of an already-emitted
+ /// declaration.
+ pch::DeclID getDeclID(const Decl *D);
+
+ /// \brief Emit a declaration name.
+ void AddDeclarationName(DeclarationName Name, RecordData &Record);
+
+ /// \brief Add a string to the given record.
+ void AddString(const std::string &Str, RecordData &Record);
+
+ /// \brief Note that the identifier II occurs at the given offset
+ /// within the identifier table.
+ void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset);
+
+ /// \brief Note that the selector Sel occurs at the given offset
+ /// within the method pool/selector table.
+ void SetSelectorOffset(Selector Sel, uint32_t Offset);
+
+ /// \brief Add the given statement or expression to the queue of
+ /// statements to emit.
+ ///
+ /// This routine should be used when emitting types and declarations
+ /// that have expressions as part of their formulation. Once the
+ /// type or declaration has been written, call FlushStmts() to write
+ /// the corresponding statements just after the type or
+ /// declaration.
+ void AddStmt(Stmt *S) { StmtsToEmit.push_back(S); }
+
+ /// \brief Write the given subexpression to the bitstream.
+ void WriteSubStmt(Stmt *S);
+
+ /// \brief Flush all of the statements and expressions that have
+ /// been added to the queue via AddStmt().
+ void FlushStmts();
+
+ /// \brief Record an ID for the given switch-case statement.
+ unsigned RecordSwitchCaseID(SwitchCase *S);
+
+ /// \brief Retrieve the ID for the given switch-case statement.
+ unsigned getSwitchCaseID(SwitchCase *S);
+
+ /// \brief Retrieve the ID for the given label statement, which may
+ /// or may not have been emitted yet.
+ unsigned GetLabelID(LabelStmt *S);
+
+ unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Frontend/PathDiagnosticClients.h b/include/clang/Frontend/PathDiagnosticClients.h
new file mode 100644
index 000000000000..028cd8549272
--- /dev/null
+++ b/include/clang/Frontend/PathDiagnosticClients.h
@@ -0,0 +1,34 @@
+//===--- PathDiagnosticClients.h - Path Diagnostic Clients ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface to create different path diagostic clients.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H
+#define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H
+
+#include <string>
+
+namespace clang {
+
+class PathDiagnosticClient;
+class Preprocessor;
+class PreprocessorFactory;
+
+PathDiagnosticClient* CreateHTMLDiagnosticClient(const std::string& prefix,
+ Preprocessor* PP = 0,
+ PreprocessorFactory* PPF = 0);
+
+PathDiagnosticClient* CreatePlistDiagnosticClient(const std::string& prefix,
+ Preprocessor* PP,
+ PreprocessorFactory* PPF);
+}
+
+#endif
diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h
new file mode 100644
index 000000000000..4e907e1965ea
--- /dev/null
+++ b/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -0,0 +1,48 @@
+//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_
+#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_
+
+#include "clang/Basic/Diagnostic.h"
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class SourceManager;
+
+class TextDiagnosticBuffer : public DiagnosticClient {
+public:
+ typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
+ typedef DiagList::iterator iterator;
+ typedef DiagList::const_iterator const_iterator;
+private:
+ DiagList Errors, Warnings, Notes;
+public:
+ const_iterator err_begin() const { return Errors.begin(); }
+ const_iterator err_end() const { return Errors.end(); }
+
+ const_iterator warn_begin() const { return Warnings.begin(); }
+ const_iterator warn_end() const { return Warnings.end(); }
+
+ const_iterator note_begin() const { return Notes.begin(); }
+ const_iterator note_end() const { return Notes.end(); }
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+};
+
+} // end namspace clang
+
+#endif
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
new file mode 100644
index 000000000000..3c9dcb8d9c17
--- /dev/null
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -0,0 +1,85 @@
+//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which prints the diagnostics to
+// standard error.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_
+#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+class SourceManager;
+class LangOptions;
+
+class TextDiagnosticPrinter : public DiagnosticClient {
+ llvm::raw_ostream &OS;
+ const LangOptions *LangOpts;
+ SourceLocation LastWarningLoc;
+ FullSourceLoc LastLoc;
+ bool LastCaretDiagnosticWasNote;
+
+ bool ShowColumn;
+ bool CaretDiagnostics;
+ bool ShowLocation;
+ bool PrintRangeInfo;
+ bool PrintDiagnosticOption;
+ bool PrintFixItInfo;
+ unsigned MessageLength;
+
+public:
+ TextDiagnosticPrinter(llvm::raw_ostream &os,
+ bool showColumn = true,
+ bool caretDiagnistics = true, bool showLocation = true,
+ bool printRangeInfo = true,
+ bool printDiagnosticOption = true,
+ bool printFixItInfo = true,
+ unsigned messageLength = 0)
+ : OS(os), LangOpts(0),
+ LastCaretDiagnosticWasNote(false), ShowColumn(showColumn),
+ CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation),
+ PrintRangeInfo(printRangeInfo),
+ PrintDiagnosticOption(printDiagnosticOption),
+ PrintFixItInfo(printFixItInfo),
+ MessageLength(messageLength) {}
+
+ void setLangOptions(const LangOptions *LO) {
+ LangOpts = LO;
+ }
+
+ void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
+
+ void HighlightRange(const SourceRange &R,
+ const SourceManager &SrcMgr,
+ unsigned LineNo, FileID FID,
+ std::string &CaretLine,
+ const std::string &SourceLine);
+
+ void EmitCaretDiagnostic(SourceLocation Loc,
+ SourceRange *Ranges, unsigned NumRanges,
+ SourceManager &SM,
+ const CodeModificationHint *Hints,
+ unsigned NumHints,
+ unsigned Columns);
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+};
+
+} // end namspace clang
+
+#endif
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
new file mode 100644
index 000000000000..41eb31a0fc35
--- /dev/null
+++ b/include/clang/Frontend/Utils.h
@@ -0,0 +1,79 @@
+//===--- Utils.h - Misc utilities for the front-end------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains miscellaneous utilities for various front-end actions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_UTILS_H
+#define LLVM_CLANG_FRONTEND_UTILS_H
+
+#include <vector>
+#include <string>
+
+namespace llvm {
+class raw_ostream;
+class raw_fd_ostream;
+}
+
+namespace clang {
+class Preprocessor;
+class MinimalAction;
+class TargetInfo;
+class Diagnostic;
+class ASTConsumer;
+class IdentifierTable;
+class SourceManager;
+class PreprocessorFactory;
+class LangOptions;
+
+/// ProcessWarningOptions - Initialize the diagnostic client and process the
+/// warning options specified on the command line.
+bool ProcessWarningOptions(Diagnostic &Diags,
+ std::vector<std::string> &Warnings,
+ bool Pedantic, bool PedanticErrors,
+ bool NoWarnings);
+
+/// DoPrintPreprocessedInput - Implement -E -dM mode.
+void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream* OS);
+
+/// DoPrintPreprocessedInput - Implement -E mode.
+void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
+ bool EnableCommentOutput,
+ bool EnableMacroCommentOutput,
+ bool DisableLineMarkers,
+ bool DumpDefines);
+
+/// RewriteMacrosInInput - Implement -rewrite-macros mode.
+void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS);
+
+/// RewriteMacrosInInput - A simple test for the TokenRewriter class.
+void DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS);
+
+/// CreatePrintParserActionsAction - Return the actions implementation that
+/// implements the -parse-print-callbacks option.
+MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP,
+ llvm::raw_ostream* OS);
+
+/// CheckDiagnostics - Gather the expected diagnostics and check them.
+bool CheckDiagnostics(Preprocessor &PP);
+
+/// AttachDependencyFileGen - Create a dependency file generator, and attach
+/// it to the given preprocessor. This takes ownership of the output stream.
+void AttachDependencyFileGen(Preprocessor *PP, llvm::raw_ostream *OS,
+ std::vector<std::string> &Targets,
+ bool IncludeSystemHeaders, bool PhonyTarget);
+
+/// CacheTokens - Cache tokens for use with PCH. Note that this requires
+/// a seekable stream.
+void CacheTokens(Preprocessor& PP, llvm::raw_fd_ostream* OS);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
new file mode 100644
index 000000000000..618de39233db
--- /dev/null
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -0,0 +1,133 @@
+//===--- DirectoryLookup.h - Info for searching for headers -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DirectoryLookup interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
+#define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
+
+#include "clang/Basic/SourceManager.h"
+
+namespace clang {
+class HeaderMap;
+class DirectoryEntry;
+class FileEntry;
+class HeaderSearch;
+
+/// DirectoryLookup - This class represents one entry in the search list that
+/// specifies the search order for directories in #include directives. It
+/// represents either a directory, a framework, or a headermap.
+///
+class DirectoryLookup {
+public:
+ enum LookupType_t {
+ LT_NormalDir,
+ LT_Framework,
+ LT_HeaderMap
+ };
+private:
+ union { // This union is discriminated by isHeaderMap.
+ /// Dir - This is the actual directory that we're referring to for a normal
+ /// directory or a framework.
+ const DirectoryEntry *Dir;
+
+ /// Map - This is the HeaderMap if this is a headermap lookup.
+ ///
+ const HeaderMap *Map;
+ } u;
+
+ /// DirCharacteristic - The type of directory this is: this is an instance of
+ /// SrcMgr::CharacteristicKind.
+ unsigned DirCharacteristic : 2;
+
+ /// UserSupplied - True if this is a user-supplied directory.
+ ///
+ bool UserSupplied : 1;
+
+ /// LookupType - This indicates whether this DirectoryLookup object is a
+ /// normal directory, a framework, or a headermap.
+ unsigned LookupType : 2;
+public:
+ /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+ /// 'dir'.
+ DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT,
+ bool isUser, bool isFramework)
+ : DirCharacteristic(DT), UserSupplied(isUser),
+ LookupType(isFramework ? LT_Framework : LT_NormalDir) {
+ u.Dir = dir;
+ }
+
+ /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+ /// 'map'.
+ DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT,
+ bool isUser)
+ : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) {
+ u.Map = map;
+ }
+
+ /// getLookupType - Return the kind of directory lookup that this is: either a
+ /// normal directory, a framework path, or a HeaderMap.
+ LookupType_t getLookupType() const { return (LookupType_t)LookupType; }
+
+ /// getName - Return the directory or filename corresponding to this lookup
+ /// object.
+ const char *getName() const;
+
+ /// getDir - Return the directory that this entry refers to.
+ ///
+ const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; }
+
+ /// getFrameworkDir - Return the directory that this framework refers to.
+ ///
+ const DirectoryEntry *getFrameworkDir() const {
+ return isFramework() ? u.Dir : 0;
+ }
+
+ /// getHeaderMap - Return the directory that this entry refers to.
+ ///
+ const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; }
+
+ /// isNormalDir - Return true if this is a normal directory, not a header map.
+ bool isNormalDir() const { return getLookupType() == LT_NormalDir; }
+
+ /// isFramework - True if this is a framework directory.
+ ///
+ bool isFramework() const { return getLookupType() == LT_Framework; }
+
+ /// isHeaderMap - Return true if this is a header map, not a normal directory.
+ bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; }
+
+ /// DirCharacteristic - The type of directory this is, one of the DirType enum
+ /// values.
+ SrcMgr::CharacteristicKind getDirCharacteristic() const {
+ return (SrcMgr::CharacteristicKind)DirCharacteristic;
+ }
+
+ /// isUserSupplied - True if this is a user-supplied directory.
+ ///
+ bool isUserSupplied() const { return UserSupplied; }
+
+
+ /// LookupFile - Lookup the specified file in this search path, returning it
+ /// if it exists or returning null if not.
+ const FileEntry *LookupFile(const char *FilenameStart,
+ const char *FilenameEnd, HeaderSearch &HS) const;
+
+private:
+ const FileEntry *DoFrameworkLookup(const char *FilenameStart,
+ const char *FilenameEnd,
+ HeaderSearch &HS) const;
+
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
new file mode 100644
index 000000000000..d8033093bd8e
--- /dev/null
+++ b/include/clang/Lex/HeaderMap.h
@@ -0,0 +1,67 @@
+//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the HeaderMap interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERMAP_H
+#define LLVM_CLANG_LEX_HEADERMAP_H
+
+namespace llvm {
+ class MemoryBuffer;
+}
+namespace clang {
+ class FileEntry;
+ class FileManager;
+ struct HMapBucket;
+ struct HMapHeader;
+
+/// This class represents an Apple concept known as a 'header map'. To the
+/// #include file resolution process, it basically acts like a directory of
+/// symlinks to files. Its advantages are that it is dense and more efficient
+/// to create and process than a directory of symlinks.
+class HeaderMap {
+ HeaderMap(const HeaderMap&); // DO NOT IMPLEMENT
+ void operator=(const HeaderMap&); // DO NOT IMPLEMENT
+
+ const llvm::MemoryBuffer *FileBuffer;
+ bool NeedsBSwap;
+
+ HeaderMap(const llvm::MemoryBuffer *File, bool BSwap)
+ : FileBuffer(File), NeedsBSwap(BSwap) {
+ }
+public:
+ ~HeaderMap();
+
+ /// HeaderMap::Create - This attempts to load the specified file as a header
+ /// map. If it doesn't look like a HeaderMap, it gives up and returns null.
+ static const HeaderMap *Create(const FileEntry *FE);
+
+ /// LookupFile - Check to see if the specified relative filename is located in
+ /// this HeaderMap. If so, open it and return its FileEntry.
+ const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
+ FileManager &FM) const;
+
+ /// getFileName - Return the filename of the headermap.
+ const char *getFileName() const;
+
+ /// dump - Print the contents of this headermap to stderr.
+ void dump() const;
+
+private:
+ unsigned getEndianAdjustedWord(unsigned X) const;
+ const HMapHeader &getHeader() const;
+ HMapBucket getBucket(unsigned BucketNo) const;
+ const char *getString(unsigned StrTabIdx) const;
+};
+
+} // end namespace clang.
+
+#endif
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
new file mode 100644
index 000000000000..f21aab1b4015
--- /dev/null
+++ b/include/clang/Lex/HeaderSearch.h
@@ -0,0 +1,237 @@
+//===--- HeaderSearch.h - Resolve Header File Locations ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the HeaderSearch interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
+#define LLVM_CLANG_LEX_HEADERSEARCH_H
+
+#include "clang/Lex/DirectoryLookup.h"
+#include "llvm/ADT/StringMap.h"
+#include <vector>
+
+namespace clang {
+
+class ExternalIdentifierLookup;
+class FileEntry;
+class FileManager;
+class IdentifierInfo;
+
+/// HeaderFileInfo - The preprocessor keeps track of this information for each
+/// file that is #included.
+struct HeaderFileInfo {
+ /// isImport - True if this is a #import'd or #pragma once file.
+ bool isImport : 1;
+
+ /// DirInfo - Keep track of whether this is a system header, and if so,
+ /// whether it is C++ clean or not. This can be set by the include paths or
+ /// by #pragma gcc system_header. This is an instance of
+ /// SrcMgr::CharacteristicKind.
+ unsigned DirInfo : 2;
+
+ /// NumIncludes - This is the number of times the file has been included
+ /// already.
+ unsigned short NumIncludes;
+
+ /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
+ /// that protects the entire contents of the file, this is the identifier
+ /// for the macro that controls whether or not it has any effect.
+ ///
+ /// Note: Most clients should use getControllingMacro() to access
+ /// the controlling macro of this header, since
+ /// getControllingMacro() is able to load a controlling macro from
+ /// external storage.
+ const IdentifierInfo *ControllingMacro;
+
+ /// \brief The ID number of the controlling macro.
+ ///
+ /// This ID number will be non-zero when there is a controlling
+ /// macro whose IdentifierInfo may not yet have been loaded from
+ /// external storage.
+ unsigned ControllingMacroID;
+
+ HeaderFileInfo()
+ : isImport(false), DirInfo(SrcMgr::C_User),
+ NumIncludes(0), ControllingMacro(0), ControllingMacroID(0) {}
+
+ /// \brief Retrieve the controlling macro for this header file, if
+ /// any.
+ const IdentifierInfo *getControllingMacro(ExternalIdentifierLookup *External);
+};
+
+/// HeaderSearch - This class encapsulates the information needed to find the
+/// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
+class HeaderSearch {
+ FileManager &FileMgr;
+
+ /// #include search path information. Requests for #include "x" search the
+ /// directory of the #including file first, then each directory in SearchDirs
+ /// consequtively. Requests for <x> search the current dir first, then each
+ /// directory in SearchDirs, starting at SystemDirIdx, consequtively. If
+ /// NoCurDirSearch is true, then the check for the file in the current
+ /// directory is supressed.
+ std::vector<DirectoryLookup> SearchDirs;
+ unsigned SystemDirIdx;
+ bool NoCurDirSearch;
+
+ /// FileInfo - This contains all of the preprocessor-specific data about files
+ /// that are included. The vector is indexed by the FileEntry's UID.
+ ///
+ std::vector<HeaderFileInfo> FileInfo;
+
+ /// LookupFileCache - This is keeps track of each lookup performed by
+ /// LookupFile. The first part of the value is the starting index in
+ /// SearchDirs that the cached search was performed from. If there is a hit
+ /// and this value doesn't match the current query, the cache has to be
+ /// ignored. The second value is the entry in SearchDirs that satisfied the
+ /// query.
+ llvm::StringMap<std::pair<unsigned, unsigned> > LookupFileCache;
+
+
+ /// FrameworkMap - This is a collection mapping a framework or subframework
+ /// name like "Carbon" to the Carbon.framework directory.
+ llvm::StringMap<const DirectoryEntry *> FrameworkMap;
+
+ /// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
+ /// headermaps. This vector owns the headermap.
+ std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
+
+ /// \brief Entity used to resolve the identifier IDs of controlling
+ /// macros into IdentifierInfo pointers, as needed.
+ ExternalIdentifierLookup *ExternalLookup;
+
+ // Various statistics we track for performance analysis.
+ unsigned NumIncluded;
+ unsigned NumMultiIncludeFileOptzn;
+ unsigned NumFrameworkLookups, NumSubFrameworkLookups;
+
+ // HeaderSearch doesn't support default or copy construction.
+ explicit HeaderSearch();
+ explicit HeaderSearch(const HeaderSearch&);
+ void operator=(const HeaderSearch&);
+public:
+ HeaderSearch(FileManager &FM);
+ ~HeaderSearch();
+
+ FileManager &getFileMgr() const { return FileMgr; }
+
+ /// SetSearchPaths - Interface for setting the file search paths.
+ ///
+ void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
+ unsigned systemDirIdx, bool noCurDirSearch) {
+ SearchDirs = dirs;
+ SystemDirIdx = systemDirIdx;
+ NoCurDirSearch = noCurDirSearch;
+ //LookupFileCache.clear();
+ }
+
+ /// ClearFileInfo - Forget everything we know about headers so far.
+ void ClearFileInfo() {
+ FileInfo.clear();
+ }
+
+ void SetExternalLookup(ExternalIdentifierLookup *EIL) {
+ ExternalLookup = EIL;
+ }
+
+ /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// return null on failure. isAngled indicates whether the file reference is
+ /// a <> reference. If successful, this returns 'UsedDir', the
+ /// DirectoryLookup member the file was found in, or null if not applicable.
+ /// If CurDir is non-null, the file was found in the specified directory
+ /// search location. This is used to implement #include_next. CurFileEnt, if
+ /// non-null, indicates where the #including file is, in case a relative
+ /// search is needed.
+ const FileEntry *LookupFile(const char *FilenameStart,
+ const char *FilenameEnd, bool isAngled,
+ const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir,
+ const FileEntry *CurFileEnt);
+
+ /// LookupSubframeworkHeader - Look up a subframework for the specified
+ /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
+ /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
+ /// is a subframework within Carbon.framework. If so, return the FileEntry
+ /// for the designated file, otherwise return null.
+ const FileEntry *LookupSubframeworkHeader(const char *FilenameStart,
+ const char *FilenameEnd,
+ const FileEntry *RelativeFileEnt);
+
+ /// LookupFrameworkCache - Look up the specified framework name in our
+ /// framework cache, returning the DirectoryEntry it is in if we know,
+ /// otherwise, return null.
+ const DirectoryEntry *&LookupFrameworkCache(const char *FWNameStart,
+ const char *FWNameEnd) {
+ return FrameworkMap.GetOrCreateValue(FWNameStart, FWNameEnd).getValue();
+ }
+
+ /// ShouldEnterIncludeFile - Mark the specified file as a target of of a
+ /// #include, #include_next, or #import directive. Return false if #including
+ /// the file will have no effect or true if we should include it.
+ bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport);
+
+
+ /// getFileDirFlavor - Return whether the specified file is a normal header,
+ /// a system header, or a C++ friendly system header.
+ SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
+ return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
+ }
+
+ /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
+ /// due to #pragma once.
+ void MarkFileIncludeOnce(const FileEntry *File) {
+ getFileInfo(File).isImport = true;
+ }
+
+ /// MarkFileSystemHeader - Mark the specified file as a system header, e.g.
+ /// due to #pragma GCC system_header.
+ void MarkFileSystemHeader(const FileEntry *File) {
+ getFileInfo(File).DirInfo = SrcMgr::C_System;
+ }
+
+ /// IncrementIncludeCount - Increment the count for the number of times the
+ /// specified FileEntry has been entered.
+ void IncrementIncludeCount(const FileEntry *File) {
+ ++getFileInfo(File).NumIncludes;
+ }
+
+ /// SetFileControllingMacro - Mark the specified file as having a controlling
+ /// macro. This is used by the multiple-include optimization to eliminate
+ /// no-op #includes.
+ void SetFileControllingMacro(const FileEntry *File,
+ const IdentifierInfo *ControllingMacro) {
+ getFileInfo(File).ControllingMacro = ControllingMacro;
+ }
+
+ /// CreateHeaderMap - This method returns a HeaderMap for the specified
+ /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
+ const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+
+ void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
+
+ typedef std::vector<HeaderFileInfo>::iterator header_file_iterator;
+ header_file_iterator header_file_begin() { return FileInfo.begin(); }
+ header_file_iterator header_file_end() { return FileInfo.end(); }
+
+ // Used by PCHReader.
+ void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
+
+ void PrintStats();
+private:
+
+ /// getFileInfo - Return the HeaderFileInfo structure for the specified
+ /// FileEntry.
+ HeaderFileInfo &getFileInfo(const FileEntry *FE);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h
new file mode 100644
index 000000000000..1502efb55e63
--- /dev/null
+++ b/include/clang/Lex/LexDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticLex.h - Diagnostics for liblex ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICLEX_H
+#define LLVM_CLANG_DIAGNOSTICLEX_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define LEXSTART
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_LEX_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
new file mode 100644
index 000000000000..3a73147152af
--- /dev/null
+++ b/include/clang/Lex/Lexer.h
@@ -0,0 +1,376 @@
+//===--- Lexer.h - C Language Family Lexer ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Lexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEXER_H
+#define LLVM_CLANG_LEXER_H
+
+#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+#include <vector>
+#include <cassert>
+
+namespace clang {
+class Diagnostic;
+class SourceManager;
+class Preprocessor;
+class DiagnosticBuilder;
+
+/// Lexer - This provides a simple interface that turns a text buffer into a
+/// stream of tokens. This provides no support for file reading or buffering,
+/// or buffering/seeking of tokens, only forward lexing is supported. It relies
+/// on the specified Preprocessor object to handle preprocessor directives, etc.
+class Lexer : public PreprocessorLexer {
+ //===--------------------------------------------------------------------===//
+ // Constant configuration values for this lexer.
+ const char *BufferStart; // Start of the buffer.
+ const char *BufferEnd; // End of the buffer.
+ SourceLocation FileLoc; // Location for start of file.
+ LangOptions Features; // Features enabled by this language (cache).
+ bool Is_PragmaLexer; // True if lexer for _Pragma handling.
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //
+
+ /// ExtendedTokenMode - The lexer can optionally keep comments and whitespace
+ /// and return them as tokens. This is used for -C and -CC modes, and
+ /// whitespace preservation can be useful for some clients that want to lex
+ /// the file in raw mode and get every character from the file.
+ ///
+ /// When this is set to 2 it returns comments and whitespace. When set to 1
+ /// it returns comments, when it is set to 0 it returns normal tokens only.
+ unsigned char ExtendedTokenMode;
+
+ //===--------------------------------------------------------------------===//
+ // Context that changes as the file is lexed.
+ // NOTE: any state that mutates when in raw mode must have save/restore code
+ // in Lexer::isNextPPTokenLParen.
+
+ // BufferPtr - Current pointer into the buffer. This is the next character
+ // to be lexed.
+ const char *BufferPtr;
+
+ // IsAtStartOfLine - True if the next lexed token should get the "start of
+ // line" flag set on it.
+ bool IsAtStartOfLine;
+
+ Lexer(const Lexer&); // DO NOT IMPLEMENT
+ void operator=(const Lexer&); // DO NOT IMPLEMENT
+ friend class Preprocessor;
+
+ void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd);
+public:
+
+ /// Lexer constructor - Create a new lexer object for the specified buffer
+ /// with the specified preprocessor managing the lexing process. This lexer
+ /// assumes that the associated file buffer and Preprocessor objects will
+ /// outlive it, so it doesn't take ownership of either of them.
+ Lexer(FileID FID, Preprocessor &PP);
+
+ /// Lexer constructor - Create a new raw lexer object. This object is only
+ /// suitable for calls to 'LexRawToken'. This lexer assumes that the text
+ /// range will outlive it, so it doesn't take ownership of it.
+ Lexer(SourceLocation FileLoc, const LangOptions &Features,
+ const char *BufStart, const char *BufPtr, const char *BufEnd);
+
+ /// Lexer constructor - Create a new raw lexer object. This object is only
+ /// suitable for calls to 'LexRawToken'. This lexer assumes that the text
+ /// range will outlive it, so it doesn't take ownership of it.
+ Lexer(FileID FID, const SourceManager &SM, const LangOptions &Features);
+
+ /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
+ /// _Pragma expansion. This has a variety of magic semantics that this method
+ /// sets up. It returns a new'd Lexer that must be delete'd when done.
+ static Lexer *Create_PragmaLexer(SourceLocation SpellingLoc,
+ SourceLocation InstantiationLocStart,
+ SourceLocation InstantiationLocEnd,
+ unsigned TokLen, Preprocessor &PP);
+
+
+ /// getFeatures - Return the language features currently enabled. NOTE: this
+ /// lexer modifies features as a file is parsed!
+ const LangOptions &getFeatures() const { return Features; }
+
+ /// getFileLoc - Return the File Location for the file we are lexing out of.
+ /// The physical location encodes the location where the characters come from,
+ /// the virtual location encodes where we should *claim* the characters came
+ /// from. Currently this is only used by _Pragma handling.
+ SourceLocation getFileLoc() const { return FileLoc; }
+
+ /// Lex - Return the next token in the file. If this is the end of file, it
+ /// return the tok::eof token. Return true if an error occurred and
+ /// compilation should terminate, false if normal. This implicitly involves
+ /// the preprocessor.
+ void Lex(Token &Result) {
+ // Start a new token.
+ Result.startToken();
+
+ // NOTE, any changes here should also change code after calls to
+ // Preprocessor::HandleDirective
+ if (IsAtStartOfLine) {
+ Result.setFlag(Token::StartOfLine);
+ IsAtStartOfLine = false;
+ }
+
+ // Get a token. Note that this may delete the current lexer if the end of
+ // file is reached.
+ LexTokenInternal(Result);
+ }
+
+ /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
+ bool isPragmaLexer() const { return Is_PragmaLexer; }
+
+ /// IndirectLex - An indirect call to 'Lex' that can be invoked via
+ /// the PreprocessorLexer interface.
+ void IndirectLex(Token &Result) { Lex(Result); }
+
+ /// LexFromRawLexer - Lex a token from a designated raw lexer (one with no
+ /// associated preprocessor object. Return true if the 'next character to
+ /// read' pointer points at the end of the lexer buffer, false otherwise.
+ bool LexFromRawLexer(Token &Result) {
+ assert(LexingRawMode && "Not already in raw mode!");
+ Lex(Result);
+ // Note that lexing to the end of the buffer doesn't implicitly delete the
+ // lexer when in raw mode.
+ return BufferPtr == BufferEnd;
+ }
+
+ /// isKeepWhitespaceMode - Return true if the lexer should return tokens for
+ /// every character in the file, including whitespace and comments. This
+ /// should only be used in raw mode, as the preprocessor is not prepared to
+ /// deal with the excess tokens.
+ bool isKeepWhitespaceMode() const {
+ return ExtendedTokenMode > 1;
+ }
+
+ /// SetKeepWhitespaceMode - This method lets clients enable or disable
+ /// whitespace retention mode.
+ void SetKeepWhitespaceMode(bool Val) {
+ assert((!Val || LexingRawMode) &&
+ "Can only enable whitespace retention in raw mode");
+ ExtendedTokenMode = Val ? 2 : 0;
+ }
+
+ /// inKeepCommentMode - Return true if the lexer should return comments as
+ /// tokens.
+ bool inKeepCommentMode() const {
+ return ExtendedTokenMode > 0;
+ }
+
+ /// SetCommentRetentionMode - Change the comment retention mode of the lexer
+ /// to the specified mode. This is really only useful when lexing in raw
+ /// mode, because otherwise the lexer needs to manage this.
+ void SetCommentRetentionState(bool Mode) {
+ assert(!isKeepWhitespaceMode() &&
+ "Can't play with comment retention state when retaining whitespace");
+ ExtendedTokenMode = Mode ? 1 : 0;
+ }
+
+ const char *getBufferStart() const { return BufferStart; }
+
+ /// ReadToEndOfLine - Read the rest of the current preprocessor line as an
+ /// uninterpreted string. This switches the lexer out of directive mode.
+ std::string ReadToEndOfLine();
+
+
+ /// Diag - Forwarding function for diagnostics. This translate a source
+ /// position in the current buffer into a SourceLocation object for rendering.
+ DiagnosticBuilder Diag(const char *Loc, unsigned DiagID) const;
+
+ /// getSourceLocation - Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getSourceLocation(const char *Loc, unsigned TokLen = 1) const;
+
+ /// getSourceLocation - Return a source location for the next character in
+ /// the current file.
+ SourceLocation getSourceLocation() { return getSourceLocation(BufferPtr); }
+
+ /// Stringify - Convert the specified string into a C string by escaping '\'
+ /// and " characters. This does not add surrounding ""'s to the string.
+ /// If Charify is true, this escapes the ' character instead of ".
+ static std::string Stringify(const std::string &Str, bool Charify = false);
+
+ /// Stringify - Convert the specified string into a C string by escaping '\'
+ /// and " characters. This does not add surrounding ""'s to the string.
+ static void Stringify(llvm::SmallVectorImpl<char> &Str);
+
+ /// MeasureTokenLength - Relex the token at the specified location and return
+ /// its length in bytes in the input file. If the token needs cleaning (e.g.
+ /// includes a trigraph or an escaped newline) then this count includes bytes
+ /// that are part of that.
+ static unsigned MeasureTokenLength(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ //===--------------------------------------------------------------------===//
+ // Internal implementation interfaces.
+private:
+
+ /// LexTokenInternal - Internal interface to lex a preprocessing token. Called
+ /// by Lex.
+ ///
+ void LexTokenInternal(Token &Result);
+
+ /// FormTokenWithChars - When we lex a token, we have identified a span
+ /// starting at BufferPtr, going to TokEnd that forms the token. This method
+ /// takes that range and assigns it to the token as its location and size. In
+ /// addition, since tokens cannot overlap, this also updates BufferPtr to be
+ /// TokEnd.
+ void FormTokenWithChars(Token &Result, const char *TokEnd,
+ tok::TokenKind Kind) {
+ unsigned TokLen = TokEnd-BufferPtr;
+ Result.setLength(TokLen);
+ Result.setLocation(getSourceLocation(BufferPtr, TokLen));
+ Result.setKind(Kind);
+ BufferPtr = TokEnd;
+ }
+
+ /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
+ /// tok::l_paren token, 0 if it is something else and 2 if there are no more
+ /// tokens in the buffer controlled by this lexer.
+ unsigned isNextPPTokenLParen();
+
+ //===--------------------------------------------------------------------===//
+ // Lexer character reading interfaces.
+public:
+
+ // This lexer is built on two interfaces for reading characters, both of which
+ // automatically provide phase 1/2 translation. getAndAdvanceChar is used
+ // when we know that we will be reading a character from the input buffer and
+ // that this character will be part of the result token. This occurs in (f.e.)
+ // string processing, because we know we need to read until we find the
+ // closing '"' character.
+ //
+ // The second interface is the combination of PeekCharAndSize with
+ // ConsumeChar. PeekCharAndSize reads a phase 1/2 translated character,
+ // returning it and its size. If the lexer decides that this character is
+ // part of the current token, it calls ConsumeChar on it. This two stage
+ // approach allows us to emit diagnostics for characters (e.g. warnings about
+ // trigraphs), knowing that they only are emitted if the character is
+ // consumed.
+
+ /// isObviouslySimpleCharacter - Return true if the specified character is
+ /// obviously the same in translation phase 1 and translation phase 3. This
+ /// can return false for characters that end up being the same, but it will
+ /// never return true for something that needs to be mapped.
+ static bool isObviouslySimpleCharacter(char C) {
+ return C != '?' && C != '\\';
+ }
+
+ /// getAndAdvanceChar - Read a single 'character' from the specified buffer,
+ /// advance over it, and return it. This is tricky in several cases. Here we
+ /// just handle the trivial case and fall-back to the non-inlined
+ /// getCharAndSizeSlow method to handle the hard case.
+ inline char getAndAdvanceChar(const char *&Ptr, Token &Tok) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) return *Ptr++;
+
+ unsigned Size = 0;
+ char C = getCharAndSizeSlow(Ptr, Size, &Tok);
+ Ptr += Size;
+ return C;
+ }
+
+private:
+ /// ConsumeChar - When a character (identified by PeekCharAndSize) is consumed
+ /// and added to a given token, check to see if there are diagnostics that
+ /// need to be emitted or flags that need to be set on the token. If so, do
+ /// it.
+ const char *ConsumeChar(const char *Ptr, unsigned Size, Token &Tok) {
+ // Normal case, we consumed exactly one token. Just return it.
+ if (Size == 1)
+ return Ptr+Size;
+
+ // Otherwise, re-lex the character with a current token, allowing
+ // diagnostics to be emitted and flags to be set.
+ Size = 0;
+ getCharAndSizeSlow(Ptr, Size, &Tok);
+ return Ptr+Size;
+ }
+
+ /// getCharAndSize - Peek a single 'character' from the specified buffer,
+ /// get its size, and return it. This is tricky in several cases. Here we
+ /// just handle the trivial case and fall-back to the non-inlined
+ /// getCharAndSizeSlow method to handle the hard case.
+ inline char getCharAndSize(const char *Ptr, unsigned &Size) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) {
+ Size = 1;
+ return *Ptr;
+ }
+
+ Size = 0;
+ return getCharAndSizeSlow(Ptr, Size);
+ }
+
+ /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize
+ /// method.
+ char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0);
+public:
+
+ /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever
+ /// emit a warning.
+ static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &Features) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) {
+ Size = 1;
+ return *Ptr;
+ }
+
+ Size = 0;
+ return getCharAndSizeSlowNoWarn(Ptr, Size, Features);
+ }
+
+ /// getEscapedNewLineSize - Return the size of the specified escaped newline,
+ /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry
+ /// to this function.
+ static unsigned getEscapedNewLineSize(const char *P);
+
+ /// SkipEscapedNewLines - If P points to an escaped newline (or a series of
+ /// them), skip over them and return the first non-escaped-newline found,
+ /// otherwise return P.
+ static const char *SkipEscapedNewLines(const char *P);
+private:
+
+ /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a
+ /// diagnostic.
+ static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &Features);
+
+ //===--------------------------------------------------------------------===//
+ // Other lexer functions.
+
+ // Helper functions to lex the remainder of a token of the specific type.
+ void LexIdentifier (Token &Result, const char *CurPtr);
+ void LexNumericConstant (Token &Result, const char *CurPtr);
+ void LexStringLiteral (Token &Result, const char *CurPtr,bool Wide);
+ void LexAngledStringLiteral(Token &Result, const char *CurPtr);
+ void LexCharConstant (Token &Result, const char *CurPtr);
+ bool LexEndOfFile (Token &Result, const char *CurPtr);
+
+ bool SkipWhitespace (Token &Result, const char *CurPtr);
+ bool SkipBCPLComment (Token &Result, const char *CurPtr);
+ bool SkipBlockComment (Token &Result, const char *CurPtr);
+ bool SaveBCPLComment (Token &Result, const char *CurPtr);
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
new file mode 100644
index 000000000000..8ee8ecf7359f
--- /dev/null
+++ b/include/clang/Lex/LiteralSupport.h
@@ -0,0 +1,176 @@
+//===--- LiteralSupport.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NumericLiteralParser, CharLiteralParser, and
+// StringLiteralParser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LITERALSUPPORT_H
+#define CLANG_LITERALSUPPORT_H
+
+#include <string>
+#include "llvm/ADT/SmallString.h"
+
+namespace llvm {
+ class APInt;
+ class APFloat;
+ struct fltSemantics;
+}
+
+namespace clang {
+
+class Diagnostic;
+class Preprocessor;
+class Token;
+class SourceLocation;
+class TargetInfo;
+
+/// NumericLiteralParser - This performs strict semantic analysis of the content
+/// of a ppnumber, classifying it as either integer, floating, or erroneous,
+/// determines the radix of the value and can convert it to a useful value.
+class NumericLiteralParser {
+ Preprocessor &PP; // needed for diagnostics
+
+ const char *const ThisTokBegin;
+ const char *const ThisTokEnd;
+ const char *DigitsBegin, *SuffixBegin; // markers
+ const char *s; // cursor
+
+ unsigned radix;
+
+ bool saw_exponent, saw_period;
+
+public:
+ NumericLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP);
+ bool hadError;
+ bool isUnsigned;
+ bool isLong; // This is *not* set for long long.
+ bool isLongLong;
+ bool isFloat; // 1.0f
+ bool isImaginary; // 1.0i
+
+ bool isIntegerLiteral() const {
+ return !saw_period && !saw_exponent;
+ }
+ bool isFloatingLiteral() const {
+ return saw_period || saw_exponent;
+ }
+ bool hasSuffix() const {
+ return SuffixBegin != ThisTokEnd;
+ }
+
+ unsigned getRadix() const { return radix; }
+
+ /// GetIntegerValue - Convert this numeric literal value to an APInt that
+ /// matches Val's input width. If there is an overflow (i.e., if the unsigned
+ /// value read is larger than the APInt's bits will hold), set Val to the low
+ /// bits of the result and return true. Otherwise, return false.
+ bool GetIntegerValue(llvm::APInt &Val);
+
+ /// GetFloatValue - Convert this numeric literal to a floating value, using
+ /// the specified APFloat fltSemantics (specifying float, double, etc).
+ /// The optional bool isExact (passed-by-reference) has its value
+ /// set to true if the returned APFloat can represent the number in the
+ /// literal exactly, and false otherwise.
+ llvm::APFloat GetFloatValue(const llvm::fltSemantics &Format,
+ bool* isExact = NULL);
+
+private:
+
+ void ParseNumberStartingWithZero(SourceLocation TokLoc);
+
+ /// SkipHexDigits - Read and skip over any hex digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipHexDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && isxdigit(*ptr))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipOctalDigits - Read and skip over any octal digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipOctalDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && ((*ptr >= '0') && (*ptr <= '7')))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipDigits - Read and skip over any digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && isdigit(*ptr))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipBinaryDigits - Read and skip over any binary digits, up to End.
+ /// Return a pointer to the first non-binary digit or End.
+ const char *SkipBinaryDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && (*ptr == '0' || *ptr == '1'))
+ ptr++;
+ return ptr;
+ }
+
+};
+
+/// CharLiteralParser - Perform interpretation and semantic analysis of a
+/// character literal.
+class CharLiteralParser {
+ uint64_t Value;
+ bool IsWide;
+ bool IsMultiChar;
+ bool HadError;
+public:
+ CharLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP);
+
+ bool hadError() const { return HadError; }
+ bool isWide() const { return IsWide; }
+ bool isMultiChar() const { return IsMultiChar; }
+ uint64_t getValue() const { return Value; }
+};
+
+/// StringLiteralParser - This decodes string escape characters and performs
+/// wide string analysis and Translation Phase #6 (concatenation of string
+/// literals) (C99 5.1.1.2p1).
+class StringLiteralParser {
+ Preprocessor &PP;
+
+ unsigned MaxTokenLength;
+ unsigned SizeBound;
+ unsigned wchar_tByteWidth;
+ llvm::SmallString<512> ResultBuf;
+ char *ResultPtr; // cursor
+public:
+ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ Preprocessor &PP);
+ bool hadError;
+ bool AnyWide;
+ bool Pascal;
+
+ const char *GetString() { return &ResultBuf[0]; }
+ unsigned GetStringLength() const { return ResultPtr-&ResultBuf[0]; }
+
+ unsigned GetNumStringChars() const {
+ if (AnyWide)
+ return GetStringLength() / wchar_tByteWidth;
+ return GetStringLength();
+ }
+ /// getOffsetOfStringByte - This function returns the offset of the
+ /// specified byte of the string data represented by Token. This handles
+ /// advancing over escape sequences in the string.
+ static unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo,
+ Preprocessor &PP);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
new file mode 100644
index 000000000000..ccd13c80d354
--- /dev/null
+++ b/include/clang/Lex/MacroInfo.h
@@ -0,0 +1,218 @@
+//===--- MacroInfo.h - Information about #defined identifiers ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MacroInfo interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_MACROINFO_H
+#define LLVM_CLANG_MACROINFO_H
+
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+#include <cassert>
+
+namespace clang {
+ class Preprocessor;
+
+/// MacroInfo - Each identifier that is #define'd has an instance of this class
+/// associated with it, used to implement macro expansion.
+class MacroInfo {
+ //===--------------------------------------------------------------------===//
+ // State set when the macro is defined.
+
+ /// Location - This is the place the macro is defined.
+ SourceLocation Location;
+ /// EndLocation - The location of the last token in the macro.
+ SourceLocation EndLocation;
+
+ /// Arguments - The list of arguments for a function-like macro. This can be
+ /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this
+ /// includes the __VA_ARGS__ identifier on the list.
+ IdentifierInfo **ArgumentList;
+ unsigned NumArguments;
+
+ /// ReplacementTokens - This is the list of tokens that the macro is defined
+ /// to.
+ llvm::SmallVector<Token, 8> ReplacementTokens;
+
+ /// IsFunctionLike - True if this macro is a function-like macro, false if it
+ /// is an object-like macro.
+ bool IsFunctionLike : 1;
+
+ /// IsC99Varargs - True if this macro is of the form "#define X(...)" or
+ /// "#define X(Y,Z,...)". The __VA_ARGS__ token should be replaced with the
+ /// contents of "..." in an invocation.
+ bool IsC99Varargs : 1;
+
+ /// IsGNUVarargs - True if this macro is of the form "#define X(a...)". The
+ /// "a" identifier in the replacement list will be replaced with all arguments
+ /// of the macro starting with the specified one.
+ bool IsGNUVarargs : 1;
+
+ /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if
+ /// it has not yet been redefined or undefined.
+ bool IsBuiltinMacro : 1;
+
+private:
+ //===--------------------------------------------------------------------===//
+ // State that changes as the macro is used.
+
+ /// IsDisabled - True if we have started an expansion of this macro already.
+ /// This disbles recursive expansion, which would be quite bad for things like
+ /// #define A A.
+ bool IsDisabled : 1;
+
+ /// IsUsed - True if this macro is either defined in the main file and has
+ /// been used, or if it is not defined in the main file. This is used to
+ /// emit -Wunused-macros diagnostics.
+ bool IsUsed : 1;
+
+ ~MacroInfo() {
+ assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
+ }
+
+public:
+ MacroInfo(SourceLocation DefLoc);
+
+ /// FreeArgumentList - Free the argument list of the macro, restoring it to a
+ /// state where it can be reused for other devious purposes.
+ void FreeArgumentList(llvm::BumpPtrAllocator &PPAllocator) {
+ PPAllocator.Deallocate(ArgumentList);
+ ArgumentList = 0;
+ NumArguments = 0;
+ }
+
+ /// Destroy - destroy this MacroInfo object.
+ void Destroy(llvm::BumpPtrAllocator &PPAllocator) {
+ FreeArgumentList(PPAllocator);
+ this->~MacroInfo();
+ }
+
+ /// getDefinitionLoc - Return the location that the macro was defined at.
+ ///
+ SourceLocation getDefinitionLoc() const { return Location; }
+
+ /// setDefinitionEndLoc - Set the location of the last token in the macro.
+ ///
+ void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
+ /// getDefinitionEndLoc - Return the location of the last token in the macro.
+ ///
+ SourceLocation getDefinitionEndLoc() const { return EndLocation; }
+
+ /// isIdenticalTo - Return true if the specified macro definition is equal to
+ /// this macro in spelling, arguments, and whitespace. This is used to emit
+ /// duplicate definition warnings. This implements the rules in C99 6.10.3.
+ bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const;
+
+ /// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag.
+ ///
+ void setIsBuiltinMacro(bool Val = true) {
+ IsBuiltinMacro = Val;
+ }
+
+ /// setIsUsed - Set the value of the IsUsed flag.
+ ///
+ void setIsUsed(bool Val) {
+ IsUsed = Val;
+ }
+
+ /// setArgumentList - Set the specified list of identifiers as the argument
+ /// list for this macro.
+ void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
+ llvm::BumpPtrAllocator &PPAllocator) {
+ assert(ArgumentList == 0 && NumArguments == 0 &&
+ "Argument list already set!");
+ if (NumArgs == 0) return;
+
+ NumArguments = NumArgs;
+ ArgumentList = PPAllocator.Allocate<IdentifierInfo*>(NumArgs);
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ArgumentList[i] = List[i];
+ }
+
+ /// Arguments - The list of arguments for a function-like macro. This can be
+ /// empty, for, e.g. "#define X()".
+ typedef IdentifierInfo* const *arg_iterator;
+ bool arg_empty() const { return NumArguments == 0; }
+ arg_iterator arg_begin() const { return ArgumentList; }
+ arg_iterator arg_end() const { return ArgumentList+NumArguments; }
+ unsigned getNumArgs() const { return NumArguments; }
+
+ /// getArgumentNum - Return the argument number of the specified identifier,
+ /// or -1 if the identifier is not a formal argument identifier.
+ int getArgumentNum(IdentifierInfo *Arg) const {
+ for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I)
+ if (*I == Arg) return I-arg_begin();
+ return -1;
+ }
+
+ /// Function/Object-likeness. Keep track of whether this macro has formal
+ /// parameters.
+ void setIsFunctionLike() { IsFunctionLike = true; }
+ bool isFunctionLike() const { return IsFunctionLike; }
+ bool isObjectLike() const { return !IsFunctionLike; }
+
+ /// Varargs querying methods. This can only be set for function-like macros.
+ void setIsC99Varargs() { IsC99Varargs = true; }
+ void setIsGNUVarargs() { IsGNUVarargs = true; }
+ bool isC99Varargs() const { return IsC99Varargs; }
+ bool isGNUVarargs() const { return IsGNUVarargs; }
+ bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }
+
+ /// isBuiltinMacro - Return true if this macro is a builtin macro, such as
+ /// __LINE__, which requires processing before expansion.
+ bool isBuiltinMacro() const { return IsBuiltinMacro; }
+
+ /// isUsed - Return false if this macro is defined in the main file and has
+ /// not yet been used.
+ bool isUsed() const { return IsUsed; }
+
+ /// getNumTokens - Return the number of tokens that this macro expands to.
+ ///
+ unsigned getNumTokens() const {
+ return ReplacementTokens.size();
+ }
+
+ const Token &getReplacementToken(unsigned Tok) const {
+ assert(Tok < ReplacementTokens.size() && "Invalid token #");
+ return ReplacementTokens[Tok];
+ }
+
+ typedef llvm::SmallVector<Token, 8>::const_iterator tokens_iterator;
+ tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
+ tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
+ bool tokens_empty() const { return ReplacementTokens.empty(); }
+
+ /// AddTokenToBody - Add the specified token to the replacement text for the
+ /// macro.
+ void AddTokenToBody(const Token &Tok) {
+ ReplacementTokens.push_back(Tok);
+ }
+
+ /// isEnabled - Return true if this macro is enabled: in other words, that we
+ /// are not currently in an expansion of this macro.
+ bool isEnabled() const { return !IsDisabled; }
+
+ void EnableMacro() {
+ assert(IsDisabled && "Cannot enable an already-enabled macro!");
+ IsDisabled = false;
+ }
+
+ void DisableMacro() {
+ assert(!IsDisabled && "Cannot disable an already-disabled macro!");
+ IsDisabled = true;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h
new file mode 100644
index 000000000000..94d4677f9d29
--- /dev/null
+++ b/include/clang/Lex/MultipleIncludeOpt.h
@@ -0,0 +1,130 @@
+//===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MultipleIncludeOpt interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H
+#define LLVM_CLANG_MULTIPLEINCLUDEOPT_H
+
+namespace clang {
+class IdentifierInfo;
+
+/// MultipleIncludeOpt - This class implements the simple state machine that the
+/// Lexer class uses to detect files subject to the 'multiple-include'
+/// optimization. The public methods in this class are triggered by various
+/// events that occur when a file is lexed, and after the entire file is lexed,
+/// information about which macro (if any) controls the header is returned.
+class MultipleIncludeOpt {
+ /// ReadAnyTokens - This is set to false when a file is first opened and true
+ /// any time a token is returned to the client or a (non-multiple-include)
+ /// directive is parsed. When the final #endif is parsed this is reset back
+ /// to false, that way any tokens before the first #ifdef or after the last
+ /// #endif can be easily detected.
+ bool ReadAnyTokens;
+
+ /// ReadAnyTokens - This is set to false when a file is first opened and true
+ /// any time a token is returned to the client or a (non-multiple-include)
+ /// directive is parsed. When the final #endif is parsed this is reset back
+ /// to false, that way any tokens before the first #ifdef or after the last
+ /// #endif can be easily detected.
+ bool DidMacroExpansion;
+
+ /// TheMacro - The controlling macro for a file, if valid.
+ ///
+ const IdentifierInfo *TheMacro;
+public:
+ MultipleIncludeOpt() {
+ ReadAnyTokens = false;
+ DidMacroExpansion = false;
+ TheMacro = 0;
+ }
+
+ /// Invalidate - Permenantly mark this file as not being suitable for the
+ /// include-file optimization.
+ void Invalidate() {
+ // If we have read tokens but have no controlling macro, the state-machine
+ // below can never "accept".
+ ReadAnyTokens = true;
+ TheMacro = 0;
+ }
+
+ /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the
+ /// top of the file when reading preprocessor directives. Otherwise, reading
+ /// the "ifndef x" would count as reading tokens.
+ bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
+
+ // If a token is read, remember that we have seen a side-effect in this file.
+ void ReadToken() { ReadAnyTokens = true; }
+
+ /// ExpandedMacro - When a macro is expanded with this lexer as the current
+ /// buffer, this method is called to disable the MIOpt if needed.
+ void ExpandedMacro() { DidMacroExpansion = true; }
+
+ /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the
+ /// "#if !defined" equivalent) without any preceding tokens, this method is
+ /// called.
+ ///
+ /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
+ /// ensures that this is only called if there are no tokens read before the
+ /// #ifndef. The caller is required to do this, because reading the #if line
+ /// obviously reads in in tokens.
+ void EnterTopLevelIFNDEF(const IdentifierInfo *M) {
+ // If the macro is already set, this is after the top-level #endif.
+ if (TheMacro)
+ return Invalidate();
+
+ // If we have already expanded a macro by the end of the #ifndef line, then
+ // there is a macro expansion *in* the #ifndef line. This means that the
+ // condition could evaluate differently when subsequently #included. Reject
+ // this.
+ if (DidMacroExpansion)
+ return Invalidate();
+
+ // Remember that we're in the #if and that we have the macro.
+ ReadAnyTokens = true;
+ TheMacro = M;
+ }
+
+ /// EnterTopLevelConditional - This is invoked when a top level conditional
+ /// (except #ifndef) is found.
+ void EnterTopLevelConditional() {
+ /// If a conditional directive (except #ifndef) is found at the top level,
+ /// there is a chunk of the file not guarded by the controlling macro.
+ Invalidate();
+ }
+
+ /// ExitTopLevelConditional - This method is called when the lexer exits the
+ /// top-level conditional.
+ void ExitTopLevelConditional() {
+ // If we have a macro, that means the top of the file was ok. Set our state
+ // back to "not having read any tokens" so we can detect anything after the
+ // #endif.
+ if (!TheMacro) return Invalidate();
+
+ // At this point, we haven't "read any tokens" but we do have a controlling
+ // macro.
+ ReadAnyTokens = false;
+ }
+
+ /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if
+ /// there is a controlling macro, return it.
+ const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
+ // If we haven't read any tokens after the #endif, return the controlling
+ // macro if it's valid (if it isn't, it will be null).
+ if (!ReadAnyTokens)
+ return TheMacro;
+ return 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
new file mode 100644
index 000000000000..e5cbeebd22aa
--- /dev/null
+++ b/include/clang/Lex/PPCallbacks.h
@@ -0,0 +1,122 @@
+//===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PPCallbacks interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
+#define LLVM_CLANG_LEX_PPCALLBACKS_H
+
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Basic/SourceLocation.h"
+#include <string>
+
+namespace clang {
+ class SourceLocation;
+ class Token;
+ class IdentifierInfo;
+ class MacroInfo;
+
+/// PPCallbacks - This interface provides a way to observe the actions of the
+/// preprocessor as it does its thing. Clients can define their hooks here to
+/// implement preprocessor level tools.
+class PPCallbacks {
+public:
+ virtual ~PPCallbacks();
+
+ enum FileChangeReason {
+ EnterFile, ExitFile, SystemHeaderPragma, RenameFile
+ };
+
+ /// FileChanged - This callback is invoked whenever a source file is
+ /// entered or exited. The SourceLocation indicates the new location, and
+ /// EnteringFile indicates whether this is because we are entering a new
+ /// #include'd file (when true) or whether we're exiting one because we ran
+ /// off the end (when false).
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType) {
+ }
+
+ /// Ident - This callback is invoked when a #ident or #sccs directive is read.
+ ///
+ virtual void Ident(SourceLocation Loc, const std::string &str) {
+ }
+
+ /// PragmaComment - This callback is invoked when a #pragma comment directive
+ /// is read.
+ ///
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ const std::string &Str) {
+ }
+
+ /// MacroExpands - This is called by
+ /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is
+ /// found.
+ virtual void MacroExpands(const Token &Id, const MacroInfo* MI) {
+ }
+
+ /// MacroDefined - This hook is called whenever a macro definition is seen.
+ virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ }
+
+ /// MacroUndefined - This hook is called whenever a macro #undef is seen.
+ /// MI is released immediately following this callback.
+ virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ }
+};
+
+/// PPChainedCallbacks - Simple wrapper class for chaining callbacks.
+class PPChainedCallbacks : public PPCallbacks {
+ PPCallbacks *First, *Second;
+
+public:
+ PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second)
+ : First(_First), Second(_Second) {}
+ ~PPChainedCallbacks() {
+ delete Second;
+ delete First;
+ }
+
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType) {
+ First->FileChanged(Loc, Reason, FileType);
+ Second->FileChanged(Loc, Reason, FileType);
+ }
+
+ virtual void Ident(SourceLocation Loc, const std::string &str) {
+ First->Ident(Loc, str);
+ Second->Ident(Loc, str);
+ }
+
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ const std::string &Str) {
+ First->PragmaComment(Loc, Kind, Str);
+ Second->PragmaComment(Loc, Kind, Str);
+ }
+
+ virtual void MacroExpands(const Token &Id, const MacroInfo* MI) {
+ First->MacroExpands(Id, MI);
+ Second->MacroExpands(Id, MI);
+ }
+
+ virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ First->MacroDefined(II, MI);
+ Second->MacroDefined(II, MI);
+ }
+
+ virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ First->MacroUndefined(II, MI);
+ Second->MacroUndefined(II, MI);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
new file mode 100644
index 000000000000..369b818a1fc9
--- /dev/null
+++ b/include/clang/Lex/PTHLexer.h
@@ -0,0 +1,104 @@
+//===--- PTHLexer.h - Lexer based on Pre-tokenized input --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PTHLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PTHLEXER_H
+#define LLVM_CLANG_PTHLEXER_H
+
+#include "clang/Lex/PreprocessorLexer.h"
+#include <vector>
+
+namespace clang {
+
+class PTHManager;
+class PTHSpellingSearch;
+
+class PTHLexer : public PreprocessorLexer {
+ SourceLocation FileStartLoc;
+
+ /// TokBuf - Buffer from PTH file containing raw token data.
+ const unsigned char* TokBuf;
+
+ /// CurPtr - Pointer into current offset of the token buffer where
+ /// the next token will be read.
+ const unsigned char* CurPtr;
+
+ /// LastHashTokPtr - Pointer into TokBuf of the last processed '#'
+ /// token that appears at the start of a line.
+ const unsigned char* LastHashTokPtr;
+
+ /// PPCond - Pointer to a side table in the PTH file that provides a
+ /// a consise summary of the preproccessor conditional block structure.
+ /// This is used to perform quick skipping of conditional blocks.
+ const unsigned char* PPCond;
+
+ /// CurPPCondPtr - Pointer inside PPCond that refers to the next entry
+ /// to process when doing quick skipping of preprocessor blocks.
+ const unsigned char* CurPPCondPtr;
+
+ PTHLexer(const PTHLexer&); // DO NOT IMPLEMENT
+ void operator=(const PTHLexer&); // DO NOT IMPLEMENT
+
+ /// ReadToken - Used by PTHLexer to read tokens TokBuf.
+ void ReadToken(Token& T);
+
+ /// PTHMgr - The PTHManager object that created this PTHLexer.
+ PTHManager& PTHMgr;
+
+ Token EofToken;
+
+protected:
+ friend class PTHManager;
+
+ /// Create a PTHLexer for the specified token stream.
+ PTHLexer(Preprocessor& pp, FileID FID, const unsigned char *D,
+ const unsigned char* ppcond, PTHManager &PM);
+public:
+
+ ~PTHLexer() {}
+
+ /// Lex - Return the next token.
+ void Lex(Token &Tok);
+
+ void getEOF(Token &Tok);
+
+ /// DiscardToEndOfLine - Read the rest of the current preprocessor line as an
+ /// uninterpreted string. This switches the lexer out of directive mode.
+ void DiscardToEndOfLine();
+
+ /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
+ /// tok::l_paren token, 0 if it is something else and 2 if there are no more
+ /// tokens controlled by this lexer.
+ unsigned isNextPPTokenLParen() {
+ // isNextPPTokenLParen is not on the hot path, and all we care about is
+ // whether or not we are at a token with kind tok::eof or tok::l_paren.
+ // Just read the first byte from the current token pointer to determine
+ // its kind.
+ tok::TokenKind x = (tok::TokenKind)*CurPtr;
+ return x == tok::eof ? 2 : x == tok::l_paren;
+ }
+
+ /// IndirectLex - An indirect call to 'Lex' that can be invoked via
+ /// the PreprocessorLexer interface.
+ void IndirectLex(Token &Result) { Lex(Result); }
+
+ /// getSourceLocation - Return a source location for the token in
+ /// the current file.
+ SourceLocation getSourceLocation();
+
+ /// SkipBlock - Used by Preprocessor to skip the current conditional block.
+ bool SkipBlock();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
new file mode 100644
index 000000000000..507576473f60
--- /dev/null
+++ b/include/clang/Lex/PTHManager.h
@@ -0,0 +1,141 @@
+//===--- PTHManager.h - Manager object for PTH processing -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PTHManager interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PTHMANAGER_H
+#define LLVM_CLANG_PTHMANAGER_H
+
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+#include <string>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class FileEntry;
+class PTHLexer;
+class Diagnostic;
+class StatSysCallCache;
+
+class PTHManager : public IdentifierInfoLookup {
+ friend class PTHLexer;
+
+ /// The memory mapped PTH file.
+ const llvm::MemoryBuffer* Buf;
+
+ /// Alloc - Allocator used for IdentifierInfo objects.
+ llvm::BumpPtrAllocator Alloc;
+
+ /// IdMap - A lazily generated cache mapping from persistent identifiers to
+ /// IdentifierInfo*.
+ IdentifierInfo** PerIDCache;
+
+ /// FileLookup - Abstract data structure used for mapping between files
+ /// and token data in the PTH file.
+ void* FileLookup;
+
+ /// IdDataTable - Array representing the mapping from persistent IDs to the
+ /// data offset within the PTH file containing the information to
+ /// reconsitute an IdentifierInfo.
+ const unsigned char* const IdDataTable;
+
+ /// SortedIdTable - Abstract data structure mapping from strings to
+ /// persistent IDs. This is used by get().
+ void* StringIdLookup;
+
+ /// NumIds - The number of identifiers in the PTH file.
+ const unsigned NumIds;
+
+ /// PP - The Preprocessor object that will use this PTHManager to create
+ /// PTHLexer objects.
+ Preprocessor* PP;
+
+ /// SpellingBase - The base offset within the PTH memory buffer that
+ /// contains the cached spellings for literals.
+ const unsigned char* const SpellingBase;
+
+ /// OriginalSourceFile - A null-terminated C-string that specifies the name
+ /// if the file (if any) that was to used to generate the PTH cache.
+ const char* OriginalSourceFile;
+
+ /// This constructor is intended to only be called by the static 'Create'
+ /// method.
+ PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup,
+ const unsigned char* idDataTable, IdentifierInfo** perIDCache,
+ void* stringIdLookup, unsigned numIds,
+ const unsigned char* spellingBase, const char *originalSourceFile);
+
+ // Do not implement.
+ PTHManager();
+ void operator=(const PTHManager&);
+
+ /// getSpellingAtPTHOffset - Used by PTHLexer classes to get the cached
+ /// spelling for a token.
+ unsigned getSpellingAtPTHOffset(unsigned PTHOffset, const char*& Buffer);
+
+ /// GetIdentifierInfo - Used to reconstruct IdentifierInfo objects from the
+ /// PTH file.
+ inline IdentifierInfo* GetIdentifierInfo(unsigned PersistentID) {
+ // Check if the IdentifierInfo has already been resolved.
+ if (IdentifierInfo* II = PerIDCache[PersistentID])
+ return II;
+ return LazilyCreateIdentifierInfo(PersistentID);
+ }
+ IdentifierInfo* LazilyCreateIdentifierInfo(unsigned PersistentID);
+
+public:
+ // The current PTH version.
+ enum { Version = 9 };
+
+ ~PTHManager();
+
+ /// getOriginalSourceFile - Return the full path to the original header
+ /// file name that was used to generate the PTH cache.
+ const char* getOriginalSourceFile() const {
+ return OriginalSourceFile;
+ }
+
+ /// get - Return the identifier token info for the specified named identifier.
+ /// Unlike the version in IdentifierTable, this returns a pointer instead
+ /// of a reference. If the pointer is NULL then the IdentifierInfo cannot
+ /// be found.
+ IdentifierInfo *get(const char *NameStart, const char *NameEnd);
+
+ /// Create - This method creates PTHManager objects. The 'file' argument
+ /// is the name of the PTH file. This method returns NULL upon failure.
+ static PTHManager *Create(const std::string& file, Diagnostic* Diags = 0,
+ Diagnostic::Level failureLevel=Diagnostic::Warning);
+
+ void setPreprocessor(Preprocessor *pp) { PP = pp; }
+
+ /// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the
+ /// specified file. This method returns NULL if no cached tokens exist.
+ /// It is the responsibility of the caller to 'delete' the returned object.
+ PTHLexer *CreateLexer(FileID FID);
+
+ /// createStatCache - Returns a StatSysCallCache object for use with
+ /// FileManager objects. These objects use the PTH data to speed up
+ /// calls to stat by memoizing their results from when the PTH file
+ /// was generated.
+ StatSysCallCache *createStatCache();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h
new file mode 100644
index 000000000000..136dc6fabfb6
--- /dev/null
+++ b/include/clang/Lex/Pragma.h
@@ -0,0 +1,90 @@
+//===--- Pragma.h - Pragma registration and handling ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PragmaHandler and PragmaTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PRAGMA_H
+#define LLVM_CLANG_PRAGMA_H
+
+#include <cassert>
+#include <vector>
+
+namespace clang {
+ class Preprocessor;
+ class Token;
+ class IdentifierInfo;
+ class PragmaNamespace;
+
+/// PragmaHandler - Instances of this interface defined to handle the various
+/// pragmas that the language front-end uses. Each handler optionally has a
+/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
+/// that identifier is found. If a handler does not match any of the declared
+/// pragmas the handler with a null identifier is invoked, if it exists.
+///
+/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g.
+/// we treat "#pragma STDC" and "#pragma GCC" as namespaces that contain other
+/// pragmas.
+class PragmaHandler {
+ const IdentifierInfo *Name;
+public:
+ PragmaHandler(const IdentifierInfo *name) : Name(name) {}
+ virtual ~PragmaHandler();
+
+ const IdentifierInfo *getName() const { return Name; }
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken) = 0;
+
+ /// getIfNamespace - If this is a namespace, return it. This is equivalent to
+ /// using a dynamic_cast, but doesn't require RTTI.
+ virtual PragmaNamespace *getIfNamespace() { return 0; }
+};
+
+/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
+/// allowing hierarchical pragmas to be defined. Common examples of namespaces
+/// are "#pragma GCC", "#pragma STDC", and "#pragma omp", but any namespaces may
+/// be (potentially recursively) defined.
+class PragmaNamespace : public PragmaHandler {
+ /// Handlers - This is the list of handlers in this namespace.
+ ///
+ std::vector<PragmaHandler*> Handlers;
+public:
+ PragmaNamespace(const IdentifierInfo *Name) : PragmaHandler(Name) {}
+ virtual ~PragmaNamespace();
+
+ /// FindHandler - Check to see if there is already a handler for the
+ /// specified name. If not, return the handler for the null identifier if it
+ /// exists, otherwise return null. If IgnoreNull is true (the default) then
+ /// the null handler isn't returned on failure to match.
+ PragmaHandler *FindHandler(const IdentifierInfo *Name,
+ bool IgnoreNull = true) const;
+
+ /// AddPragma - Add a pragma to this namespace.
+ ///
+ void AddPragma(PragmaHandler *Handler) {
+ Handlers.push_back(Handler);
+ }
+
+ /// RemovePragmaHandler - Remove the given handler from the
+ /// namespace.
+ void RemovePragmaHandler(PragmaHandler *Handler);
+
+ bool IsEmpty() {
+ return Handlers.empty();
+ }
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+
+ virtual PragmaNamespace *getIfNamespace() { return this; }
+};
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
new file mode 100644
index 000000000000..5b9959c32a2d
--- /dev/null
+++ b/include/clang/Lex/Preprocessor.h
@@ -0,0 +1,801 @@
+//===--- Preprocessor.h - C Language Family Preprocessor --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Preprocessor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
+#define LLVM_CLANG_LEX_PREPROCESSOR_H
+
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/TokenLexer.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+
+class SourceManager;
+class FileManager;
+class FileEntry;
+class HeaderSearch;
+class PragmaNamespace;
+class PragmaHandler;
+class ScratchBuffer;
+class TargetInfo;
+class PPCallbacks;
+class DirectoryLookup;
+
+/// Preprocessor - This object engages in a tight little dance with the lexer to
+/// efficiently preprocess tokens. Lexers know only about tokens within a
+/// single source file, and don't know anything about preprocessor-level issues
+/// like the #include stack, token expansion, etc.
+///
+class Preprocessor {
+ Diagnostic *Diags;
+ const LangOptions &Features;
+ TargetInfo &Target;
+ FileManager &FileMgr;
+ SourceManager &SourceMgr;
+ ScratchBuffer *ScratchBuf;
+ HeaderSearch &HeaderInfo;
+
+ /// PTH - An optional PTHManager object used for getting tokens from
+ /// a token cache rather than lexing the original source file.
+ llvm::OwningPtr<PTHManager> PTH;
+
+ /// BP - A BumpPtrAllocator object used to quickly allocate and release
+ /// objects internal to the Preprocessor.
+ llvm::BumpPtrAllocator BP;
+
+ /// Identifiers for builtin macros and other builtins.
+ IdentifierInfo *Ident__LINE__, *Ident__FILE__; // __LINE__, __FILE__
+ IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
+ IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__
+ IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
+ IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
+ IdentifierInfo *Ident__COUNTER__; // __COUNTER__
+ IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
+
+ SourceLocation DATELoc, TIMELoc;
+ unsigned CounterValue; // Next __COUNTER__ value.
+
+ enum {
+ /// MaxIncludeStackDepth - Maximum depth of #includes.
+ MaxAllowedIncludeStackDepth = 200
+ };
+
+ // State that is set before the preprocessor begins.
+ bool KeepComments : 1;
+ bool KeepMacroComments : 1;
+
+ // State that changes while the preprocessor runs:
+ bool DisableMacroExpansion : 1; // True if macro expansion is disabled.
+ bool InMacroArgs : 1; // True if parsing fn macro invocation args.
+
+ /// Identifiers - This is mapping/lookup information for all identifiers in
+ /// the program, including program keywords.
+ IdentifierTable Identifiers;
+
+ /// Selectors - This table contains all the selectors in the program. Unlike
+ /// IdentifierTable above, this table *isn't* populated by the preprocessor.
+ /// It is declared/instantiated here because it's role/lifetime is
+ /// conceptually similar the IdentifierTable. In addition, the current control
+ /// flow (in clang::ParseAST()), make it convenient to put here.
+ /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
+ /// the lifetime fo the preprocessor.
+ SelectorTable Selectors;
+
+ /// PragmaHandlers - This tracks all of the pragmas that the client registered
+ /// with this preprocessor.
+ PragmaNamespace *PragmaHandlers;
+
+ /// CurLexer - This is the current top of the stack that we're lexing from if
+ /// not expanding a macro and we are lexing directly from source code.
+ /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
+ llvm::OwningPtr<Lexer> CurLexer;
+
+ /// CurPTHLexer - This is the current top of stack that we're lexing from if
+ /// not expanding from a macro and we are lexing from a PTH cache.
+ /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
+ llvm::OwningPtr<PTHLexer> CurPTHLexer;
+
+ /// CurPPLexer - This is the current top of the stack what we're lexing from
+ /// if not expanding a macro. This is an alias for either CurLexer or
+ /// CurPTHLexer.
+ PreprocessorLexer* CurPPLexer;
+
+ /// CurLookup - The DirectoryLookup structure used to find the current
+ /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
+ /// implement #include_next and find directory-specific properties.
+ const DirectoryLookup *CurDirLookup;
+
+ /// CurTokenLexer - This is the current macro we are expanding, if we are
+ /// expanding a macro. One of CurLexer and CurTokenLexer must be null.
+ llvm::OwningPtr<TokenLexer> CurTokenLexer;
+
+ /// IncludeMacroStack - This keeps track of the stack of files currently
+ /// #included, and macros currently being expanded from, not counting
+ /// CurLexer/CurTokenLexer.
+ struct IncludeStackInfo {
+ Lexer *TheLexer;
+ PTHLexer *ThePTHLexer;
+ PreprocessorLexer *ThePPLexer;
+ TokenLexer *TheTokenLexer;
+ const DirectoryLookup *TheDirLookup;
+
+ IncludeStackInfo(Lexer *L, PTHLexer* P, PreprocessorLexer* PPL,
+ TokenLexer* TL, const DirectoryLookup *D)
+ : TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), TheTokenLexer(TL),
+ TheDirLookup(D) {}
+ };
+ std::vector<IncludeStackInfo> IncludeMacroStack;
+
+ /// Callbacks - These are actions invoked when some preprocessor activity is
+ /// encountered (e.g. a file is #included, etc).
+ PPCallbacks *Callbacks;
+
+ /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping
+ /// to the actual definition of the macro.
+ llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros;
+
+ /// MICache - A "freelist" of MacroInfo objects that can be reused for quick
+ /// allocation.
+ std::vector<MacroInfo*> MICache;
+
+ // Various statistics we track for performance analysis.
+ unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
+ unsigned NumIf, NumElse, NumEndif;
+ unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
+ unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
+ unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
+ unsigned NumSkipped;
+
+ /// Predefines - This string is the predefined macros that preprocessor
+ /// should use from the command line etc.
+ std::string Predefines;
+
+ /// TokenLexerCache - Cache macro expanders to reduce malloc traffic.
+ enum { TokenLexerCacheSize = 8 };
+ unsigned NumCachedTokenLexers;
+ TokenLexer *TokenLexerCache[TokenLexerCacheSize];
+
+private: // Cached tokens state.
+ typedef std::vector<Token> CachedTokensTy;
+
+ /// CachedTokens - Cached tokens are stored here when we do backtracking or
+ /// lookahead. They are "lexed" by the CachingLex() method.
+ CachedTokensTy CachedTokens;
+
+ /// CachedLexPos - The position of the cached token that CachingLex() should
+ /// "lex" next. If it points beyond the CachedTokens vector, it means that
+ /// a normal Lex() should be invoked.
+ CachedTokensTy::size_type CachedLexPos;
+
+ /// BacktrackPositions - Stack of backtrack positions, allowing nested
+ /// backtracks. The EnableBacktrackAtThisPos() method pushes a position to
+ /// indicate where CachedLexPos should be set when the BackTrack() method is
+ /// invoked (at which point the last position is popped).
+ std::vector<CachedTokensTy::size_type> BacktrackPositions;
+
+public:
+ Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target,
+ SourceManager &SM, HeaderSearch &Headers,
+ IdentifierInfoLookup* IILookup = 0);
+
+ ~Preprocessor();
+
+ Diagnostic &getDiagnostics() const { return *Diags; }
+ void setDiagnostics(Diagnostic &D) { Diags = &D; }
+
+
+ const LangOptions &getLangOptions() const { return Features; }
+ TargetInfo &getTargetInfo() const { return Target; }
+ FileManager &getFileManager() const { return FileMgr; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
+
+ IdentifierTable &getIdentifierTable() { return Identifiers; }
+ SelectorTable &getSelectorTable() { return Selectors; }
+ llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; }
+
+ void setPTHManager(PTHManager* pm);
+
+ PTHManager *getPTHManager() { return PTH.get(); }
+
+ /// SetCommentRetentionState - Control whether or not the preprocessor retains
+ /// comments in output.
+ void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
+ this->KeepComments = KeepComments | KeepMacroComments;
+ this->KeepMacroComments = KeepMacroComments;
+ }
+
+ bool getCommentRetentionState() const { return KeepComments; }
+
+ /// isCurrentLexer - Return true if we are lexing directly from the specified
+ /// lexer.
+ bool isCurrentLexer(const PreprocessorLexer *L) const {
+ return CurPPLexer == L;
+ }
+
+ /// getCurrentLexer - Return the current file lexer being lexed from. Note
+ /// that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentFileLexer() const;
+
+ /// getPPCallbacks/setPPCallbacks - Accessors for preprocessor callbacks.
+ /// Note that this class takes ownership of any PPCallbacks object given to
+ /// it.
+ PPCallbacks *getPPCallbacks() const { return Callbacks; }
+ void setPPCallbacks(PPCallbacks *C) {
+ if (Callbacks)
+ C = new PPChainedCallbacks(C, Callbacks);
+ Callbacks = C;
+ }
+
+ /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to
+ /// or null if it isn't #define'd.
+ MacroInfo *getMacroInfo(IdentifierInfo *II) const {
+ return II->hasMacroDefinition() ? Macros.find(II)->second : 0;
+ }
+
+ /// setMacroInfo - Specify a macro for this identifier.
+ ///
+ void setMacroInfo(IdentifierInfo *II, MacroInfo *MI);
+
+ /// macro_iterator/macro_begin/macro_end - This allows you to walk the current
+ /// state of the macro table. This visits every currently-defined macro.
+ typedef llvm::DenseMap<IdentifierInfo*,
+ MacroInfo*>::const_iterator macro_iterator;
+ macro_iterator macro_begin() const { return Macros.begin(); }
+ macro_iterator macro_end() const { return Macros.end(); }
+
+
+
+ const std::string &getPredefines() const { return Predefines; }
+ /// setPredefines - Set the predefines for this Preprocessor. These
+ /// predefines are automatically injected when parsing the main file.
+ void setPredefines(const char *P) { Predefines = P; }
+ void setPredefines(const std::string &P) { Predefines = P; }
+
+ /// getIdentifierInfo - Return information about the specified preprocessor
+ /// identifier token. The version of this method that takes two character
+ /// pointers is preferred unless the identifier is already available as a
+ /// string (this avoids allocation and copying of memory to construct an
+ /// std::string).
+ IdentifierInfo *getIdentifierInfo(const char *NameStart,
+ const char *NameEnd) {
+ return &Identifiers.get(NameStart, NameEnd);
+ }
+ IdentifierInfo *getIdentifierInfo(const char *NameStr) {
+ return getIdentifierInfo(NameStr, NameStr+strlen(NameStr));
+ }
+
+ /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
+ /// If 'Namespace' is non-null, then it is a token required to exist on the
+ /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
+ void AddPragmaHandler(const char *Namespace, PragmaHandler *Handler);
+
+ /// RemovePragmaHandler - Remove the specific pragma handler from
+ /// the preprocessor. If \arg Namespace is non-null, then it should
+ /// be the namespace that \arg Handler was added to. It is an error
+ /// to remove a handler that has not been registered.
+ void RemovePragmaHandler(const char *Namespace, PragmaHandler *Handler);
+
+ /// EnterMainSourceFile - Enter the specified FileID as the main source file,
+ /// which implicitly adds the builtin defines etc.
+ void EnterMainSourceFile();
+
+ /// EnterSourceFile - Add a source file to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer. If isMainFile
+ /// is true, this is the main file for the translation unit.
+ void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir);
+
+ /// EnterMacro - Add a Macro to the top of the include stack and start lexing
+ /// tokens from it instead of the current buffer. Args specifies the
+ /// tokens input to a function-like macro.
+ ///
+ /// ILEnd specifies the location of the ')' for a function-like macro or the
+ /// identifier for an object-like macro.
+ void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroArgs *Args);
+
+ /// EnterTokenStream - Add a "macro" context to the top of the include stack,
+ /// which will cause the lexer to start returning the specified tokens.
+ ///
+ /// If DisableMacroExpansion is true, tokens lexed from the token stream will
+ /// not be subject to further macro expansion. Otherwise, these tokens will
+ /// be re-macro-expanded when/if expansion is enabled.
+ ///
+ /// If OwnsTokens is false, this method assumes that the specified stream of
+ /// tokens has a permanent owner somewhere, so they do not need to be copied.
+ /// If it is true, it assumes the array of tokens is allocated with new[] and
+ /// must be freed.
+ ///
+ void EnterTokenStream(const Token *Toks, unsigned NumToks,
+ bool DisableMacroExpansion, bool OwnsTokens);
+
+ /// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
+ /// lexer stack. This should only be used in situations where the current
+ /// state of the top-of-stack lexer is known.
+ void RemoveTopOfLexerStack();
+
+ /// EnableBacktrackAtThisPos - From the point that this method is called, and
+ /// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
+ /// keeps track of the lexed tokens so that a subsequent Backtrack() call will
+ /// make the Preprocessor re-lex the same tokens.
+ ///
+ /// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
+ /// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
+ /// be combined with the EnableBacktrackAtThisPos calls in reverse order.
+ ///
+ /// NOTE: *DO NOT* forget to call either CommitBacktrackedTokens or Backtrack
+ /// at some point after EnableBacktrackAtThisPos. If you don't, caching of
+ /// tokens will continue indefinitely.
+ ///
+ void EnableBacktrackAtThisPos();
+
+ /// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
+ void CommitBacktrackedTokens();
+
+ /// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
+ /// EnableBacktrackAtThisPos() was previously called.
+ void Backtrack();
+
+ /// isBacktrackEnabled - True if EnableBacktrackAtThisPos() was called and
+ /// caching of tokens is on.
+ bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
+
+ /// Lex - To lex a token from the preprocessor, just pull a token from the
+ /// current lexer or macro object.
+ void Lex(Token &Result) {
+ if (CurLexer)
+ CurLexer->Lex(Result);
+ else if (CurPTHLexer)
+ CurPTHLexer->Lex(Result);
+ else if (CurTokenLexer)
+ CurTokenLexer->Lex(Result);
+ else
+ CachingLex(Result);
+ }
+
+ /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get
+ /// something not a comment. This is useful in -E -C mode where comments
+ /// would foul up preprocessor directive handling.
+ void LexNonComment(Token &Result) {
+ do
+ Lex(Result);
+ while (Result.getKind() == tok::comment);
+ }
+
+ /// LexUnexpandedToken - This is just like Lex, but this disables macro
+ /// expansion of identifier tokens.
+ void LexUnexpandedToken(Token &Result) {
+ // Disable macro expansion.
+ bool OldVal = DisableMacroExpansion;
+ DisableMacroExpansion = true;
+ // Lex the token.
+ Lex(Result);
+
+ // Reenable it.
+ DisableMacroExpansion = OldVal;
+ }
+
+ /// LookAhead - This peeks ahead N tokens and returns that token without
+ /// consuming any tokens. LookAhead(0) returns the next token that would be
+ /// returned by Lex(), LookAhead(1) returns the token after it, etc. This
+ /// returns normal tokens after phase 5. As such, it is equivalent to using
+ /// 'Lex', not 'LexUnexpandedToken'.
+ const Token &LookAhead(unsigned N) {
+ if (CachedLexPos + N < CachedTokens.size())
+ return CachedTokens[CachedLexPos+N];
+ else
+ return PeekAhead(N+1);
+ }
+
+ /// RevertCachedTokens - When backtracking is enabled and tokens are cached,
+ /// this allows to revert a specific number of tokens.
+ /// Note that the number of tokens being reverted should be up to the last
+ /// backtrack position, not more.
+ void RevertCachedTokens(unsigned N) {
+ assert(isBacktrackEnabled() &&
+ "Should only be called when tokens are cached for backtracking");
+ assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back())
+ && "Should revert tokens up to the last backtrack position, not more");
+ assert(signed(CachedLexPos) - signed(N) >= 0 &&
+ "Corrupted backtrack positions ?");
+ CachedLexPos -= N;
+ }
+
+ /// EnterToken - Enters a token in the token stream to be lexed next. If
+ /// BackTrack() is called afterwards, the token will remain at the insertion
+ /// point.
+ void EnterToken(const Token &Tok) {
+ EnterCachingLexMode();
+ CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Tok);
+ }
+
+ /// AnnotateCachedTokens - We notify the Preprocessor that if it is caching
+ /// tokens (because backtrack is enabled) it should replace the most recent
+ /// cached tokens with the given annotation token. This function has no effect
+ /// if backtracking is not enabled.
+ ///
+ /// Note that the use of this function is just for optimization; so that the
+ /// cached tokens doesn't get re-parsed and re-resolved after a backtrack is
+ /// invoked.
+ void AnnotateCachedTokens(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ AnnotatePreviousCachedTokens(Tok);
+ }
+
+ /// \brief Replace the last token with an annotation token.
+ ///
+ /// Like AnnotateCachedTokens(), this routine replaces an
+ /// already-parsed (and resolved) token with an annotation
+ /// token. However, this routine only replaces the last token with
+ /// the annotation token; it does not affect any other cached
+ /// tokens. This function has no effect if backtracking is not
+ /// enabled.
+ void ReplaceLastTokenWithAnnotation(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ CachedTokens[CachedLexPos-1] = Tok;
+ }
+
+ /// Diag - Forwarding function for diagnostics. This emits a diagnostic at
+ /// the specified Token's location, translating the token's start
+ /// position in the current buffer into a SourcePosition object for rendering.
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags->Report(FullSourceLoc(Loc, getSourceManager()), DiagID);
+ }
+
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) {
+ return Diags->Report(FullSourceLoc(Tok.getLocation(), getSourceManager()),
+ DiagID);
+ }
+
+ /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
+ /// token is the characters used to represent the token in the source file
+ /// after trigraph expansion and escaped-newline folding. In particular, this
+ /// wants to get the true, uncanonicalized, spelling of things like digraphs
+ /// UCNs, etc.
+ std::string getSpelling(const Token &Tok) const;
+
+ /// getSpelling - This method is used to get the spelling of a token into a
+ /// preallocated buffer, instead of as an std::string. The caller is required
+ /// to allocate enough space for the token, which is guaranteed to be at least
+ /// Tok.getLength() bytes long. The length of the actual result is returned.
+ ///
+ /// Note that this method may do two possible things: it may either fill in
+ /// the buffer specified with characters, or it may *change the input pointer*
+ /// to point to a constant buffer with the data already in it (avoiding a
+ /// copy). The caller is not allowed to modify the returned buffer pointer
+ /// if an internal buffer is returned.
+ unsigned getSpelling(const Token &Tok, const char *&Buffer) const;
+
+ /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant
+ /// with length 1, return the character.
+ char getSpellingOfSingleCharacterNumericConstant(const Token &Tok) const {
+ assert(Tok.is(tok::numeric_constant) &&
+ Tok.getLength() == 1 && "Called on unsupported token");
+ assert(!Tok.needsCleaning() && "Token can't need cleaning with length 1");
+
+ // If the token is carrying a literal data pointer, just use it.
+ if (const char *D = Tok.getLiteralData())
+ return *D;
+
+ // Otherwise, fall back on getCharacterData, which is slower, but always
+ // works.
+ return *SourceMgr.getCharacterData(Tok.getLocation());
+ }
+
+ /// CreateString - Plop the specified string into a scratch buffer and set the
+ /// specified token's location and length to it. If specified, the source
+ /// location provides a location of the instantiation point of the token.
+ void CreateString(const char *Buf, unsigned Len,
+ Token &Tok, SourceLocation SourceLoc = SourceLocation());
+
+ /// \brief Computes the source location just past the end of the
+ /// token at this source location.
+ ///
+ /// This routine can be used to produce a source location that
+ /// points just past the end of the token referenced by \p Loc, and
+ /// is generally used when a diagnostic needs to point just after a
+ /// token where it expected something different that it received. If
+ /// the returned source location would not be meaningful (e.g., if
+ /// it points into a macro), this routine returns an invalid
+ /// source location.
+ SourceLocation getLocForEndOfToken(SourceLocation Loc);
+
+ /// DumpToken - Print the token to stderr, used for debugging.
+ ///
+ void DumpToken(const Token &Tok, bool DumpFlags = false) const;
+ void DumpLocation(SourceLocation Loc) const;
+ void DumpMacro(const MacroInfo &MI) const;
+
+ /// AdvanceToTokenCharacter - Given a location that specifies the start of a
+ /// token, return a new location that specifies a character within the token.
+ SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,unsigned Char);
+
+ /// IncrementPasteCounter - Increment the counters for the number of token
+ /// paste operations performed. If fast was specified, this is a 'fast paste'
+ /// case we handled.
+ ///
+ void IncrementPasteCounter(bool isFast) {
+ if (isFast)
+ ++NumFastTokenPaste;
+ else
+ ++NumTokenPaste;
+ }
+
+ void PrintStats();
+
+ /// HandleMicrosoftCommentPaste - When the macro expander pastes together a
+ /// comment (/##/) in microsoft mode, this method handles updating the current
+ /// state, returning the token on the next source line.
+ void HandleMicrosoftCommentPaste(Token &Tok);
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor callback methods. These are invoked by a lexer as various
+ // directives and events are found.
+
+ /// LookUpIdentifierInfo - Given a tok::identifier token, look up the
+ /// identifier information for the token and install it into the token.
+ IdentifierInfo *LookUpIdentifierInfo(Token &Identifier,
+ const char *BufPtr = 0);
+
+ /// HandleIdentifier - This callback is invoked when the lexer reads an
+ /// identifier and has filled in the tokens IdentifierInfo member. This
+ /// callback potentially macro expands it or turns it into a named token (like
+ /// 'for').
+ void HandleIdentifier(Token &Identifier);
+
+
+ /// HandleEndOfFile - This callback is invoked when the lexer hits the end of
+ /// the current file. This either returns the EOF token and returns true, or
+ /// pops a level off the include stack and returns false, at which point the
+ /// client should call lex again.
+ bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
+
+ /// HandleEndOfTokenLexer - This callback is invoked when the current
+ /// TokenLexer hits the end of its token stream.
+ bool HandleEndOfTokenLexer(Token &Result);
+
+ /// HandleDirective - This callback is invoked when the lexer sees a # token
+ /// at the start of a line. This consumes the directive, modifies the
+ /// lexer/preprocessor state, and advances the lexer(s) so that the next token
+ /// read is the correct one.
+ void HandleDirective(Token &Result);
+
+ /// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If
+ /// not, emit a diagnostic and consume up until the eom. If EnableMacros is
+ /// true, then we consider macros that expand to zero tokens as being ok.
+ void CheckEndOfDirective(const char *Directive, bool EnableMacros = false);
+
+ /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
+ /// current line until the tok::eom token is found.
+ void DiscardUntilEndOfDirective();
+
+ /// SawDateOrTime - This returns true if the preprocessor has seen a use of
+ /// __DATE__ or __TIME__ in the file so far.
+ bool SawDateOrTime() const {
+ return DATELoc != SourceLocation() || TIMELoc != SourceLocation();
+ }
+ unsigned getCounterValue() const { return CounterValue; }
+ void setCounterValue(unsigned V) { CounterValue = V; }
+
+ /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide
+ /// SourceLocation.
+ MacroInfo* AllocateMacroInfo(SourceLocation L);
+
+private:
+
+ void PushIncludeMacroStack() {
+ IncludeMacroStack.push_back(IncludeStackInfo(CurLexer.take(),
+ CurPTHLexer.take(),
+ CurPPLexer,
+ CurTokenLexer.take(),
+ CurDirLookup));
+ CurPPLexer = 0;
+ }
+
+ void PopIncludeMacroStack() {
+ CurLexer.reset(IncludeMacroStack.back().TheLexer);
+ CurPTHLexer.reset(IncludeMacroStack.back().ThePTHLexer);
+ CurPPLexer = IncludeMacroStack.back().ThePPLexer;
+ CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer);
+ CurDirLookup = IncludeMacroStack.back().TheDirLookup;
+ IncludeMacroStack.pop_back();
+ }
+
+ /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
+ /// be reused for allocating new MacroInfo objects.
+ void ReleaseMacroInfo(MacroInfo* MI);
+
+ /// isInPrimaryFile - Return true if we're in the top-level file, not in a
+ /// #include.
+ bool isInPrimaryFile() const;
+
+ /// ReadMacroName - Lex and validate a macro name, which occurs after a
+ /// #define or #undef. This emits a diagnostic, sets the token kind to eom,
+ /// and discards the rest of the macro line if the macro name is invalid.
+ void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0);
+
+ /// ReadMacroDefinitionArgList - The ( starting an argument list of a macro
+ /// definition has just been read. Lex the rest of the arguments and the
+ /// closing ), updating MI with what we learn. Return true if an error occurs
+ /// parsing the arg list.
+ bool ReadMacroDefinitionArgList(MacroInfo *MI);
+
+ /// SkipExcludedConditionalBlock - We just read a #if or related directive and
+ /// decided that the subsequent tokens are in the #if'd out portion of the
+ /// file. Lex the rest of the file, until we see an #endif. If
+ /// FoundNonSkipPortion is true, then we have already emitted code for part of
+ /// this #if directive, so #else/#elif blocks should never be entered. If
+ /// FoundElse is false, then #else directives are ok, if not, then we have
+ /// already seen one so a #else directive is a duplicate. When this returns,
+ /// the caller can lex the first valid token.
+ void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion, bool FoundElse);
+
+ /// PTHSkipExcludedConditionalBlock - A fast PTH version of
+ /// SkipExcludedConditionalBlock.
+ void PTHSkipExcludedConditionalBlock();
+
+ /// EvaluateDirectiveExpression - Evaluate an integer constant expression that
+ /// may occur after a #if or #elif directive and return it as a bool. If the
+ /// expression is equivalent to "!defined(X)" return X in IfNDefMacro.
+ bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
+
+ /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
+ /// #pragma GCC poison/system_header/dependency and #pragma once.
+ void RegisterBuiltinPragmas();
+
+ /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
+ /// identifier table.
+ void RegisterBuiltinMacros();
+ IdentifierInfo *RegisterBuiltinMacro(const char *Name);
+
+ /// HandleMacroExpandedIdentifier - If an identifier token is read that is to
+ /// be expanded as a macro, handle it and return the next token as 'Tok'. If
+ /// the macro should not be expanded return true, otherwise return false.
+ bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI);
+
+ /// isNextPPTokenLParen - Determine whether the next preprocessor token to be
+ /// lexed is a '('. If so, consume the token and return true, if not, this
+ /// method should have no observable side-effect on the lexed tokens.
+ bool isNextPPTokenLParen();
+
+ /// ReadFunctionLikeMacroArgs - After reading "MACRO(", this method is
+ /// invoked to read all of the formal arguments specified for the macro
+ /// invocation. This returns null on error.
+ MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI,
+ SourceLocation &InstantiationEnd);
+
+ /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
+ /// as a builtin macro, handle it and return the next token as 'Tok'.
+ void ExpandBuiltinMacro(Token &Tok);
+
+ /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+ /// return the first token after the directive. The _Pragma token has just
+ /// been read into 'Tok'.
+ void Handle_Pragma(Token &Tok);
+
+ /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer.
+ void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
+
+ /// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and
+ /// start getting tokens from it using the PTH cache.
+ void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
+
+ /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+ /// checked and spelled filename, e.g. as an operand of #include. This returns
+ /// true if the input filename was in <>'s or false if it were in ""'s. The
+ /// caller is expected to provide a buffer that is large enough to hold the
+ /// spelling of the filename, but is also expected to handle the case when
+ /// this method decides to use a different buffer.
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,
+ const char *&BufStart, const char *&BufEnd);
+
+ /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
+ /// return null on failure. isAngled indicates whether the file reference is
+ /// for system #include's or not (i.e. using <> instead of "").
+ const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
+ bool isAngled, const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir);
+
+
+
+ /// IsFileLexer - Returns true if we are lexing from a file and not a
+ /// pragma or a macro.
+ static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
+ return L ? !L->isPragmaLexer() : P != 0;
+ }
+
+ static bool IsFileLexer(const IncludeStackInfo& I) {
+ return IsFileLexer(I.TheLexer, I.ThePPLexer);
+ }
+
+ bool IsFileLexer() const {
+ return IsFileLexer(CurLexer.get(), CurPPLexer);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Caching stuff.
+ void CachingLex(Token &Result);
+ bool InCachingLexMode() const { return CurPPLexer == 0 && CurTokenLexer == 0;}
+ void EnterCachingLexMode();
+ void ExitCachingLexMode() {
+ if (InCachingLexMode())
+ RemoveTopOfLexerStack();
+ }
+ const Token &PeekAhead(unsigned N);
+ void AnnotatePreviousCachedTokens(const Token &Tok);
+
+ //===--------------------------------------------------------------------===//
+ /// Handle*Directive - implement the various preprocessor directives. These
+ /// should side-effect the current preprocessor object so that the next call
+ /// to Lex() will return the appropriate token next.
+ void HandleLineDirective(Token &Tok);
+ void HandleDigitDirective(Token &Tok);
+ void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
+ void HandleIdentSCCSDirective(Token &Tok);
+
+ // File inclusion.
+ void HandleIncludeDirective(Token &Tok,
+ const DirectoryLookup *LookupFrom = 0,
+ bool isImport = false);
+ void HandleIncludeNextDirective(Token &Tok);
+ void HandleIncludeMacrosDirective(Token &Tok);
+ void HandleImportDirective(Token &Tok);
+
+ // Macro handling.
+ void HandleDefineDirective(Token &Tok);
+ void HandleUndefDirective(Token &Tok);
+ // HandleAssertDirective(Token &Tok);
+ // HandleUnassertDirective(Token &Tok);
+
+ // Conditional Inclusion.
+ void HandleIfdefDirective(Token &Tok, bool isIfndef,
+ bool ReadAnyTokensBeforeDirective);
+ void HandleIfDirective(Token &Tok, bool ReadAnyTokensBeforeDirective);
+ void HandleEndifDirective(Token &Tok);
+ void HandleElseDirective(Token &Tok);
+ void HandleElifDirective(Token &Tok);
+
+ // Pragmas.
+ void HandlePragmaDirective();
+public:
+ void HandlePragmaOnce(Token &OnceTok);
+ void HandlePragmaMark();
+ void HandlePragmaPoison(Token &PoisonTok);
+ void HandlePragmaSystemHeader(Token &SysHeaderTok);
+ void HandlePragmaDependency(Token &DependencyTok);
+ void HandlePragmaComment(Token &CommentTok);
+};
+
+/// PreprocessorFactory - A generic factory interface for lazily creating
+/// Preprocessor objects on-demand when they are needed.
+class PreprocessorFactory {
+public:
+ virtual ~PreprocessorFactory();
+ virtual Preprocessor* CreatePreprocessor() = 0;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
new file mode 100644
index 000000000000..f98b5599658f
--- /dev/null
+++ b/include/clang/Lex/PreprocessorLexer.h
@@ -0,0 +1,161 @@
+//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PreprocessorLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PreprocessorLexer_H
+#define LLVM_CLANG_PreprocessorLexer_H
+
+#include "clang/Lex/MultipleIncludeOpt.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+
+namespace clang {
+
+class Preprocessor;
+
+class PreprocessorLexer {
+protected:
+ Preprocessor *PP; // Preprocessor object controlling lexing.
+
+ /// The SourceManager FileID corresponding to the file being lexed.
+ const FileID FID;
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //===--------------------------------------------------------------------===//
+
+ /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns
+ /// '\n' into a tok::eom token.
+ bool ParsingPreprocessorDirective;
+
+ /// ParsingFilename - True after #include: this turns <xx> into a
+ /// tok::angle_string_literal token.
+ bool ParsingFilename;
+
+ /// LexingRawMode - True if in raw mode: This flag disables interpretation of
+ /// tokens and is a far faster mode to lex in than non-raw-mode. This flag:
+ /// 1. If EOF of the current lexer is found, the include stack isn't popped.
+ /// 2. Identifier information is not looked up for identifier tokens. As an
+ /// effect of this, implicit macro expansion is naturally disabled.
+ /// 3. "#" tokens at the start of a line are treated as normal tokens, not
+ /// implicitly transformed by the lexer.
+ /// 4. All diagnostic messages are disabled.
+ /// 5. No callbacks are made into the preprocessor.
+ ///
+ /// Note that in raw mode that the PP pointer may be null.
+ bool LexingRawMode;
+
+ /// MIOpt - This is a state machine that detects the #ifndef-wrapping a file
+ /// idiom for the multiple-include optimization.
+ MultipleIncludeOpt MIOpt;
+
+ /// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks
+ /// we are currently in.
+ llvm::SmallVector<PPConditionalInfo, 4> ConditionalStack;
+
+ PreprocessorLexer(const PreprocessorLexer&); // DO NOT IMPLEMENT
+ void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT
+ friend class Preprocessor;
+
+ PreprocessorLexer(Preprocessor *pp, FileID fid)
+ : PP(pp), FID(fid), ParsingPreprocessorDirective(false),
+ ParsingFilename(false), LexingRawMode(false) {}
+
+ PreprocessorLexer()
+ : PP(0),
+ ParsingPreprocessorDirective(false),
+ ParsingFilename(false),
+ LexingRawMode(false) {}
+
+ virtual ~PreprocessorLexer() {}
+
+ virtual void IndirectLex(Token& Result) = 0;
+
+ /// getSourceLocation - Return the source location for the next observable
+ /// location.
+ virtual SourceLocation getSourceLocation() = 0;
+
+ //===--------------------------------------------------------------------===//
+ // #if directive handling.
+
+ /// pushConditionalLevel - When we enter a #if directive, this keeps track of
+ /// what we are currently in for diagnostic emission (e.g. #if with missing
+ /// #endif).
+ void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
+ bool FoundNonSkip, bool FoundElse) {
+ PPConditionalInfo CI;
+ CI.IfLoc = DirectiveStart;
+ CI.WasSkipping = WasSkipping;
+ CI.FoundNonSkip = FoundNonSkip;
+ CI.FoundElse = FoundElse;
+ ConditionalStack.push_back(CI);
+ }
+ void pushConditionalLevel(const PPConditionalInfo &CI) {
+ ConditionalStack.push_back(CI);
+ }
+
+ /// popConditionalLevel - Remove an entry off the top of the conditional
+ /// stack, returning information about it. If the conditional stack is empty,
+ /// this returns true and does not fill in the arguments.
+ bool popConditionalLevel(PPConditionalInfo &CI) {
+ if (ConditionalStack.empty()) return true;
+ CI = ConditionalStack.back();
+ ConditionalStack.pop_back();
+ return false;
+ }
+
+ /// peekConditionalLevel - Return the top of the conditional stack. This
+ /// requires that there be a conditional active.
+ PPConditionalInfo &peekConditionalLevel() {
+ assert(!ConditionalStack.empty() && "No conditionals active!");
+ return ConditionalStack.back();
+ }
+
+ unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
+
+public:
+
+ //===--------------------------------------------------------------------===//
+ // Misc. lexing methods.
+
+ /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
+ /// (potentially) macro expand the filename. If the sequence parsed is not
+ /// lexically legal, emit a diagnostic and return a result EOM token.
+ void LexIncludeFilename(Token &Result);
+
+ /// setParsingPreprocessorDirective - Inform the lexer whether or not
+ /// we are currently lexing a preprocessor directive.
+ void setParsingPreprocessorDirective(bool f) {
+ ParsingPreprocessorDirective = f;
+ }
+
+ /// isLexingRawMode - Return true if this lexer is in raw mode or not.
+ bool isLexingRawMode() const { return LexingRawMode; }
+
+ /// getPP - Return the preprocessor object for this lexer.
+ Preprocessor *getPP() const { return PP; }
+
+ FileID getFileID() const {
+ assert(PP &&
+ "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
+ return FID;
+ }
+
+ /// getFileEntry - Return the FileEntry corresponding to this FileID. Like
+ /// getFileID(), this only works for lexers with attached preprocessors.
+ const FileEntry *getFileEntry() const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/ScratchBuffer.h b/include/clang/Lex/ScratchBuffer.h
new file mode 100644
index 000000000000..6506f9262947
--- /dev/null
+++ b/include/clang/Lex/ScratchBuffer.h
@@ -0,0 +1,45 @@
+//===--- ScratchBuffer.h - Scratch space for forming tokens -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ScratchBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCRATCHBUFFER_H
+#define LLVM_CLANG_SCRATCHBUFFER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+ class SourceManager;
+
+/// ScratchBuffer - This class exposes a simple interface for the dynamic
+/// construction of tokens. This is used for builtin macros (e.g. __LINE__) as
+/// well as token pasting, etc.
+class ScratchBuffer {
+ SourceManager &SourceMgr;
+ char *CurBuffer;
+ SourceLocation BufferStartLoc;
+ unsigned BytesUsed;
+public:
+ ScratchBuffer(SourceManager &SM);
+
+ /// getToken - Splat the specified text into a temporary MemoryBuffer and
+ /// return a SourceLocation that refers to the token. This is just like the
+ /// previous method, but returns a location that indicates the physloc of the
+ /// token.
+ SourceLocation getToken(const char *Buf, unsigned Len, const char *&DestPtr);
+
+private:
+ void AllocScratchBuffer(unsigned RequestLen);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
new file mode 100644
index 000000000000..2c8f2ad3f2b6
--- /dev/null
+++ b/include/clang/Lex/Token.h
@@ -0,0 +1,312 @@
+//===--- Token.h - Token interface ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Token interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKEN_H
+#define LLVM_CLANG_TOKEN_H
+
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cstdlib>
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// Token - This structure provides full information about a lexed token.
+/// It is not intended to be space efficient, it is intended to return as much
+/// information as possible about each returned token. This is expected to be
+/// compressed into a smaller form if memory footprint is important.
+///
+/// The parser can create a special "annotation token" representing a stream of
+/// tokens that were parsed and semantically resolved, e.g.: "foo::MyClass<int>"
+/// can be represented by a single typename annotation token that carries
+/// information about the SourceRange of the tokens and the type object.
+class Token {
+ /// The location of the token.
+ SourceLocation Loc;
+
+ // Conceptually these next two fields could be in a union. However, this
+ // causes gcc 4.2 to pessimize LexTokenInternal, a very performance critical
+ // routine. Keeping as separate members with casts until a more beautiful fix
+ // presents itself.
+
+ /// UintData - This holds either the length of the token text, when
+ /// a normal token, or the end of the SourceRange when an annotation
+ /// token.
+ unsigned UintData;
+
+ /// PtrData - This is a union of four different pointer types, which depends
+ /// on what type of token this is:
+ /// Identifiers, keywords, etc:
+ /// This is an IdentifierInfo*, which contains the uniqued identifier
+ /// spelling.
+ /// Literals: isLiteral() returns true.
+ /// This is a pointer to the start of the token in a text buffer, which
+ /// may be dirty (have trigraphs / escaped newlines).
+ /// Annotations (resolved type names, C++ scopes, etc): isAnnotation().
+ /// This is a pointer to sema-specific data for the annotation token.
+ /// Other:
+ /// This is null.
+ void *PtrData;
+
+ /// Kind - The actual flavor of token this is.
+ ///
+ unsigned Kind : 8; // DON'T make Kind a 'tok::TokenKind';
+ // MSVC will treat it as a signed char and
+ // TokenKinds > 127 won't be handled correctly.
+
+ /// Flags - Bits we track about this token, members of the TokenFlags enum.
+ unsigned Flags : 8;
+public:
+
+ // Various flags set per token:
+ enum TokenFlags {
+ StartOfLine = 0x01, // At start of line or only after whitespace.
+ LeadingSpace = 0x02, // Whitespace exists before this token.
+ DisableExpand = 0x04, // This identifier may never be macro expanded.
+ NeedsCleaning = 0x08 // Contained an escaped newline or trigraph.
+ };
+
+ tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }
+ void setKind(tok::TokenKind K) { Kind = K; }
+
+ /// is/isNot - Predicates to check if this token is a specific kind, as in
+ /// "if (Tok.is(tok::l_brace)) {...}".
+ bool is(tok::TokenKind K) const { return Kind == (unsigned) K; }
+ bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; }
+
+ /// isLiteral - Return true if this is a "literal", like a numeric
+ /// constant, string, etc.
+ bool isLiteral() const {
+ return is(tok::numeric_constant) || is(tok::char_constant) ||
+ is(tok::string_literal) || is(tok::wide_string_literal) ||
+ is(tok::angle_string_literal);
+ }
+
+ bool isAnnotation() const {
+ return is(tok::annot_typename) ||
+ is(tok::annot_cxxscope) ||
+ is(tok::annot_template_id);
+ }
+
+ /// getLocation - Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getLocation() const { return Loc; }
+ unsigned getLength() const {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ return UintData;
+ }
+
+ void setLocation(SourceLocation L) { Loc = L; }
+ void setLength(unsigned Len) {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ UintData = Len;
+ }
+
+ SourceLocation getAnnotationEndLoc() const {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ return SourceLocation::getFromRawEncoding(UintData);
+ }
+ void setAnnotationEndLoc(SourceLocation L) {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ UintData = L.getRawEncoding();
+ }
+
+ /// getAnnotationRange - SourceRange of the group of tokens that this
+ /// annotation token represents.
+ SourceRange getAnnotationRange() const {
+ return SourceRange(getLocation(), getAnnotationEndLoc());
+ }
+ void setAnnotationRange(SourceRange R) {
+ setLocation(R.getBegin());
+ setAnnotationEndLoc(R.getEnd());
+ }
+
+ const char *getName() const {
+ return tok::getTokenName( (tok::TokenKind) Kind);
+ }
+
+ /// startToken - Reset all flags to cleared.
+ ///
+ void startToken() {
+ Kind = tok::unknown;
+ Flags = 0;
+ PtrData = 0;
+ Loc = SourceLocation();
+ }
+
+ IdentifierInfo *getIdentifierInfo() const {
+ assert(!isAnnotation() && "Used IdentInfo on annotation token!");
+ if (isLiteral()) return 0;
+ return (IdentifierInfo*) PtrData;
+ }
+ void setIdentifierInfo(IdentifierInfo *II) {
+ PtrData = (void*) II;
+ }
+
+ /// getLiteralData - For a literal token (numeric constant, string, etc), this
+ /// returns a pointer to the start of it in the text buffer if known, null
+ /// otherwise.
+ const char *getLiteralData() const {
+ assert(isLiteral() && "Cannot get literal data of non-literal");
+ return reinterpret_cast<const char*>(PtrData);
+ }
+ void setLiteralData(const char *Ptr) {
+ assert(isLiteral() && "Cannot set literal data of non-literal");
+ PtrData = (void*)Ptr;
+ }
+
+ void *getAnnotationValue() const {
+ assert(isAnnotation() && "Used AnnotVal on non-annotation token");
+ return PtrData;
+ }
+ void setAnnotationValue(void *val) {
+ assert(isAnnotation() && "Used AnnotVal on non-annotation token");
+ PtrData = val;
+ }
+
+ /// setFlag - Set the specified flag.
+ void setFlag(TokenFlags Flag) {
+ Flags |= Flag;
+ }
+
+ /// clearFlag - Unset the specified flag.
+ void clearFlag(TokenFlags Flag) {
+ Flags &= ~Flag;
+ }
+
+ /// getFlags - Return the internal represtation of the flags.
+ /// Only intended for low-level operations such as writing tokens to
+ // disk.
+ unsigned getFlags() const {
+ return Flags;
+ }
+
+ /// setFlagValue - Set a flag to either true or false.
+ void setFlagValue(TokenFlags Flag, bool Val) {
+ if (Val)
+ setFlag(Flag);
+ else
+ clearFlag(Flag);
+ }
+
+ /// isAtStartOfLine - Return true if this token is at the start of a line.
+ ///
+ bool isAtStartOfLine() const { return (Flags & StartOfLine) ? true : false; }
+
+ /// hasLeadingSpace - Return true if this token has whitespace before it.
+ ///
+ bool hasLeadingSpace() const { return (Flags & LeadingSpace) ? true : false; }
+
+ /// isExpandDisabled - Return true if this identifier token should never
+ /// be expanded in the future, due to C99 6.10.3.4p2.
+ bool isExpandDisabled() const {
+ return (Flags & DisableExpand) ? true : false;
+ }
+
+ /// isObjCAtKeyword - Return true if we have an ObjC keyword identifier.
+ bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const;
+
+ /// getObjCKeywordID - Return the ObjC keyword kind.
+ tok::ObjCKeywordKind getObjCKeywordID() const;
+
+ /// needsCleaning - Return true if this token has trigraphs or escaped
+ /// newlines in it.
+ ///
+ bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; }
+};
+
+/// PPConditionalInfo - Information about the conditional stack (#if directives)
+/// currently active.
+struct PPConditionalInfo {
+ /// IfLoc - Location where the conditional started.
+ ///
+ SourceLocation IfLoc;
+
+ /// WasSkipping - True if this was contained in a skipping directive, e.g.
+ /// in a "#if 0" block.
+ bool WasSkipping;
+
+ /// FoundNonSkip - True if we have emitted tokens already, and now we're in
+ /// an #else block or something. Only useful in Skipping blocks.
+ bool FoundNonSkip;
+
+ /// FoundElse - True if we've seen a #else in this block. If so,
+ /// #elif/#else directives are not allowed.
+ bool FoundElse;
+};
+
+/// TemplateIdAnnotation - Information about a template-id annotation
+/// token, which contains the template declaration, template
+/// arguments, whether those template arguments were types or
+/// expressions, and the source locations for important tokens. All of
+/// the information about template arguments is allocated directly
+/// after this structure.
+struct TemplateIdAnnotation {
+ /// TemplateNameLoc - The location of the template name within the
+ /// source.
+ SourceLocation TemplateNameLoc;
+
+ /// FIXME: Temporarily stores the name of a specialization
+ IdentifierInfo *Name;
+
+ /// The declaration of the template corresponding to the
+ /// template-name. This is an Action::DeclTy*.
+ void *Template;
+
+ /// The kind of template that Template refers to.
+ TemplateNameKind Kind;
+
+ /// The location of the '<' before the template argument
+ /// list.
+ SourceLocation LAngleLoc;
+
+ /// The location of the '>' after the template argument
+ /// list.
+ SourceLocation RAngleLoc;
+
+ /// NumArgs - The number of template arguments.
+ unsigned NumArgs;
+
+ /// \brief Retrieves a pointer to the template arguments
+ void **getTemplateArgs() { return (void **)(this + 1); }
+
+ /// \brief Retrieves a pointer to the array of template argument
+ /// locations.
+ SourceLocation *getTemplateArgLocations() {
+ return (SourceLocation *)(getTemplateArgs() + NumArgs);
+ }
+
+ /// \brief Retrieves a pointer to the array of flags that states
+ /// whether the template arguments are types.
+ bool *getTemplateArgIsType() {
+ return (bool *)(getTemplateArgLocations() + NumArgs);
+ }
+
+ static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
+ TemplateIdAnnotation *TemplateId
+ = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
+ sizeof(void*) * NumArgs +
+ sizeof(SourceLocation) * NumArgs +
+ sizeof(bool) * NumArgs);
+ TemplateId->NumArgs = NumArgs;
+ return TemplateId;
+ }
+
+ void Destroy() { free(this); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Lex/TokenConcatenation.h b/include/clang/Lex/TokenConcatenation.h
new file mode 100644
index 000000000000..dfc05f4074e0
--- /dev/null
+++ b/include/clang/Lex/TokenConcatenation.h
@@ -0,0 +1,73 @@
+//===--- TokenConcatenation.h - Token Concatenation Avoidance ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenConcatenation class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LEX_TOKEN_CONCATENATION_H
+#define CLANG_LEX_TOKEN_CONCATENATION_H
+
+#include "clang/Basic/TokenKinds.h"
+
+namespace clang {
+ class Preprocessor;
+ class Token;
+
+ /// TokenConcatenation class, which answers the question of
+ /// "Is it safe to emit two tokens without a whitespace between them, or
+ /// would that cause implicit concatenation of the tokens?"
+ ///
+ /// For example, it emitting two identifiers "foo" and "bar" next to each
+ /// other would cause the lexer to produce one "foobar" token. Emitting "1"
+ /// and ")" next to each other is safe.
+ ///
+ class TokenConcatenation {
+ Preprocessor &PP;
+
+ enum AvoidConcatInfo {
+ /// By default, a token never needs to avoid concatenation. Most tokens
+ /// (e.g. ',', ')', etc) don't cause a problem when concatenated.
+ aci_never_avoid_concat = 0,
+
+ /// aci_custom_firstchar - AvoidConcat contains custom code to handle this
+ /// token's requirements, and it needs to know the first character of the
+ /// token.
+ aci_custom_firstchar = 1,
+
+ /// aci_custom - AvoidConcat contains custom code to handle this token's
+ /// requirements, but it doesn't need to know the first character of the
+ /// token.
+ aci_custom = 2,
+
+ /// aci_avoid_equal - Many tokens cannot be safely followed by an '='
+ /// character. For example, "<<" turns into "<<=" when followed by an =.
+ aci_avoid_equal = 4
+ };
+
+ /// TokenInfo - This array contains information for each token on what
+ /// action to take when avoiding concatenation of tokens in the AvoidConcat
+ /// method.
+ char TokenInfo[tok::NUM_TOKENS];
+ public:
+ TokenConcatenation(Preprocessor &PP);
+
+ bool AvoidConcat(const Token &PrevTok, const Token &Tok) const;
+
+ private:
+ /// StartsWithL - Return true if the spelling of this token starts with 'L'.
+ bool StartsWithL(const Token &Tok) const;
+
+ /// IsIdentifierL - Return true if the spelling of this token is literally
+ /// 'L'.
+ bool IsIdentifierL(const Token &Tok) const;
+ };
+ } // end clang namespace
+
+#endif
diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h
new file mode 100644
index 000000000000..c0a61cf93ee5
--- /dev/null
+++ b/include/clang/Lex/TokenLexer.h
@@ -0,0 +1,154 @@
+//===--- TokenLexer.h - Lex from a token buffer -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKENLEXER_H
+#define LLVM_CLANG_TOKENLEXER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+ class MacroInfo;
+ class Preprocessor;
+ class Token;
+ class MacroArgs;
+
+/// TokenLexer - This implements a lexer that returns token from a macro body
+/// or token stream instead of lexing from a character buffer. This is used for
+/// macro expansion and _Pragma handling, for example.
+///
+class TokenLexer {
+ /// Macro - The macro we are expanding from. This is null if expanding a
+ /// token stream.
+ ///
+ MacroInfo *Macro;
+
+ /// ActualArgs - The actual arguments specified for a function-like macro, or
+ /// null. The TokenLexer owns the pointed-to object.
+ MacroArgs *ActualArgs;
+
+ /// PP - The current preprocessor object we are expanding for.
+ ///
+ Preprocessor &PP;
+
+ /// Tokens - This is the pointer to an array of tokens that the macro is
+ /// defined to, with arguments expanded for function-like macros. If this is
+ /// a token stream, these are the tokens we are returning. This points into
+ /// the macro definition we are lexing from, a scratch buffer allocated from
+ /// the preprocessor's bump pointer allocator, or some other buffer that we
+ /// may or may not own (depending on OwnsTokens).
+ const Token *Tokens;
+
+ /// NumTokens - This is the length of the Tokens array.
+ ///
+ unsigned NumTokens;
+
+ /// CurToken - This is the next token that Lex will return.
+ ///
+ unsigned CurToken;
+
+ /// InstantiateLocStart/End - The source location range where this macro was
+ /// instantiated.
+ SourceLocation InstantiateLocStart, InstantiateLocEnd;
+
+ /// Lexical information about the expansion point of the macro: the identifier
+ /// that the macro expanded from had these properties.
+ bool AtStartOfLine : 1;
+ bool HasLeadingSpace : 1;
+
+ /// OwnsTokens - This is true if this TokenLexer allocated the Tokens
+ /// array, and thus needs to free it when destroyed. For simple object-like
+ /// macros (for example) we just point into the token buffer of the macro
+ /// definition, we don't make a copy of it.
+ bool OwnsTokens : 1;
+
+ /// DisableMacroExpansion - This is true when tokens lexed from the TokenLexer
+ /// should not be subject to further macro expansion.
+ bool DisableMacroExpansion : 1;
+
+ TokenLexer(const TokenLexer&); // DO NOT IMPLEMENT
+ void operator=(const TokenLexer&); // DO NOT IMPLEMENT
+public:
+ /// Create a TokenLexer for the specified macro with the specified actual
+ /// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
+ /// ILEnd specifies the location of the ')' for a function-like macro or the
+ /// identifier for an object-like macro.
+ TokenLexer(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs,
+ Preprocessor &pp)
+ : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
+ Init(Tok, ILEnd, ActualArgs);
+ }
+
+ /// Init - Initialize this TokenLexer to expand from the specified macro
+ /// with the specified argument information. Note that this ctor takes
+ /// ownership of the ActualArgs pointer. ILEnd specifies the location of the
+ /// ')' for a function-like macro or the identifier for an object-like macro.
+ void Init(Token &Tok, SourceLocation ILEnd, MacroArgs *ActualArgs);
+
+ /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is
+ /// specified, this takes ownership of the tokens and delete[]'s them when
+ /// the token lexer is empty.
+ TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion,
+ bool ownsTokens, Preprocessor &pp)
+ : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
+ Init(TokArray, NumToks, DisableExpansion, ownsTokens);
+ }
+
+ /// Init - Initialize this TokenLexer with the specified token stream.
+ /// This does not take ownership of the specified token vector.
+ ///
+ /// DisableExpansion is true when macro expansion of tokens lexed from this
+ /// stream should be disabled.
+ void Init(const Token *TokArray, unsigned NumToks,
+ bool DisableMacroExpansion, bool OwnsTokens);
+
+ ~TokenLexer() { destroy(); }
+
+ /// isNextTokenLParen - If the next token lexed will pop this macro off the
+ /// expansion stack, return 2. If the next unexpanded token is a '(', return
+ /// 1, otherwise return 0.
+ unsigned isNextTokenLParen() const;
+
+ /// Lex - Lex and return a token from this macro stream.
+ void Lex(Token &Tok);
+
+private:
+ void destroy();
+
+ /// isAtEnd - Return true if the next lex call will pop this macro off the
+ /// include stack.
+ bool isAtEnd() const {
+ return CurToken == NumTokens;
+ }
+
+ /// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
+ /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there
+ /// are is another ## after it, chomp it iteratively. Return the result as
+ /// Tok. If this returns true, the caller should immediately return the
+ /// token.
+ bool PasteTokens(Token &Tok);
+
+ /// Expand the arguments of a function-like macro so that we can quickly
+ /// return preexpanded tokens from Tokens.
+ void ExpandFunctionArguments();
+
+ /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes
+ /// together to form a comment that comments out everything in the current
+ /// macro, other active macros, and anything left on the current physical
+ /// source line of the instantiated buffer. Handle this by returning the
+ /// first token on the next line.
+ void HandleMicrosoftCommentPaste(Token &Tok);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Makefile b/include/clang/Makefile
new file mode 100644
index 000000000000..82a16d53ea33
--- /dev/null
+++ b/include/clang/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../..
+DIRS := Basic
+
+include $(LEVEL)/Makefile.common
diff --git a/include/clang/Parse/AccessSpecifier.h b/include/clang/Parse/AccessSpecifier.h
new file mode 100644
index 000000000000..8d2cee8ea43a
--- /dev/null
+++ b/include/clang/Parse/AccessSpecifier.h
@@ -0,0 +1,30 @@
+//===--- AccessSpecifier.h - C++ Access Specifiers -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces used for C++ access specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H
+#define LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H
+
+namespace clang {
+
+/// AccessSpecifier - A C++ access specifier (none, public, private,
+/// protected).
+enum AccessSpecifier {
+ AS_none,
+ AS_public,
+ AS_protected,
+ AS_private
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
new file mode 100644
index 000000000000..5c23f9ac6147
--- /dev/null
+++ b/include/clang/Parse/Action.h
@@ -0,0 +1,1839 @@
+//===--- Action.h - Parser Action Interface ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Action and EmptyAction interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_ACTION_H
+#define LLVM_CLANG_PARSE_ACTION_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TypeTraits.h"
+#include "clang/Parse/AccessSpecifier.h"
+#include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Ownership.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+ // Semantic.
+ class DeclSpec;
+ class ObjCDeclSpec;
+ class CXXScopeSpec;
+ class Declarator;
+ class AttributeList;
+ struct FieldDeclarator;
+ // Parse.
+ class Scope;
+ class Action;
+ class Selector;
+ class Designation;
+ class InitListDesignations;
+ // Lex.
+ class Preprocessor;
+ class Token;
+
+ // We can re-use the low bit of expression, statement, base, and
+ // member-initializer pointers for the "invalid" flag of
+ // ActionResult.
+ template<> struct IsResultPtrLowBitFree<0> { static const bool value = true;};
+ template<> struct IsResultPtrLowBitFree<1> { static const bool value = true;};
+ template<> struct IsResultPtrLowBitFree<3> { static const bool value = true;};
+ template<> struct IsResultPtrLowBitFree<4> { static const bool value = true;};
+ template<> struct IsResultPtrLowBitFree<5> { static const bool value = true;};
+
+/// Action - As the parser reads the input file and recognizes the productions
+/// of the grammar, it invokes methods on this class to turn the parsed input
+/// into something useful: e.g. a parse tree.
+///
+/// The callback methods that this class provides are phrased as actions that
+/// the parser has just done or is about to do when the method is called. They
+/// are not requests that the actions module do the specified action.
+///
+/// All of the methods here are optional except getTypeName() and
+/// isCurrentClassName(), which must be specified in order for the
+/// parse to complete accurately. The MinimalAction class does this
+/// bare-minimum of tracking to implement this functionality.
+class Action : public ActionBase {
+public:
+ /// Out-of-line virtual destructor to provide home for this class.
+ virtual ~Action();
+
+ // Types - Though these don't actually enforce strong typing, they document
+ // what types are required to be identical for the actions.
+ typedef ActionBase::ExprTy ExprTy;
+ typedef ActionBase::StmtTy StmtTy;
+
+ /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
+ /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
+ /// allowing for failure.
+ typedef ActionResult<0> ExprResult;
+ typedef ActionResult<1> StmtResult;
+ typedef ActionResult<2> TypeResult;
+ typedef ActionResult<3> BaseResult;
+ typedef ActionResult<4> MemInitResult;
+ typedef ActionResult<5, DeclPtrTy> DeclResult;
+
+ /// Same, but with ownership.
+ typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
+ typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
+ // Note that these will replace ExprResult and StmtResult when the transition
+ // is complete.
+
+ /// Single expressions or statements as arguments.
+#if !defined(DISABLE_SMART_POINTERS)
+ typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg;
+ typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg;
+#else
+ typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
+ typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
+#endif
+
+ /// Multiple expressions or statements as arguments.
+ typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
+ typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
+ typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
+
+ class FullExprArg {
+ public:
+ // FIXME: The const_cast here is ugly. RValue references would make this
+ // much nicer (or we could duplicate a bunch of the move semantics
+ // emulation code from Ownership.h).
+ FullExprArg(const FullExprArg& Other)
+ : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {}
+
+ OwningExprResult release() {
+ return move(Expr);
+ }
+
+ ExprArg* operator->() {
+ return &Expr;
+ }
+
+ private:
+ // FIXME: No need to make the entire Action class a friend when it's just
+ // Action::FullExpr that needs access to the constructor below.
+ friend class Action;
+
+ explicit FullExprArg(ExprArg expr)
+ : Expr(move(expr)) {}
+
+ ExprArg Expr;
+ };
+
+ template<typename T>
+ FullExprArg FullExpr(T &Arg) {
+ return FullExprArg(ActOnFinishFullExpr(move(Arg)));
+ }
+
+ // Utilities for Action implementations to return smart results.
+
+ OwningExprResult ExprError() { return OwningExprResult(*this, true); }
+ OwningStmtResult StmtError() { return OwningStmtResult(*this, true); }
+
+ OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
+ OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
+
+ OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); }
+ OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); }
+
+ /// Statistics.
+ virtual void PrintStats() const {}
+
+ /// getDeclName - Return a pretty name for the specified decl if possible, or
+ /// an empty string if not. This is used for pretty crash reporting.
+ virtual std::string getDeclName(DeclPtrTy D) { return ""; }
+
+ //===--------------------------------------------------------------------===//
+ // Declaration Tracking Callbacks.
+ //===--------------------------------------------------------------------===//
+
+ /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
+ /// needs a decl group, it calls this to convert between the two
+ /// representations.
+ virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
+ return DeclGroupPtrTy();
+ }
+
+ /// getTypeName - Return non-null if the specified identifier is a type name
+ /// in the current scope.
+ /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
+ /// namespace) that the identifier must be a member of.
+ /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
+ virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, const CXXScopeSpec *SS = 0) = 0;
+
+ /// isTagName() - This method is called *for error recovery purposes only*
+ /// to determine if the specified name is a valid tag name ("struct foo"). If
+ /// so, this returns the TST for the tag corresponding to it (TST_enum,
+ /// TST_union, TST_struct, TST_class). This is used to diagnose cases in C
+ /// where the user forgot to specify the tag.
+ virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S) {
+ return DeclSpec::TST_unspecified;
+ }
+
+ /// isCurrentClassName - Return true if the specified name is the
+ /// name of the innermost C++ class type currently being defined.
+ virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0) = 0;
+
+ /// \brief Determines whether the identifier II is a template name
+ /// in the current scope. If so, the kind of template name is
+ /// returned, and \p TemplateDecl receives the declaration. An
+ /// optional CXXScope can be passed to indicate the C++ scope in
+ /// which the identifier will be found.
+ virtual TemplateNameKind isTemplateName(const IdentifierInfo &II, Scope *S,
+ TemplateTy &Template,
+ const CXXScopeSpec *SS = 0) = 0;
+
+ /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+ /// global scope ('::').
+ virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
+ SourceLocation CCLoc) {
+ return 0;
+ }
+
+ /// ActOnCXXNestedNameSpecifier - Called during parsing of a
+ /// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
+ /// we want to resolve "bar::". 'SS' is empty or the previously parsed
+ /// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
+ /// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
+ /// Returns a CXXScopeTy* object representing the C++ scope.
+ virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II) {
+ return 0;
+ }
+
+ /// ActOnCXXNestedNameSpecifier - Called during parsing of a
+ /// nested-name-specifier that involves a template-id, e.g.,
+ /// "foo::bar<int, float>::", and now we need to build a scope
+ /// specifier. \p SS is empty or the previously parsed nested-name
+ /// part ("foo::"), \p Type is the already-parsed class template
+ /// specialization (or other template-id that names a type), \p
+ /// TypeRange is the source range where the type is located, and \p
+ /// CCLoc is the location of the trailing '::'.
+ virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ TypeTy *Type,
+ SourceRange TypeRange,
+ SourceLocation CCLoc) {
+ return 0;
+ }
+
+ /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+ /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+ /// After this method is called, according to [C++ 3.4.3p3], names should be
+ /// looked up in the declarator-id's scope, until the declarator is parsed and
+ /// ActOnCXXExitDeclaratorScope is called.
+ /// The 'SS' should be a non-empty valid CXXScopeSpec.
+ virtual void ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ }
+
+ /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+ /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+ /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+ /// Used to indicate that names should revert to being looked up in the
+ /// defining scope.
+ virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ }
+
+ /// ActOnDeclarator - This callback is invoked when a declarator is parsed and
+ /// 'Init' specifies the initializer if any. This is for things like:
+ /// "int X = 4" or "typedef int foo".
+ ///
+ virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnParamDeclarator - This callback is invoked when a parameter
+ /// declarator is parsed. This callback only occurs for functions
+ /// with prototypes. S is the function prototype scope for the
+ /// parameters (C++ [basic.scope.proto]).
+ virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) {
+ return DeclPtrTy();
+ }
+
+ /// AddInitializerToDecl - This action is called immediately after
+ /// ActOnDeclarator (when an initializer is present). The code is factored
+ /// this way to make sure we are able to handle the following:
+ /// void func() { int xx = xx; }
+ /// This allows ActOnDeclarator to register "xx" prior to parsing the
+ /// initializer. The declaration above should still result in a warning,
+ /// since the reference to "xx" is uninitialized.
+ virtual void AddInitializerToDecl(DeclPtrTy Dcl, FullExprArg Init) {
+ return;
+ }
+
+ /// SetDeclDeleted - This action is called immediately after ActOnDeclarator
+ /// if =delete is parsed. C++0x [dcl.fct.def]p10
+ /// Note that this can be called even for variable declarations. It's the
+ /// action's job to reject it.
+ virtual void SetDeclDeleted(DeclPtrTy Dcl, SourceLocation DelLoc) {
+ return;
+ }
+
+ /// ActOnUninitializedDecl - This action is called immediately after
+ /// ActOnDeclarator (when an initializer is *not* present).
+ virtual void ActOnUninitializedDecl(DeclPtrTy Dcl) {
+ return;
+ }
+
+ /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
+ /// gives the actions implementation a chance to process the group as a whole.
+ virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS,
+ DeclPtrTy *Group,
+ unsigned NumDecls) {
+ return DeclGroupPtrTy();
+ }
+
+
+ /// @brief Indicates that all K&R-style parameter declarations have
+ /// been parsed prior to a function definition.
+ /// @param S The function prototype scope.
+ /// @param D The function declarator.
+ virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls) {
+ }
+
+ /// ActOnStartOfFunctionDef - This is called at the start of a function
+ /// definition, instead of calling ActOnDeclarator. The Declarator includes
+ /// information about formal arguments that are part of this function.
+ virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
+ // Default to ActOnDeclarator.
+ return ActOnStartOfFunctionDef(FnBodyScope,
+ ActOnDeclarator(FnBodyScope, D));
+ }
+
+ /// ActOnStartOfFunctionDef - This is called at the start of a function
+ /// definition, after the FunctionDecl has already been created.
+ virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+ return D;
+ }
+
+ virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
+ return;
+ }
+
+ /// ActOnFinishFunctionBody - This is called when a function body has
+ /// completed parsing. Decl is returned by ParseStartOfFunctionDef.
+ virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) {
+ return Decl;
+ }
+
+ virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc,
+ ExprArg AsmString) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnPopScope - This callback is called immediately before the specified
+ /// scope is popped and deleted.
+ virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {}
+
+ /// ActOnTranslationUnitScope - This callback is called once, immediately
+ /// after creating the translation unit scope (in Parser::Initialize).
+ virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {}
+
+ /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
+ /// no declarator (e.g. "struct foo;") is parsed.
+ virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+ /// linkage specification, including the language and (if present)
+ /// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+ /// the location of the language string literal, which is provided
+ /// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+ /// the '{' brace. Otherwise, this linkage specification does not
+ /// have any braces.
+ virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ const char *Lang,
+ unsigned StrSize,
+ SourceLocation LBraceLoc) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnFinishLinkageSpecification - Completely the definition of
+ /// the C++ linkage specification LinkageSpec. If RBraceLoc is
+ /// valid, it's the position of the closing '}' brace in a linkage
+ /// specification that uses braces.
+ virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S,
+ DeclPtrTy LinkageSpec,
+ SourceLocation RBraceLoc) {
+ return LinkageSpec;
+ }
+
+ /// ActOnEndOfTranslationUnit - This is called at the very end of the
+ /// translation unit when EOF is reached and all but the top-level scope is
+ /// popped.
+ virtual void ActOnEndOfTranslationUnit() {}
+
+ //===--------------------------------------------------------------------===//
+ // Type Parsing Callbacks.
+ //===--------------------------------------------------------------------===//
+
+ /// ActOnTypeName - A type-name (type-id in C++) was parsed.
+ virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
+ return TypeResult();
+ }
+
+ enum TagKind {
+ TK_Reference, // Reference to a tag: 'struct foo *X;'
+ TK_Declaration, // Fwd decl of a tag: 'struct foo;'
+ TK_Definition // Definition of a tag: 'struct foo { int X; } Y;'
+ };
+ virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
+ SourceLocation KWLoc, const CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr, AccessSpecifier AS,
+ bool &OwnedDecl) {
+ // TagType is an instance of DeclSpec::TST, indicating what kind of tag this
+ // is (struct/union/enum/class).
+ return DeclPtrTy();
+ }
+
+ /// Act on @defs() element found when parsing a structure. ClassName is the
+ /// name of the referenced class.
+ virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
+ IdentifierInfo *ClassName,
+ llvm::SmallVectorImpl<DeclPtrTy> &Decls) {}
+ virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
+ SourceLocation DeclStart,
+ Declarator &D, ExprTy *BitfieldWidth) {
+ return DeclPtrTy();
+ }
+
+ virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
+ Declarator &D, ExprTy *BitfieldWidth,
+ tok::ObjCKeywordKind visibility) {
+ return DeclPtrTy();
+ }
+
+ virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl,
+ DeclPtrTy *Fields, unsigned NumFields,
+ SourceLocation LBrac, SourceLocation RBrac,
+ AttributeList *AttrList) {}
+
+ /// ActOnTagStartDefinition - Invoked when we have entered the
+ /// scope of a tag's definition (e.g., for an enumeration, class,
+ /// struct, or union).
+ virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { }
+
+ /// ActOnTagFinishDefinition - Invoked once we have finished parsing
+ /// the definition of a tag (enumeration, class, struct, or union).
+ virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl) { }
+
+ virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
+ DeclPtrTy LastEnumConstant,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, ExprTy *Val) {
+ return DeclPtrTy();
+ }
+ virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
+ DeclPtrTy *Elements, unsigned NumElements) {}
+
+ //===--------------------------------------------------------------------===//
+ // Statement Parsing Callbacks.
+ //===--------------------------------------------------------------------===//
+
+ virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ MultiStmtArg Elts,
+ bool isStmtExpr) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) {
+ return OwningStmtResult(*this, Expr->release());
+ }
+
+ /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
+ /// which can specify an RHS value. The sub-statement of the case is
+ /// specified in a separate action.
+ virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
+ SourceLocation DotDotDotLoc,
+ ExprArg RHSVal,
+ SourceLocation ColonLoc) {
+ return StmtEmpty();
+ }
+
+ /// ActOnCaseStmtBody - This installs a statement as the body of a case.
+ virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt) {}
+
+ virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ StmtArg SubStmt, Scope *CurScope){
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
+ IdentifierInfo *II,
+ SourceLocation ColonLoc,
+ StmtArg SubStmt) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
+ FullExprArg CondVal, StmtArg ThenVal,
+ SourceLocation ElseLoc,
+ StmtArg ElseVal) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+ StmtArg Switch, StmtArg Body) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
+ FullExprArg Cond, StmtArg Body) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
+ SourceLocation WhileLoc, ExprArg Cond) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ StmtArg First, ExprArg Second,
+ ExprArg Third, SourceLocation RParenLoc,
+ StmtArg Body) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
+ SourceLocation LParenLoc,
+ StmtArg First, ExprArg Second,
+ SourceLocation RParenLoc, StmtArg Body) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
+ SourceLocation LabelLoc,
+ IdentifierInfo *LabelII) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+ SourceLocation StarLoc,
+ ExprArg DestExp) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
+ Scope *CurScope) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
+ Scope *CurScope) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
+ FullExprArg RetValExp) {
+ return StmtEmpty();
+ }
+ virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple,
+ bool IsVolatile,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ std::string *Names,
+ MultiExprArg Constraints,
+ MultiExprArg Exprs,
+ ExprArg AsmString,
+ MultiExprArg Clobbers,
+ SourceLocation RParenLoc) {
+ return StmtEmpty();
+ }
+
+ // Objective-c statements
+ virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
+ SourceLocation RParen,
+ DeclPtrTy Parm, StmtArg Body,
+ StmtArg CatchList) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
+ StmtArg Body) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
+ StmtArg Try, StmtArg Catch,
+ StmtArg Finally) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
+ ExprArg Throw,
+ Scope *CurScope) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ ExprArg SynchExpr,
+ StmtArg SynchBody) {
+ return StmtEmpty();
+ }
+
+ // C++ Statements
+ virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+ return DeclPtrTy();
+ }
+
+ virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+ DeclPtrTy ExceptionDecl,
+ StmtArg HandlerBlock) {
+ return StmtEmpty();
+ }
+
+ virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+ StmtArg TryBlock,
+ MultiStmtArg Handlers) {
+ return StmtEmpty();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Expression Parsing Callbacks.
+ //===--------------------------------------------------------------------===//
+
+ // Primary Expressions.
+
+ /// \brief Retrieve the source range that corresponds to the given
+ /// expression.
+ virtual SourceRange getExprRange(ExprTy *E) const {
+ return SourceRange();
+ }
+
+ /// ActOnIdentifierExpr - Parse an identifier in expression context.
+ /// 'HasTrailingLParen' indicates whether or not the identifier has a '('
+ /// token immediately after it.
+ /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
+ /// namespace) that the identifier must be a member of.
+ /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
+ virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
+ IdentifierInfo &II,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS = 0,
+ bool isAddressOfOperand = false){
+ return ExprEmpty();
+ }
+
+ /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
+ /// name (e.g., @c operator+ ) as an expression. This is very
+ /// similar to ActOnIdentifierExpr, except that instead of providing
+ /// an identifier the parser provides the kind of overloaded
+ /// operator that was parsed.
+ virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
+ Scope *S, SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ bool HasTrailingLParen, const CXXScopeSpec &SS,
+ bool isAddressOfOperand = false) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
+ /// name (e.g., @c operator void const *) as an expression. This is
+ /// very similar to ActOnIdentifierExpr, except that instead of
+ /// providing an identifier the parser provides the type of the
+ /// conversion function.
+ virtual OwningExprResult ActOnCXXConversionFunctionExpr(
+ Scope *S, SourceLocation OperatorLoc,
+ TypeTy *Type, bool HasTrailingLParen,
+ const CXXScopeSpec &SS,
+ bool isAddressOfOperand = false) {
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
+ tok::TokenKind Kind) {
+ return ExprEmpty();
+ }
+ virtual OwningExprResult ActOnCharacterConstant(const Token &) {
+ return ExprEmpty();
+ }
+ virtual OwningExprResult ActOnNumericConstant(const Token &) {
+ return ExprEmpty();
+ }
+
+ /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+ /// fragments (e.g. "foo" "bar" L"baz").
+ virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
+ unsigned NumToks) {
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
+ ExprArg Val) {
+ return move(Val); // Default impl returns operand.
+ }
+
+ // Postfix Expressions.
+ virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ ExprArg Input) {
+ return ExprEmpty();
+ }
+ virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
+ SourceLocation LLoc,
+ ExprArg Idx,
+ SourceLocation RLoc) {
+ return ExprEmpty();
+ }
+ virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceLocation MemberLoc,
+ IdentifierInfo &Member,
+ DeclPtrTy ObjCImpDecl) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
+ /// This provides the location of the left/right parens and a list of comma
+ /// locations. There are guaranteed to be one fewer commas than arguments,
+ /// unless there are zero arguments.
+ virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc) {
+ return ExprEmpty();
+ }
+
+ // Unary Operators. 'Tok' is the token for the operator.
+ virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, ExprArg Input) {
+ return ExprEmpty();
+ }
+ virtual OwningExprResult
+ ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
+ void *TyOrEx, const SourceRange &ArgRange) {
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen,
+ TypeTy *Ty,
+ SourceLocation RParen,
+ ExprArg Op) {
+ return ExprEmpty();
+ }
+ virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
+ MultiExprArg InitList,
+ SourceLocation RParenLoc) {
+ return ExprEmpty();
+ }
+ /// @brief Parsed a C99 designated initializer.
+ ///
+ /// @param Desig Contains the designation with one or more designators.
+ ///
+ /// @param Loc The location of the '=' or ':' prior to the
+ /// initialization expression.
+ ///
+ /// @param GNUSyntax If true, then this designated initializer used
+ /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather
+ /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo.
+ ///
+ /// @param Init The value that the entity (or entities) described by
+ /// the designation will be initialized with.
+ virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ bool GNUSyntax,
+ OwningExprResult Init) {
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
+ SourceLocation RParenLoc, ExprArg Op) {
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind,
+ ExprArg LHS, ExprArg RHS) {
+ return ExprEmpty();
+ }
+
+ /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
+ /// in the case of a the GNU conditional expr extension.
+ virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+ SourceLocation ColonLoc,
+ ExprArg Cond, ExprArg LHS,
+ ExprArg RHS) {
+ return ExprEmpty();
+ }
+
+ //===---------------------- GNU Extension Expressions -------------------===//
+
+ virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
+ SourceLocation LabLoc,
+ IdentifierInfo *LabelII) { // "&&foo"
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt,
+ SourceLocation RPLoc) { // "({..})"
+ return ExprEmpty();
+ }
+
+ // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+ struct OffsetOfComponent {
+ SourceLocation LocStart, LocEnd;
+ bool isBrackets; // true if [expr], false if .ident
+ union {
+ IdentifierInfo *IdentInfo;
+ ExprTy *E;
+ } U;
+ };
+
+ virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ TypeTy *Arg1,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc) {
+ return ExprEmpty();
+ }
+
+ // __builtin_types_compatible_p(type1, type2)
+ virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ TypeTy *arg1, TypeTy *arg2,
+ SourceLocation RPLoc) {
+ return ExprEmpty();
+ }
+ // __builtin_choose_expr(constExpr, expr1, expr2)
+ virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+ ExprArg cond, ExprArg expr1,
+ ExprArg expr2, SourceLocation RPLoc){
+ return ExprEmpty();
+ }
+
+ // __builtin_va_arg(expr, type)
+ virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+ ExprArg expr, TypeTy *type,
+ SourceLocation RPLoc) {
+ return ExprEmpty();
+ }
+
+ /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token
+ /// for which is at position TokenLoc.
+ virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) {
+ return ExprEmpty();
+ }
+
+ //===------------------------- "Block" Extension ------------------------===//
+
+ /// ActOnBlockStart - This callback is invoked when a block literal is
+ /// started. The result pointer is passed into the block finalizers.
+ virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {}
+
+ /// ActOnBlockArguments - This callback allows processing of block arguments.
+ /// If there are no arguments, this is still invoked.
+ virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {}
+
+ /// ActOnBlockError - If there is an error parsing a block, this callback
+ /// is invoked to pop the information about the block from the action impl.
+ virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {}
+
+ /// ActOnBlockStmtExpr - This is called when the body of a block statement
+ /// literal was successfully completed. ^(int x){...}
+ virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ StmtArg Body,
+ Scope *CurScope) {
+ return ExprEmpty();
+ }
+
+ //===------------------------- C++ Declarations -------------------------===//
+
+ /// ActOnStartNamespaceDef - This is called at the start of a namespace
+ /// definition.
+ virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ SourceLocation LBrace) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnFinishNamespaceDef - This callback is called after a namespace is
+ /// exited. Decl is returned by ActOnStartNamespaceDef.
+ virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) {
+ return;
+ }
+
+ /// ActOnUsingDirective - This is called when using-directive is parsed.
+ virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList);
+
+ /// ActOnNamespaceAliasDef - This is called when a namespace alias definition
+ /// is parsed.
+ virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnParamDefaultArgument - Parse default argument for function parameter
+ virtual void ActOnParamDefaultArgument(DeclPtrTy param,
+ SourceLocation EqualLoc,
+ ExprArg defarg) {
+ }
+
+ /// ActOnParamUnparsedDefaultArgument - We've seen a default
+ /// argument for a function parameter, but we can't parse it yet
+ /// because we're inside a class definition. Note that this default
+ /// argument will be parsed later.
+ virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
+ SourceLocation EqualLoc) { }
+
+ /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
+ /// the default argument for the parameter param failed.
+ virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { }
+
+ /// AddCXXDirectInitializerToDecl - This action is called immediately after
+ /// ActOnDeclarator, when a C++ direct initializer is present.
+ /// e.g: "int x(1);"
+ virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc) {
+ return;
+ }
+
+ /// \brief Called when we re-enter a template parameter scope.
+ ///
+ /// This action occurs when we are going to parse an member
+ /// function's default arguments or inline definition after the
+ /// outermost class definition has been completed, and when one or
+ /// more of the class definitions enclosing the member function is a
+ /// template. The "entity" in the given scope will be set as it was
+ /// when we entered the scope of the template initially, and should
+ /// be used to, e.g., reintroduce the names of template parameters
+ /// into the current scope so that they can be found by name lookup.
+ ///
+ /// \param S The (new) template parameter scope.
+ ///
+ /// \param Template the class template declaration whose template
+ /// parameters should be reintroduced into the current scope.
+ virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) {
+ }
+
+ /// ActOnStartDelayedCXXMethodDeclaration - We have completed
+ /// parsing a top-level (non-nested) C++ class, and we are now
+ /// parsing those parts of the given Method declaration that could
+ /// not be parsed earlier (C++ [class.mem]p2), such as default
+ /// arguments. This action should enter the scope of the given
+ /// Method declaration as if we had just parsed the qualified method
+ /// name. However, it should not bring the parameters into scope;
+ /// that will be performed by ActOnDelayedCXXMethodParameter.
+ virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
+ DeclPtrTy Method) {
+ }
+
+ /// ActOnDelayedCXXMethodParameter - We've already started a delayed
+ /// C++ method declaration. We're (re-)introducing the given
+ /// function parameter into scope for use in parsing later parts of
+ /// the method declaration. For example, we could see an
+ /// ActOnParamDefaultArgument event for this parameter.
+ virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) {
+ }
+
+ /// ActOnFinishDelayedCXXMethodDeclaration - We have finished
+ /// processing the delayed method declaration for Method. The method
+ /// declaration is now considered finished. There may be a separate
+ /// ActOnStartOfFunctionDef action later (not necessarily
+ /// immediately!) for this method, if it was also defined inside the
+ /// class body.
+ virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
+ DeclPtrTy Method) {
+ }
+
+ /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
+ virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ ExprArg AssertExpr,
+ ExprArg AssertMessageExpr) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnFriendDecl - This action is called when a friend declaration is
+ /// encountered. Returns false on success.
+ virtual bool ActOnFriendDecl(Scope *S, SourceLocation FriendLoc,
+ DeclPtrTy Dcl) {
+ return false;
+ }
+
+
+ //===------------------------- C++ Expressions --------------------------===//
+
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc,
+ TypeTy *Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc,
+ ExprArg Op,
+ SourceLocation RParenLoc) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
+ virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXThis - Parse the C++ 'this' pointer.
+ virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
+ tok::TokenKind Kind) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXThrow - Parse throw expressions.
+ virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+ /// Can be interpreted either as function-style casting ("int(x)")
+ /// or class type construction ("ClassType(x,y,z)")
+ /// or creation of a value-initialized type ("int()").
+ virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
+ TypeTy *TypeRep,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
+ /// C++ if/switch/while/for statement.
+ /// e.g: "if (int x = f()) {...}"
+ virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S,
+ SourceLocation StartLoc,
+ Declarator &D,
+ SourceLocation EqualLoc,
+ ExprArg AssignExprVal) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the
+ /// new was qualified (::new). In a full new like
+ /// @code new (p1, p2) type(c1, c2) @endcode
+ /// the p1 and p2 expressions will be in PlacementArgs and the c1 and c2
+ /// expressions in ConstructorArgs. The type is passed as a declarator.
+ virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ bool ParenTypeId, Declarator &D,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen) {
+ return ExprEmpty();
+ }
+
+ /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if
+ /// the delete was qualified (::delete). ArrayForm is true if the array form
+ /// was used (delete[]).
+ virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
+ bool UseGlobal, bool ArrayForm,
+ ExprArg Operand) {
+ return ExprEmpty();
+ }
+
+ virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ SourceLocation LParen,
+ TypeTy *Ty,
+ SourceLocation RParen) {
+ return ExprEmpty();
+ }
+
+
+ /// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
+ /// (C++ [intro.execution]p12).
+ virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
+ return move(Expr);
+ }
+
+ //===---------------------------- C++ Classes ---------------------------===//
+ /// ActOnBaseSpecifier - Parsed a base specifier
+ virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeTy *basetype,
+ SourceLocation BaseLoc) {
+ return BaseResult();
+ }
+
+ virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
+ unsigned NumBases) {
+ }
+
+ /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
+ /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth'
+ /// specifies the bitfield width if there is one and 'Init' specifies the
+ /// initializer if any. 'Deleted' is true if there's a =delete
+ /// specifier on the function.
+ virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+ Declarator &D,
+ ExprTy *BitfieldWidth,
+ ExprTy *Init,
+ bool Deleted = false) {
+ return DeclPtrTy();
+ }
+
+ virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl,
+ Scope *S,
+ IdentifierInfo *MemberOrBase,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ ExprTy **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc) {
+ return true;
+ }
+
+ /// ActOnMemInitializers - This is invoked when all of the member
+ /// initializers of a constructor have been parsed. ConstructorDecl
+ /// is the function declaration (which will be a C++ constructor in
+ /// a well-formed program), ColonLoc is the location of the ':' that
+ /// starts the constructor initializer, and MemInit/NumMemInits
+ /// contains the individual member (and base) initializers.
+ virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
+ SourceLocation ColonLoc,
+ MemInitTy **MemInits, unsigned NumMemInits){
+ }
+
+ /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators
+ /// are parsed but *before* parsing of inline method definitions.
+ virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+ DeclPtrTy TagDecl,
+ SourceLocation LBrac,
+ SourceLocation RBrac) {
+ }
+
+ //===---------------------------C++ Templates----------------------------===//
+
+ /// ActOnTypeParameter - Called when a C++ template type parameter
+ /// (e.g., "typename T") has been parsed. Typename specifies whether
+ /// the keyword "typename" was used to declare the type parameter
+ /// (otherwise, "class" was used), and KeyLoc is the location of the
+ /// "class" or "typename" keyword. ParamName is the name of the
+ /// parameter (NULL indicates an unnamed template parameter) and
+ /// ParamNameLoc is the location of the parameter name (if any).
+ /// If the type parameter has a default argument, it will be added
+ /// later via ActOnTypeParameterDefault. Depth and Position provide
+ /// the number of enclosing templates (see
+ /// ActOnTemplateParameterList) and the number of previous
+ /// parameters within this template parameter list.
+ virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnTypeParameterDefault - Adds a default argument (the type
+ /// Default) to the given template type parameter (TypeParam).
+ virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam,
+ SourceLocation EqualLoc,
+ SourceLocation DefaultLoc,
+ TypeTy *Default) {
+ }
+
+ /// ActOnNonTypeTemplateParameter - Called when a C++ non-type
+ /// template parameter (e.g., "int Size" in "template<int Size>
+ /// class Array") has been parsed. S is the current scope and D is
+ /// the parsed declarator. Depth and Position provide the number of
+ /// enclosing templates (see
+ /// ActOnTemplateParameterList) and the number of previous
+ /// parameters within this template parameter list.
+ virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position) {
+ return DeclPtrTy();
+ }
+
+ /// \brief Adds a default argument to the given non-type template
+ /// parameter.
+ virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
+ SourceLocation EqualLoc,
+ ExprArg Default) {
+ }
+
+ /// ActOnTemplateTemplateParameter - Called when a C++ template template
+ /// parameter (e.g., "int T" in "template<template <typename> class T> class
+ /// Array") has been parsed. TmpLoc is the location of the "template" keyword,
+ /// TemplateParams is the sequence of parameters required by the template,
+ /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc
+ /// is the source location of the identifier (if given).
+ virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
+ SourceLocation TmpLoc,
+ TemplateParamsTy *Params,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth,
+ unsigned Position) {
+ return DeclPtrTy();
+ }
+
+ /// \brief Adds a default argument to the given template template
+ /// parameter.
+ virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
+ SourceLocation EqualLoc,
+ ExprArg Default) {
+ }
+
+ /// ActOnTemplateParameterList - Called when a complete template
+ /// parameter list has been parsed, e.g.,
+ ///
+ /// @code
+ /// export template<typename T, T Size>
+ /// @endcode
+ ///
+ /// Depth is the number of enclosing template parameter lists. This
+ /// value does not include templates from outer scopes. For example:
+ ///
+ /// @code
+ /// template<typename T> // depth = 0
+ /// class A {
+ /// template<typename U> // depth = 0
+ /// class B;
+ /// };
+ ///
+ /// template<typename T> // depth = 0
+ /// template<typename U> // depth = 1
+ /// class A<T>::B { ... };
+ /// @endcode
+ ///
+ /// ExportLoc, if valid, is the position of the "export"
+ /// keyword. Otherwise, "export" was not specified.
+ /// TemplateLoc is the position of the template keyword, LAngleLoc
+ /// is the position of the left angle bracket, and RAngleLoc is the
+ /// position of the corresponding right angle bracket.
+ /// Params/NumParams provides the template parameters that were
+ /// parsed as part of the template-parameter-list.
+ virtual TemplateParamsTy *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ DeclPtrTy *Params, unsigned NumParams,
+ SourceLocation RAngleLoc) {
+ return 0;
+ }
+
+ /// \brief Process the declaration or definition of a class template
+ /// with the given template parameter lists.
+ virtual DeclResult
+ ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
+ SourceLocation KWLoc, const CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists,
+ AccessSpecifier AS) {
+ return DeclResult();
+ }
+
+ /// \brief Form a type from a template and a list of template
+ /// arguments.
+ ///
+ /// This action merely forms the type for the template-id, possibly
+ /// checking well-formedness of the template arguments. It does not
+ /// imply the declaration of any entity.
+ ///
+ /// \param Template A template whose specialization results in a
+ /// type, e.g., a class template or template template parameter.
+ ///
+ /// \param IsSpecialization true when we are naming the class
+ /// template specialization as part of an explicit class
+ /// specialization or class template partial specialization.
+ virtual TypeResult ActOnTemplateIdType(TemplateTy Template,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc) {
+ return TypeResult();
+ };
+
+ /// \brief Form a dependent template name.
+ ///
+ /// This action forms a dependent template name given the template
+ /// name and its (presumably dependent) scope specifier. For
+ /// example, given "MetaFun::template apply", the scope specifier \p
+ /// SS will be "MetaFun::", \p TemplateKWLoc contains the location
+ /// of the "template" keyword, and "apply" is the \p Name.
+ virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
+ const IdentifierInfo &Name,
+ SourceLocation NameLoc,
+ const CXXScopeSpec &SS) {
+ return TemplateTy();
+ }
+
+ /// \brief Process the declaration or definition of an explicit
+ /// class template specialization or a class template partial
+ /// specialization.
+ ///
+ /// This routine is invoked when an explicit class template
+ /// specialization or a class template partial specialization is
+ /// declared or defined, to introduce the (partial) specialization
+ /// and produce a declaration for it. In the following example,
+ /// ActOnClassTemplateSpecialization will be invoked for the
+ /// declarations at both A and B:
+ ///
+ /// \code
+ /// template<typename T> class X;
+ /// template<> class X<int> { }; // A: explicit specialization
+ /// template<typename T> class X<T*> { }; // B: partial specialization
+ /// \endcode
+ ///
+ /// Note that it is the job of semantic analysis to determine which
+ /// of the two cases actually occurred in the source code, since
+ /// they are parsed through the same path. The formulation of the
+ /// template parameter lists describes which case we are in.
+ ///
+ /// \param S the current scope
+ ///
+ /// \param TagSpec whether this declares a class, struct, or union
+ /// (template)
+ ///
+ /// \param TK whether this is a declaration or a definition
+ ///
+ /// \param KWLoc the location of the 'class', 'struct', or 'union'
+ /// keyword.
+ ///
+ /// \param SS the scope specifier preceding the template-id
+ ///
+ /// \param Template the declaration of the class template that we
+ /// are specializing.
+ ///
+ /// \param Attr attributes on the specialization
+ ///
+ /// \param TemplateParameterLists the set of template parameter
+ /// lists that apply to this declaration. In a well-formed program,
+ /// the number of template parameter lists will be one more than the
+ /// number of template-ids in the scope specifier. However, it is
+ /// common for users to provide the wrong number of template
+ /// parameter lists (such as a missing \c template<> prior to a
+ /// specialization); the parser does not check this condition.
+ virtual DeclResult
+ ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
+ SourceLocation KWLoc,
+ const CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists) {
+ return DeclResult();
+ }
+
+ /// \brief Process the explicit instantiation of a class template
+ /// specialization.
+ ///
+ /// This routine is invoked when an explicit instantiation of a
+ /// class template specialization is encountered. In the following
+ /// example, ActOnExplicitInstantiation will be invoked to force the
+ /// instantiation of X<int>:
+ ///
+ /// \code
+ /// template<typename T> class X { /* ... */ };
+ /// template class X<int>; // explicit instantiation
+ /// \endcode
+ ///
+ /// \param S the current scope
+ ///
+ /// \param TemplateLoc the location of the 'template' keyword that
+ /// specifies that this is an explicit instantiation.
+ ///
+ /// \param TagSpec whether this declares a class, struct, or union
+ /// (template).
+ ///
+ /// \param KWLoc the location of the 'class', 'struct', or 'union'
+ /// keyword.
+ ///
+ /// \param SS the scope specifier preceding the template-id.
+ ///
+ /// \param Template the declaration of the class template that we
+ /// are instantiation.
+ ///
+ /// \param LAngleLoc the location of the '<' token in the template-id.
+ ///
+ /// \param TemplateArgs the template arguments used to form the
+ /// template-id.
+ ///
+ /// \param TemplateArgLocs the locations of the template arguments.
+ ///
+ /// \param RAngleLoc the location of the '>' token in the template-id.
+ ///
+ /// \param Attr attributes that apply to this instantiation.
+ virtual DeclResult
+ ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ const CXXScopeSpec &SS,
+ TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc,
+ AttributeList *Attr) {
+ return DeclResult();
+ }
+
+ /// \brief Process the explicit instantiation of a member class of a
+ /// class template specialization.
+ ///
+ /// This routine is invoked when an explicit instantiation of a
+ /// member class of a class template specialization is
+ /// encountered. In the following example,
+ /// ActOnExplicitInstantiation will be invoked to force the
+ /// instantiation of X<int>::Inner:
+ ///
+ /// \code
+ /// template<typename T> class X { class Inner { /* ... */}; };
+ /// template class X<int>::Inner; // explicit instantiation
+ /// \endcode
+ ///
+ /// \param S the current scope
+ ///
+ /// \param TemplateLoc the location of the 'template' keyword that
+ /// specifies that this is an explicit instantiation.
+ ///
+ /// \param TagSpec whether this declares a class, struct, or union
+ /// (template).
+ ///
+ /// \param KWLoc the location of the 'class', 'struct', or 'union'
+ /// keyword.
+ ///
+ /// \param SS the scope specifier preceding the template-id.
+ ///
+ /// \param Template the declaration of the class template that we
+ /// are instantiation.
+ ///
+ /// \param LAngleLoc the location of the '<' token in the template-id.
+ ///
+ /// \param TemplateArgs the template arguments used to form the
+ /// template-id.
+ ///
+ /// \param TemplateArgLocs the locations of the template arguments.
+ ///
+ /// \param RAngleLoc the location of the '>' token in the template-id.
+ ///
+ /// \param Attr attributes that apply to this instantiation.
+ virtual DeclResult
+ ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
+ unsigned TagSpec,
+ SourceLocation KWLoc,
+ const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ AttributeList *Attr) {
+ return DeclResult();
+ }
+
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier that ends in an identifier, e.g., "typename T::type".
+ ///
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param II the identifier we're retrieving (e.g., 'type' in the example).
+ /// \param IdLoc the location of the identifier.
+ virtual TypeResult
+ ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+ const IdentifierInfo &II, SourceLocation IdLoc) {
+ return TypeResult();
+ }
+
+ /// \brief Called when the parser has parsed a C++ typename
+ /// specifier that ends in a template-id, e.g.,
+ /// "typename MetaFun::template apply<T1, T2>".
+ ///
+ /// \param TypenameLoc the location of the 'typename' keyword
+ /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+ /// \param TemplateLoc the location of the 'template' keyword, if any.
+ /// \param Ty the type that the typename specifier refers to.
+ virtual TypeResult
+ ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+ SourceLocation TemplateLoc, TypeTy *Ty) {
+ return TypeResult();
+ }
+
+ //===----------------------- Obj-C Declarations -------------------------===//
+
+ // ActOnStartClassInterface - this action is called immediately after parsing
+ // the prologue for a class interface (before parsing the instance
+ // variables). Instance variables are processed by ActOnFields().
+ virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ const DeclPtrTy *ProtoRefs,
+ unsigned NumProtoRefs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList) {
+ return DeclPtrTy();
+ }
+
+ /// ActOnCompatiblityAlias - this action is called after complete parsing of
+ /// @compaatibility_alias declaration. It sets up the alias relationships.
+ virtual DeclPtrTy ActOnCompatiblityAlias(
+ SourceLocation AtCompatibilityAliasLoc,
+ IdentifierInfo *AliasName, SourceLocation AliasLocation,
+ IdentifierInfo *ClassName, SourceLocation ClassLocation) {
+ return DeclPtrTy();
+ }
+
+ // ActOnStartProtocolInterface - this action is called immdiately after
+ // parsing the prologue for a protocol interface.
+ virtual DeclPtrTy ActOnStartProtocolInterface(SourceLocation AtProtoLoc,
+ IdentifierInfo *ProtocolName,
+ SourceLocation ProtocolLoc,
+ const DeclPtrTy *ProtoRefs,
+ unsigned NumProtoRefs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList) {
+ return DeclPtrTy();
+ }
+ // ActOnStartCategoryInterface - this action is called immdiately after
+ // parsing the prologue for a category interface.
+ virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CategoryName,
+ SourceLocation CategoryLoc,
+ const DeclPtrTy *ProtoRefs,
+ unsigned NumProtoRefs,
+ SourceLocation EndProtoLoc) {
+ return DeclPtrTy();
+ }
+ // ActOnStartClassImplementation - this action is called immdiately after
+ // parsing the prologue for a class implementation. Instance variables are
+ // processed by ActOnFields().
+ virtual DeclPtrTy ActOnStartClassImplementation(
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc) {
+ return DeclPtrTy();
+ }
+ // ActOnStartCategoryImplementation - this action is called immdiately after
+ // parsing the prologue for a category implementation.
+ virtual DeclPtrTy ActOnStartCategoryImplementation(
+ SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc) {
+ return DeclPtrTy();
+ }
+ // ActOnPropertyImplDecl - called for every property implementation
+ virtual DeclPtrTy ActOnPropertyImplDecl(
+ SourceLocation AtLoc, // location of the @synthesize/@dynamic
+ SourceLocation PropertyNameLoc, // location for the property name
+ bool ImplKind, // true for @synthesize, false for
+ // @dynamic
+ DeclPtrTy ClassImplDecl, // class or category implementation
+ IdentifierInfo *propertyId, // name of property
+ IdentifierInfo *propertyIvar) { // name of the ivar
+ return DeclPtrTy();
+ }
+
+ struct ObjCArgInfo {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ // The Type is null if no type was specified, and the DeclSpec is invalid
+ // in this case.
+ TypeTy *Type;
+ ObjCDeclSpec DeclSpec;
+
+ /// ArgAttrs - Attribute list for this argument.
+ AttributeList *ArgAttrs;
+ };
+
+ // ActOnMethodDeclaration - called for all method declarations.
+ virtual DeclPtrTy ActOnMethodDeclaration(
+ SourceLocation BeginLoc, // location of the + or -.
+ SourceLocation EndLoc, // location of the ; or {.
+ tok::TokenKind MethodType, // tok::minus for instance, tok::plus for class.
+ DeclPtrTy ClassDecl, // class this methods belongs to.
+ ObjCDeclSpec &ReturnQT, // for return type's in inout etc.
+ TypeTy *ReturnType, // the method return type.
+ Selector Sel, // a unique name for the method.
+ ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries.
+ llvm::SmallVectorImpl<Declarator> &Cdecls, // c-style args
+ AttributeList *MethodAttrList, // optional
+ // tok::objc_not_keyword, tok::objc_optional, tok::objc_required
+ tok::ObjCKeywordKind impKind,
+ bool isVariadic = false) {
+ return DeclPtrTy();
+ }
+ // ActOnAtEnd - called to mark the @end. For declarations (interfaces,
+ // protocols, categories), the parser passes all methods/properties.
+ // For class implementations, these values default to 0. For implementations,
+ // methods are processed incrementally (by ActOnMethodDeclaration above).
+ virtual void ActOnAtEnd(SourceLocation AtEndLoc,
+ DeclPtrTy classDecl,
+ DeclPtrTy *allMethods = 0,
+ unsigned allNum = 0,
+ DeclPtrTy *allProperties = 0,
+ unsigned pNum = 0,
+ DeclGroupPtrTy *allTUVars = 0,
+ unsigned tuvNum = 0) {
+ }
+ // ActOnProperty - called to build one property AST
+ virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
+ FieldDeclarator &FD, ObjCDeclSpec &ODS,
+ Selector GetterSel, Selector SetterSel,
+ DeclPtrTy ClassCategory,
+ bool *OverridingProperty,
+ tok::ObjCKeywordKind MethodImplKind) {
+ return DeclPtrTy();
+ }
+
+ virtual OwningExprResult ActOnClassPropertyRefExpr(
+ IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation &receiverNameLoc,
+ SourceLocation &propertyNameLoc) {
+ return ExprEmpty();
+ }
+
+ // ActOnClassMessage - used for both unary and keyword messages.
+ // ArgExprs is optional - if it is present, the number of expressions
+ // is obtained from NumArgs.
+ virtual ExprResult ActOnClassMessage(
+ Scope *S,
+ IdentifierInfo *receivingClassName,
+ Selector Sel,
+ SourceLocation lbrac, SourceLocation receiverLoc,
+ SourceLocation selectorLoc,
+ SourceLocation rbrac,
+ ExprTy **ArgExprs, unsigned NumArgs) {
+ return ExprResult();
+ }
+ // ActOnInstanceMessage - used for both unary and keyword messages.
+ // ArgExprs is optional - if it is present, the number of expressions
+ // is obtained from NumArgs.
+ virtual ExprResult ActOnInstanceMessage(
+ ExprTy *receiver, Selector Sel,
+ SourceLocation lbrac, SourceLocation selectorLoc, SourceLocation rbrac,
+ ExprTy **ArgExprs, unsigned NumArgs) {
+ return ExprResult();
+ }
+ virtual DeclPtrTy ActOnForwardClassDeclaration(
+ SourceLocation AtClassLoc,
+ IdentifierInfo **IdentList,
+ unsigned NumElts) {
+ return DeclPtrTy();
+ }
+ virtual DeclPtrTy ActOnForwardProtocolDeclaration(
+ SourceLocation AtProtocolLoc,
+ const IdentifierLocPair*IdentList,
+ unsigned NumElts,
+ AttributeList *AttrList) {
+ return DeclPtrTy();
+ }
+
+ /// FindProtocolDeclaration - This routine looks up protocols and
+ /// issues error if they are not declared. It returns list of valid
+ /// protocols found.
+ virtual void FindProtocolDeclaration(bool WarnOnDeclarations,
+ const IdentifierLocPair *ProtocolId,
+ unsigned NumProtocols,
+ llvm::SmallVectorImpl<DeclPtrTy> &ResProtos) {
+ }
+
+ //===----------------------- Obj-C Expressions --------------------------===//
+
+ virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ ExprTy **Strings,
+ unsigned NumStrings) {
+ return ExprResult();
+ }
+
+ virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncLoc,
+ SourceLocation LParenLoc,
+ TypeTy *Ty,
+ SourceLocation RParenLoc) {
+ return ExprResult();
+ }
+
+ virtual ExprResult ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return ExprResult();
+ }
+
+ virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return ExprResult();
+ }
+
+ //===---------------------------- Pragmas -------------------------------===//
+
+ enum PragmaPackKind {
+ PPK_Default, // #pragma pack([n])
+ PPK_Show, // #pragma pack(show), only supported by MSVC.
+ PPK_Push, // #pragma pack(push, [identifier], [n])
+ PPK_Pop // #pragma pack(pop, [identifier], [n])
+ };
+
+ /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+ virtual void ActOnPragmaPack(PragmaPackKind Kind,
+ IdentifierInfo *Name,
+ ExprTy *Alignment,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return;
+ }
+
+ /// ActOnPragmaPack - Called on well formed #pragma pack(...).
+ virtual void ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return;
+ }
+};
+
+/// MinimalAction - Minimal actions are used by light-weight clients of the
+/// parser that do not need name resolution or significant semantic analysis to
+/// be performed. The actions implemented here are in the form of unresolved
+/// identifiers. By using a simpler interface than the SemanticAction class,
+/// the parser doesn't have to build complex data structures and thus runs more
+/// quickly.
+class MinimalAction : public Action {
+ /// Translation Unit Scope - useful to Objective-C actions that need
+ /// to lookup file scope declarations in the "ordinary" C decl namespace.
+ /// For example, user-defined classes, built-in "id" type, etc.
+ Scope *TUScope;
+ IdentifierTable &Idents;
+ Preprocessor &PP;
+ void *TypeNameInfoTablePtr;
+public:
+ MinimalAction(Preprocessor &pp);
+ ~MinimalAction();
+
+ /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to
+ /// determine whether the name is a typedef or not in this scope.
+ virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, const CXXScopeSpec *SS);
+
+ /// isCurrentClassName - Always returns false, because MinimalAction
+ /// does not support C++ classes with constructors.
+ virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S,
+ const CXXScopeSpec *SS);
+
+ virtual TemplateNameKind isTemplateName(const IdentifierInfo &II, Scope *S,
+ TemplateTy &Template,
+ const CXXScopeSpec *SS = 0);
+
+ /// ActOnDeclarator - If this is a typedef declarator, we modify the
+ /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
+ /// popped.
+ virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D);
+
+ /// ActOnPopScope - When a scope is popped, if any typedefs are now
+ /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
+ virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
+ virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
+
+ virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
+ IdentifierInfo **IdentList,
+ unsigned NumElts);
+
+ virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ const DeclPtrTy *ProtoRefs,
+ unsigned NumProtoRefs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+};
+
+/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing
+/// something related to a virtualized decl, include that virtualized decl in
+/// the stack trace.
+class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry {
+ Action::DeclPtrTy TheDecl;
+ SourceLocation Loc;
+ Action &Actions;
+ SourceManager &SM;
+ const char *Message;
+public:
+ PrettyStackTraceActionsDecl(Action::DeclPtrTy Decl, SourceLocation L,
+ Action &actions, SourceManager &sm,
+ const char *Msg)
+ : TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
new file mode 100644
index 000000000000..8225c9d33abb
--- /dev/null
+++ b/include/clang/Parse/AttributeList.h
@@ -0,0 +1,173 @@
+//===--- AttributeList.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AttributeList class interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ATTRLIST_H
+#define LLVM_CLANG_ATTRLIST_H
+
+#include "clang/Parse/Ownership.h"
+#include "clang/Basic/SourceLocation.h"
+#include <cassert>
+
+namespace clang {
+ class IdentifierInfo;
+ class Action;
+
+/// AttributeList - Represents GCC's __attribute__ declaration. There are
+/// 4 forms of this construct...they are:
+///
+/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
+/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
+/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
+/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
+///
+class AttributeList {
+ IdentifierInfo *AttrName;
+ SourceLocation AttrLoc;
+ IdentifierInfo *ParmName;
+ SourceLocation ParmLoc;
+ ActionBase::ExprTy **Args;
+ unsigned NumArgs;
+ AttributeList *Next;
+ AttributeList(const AttributeList &); // DO NOT IMPLEMENT
+ void operator=(const AttributeList &); // DO NOT IMPLEMENT
+public:
+ AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
+ IdentifierInfo *ParmName, SourceLocation ParmLoc,
+ ActionBase::ExprTy **args, unsigned numargs,
+ AttributeList *Next);
+ ~AttributeList();
+
+ enum Kind { // Please keep this list alphabetized.
+ AT_IBOutlet, // Clang-specific.
+ AT_address_space,
+ AT_alias,
+ AT_aligned,
+ AT_always_inline,
+ AT_analyzer_noreturn,
+ AT_annotate,
+ AT_blocks,
+ AT_cleanup,
+ AT_const,
+ AT_constructor,
+ AT_deprecated,
+ AT_destructor,
+ AT_dllexport,
+ AT_dllimport,
+ AT_ext_vector_type,
+ AT_fastcall,
+ AT_format,
+ AT_format_arg,
+ AT_gnu_inline,
+ AT_mode,
+ AT_nodebug,
+ AT_noinline,
+ AT_no_instrument_function,
+ AT_nonnull,
+ AT_noreturn,
+ AT_nothrow,
+ AT_nsobject,
+ AT_objc_exception,
+ AT_cf_returns_retained, // Clang-specific.
+ AT_ns_returns_retained, // Clang-specific.
+ AT_objc_gc,
+ AT_overloadable, // Clang-specific.
+ AT_packed,
+ AT_pure,
+ AT_regparm,
+ AT_section,
+ AT_sentinel,
+ AT_stdcall,
+ AT_transparent_union,
+ AT_unavailable,
+ AT_unused,
+ AT_used,
+ AT_vector_size,
+ AT_visibility,
+ AT_warn_unused_result,
+ AT_weak,
+ AT_weak_import,
+ IgnoredAttribute,
+ UnknownAttribute
+ };
+
+ IdentifierInfo *getName() const { return AttrName; }
+ SourceLocation getLoc() const { return AttrLoc; }
+ IdentifierInfo *getParameterName() const { return ParmName; }
+
+ Kind getKind() const { return getKind(getName()); }
+ static Kind getKind(const IdentifierInfo *Name);
+
+ AttributeList *getNext() const { return Next; }
+ void setNext(AttributeList *N) { Next = N; }
+
+ void addAttributeList(AttributeList *alist) {
+ assert((alist != 0) && "addAttributeList(): alist is null");
+ AttributeList *next = this, *prev;
+ do {
+ prev = next;
+ next = next->getNext();
+ } while (next);
+ prev->setNext(alist);
+ }
+
+ /// getNumArgs - Return the number of actual arguments to this attribute.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// getArg - Return the specified argument.
+ ActionBase::ExprTy *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return Args[Arg];
+ }
+
+ class arg_iterator {
+ ActionBase::ExprTy** X;
+ unsigned Idx;
+ public:
+ arg_iterator(ActionBase::ExprTy** x, unsigned idx) : X(x), Idx(idx) {}
+
+ arg_iterator& operator++() {
+ ++Idx;
+ return *this;
+ }
+
+ bool operator==(const arg_iterator& I) const {
+ assert (X == I.X &&
+ "compared arg_iterators are for different argument lists");
+ return Idx == I.Idx;
+ }
+
+ bool operator!=(const arg_iterator& I) const {
+ return !operator==(I);
+ }
+
+ ActionBase::ExprTy* operator*() const {
+ return X[Idx];
+ }
+
+ unsigned getArgNum() const {
+ return Idx+1;
+ }
+ };
+
+ arg_iterator arg_begin() const {
+ return arg_iterator(Args, 0);
+ }
+
+ arg_iterator arg_end() const {
+ return arg_iterator(Args, NumArgs);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
new file mode 100644
index 000000000000..a0b9b1e7cc23
--- /dev/null
+++ b/include/clang/Parse/DeclSpec.h
@@ -0,0 +1,1086 @@
+//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces used for Declaration Specifiers and Declarators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_DECLSPEC_H
+#define LLVM_CLANG_PARSE_DECLSPEC_H
+
+#include "clang/Parse/AttributeList.h"
+#include "clang/Lex/Token.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class LangOptions;
+ class Diagnostic;
+ class IdentifierInfo;
+ class Preprocessor;
+ class Declarator;
+
+/// DeclSpec - This class captures information about "declaration specifiers",
+/// which encompasses storage-class-specifiers, type-specifiers,
+/// type-qualifiers, and function-specifiers.
+class DeclSpec {
+public:
+ // storage-class-specifier
+ enum SCS {
+ SCS_unspecified,
+ SCS_typedef,
+ SCS_extern,
+ SCS_static,
+ SCS_auto,
+ SCS_register,
+ SCS_private_extern,
+ SCS_mutable
+ };
+
+ // type-specifier
+ enum TSW {
+ TSW_unspecified,
+ TSW_short,
+ TSW_long,
+ TSW_longlong
+ };
+
+ enum TSC {
+ TSC_unspecified,
+ TSC_imaginary,
+ TSC_complex
+ };
+
+ enum TSS {
+ TSS_unspecified,
+ TSS_signed,
+ TSS_unsigned
+ };
+
+ enum TST {
+ TST_unspecified,
+ TST_void,
+ TST_char,
+ TST_wchar, // C++ wchar_t
+ TST_int,
+ TST_float,
+ TST_double,
+ TST_bool, // _Bool
+ TST_decimal32, // _Decimal32
+ TST_decimal64, // _Decimal64
+ TST_decimal128, // _Decimal128
+ TST_enum,
+ TST_union,
+ TST_struct,
+ TST_class, // C++ class type
+ TST_typename, // Typedef, C++ class-name or enum name, etc.
+ TST_typeofType,
+ TST_typeofExpr,
+ TST_error // erroneous type
+ };
+
+ // type-qualifiers
+ enum TQ { // NOTE: These flags must be kept in sync with QualType::TQ.
+ TQ_unspecified = 0,
+ TQ_const = 1,
+ TQ_restrict = 2,
+ TQ_volatile = 4
+ };
+
+ /// ParsedSpecifiers - Flags to query which specifiers were applied. This is
+ /// returned by getParsedSpecifiers.
+ enum ParsedSpecifiers {
+ PQ_None = 0,
+ PQ_StorageClassSpecifier = 1,
+ PQ_TypeSpecifier = 2,
+ PQ_TypeQualifier = 4,
+ PQ_FunctionSpecifier = 8
+ };
+
+private:
+
+ // storage-class-specifier
+ /*SCS*/unsigned StorageClassSpec : 3;
+ bool SCS_thread_specified : 1;
+
+ // type-specifier
+ /*TSW*/unsigned TypeSpecWidth : 2;
+ /*TSC*/unsigned TypeSpecComplex : 2;
+ /*TSS*/unsigned TypeSpecSign : 2;
+ /*TST*/unsigned TypeSpecType : 5;
+ bool TypeSpecOwned : 1;
+
+ // type-qualifiers
+ unsigned TypeQualifiers : 3; // Bitwise OR of TQ.
+
+ // function-specifier
+ bool FS_inline_specified : 1;
+ bool FS_virtual_specified : 1;
+ bool FS_explicit_specified : 1;
+
+ // friend-specifier
+ bool Friend_specified : 1;
+
+ /// TypeRep - This contains action-specific information about a specific TST.
+ /// For example, for a typedef or struct, it might contain the declaration for
+ /// these.
+ void *TypeRep;
+
+ // attributes.
+ AttributeList *AttrList;
+
+ // List of protocol qualifiers for objective-c classes. Used for
+ // protocol-qualified interfaces "NString<foo>" and protocol-qualified id
+ // "id<foo>".
+ const ActionBase::DeclPtrTy *ProtocolQualifiers;
+ unsigned NumProtocolQualifiers;
+
+ // SourceLocation info. These are null if the item wasn't specified or if
+ // the setting was synthesized.
+ SourceRange Range;
+
+ SourceLocation StorageClassSpecLoc, SCS_threadLoc;
+ SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc;
+ SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
+ SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
+ SourceLocation FriendLoc;
+
+ bool BadSpecifier(TST T, const char *&PrevSpec);
+ bool BadSpecifier(TQ T, const char *&PrevSpec);
+ bool BadSpecifier(TSS T, const char *&PrevSpec);
+ bool BadSpecifier(TSC T, const char *&PrevSpec);
+ bool BadSpecifier(TSW T, const char *&PrevSpec);
+ bool BadSpecifier(SCS T, const char *&PrevSpec);
+
+ DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
+ void operator=(const DeclSpec&); // DO NOT IMPLEMENT
+public:
+
+ DeclSpec()
+ : StorageClassSpec(SCS_unspecified),
+ SCS_thread_specified(false),
+ TypeSpecWidth(TSW_unspecified),
+ TypeSpecComplex(TSC_unspecified),
+ TypeSpecSign(TSS_unspecified),
+ TypeSpecType(TST_unspecified),
+ TypeSpecOwned(false),
+ TypeQualifiers(TSS_unspecified),
+ FS_inline_specified(false),
+ FS_virtual_specified(false),
+ FS_explicit_specified(false),
+ Friend_specified(false),
+ TypeRep(0),
+ AttrList(0),
+ ProtocolQualifiers(0),
+ NumProtocolQualifiers(0) {
+ }
+ ~DeclSpec() {
+ delete AttrList;
+ delete [] ProtocolQualifiers;
+ }
+ // storage-class-specifier
+ SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
+ bool isThreadSpecified() const { return SCS_thread_specified; }
+
+ SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
+ SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
+
+ void ClearStorageClassSpecs() {
+ StorageClassSpec = DeclSpec::SCS_unspecified;
+ SCS_thread_specified = false;
+ StorageClassSpecLoc = SourceLocation();
+ SCS_threadLoc = SourceLocation();
+ }
+
+ // type-specifier
+ TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; }
+ TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
+ TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; }
+ TST getTypeSpecType() const { return (TST)TypeSpecType; }
+ bool isTypeSpecOwned() const { return TypeSpecOwned; }
+ void *getTypeRep() const { return TypeRep; }
+
+ const SourceRange &getSourceRange() const { return Range; }
+ SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
+ SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
+ SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
+ SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
+
+ /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool"
+ /// or "union".
+ static const char *getSpecifierName(DeclSpec::TST T);
+ static const char *getSpecifierName(DeclSpec::SCS S);
+
+ // type-qualifiers
+
+ /// getTypeQualifiers - Return a set of TQs.
+ unsigned getTypeQualifiers() const { return TypeQualifiers; }
+ SourceLocation getConstSpecLoc() const { return TQ_constLoc; }
+ SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
+ SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
+
+ // function-specifier
+ bool isInlineSpecified() const { return FS_inline_specified; }
+ SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
+
+ bool isVirtualSpecified() const { return FS_virtual_specified; }
+ SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
+
+ bool isExplicitSpecified() const { return FS_explicit_specified; }
+ SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; }
+
+ void ClearFunctionSpecs() {
+ FS_inline_specified = false;
+ FS_inlineLoc = SourceLocation();
+ FS_virtual_specified = false;
+ FS_virtualLoc = SourceLocation();
+ FS_explicit_specified = false;
+ FS_explicitLoc = SourceLocation();
+ }
+
+ /// hasTypeSpecifier - Return true if any type-specifier has been found.
+ bool hasTypeSpecifier() const {
+ return getTypeSpecType() != DeclSpec::TST_unspecified ||
+ getTypeSpecWidth() != DeclSpec::TSW_unspecified ||
+ getTypeSpecComplex() != DeclSpec::TSC_unspecified ||
+ getTypeSpecSign() != DeclSpec::TSS_unspecified;
+ }
+
+ /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
+ /// DeclSpec includes.
+ ///
+ unsigned getParsedSpecifiers() const;
+
+ /// isEmpty - Return true if this declaration specifier is completely empty:
+ /// no tokens were parsed in the production of it.
+ bool isEmpty() const {
+ return getParsedSpecifiers() == DeclSpec::PQ_None;
+ }
+
+ void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); }
+ void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); }
+
+ /// These methods set the specified attribute of the DeclSpec, but return true
+ /// and ignore the request if invalid (e.g. "extern" then "auto" is
+ /// specified). The name of the previous specifier is returned in prevspec.
+ bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec);
+ bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec);
+ bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec);
+ bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec);
+ bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ void *Rep = 0, bool Owned = false);
+ bool SetTypeSpecError();
+
+ bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+ const LangOptions &Lang);
+
+ bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec);
+ bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec);
+ bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec);
+
+ bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec);
+ bool isFriendSpecified() const { return Friend_specified; }
+ SourceLocation getFriendSpecLoc() const { return FriendLoc; }
+
+ /// AddAttributes - contatenates two attribute lists.
+ /// The GCC attribute syntax allows for the following:
+ ///
+ /// short __attribute__(( unused, deprecated ))
+ /// int __attribute__(( may_alias, aligned(16) )) var;
+ ///
+ /// This declares 4 attributes using 2 lists. The following syntax is
+ /// also allowed and equivalent to the previous declaration.
+ ///
+ /// short __attribute__((unused)) __attribute__((deprecated))
+ /// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
+ ///
+ void AddAttributes(AttributeList *alist) {
+ if (!alist)
+ return; // we parsed __attribute__(()) or had a syntax error
+
+ if (AttrList)
+ alist->addAttributeList(AttrList);
+ AttrList = alist;
+ }
+ void SetAttributes(AttributeList *AL) { AttrList = AL; }
+ const AttributeList *getAttributes() const { return AttrList; }
+ AttributeList *getAttributes() { return AttrList; }
+
+ /// TakeAttributes - Return the current attribute list and remove them from
+ /// the DeclSpec so that it doesn't own them.
+ AttributeList *TakeAttributes() {
+ AttributeList *AL = AttrList;
+ AttrList = 0;
+ return AL;
+ }
+
+ typedef const ActionBase::DeclPtrTy *ProtocolQualifierListTy;
+ ProtocolQualifierListTy getProtocolQualifiers() const {
+ return ProtocolQualifiers;
+ }
+ unsigned getNumProtocolQualifiers() const {
+ return NumProtocolQualifiers;
+ }
+ void setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP) {
+ if (NP == 0) return;
+ ProtocolQualifiers = new ActionBase::DeclPtrTy[NP];
+ memcpy((void*)ProtocolQualifiers, Protos, sizeof(ActionBase::DeclPtrTy)*NP);
+ NumProtocolQualifiers = NP;
+ }
+
+ /// Finish - This does final analysis of the declspec, issuing diagnostics for
+ /// things like "_Imaginary" (lacking an FP type). After calling this method,
+ /// DeclSpec is guaranteed self-consistent, even if an error occurred.
+ void Finish(Diagnostic &D, Preprocessor &PP);
+
+ /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
+ /// without a Declarator. Only tag declspecs can stand alone.
+ bool isMissingDeclaratorOk();
+};
+
+/// ObjCDeclSpec - This class captures information about
+/// "declaration specifiers" specific to objective-c
+class ObjCDeclSpec {
+public:
+ /// ObjCDeclQualifier - Qualifier used on types in method declarations
+ enum ObjCDeclQualifier {
+ DQ_None = 0x0,
+ DQ_In = 0x1,
+ DQ_Inout = 0x2,
+ DQ_Out = 0x4,
+ DQ_Bycopy = 0x8,
+ DQ_Byref = 0x10,
+ DQ_Oneway = 0x20
+ };
+
+ /// PropertyAttributeKind - list of property attributes.
+ enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0,
+ DQ_PR_readonly = 0x01,
+ DQ_PR_getter = 0x02,
+ DQ_PR_assign = 0x04,
+ DQ_PR_readwrite = 0x08,
+ DQ_PR_retain = 0x10,
+ DQ_PR_copy = 0x20,
+ DQ_PR_nonatomic = 0x40,
+ DQ_PR_setter = 0x80
+ };
+
+
+ ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
+ GetterName(0), SetterName(0)
+ {}
+ ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
+ void setObjCDeclQualifier(ObjCDeclQualifier DQVal)
+ { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); }
+
+ ObjCPropertyAttributeKind getPropertyAttributes() const
+ { return ObjCPropertyAttributeKind(PropertyAttributes); }
+ void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
+ PropertyAttributes =
+ (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal);
+ }
+
+ const IdentifierInfo *getGetterName() const { return GetterName; }
+ IdentifierInfo *getGetterName() { return GetterName; }
+ void setGetterName(IdentifierInfo *name) { GetterName = name; }
+
+ const IdentifierInfo *getSetterName() const { return SetterName; }
+ IdentifierInfo *getSetterName() { return SetterName; }
+ void setSetterName(IdentifierInfo *name) { SetterName = name; }
+private:
+ // FIXME: These two are unrelated and mutially exclusive. So perhaps
+ // we can put them in a union to reflect their mutual exclusiveness
+ // (space saving is negligible).
+ ObjCDeclQualifier objcDeclQualifier : 6;
+
+ // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
+ unsigned PropertyAttributes : 8;
+ IdentifierInfo *GetterName; // getter name of NULL if no getter
+ IdentifierInfo *SetterName; // setter name of NULL if no setter
+};
+
+/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope
+/// specifier.
+class CXXScopeSpec {
+ SourceRange Range;
+ void *ScopeRep;
+
+public:
+ CXXScopeSpec() : Range(), ScopeRep() { }
+
+ const SourceRange &getRange() const { return Range; }
+ void setRange(const SourceRange &R) { Range = R; }
+ void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
+ void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
+
+ ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; }
+ void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; }
+
+ bool isEmpty() const { return !Range.isValid(); }
+ bool isNotEmpty() const { return !isEmpty(); }
+
+ /// isInvalid - An error occured during parsing of the scope specifier.
+ bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
+
+ /// isSet - A scope specifier was resolved to a valid C++ scope.
+ bool isSet() const { return ScopeRep != 0; }
+
+ void clear() {
+ Range = SourceRange();
+ ScopeRep = 0;
+ }
+};
+
+/// CachedTokens - A set of tokens that has been cached for later
+/// parsing.
+typedef llvm::SmallVector<Token, 4> CachedTokens;
+
+/// DeclaratorChunk - One instance of this struct is used for each type in a
+/// declarator that is parsed.
+///
+/// This is intended to be a small value object.
+struct DeclaratorChunk {
+ enum {
+ Pointer, Reference, Array, Function, BlockPointer, MemberPointer
+ } Kind;
+
+ /// Loc - The place where this type was defined.
+ SourceLocation Loc;
+
+ struct PointerTypeInfo {
+ /// The type qualifiers: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+ AttributeList *AttrList;
+ void destroy() {
+ delete AttrList;
+ }
+ };
+
+ struct ReferenceTypeInfo {
+ /// The type qualifier: restrict. [GNU] C++ extension
+ bool HasRestrict : 1;
+ /// True if this is an lvalue reference, false if it's an rvalue reference.
+ bool LValueRef : 1;
+ AttributeList *AttrList;
+ void destroy() {
+ delete AttrList;
+ }
+ };
+
+ struct ArrayTypeInfo {
+ /// The type qualifiers for the array: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+
+ /// True if this dimension included the 'static' keyword.
+ bool hasStatic : 1;
+
+ /// True if this dimension was [*]. In this case, NumElts is null.
+ bool isStar : 1;
+
+ /// This is the size of the array, or null if [] or [*] was specified.
+ /// Since the parser is multi-purpose, and we don't want to impose a root
+ /// expression class on all clients, NumElts is untyped.
+ ActionBase::ExprTy *NumElts;
+ void destroy() {}
+ };
+
+ /// ParamInfo - An array of paraminfo objects is allocated whenever a function
+ /// declarator is parsed. There are two interesting styles of arguments here:
+ /// K&R-style identifier lists and parameter type lists. K&R-style identifier
+ /// lists will have information about the identifier, but no type information.
+ /// Parameter type lists will have type info (if the actions module provides
+ /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
+ struct ParamInfo {
+ IdentifierInfo *Ident;
+ SourceLocation IdentLoc;
+ ActionBase::DeclPtrTy Param;
+
+ /// DefaultArgTokens - When the parameter's default argument
+ /// cannot be parsed immediately (because it occurs within the
+ /// declaration of a member function), it will be stored here as a
+ /// sequence of tokens to be parsed once the class definition is
+ /// complete. Non-NULL indicates that there is a default argument.
+ CachedTokens *DefaultArgTokens;
+
+ ParamInfo() {}
+ ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
+ ActionBase::DeclPtrTy param,
+ CachedTokens *DefArgTokens = 0)
+ : Ident(ident), IdentLoc(iloc), Param(param),
+ DefaultArgTokens(DefArgTokens) {}
+ };
+
+ struct TypeAndRange {
+ ActionBase::TypeTy *Ty;
+ SourceRange Range;
+ };
+
+ struct FunctionTypeInfo {
+ /// hasPrototype - This is true if the function had at least one typed
+ /// argument. If the function is () or (a,b,c), then it has no prototype,
+ /// and is treated as a K&R-style function.
+ bool hasPrototype : 1;
+
+ /// isVariadic - If this function has a prototype, and if that
+ /// proto ends with ',...)', this is true. When true, EllipsisLoc
+ /// contains the location of the ellipsis.
+ bool isVariadic : 1;
+
+ /// The type qualifiers: const/volatile/restrict.
+ /// The qualifier bitmask values are the same as in QualType.
+ unsigned TypeQuals : 3;
+
+ /// hasExceptionSpec - True if the function has an exception specification.
+ bool hasExceptionSpec : 1;
+
+ /// hasAnyExceptionSpec - True if the function has a throw(...) specifier.
+ bool hasAnyExceptionSpec : 1;
+
+ /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
+ bool DeleteArgInfo : 1;
+
+ /// When isVariadic is true, the location of the ellipsis in the source.
+ unsigned EllipsisLoc;
+
+ /// NumArgs - This is the number of formal arguments provided for the
+ /// declarator.
+ unsigned NumArgs;
+
+ /// NumExceptions - This is the number of types in the exception-decl, if
+ /// the function has one.
+ unsigned NumExceptions;
+
+ /// ThrowLoc - When hasExceptionSpec is true, the location of the throw
+ /// keyword introducing the spec.
+ unsigned ThrowLoc;
+
+ /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
+ /// describe the arguments for this function declarator. This is null if
+ /// there are no arguments specified.
+ ParamInfo *ArgInfo;
+
+ /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange
+ /// objects that contain the types in the function's exception
+ /// specification and their locations.
+ TypeAndRange *Exceptions;
+
+ /// freeArgs - reset the argument list to having zero arguments. This is
+ /// used in various places for error recovery.
+ void freeArgs() {
+ if (DeleteArgInfo) {
+ delete[] ArgInfo;
+ DeleteArgInfo = false;
+ }
+ NumArgs = 0;
+ }
+
+ void destroy() {
+ if (DeleteArgInfo)
+ delete[] ArgInfo;
+ delete[] Exceptions;
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(EllipsisLoc);
+ }
+ SourceLocation getThrowLoc() const {
+ return SourceLocation::getFromRawEncoding(ThrowLoc);
+ }
+ };
+
+ struct BlockPointerTypeInfo {
+ /// For now, sema will catch these as invalid.
+ /// The type qualifiers: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+ AttributeList *AttrList;
+ void destroy() {
+ delete AttrList;
+ }
+ };
+
+ struct MemberPointerTypeInfo {
+ /// The type qualifiers: const/volatile/restrict.
+ unsigned TypeQuals : 3;
+ AttributeList *AttrList;
+ // CXXScopeSpec has a constructor, so it can't be a direct member.
+ // So we need some pointer-aligned storage and a bit of trickery.
+ union {
+ void *Aligner;
+ char Mem[sizeof(CXXScopeSpec)];
+ } ScopeMem;
+ CXXScopeSpec &Scope() {
+ return *reinterpret_cast<CXXScopeSpec*>(ScopeMem.Mem);
+ }
+ const CXXScopeSpec &Scope() const {
+ return *reinterpret_cast<const CXXScopeSpec*>(ScopeMem.Mem);
+ }
+ void destroy() {
+ delete AttrList;
+ Scope().~CXXScopeSpec();
+ }
+ };
+
+ union {
+ PointerTypeInfo Ptr;
+ ReferenceTypeInfo Ref;
+ ArrayTypeInfo Arr;
+ FunctionTypeInfo Fun;
+ BlockPointerTypeInfo Cls;
+ MemberPointerTypeInfo Mem;
+ };
+
+ void destroy() {
+ switch (Kind) {
+ default: assert(0 && "Unknown decl type!");
+ case DeclaratorChunk::Function: return Fun.destroy();
+ case DeclaratorChunk::Pointer: return Ptr.destroy();
+ case DeclaratorChunk::BlockPointer: return Cls.destroy();
+ case DeclaratorChunk::Reference: return Ref.destroy();
+ case DeclaratorChunk::Array: return Arr.destroy();
+ case DeclaratorChunk::MemberPointer: return Mem.destroy();
+ }
+ }
+
+ /// getAttrs - If there are attributes applied to this declaratorchunk, return
+ /// them.
+ const AttributeList *getAttrs() const {
+ switch (Kind) {
+ default: assert(0 && "Unknown declarator kind!");
+ case Pointer: return Ptr.AttrList;
+ case Reference: return Ref.AttrList;
+ case MemberPointer: return Mem.AttrList;
+ case Array: return 0;
+ case Function: return 0;
+ case BlockPointer: return Cls.AttrList;
+ }
+ }
+
+
+ /// getPointer - Return a DeclaratorChunk for a pointer.
+ ///
+ static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+ AttributeList *AL) {
+ DeclaratorChunk I;
+ I.Kind = Pointer;
+ I.Loc = Loc;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.AttrList = AL;
+ return I;
+ }
+
+ /// getReference - Return a DeclaratorChunk for a reference.
+ ///
+ static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
+ AttributeList *AL, bool lvalue) {
+ DeclaratorChunk I;
+ I.Kind = Reference;
+ I.Loc = Loc;
+ I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
+ I.Ref.LValueRef = lvalue;
+ I.Ref.AttrList = AL;
+ return I;
+ }
+
+ /// getArray - Return a DeclaratorChunk for an array.
+ ///
+ static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
+ bool isStar, void *NumElts,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = Array;
+ I.Loc = Loc;
+ I.Arr.TypeQuals = TypeQuals;
+ I.Arr.hasStatic = isStatic;
+ I.Arr.isStar = isStar;
+ I.Arr.NumElts = NumElts;
+ return I;
+ }
+
+ /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+ /// "TheDeclarator" is the declarator that this will be added to.
+ static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
+ SourceLocation EllipsisLoc,
+ ParamInfo *ArgInfo, unsigned NumArgs,
+ unsigned TypeQuals, bool hasExceptionSpec,
+ SourceLocation ThrowLoc,
+ bool hasAnyExceptionSpec,
+ ActionBase::TypeTy **Exceptions,
+ SourceRange *ExceptionRanges,
+ unsigned NumExceptions, SourceLocation Loc,
+ Declarator &TheDeclarator);
+
+ /// getBlockPointer - Return a DeclaratorChunk for a block.
+ ///
+ static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc,
+ AttributeList *AL) {
+ DeclaratorChunk I;
+ I.Kind = BlockPointer;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ I.Cls.AttrList = AL;
+ return I;
+ }
+
+ static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
+ unsigned TypeQuals,
+ SourceLocation Loc,
+ AttributeList *AL) {
+ DeclaratorChunk I;
+ I.Kind = MemberPointer;
+ I.Loc = Loc;
+ I.Mem.TypeQuals = TypeQuals;
+ I.Mem.AttrList = AL;
+ new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
+ return I;
+ }
+};
+
+/// Declarator - Information about one declarator, including the parsed type
+/// information and the identifier. When the declarator is fully formed, this
+/// is turned into the appropriate Decl object.
+///
+/// Declarators come in two types: normal declarators and abstract declarators.
+/// Abstract declarators are used when parsing types, and don't have an
+/// identifier. Normal declarators do have ID's.
+///
+/// Instances of this class should be a transient object that lives on the
+/// stack, not objects that are allocated in large quantities on the heap.
+class Declarator {
+public:
+ enum TheContext {
+ FileContext, // File scope declaration.
+ PrototypeContext, // Within a function prototype.
+ KNRTypeListContext, // K&R type definition list for formals.
+ TypeNameContext, // Abstract declarator for types.
+ MemberContext, // Struct/Union field.
+ BlockContext, // Declaration within a block in a function.
+ ForContext, // Declaration within first part of a for loop.
+ ConditionContext, // Condition declaration in a C++ if/switch/while/for.
+ TemplateParamContext,// Within a template parameter list.
+ CXXCatchContext, // C++ catch exception-declaration
+ BlockLiteralContext // Block literal declarator.
+ };
+
+ /// DeclaratorKind - The kind of declarator this represents.
+ enum DeclaratorKind {
+ DK_Abstract, // An abstract declarator (has no identifier)
+ DK_Normal, // A normal declarator (has an identifier).
+ DK_Constructor, // A C++ constructor (identifier is the class name)
+ DK_Destructor, // A C++ destructor (identifier is ~class name)
+ DK_Operator, // A C++ overloaded operator name
+ DK_Conversion // A C++ conversion function (identifier is
+ // "operator " then the type name)
+ };
+
+private:
+ const DeclSpec &DS;
+ CXXScopeSpec SS;
+ IdentifierInfo *Identifier;
+ SourceLocation IdentifierLoc;
+ SourceRange Range;
+
+ /// Context - Where we are parsing this declarator.
+ ///
+ TheContext Context;
+
+ /// Kind - What kind of declarator this is.
+ DeclaratorKind Kind;
+
+ /// DeclTypeInfo - This holds each type that the declarator includes as it is
+ /// parsed. This is pushed from the identifier out, which means that element
+ /// #0 will be the most closely bound to the identifier, and
+ /// DeclTypeInfo.back() will be the least closely bound.
+ llvm::SmallVector<DeclaratorChunk, 8> DeclTypeInfo;
+
+ /// InvalidType - Set by Sema::GetTypeForDeclarator().
+ bool InvalidType : 1;
+
+ /// GroupingParens - Set by Parser::ParseParenDeclarator().
+ bool GroupingParens : 1;
+
+ /// AttrList - Attributes.
+ AttributeList *AttrList;
+
+ /// AsmLabel - The asm label, if specified.
+ ActionBase::ExprTy *AsmLabel;
+
+ union {
+ // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
+ // type associated with the constructor, destructor, or conversion
+ // operator.
+ ActionBase::TypeTy *Type;
+
+ /// When Kind is DK_Operator, this is the actual overloaded
+ /// operator that this declarator names.
+ OverloadedOperatorKind OperatorKind;
+ };
+
+ /// InlineParams - This is a local array used for the first function decl
+ /// chunk to avoid going to the heap for the common case when we have one
+ /// function chunk in the declarator.
+ DeclaratorChunk::ParamInfo InlineParams[16];
+ bool InlineParamsUsed;
+
+ friend struct DeclaratorChunk;
+
+public:
+ Declarator(const DeclSpec &ds, TheContext C)
+ : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C),
+ Kind(DK_Abstract),
+ InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
+ GroupingParens(false), AttrList(0), AsmLabel(0), Type(0),
+ InlineParamsUsed(false) {
+ }
+
+ ~Declarator() {
+ clear();
+ }
+
+ /// getDeclSpec - Return the declaration-specifier that this declarator was
+ /// declared with.
+ const DeclSpec &getDeclSpec() const { return DS; }
+
+ /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This
+ /// should be used with extreme care: declspecs can often be shared between
+ /// multiple declarators, so mutating the DeclSpec affects all of the
+ /// Declarators. This should only be done when the declspec is known to not
+ /// be shared or when in error recovery etc.
+ DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); }
+
+ /// getCXXScopeSpec - Return the C++ scope specifier (global scope or
+ /// nested-name-specifier) that is part of the declarator-id.
+ const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
+ CXXScopeSpec &getCXXScopeSpec() { return SS; }
+
+ TheContext getContext() const { return Context; }
+ DeclaratorKind getKind() const { return Kind; }
+
+ /// getSourceRange - Get the source range that spans this declarator.
+ const SourceRange &getSourceRange() const { return Range; }
+
+ void SetSourceRange(SourceRange R) { Range = R; }
+ /// SetRangeBegin - Set the start of the source range to Loc, unless it's
+ /// invalid.
+ void SetRangeBegin(SourceLocation Loc) {
+ if (!Loc.isInvalid())
+ Range.setBegin(Loc);
+ }
+ /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid.
+ void SetRangeEnd(SourceLocation Loc) {
+ if (!Loc.isInvalid())
+ Range.setEnd(Loc);
+ }
+ /// ExtendWithDeclSpec - Extend the declarator source range to include the
+ /// given declspec, unless its location is invalid. Adopts the range start if
+ /// the current range start is invalid.
+ void ExtendWithDeclSpec(const DeclSpec &DS) {
+ const SourceRange &SR = DS.getSourceRange();
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(SR.getBegin());
+ if (!SR.getEnd().isInvalid())
+ Range.setEnd(SR.getEnd());
+ }
+
+ /// clear - Reset the contents of this Declarator.
+ void clear() {
+ SS.clear();
+ Identifier = 0;
+ IdentifierLoc = SourceLocation();
+ Range = DS.getSourceRange();
+ Kind = DK_Abstract;
+
+ for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
+ DeclTypeInfo[i].destroy();
+ DeclTypeInfo.clear();
+ delete AttrList;
+ AttrList = 0;
+ AsmLabel = 0;
+ Type = 0;
+ InlineParamsUsed = false;
+ }
+
+ /// mayOmitIdentifier - Return true if the identifier is either optional or
+ /// not allowed. This is true for typenames, prototypes, and template
+ /// parameter lists.
+ bool mayOmitIdentifier() const {
+ return Context == TypeNameContext || Context == PrototypeContext ||
+ Context == TemplateParamContext || Context == CXXCatchContext ||
+ Context == BlockLiteralContext;
+ }
+
+ /// mayHaveIdentifier - Return true if the identifier is either optional or
+ /// required. This is true for normal declarators and prototypes, but not
+ /// typenames.
+ bool mayHaveIdentifier() const {
+ return Context != TypeNameContext && Context != BlockLiteralContext;
+ }
+
+ /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
+ /// followed by a C++ direct initializer, e.g. "int x(1);".
+ bool mayBeFollowedByCXXDirectInit() const {
+ return !hasGroupingParens() &&
+ (Context == FileContext ||
+ Context == BlockContext ||
+ Context == ForContext);
+ }
+
+ /// isPastIdentifier - Return true if we have parsed beyond the point where
+ /// the
+ bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
+
+ /// hasName - Whether this declarator has a name, which might be an
+ /// identifier (accessible via getIdentifier()) or some kind of
+ /// special C++ name (constructor, destructor, etc.).
+ bool hasName() const { return getKind() != DK_Abstract; }
+
+ IdentifierInfo *getIdentifier() const { return Identifier; }
+ SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
+
+ void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
+ Identifier = ID;
+ IdentifierLoc = Loc;
+ if (ID)
+ Kind = DK_Normal;
+ else
+ Kind = DK_Abstract;
+ SetRangeEnd(Loc);
+ }
+
+ /// setConstructor - Set this declarator to be a C++ constructor
+ /// declarator. Also extends the range.
+ void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) {
+ IdentifierLoc = Loc;
+ Kind = DK_Constructor;
+ Type = Ty;
+ SetRangeEnd(Loc);
+ }
+
+ /// setDestructor - Set this declarator to be a C++ destructor
+ /// declarator. Also extends the range to End, which should be the identifier
+ /// token.
+ void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc,
+ SourceLocation EndLoc) {
+ IdentifierLoc = Loc;
+ Kind = DK_Destructor;
+ Type = Ty;
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// setConversionFunction - Set this declarator to be a C++
+ /// conversion function declarator (e.g., @c operator int const *).
+ /// Also extends the range to EndLoc, which should be the last token of the
+ /// type name.
+ void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc,
+ SourceLocation EndLoc) {
+ Identifier = 0;
+ IdentifierLoc = Loc;
+ Kind = DK_Conversion;
+ Type = Ty;
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// setOverloadedOperator - Set this declaration to be a C++
+ /// overloaded operator declarator (e.g., @c operator+).
+ /// Also extends the range to EndLoc, which should be the last token of the
+ /// operator.
+ void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc,
+ SourceLocation EndLoc) {
+ IdentifierLoc = Loc;
+ Kind = DK_Operator;
+ OperatorKind = Op;
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
+ /// EndLoc, which should be the last token of the chunk.
+ void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
+ DeclTypeInfo.push_back(TI);
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// getNumTypeObjects() - Return the number of types applied to this
+ /// declarator.
+ unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
+
+ /// Return the specified TypeInfo from this declarator. TypeInfo #0 is
+ /// closest to the identifier.
+ const DeclaratorChunk &getTypeObject(unsigned i) const {
+ assert(i < DeclTypeInfo.size() && "Invalid type chunk");
+ return DeclTypeInfo[i];
+ }
+ DeclaratorChunk &getTypeObject(unsigned i) {
+ assert(i < DeclTypeInfo.size() && "Invalid type chunk");
+ return DeclTypeInfo[i];
+ }
+
+ /// isFunctionDeclarator - Once this declarator is fully parsed and formed,
+ /// this method returns true if the identifier is a function declarator.
+ bool isFunctionDeclarator() const {
+ return !DeclTypeInfo.empty() &&
+ DeclTypeInfo[0].Kind == DeclaratorChunk::Function;
+ }
+
+ /// AddAttributes - simply adds the attribute list to the Declarator.
+ /// These examples both add 3 attributes to "var":
+ /// short int var __attribute__((aligned(16),common,deprecated));
+ /// short int x, __attribute__((aligned(16)) var
+ /// __attribute__((common,deprecated));
+ ///
+ /// Also extends the range of the declarator.
+ void AddAttributes(AttributeList *alist, SourceLocation LastLoc) {
+ if (!alist)
+ return; // we parsed __attribute__(()) or had a syntax error
+
+ if (AttrList)
+ alist->addAttributeList(AttrList);
+ AttrList = alist;
+
+ if (!LastLoc.isInvalid())
+ SetRangeEnd(LastLoc);
+ }
+
+ const AttributeList *getAttributes() const { return AttrList; }
+ AttributeList *getAttributes() { return AttrList; }
+
+ void setAsmLabel(ActionBase::ExprTy *E) { AsmLabel = E; }
+ ActionBase::ExprTy *getAsmLabel() const { return AsmLabel; }
+
+ ActionBase::TypeTy *getDeclaratorIdType() const { return Type; }
+
+ OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
+
+ void setInvalidType(bool Val = true) { InvalidType = Val; }
+ bool isInvalidType() const {
+ return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
+ }
+
+ void setGroupingParens(bool flag) { GroupingParens = flag; }
+ bool hasGroupingParens() const { return GroupingParens; }
+};
+
+/// FieldDeclarator - This little struct is used to capture information about
+/// structure field declarators, which is basically just a bitfield size.
+struct FieldDeclarator {
+ Declarator D;
+ ActionBase::ExprTy *BitfieldSize;
+ explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
+ BitfieldSize = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/Designator.h b/include/clang/Parse/Designator.h
new file mode 100644
index 000000000000..026286d318fb
--- /dev/null
+++ b/include/clang/Parse/Designator.h
@@ -0,0 +1,239 @@
+//===--- Designator.h - Initialization Designator ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces used to represent Designators in the parser and
+// is the input to Actions module.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H
+#define LLVM_CLANG_PARSE_DESIGNATOR_H
+
+#include "clang/Parse/Action.h"
+
+namespace clang {
+
+/// Designator - This class is a discriminated union which holds the various
+/// different sorts of designators possible. A Designation is an array of
+/// these. An example of a designator are things like this:
+/// [8] .field [47] // C99 designation: 3 designators
+/// [8 ... 47] field: // GNU extensions: 2 designators
+/// These occur in initializers, e.g.:
+/// int a[10] = {2, 4, [8]=9, 10};
+///
+class Designator {
+public:
+ enum DesignatorKind {
+ FieldDesignator, ArrayDesignator, ArrayRangeDesignator
+ };
+private:
+ DesignatorKind Kind;
+
+ struct FieldDesignatorInfo {
+ const IdentifierInfo *II;
+ unsigned DotLoc;
+ unsigned NameLoc;
+ };
+ struct ArrayDesignatorInfo {
+ ActionBase::ExprTy *Index;
+ unsigned LBracketLoc;
+ mutable unsigned RBracketLoc;
+ };
+ struct ArrayRangeDesignatorInfo {
+ ActionBase::ExprTy *Start, *End;
+ unsigned LBracketLoc, EllipsisLoc;
+ mutable unsigned RBracketLoc;
+ };
+
+ union {
+ FieldDesignatorInfo FieldInfo;
+ ArrayDesignatorInfo ArrayInfo;
+ ArrayRangeDesignatorInfo ArrayRangeInfo;
+ };
+
+public:
+
+ DesignatorKind getKind() const { return Kind; }
+ bool isFieldDesignator() const { return Kind == FieldDesignator; }
+ bool isArrayDesignator() const { return Kind == ArrayDesignator; }
+ bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
+
+ const IdentifierInfo *getField() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return FieldInfo.II;
+ }
+
+ SourceLocation getDotLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc);
+ }
+
+ SourceLocation getFieldLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc);
+ }
+
+ ActionBase::ExprTy *getArrayIndex() const {
+ assert(isArrayDesignator() && "Invalid accessor");
+ return ArrayInfo.Index;
+ }
+
+ ActionBase::ExprTy *getArrayRangeStart() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.Start;
+ }
+ ActionBase::ExprTy *getArrayRangeEnd() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.End;
+ }
+
+ SourceLocation getLBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc);
+ else
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc);
+ else
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc);
+ }
+
+ static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc,
+ SourceLocation NameLoc) {
+ Designator D;
+ D.Kind = FieldDesignator;
+ D.FieldInfo.II = II;
+ D.FieldInfo.DotLoc = DotLoc.getRawEncoding();
+ D.FieldInfo.NameLoc = NameLoc.getRawEncoding();
+ return D;
+ }
+
+ static Designator getArray(ActionBase::ExprTy *Index,
+ SourceLocation LBracketLoc) {
+ Designator D;
+ D.Kind = ArrayDesignator;
+ D.ArrayInfo.Index = Index;
+ D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding();
+ D.ArrayInfo.RBracketLoc = 0;
+ return D;
+ }
+
+ static Designator getArrayRange(ActionBase::ExprTy *Start,
+ ActionBase::ExprTy *End,
+ SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc) {
+ Designator D;
+ D.Kind = ArrayRangeDesignator;
+ D.ArrayRangeInfo.Start = Start;
+ D.ArrayRangeInfo.End = End;
+ D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding();
+ D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ D.ArrayRangeInfo.RBracketLoc = 0;
+ return D;
+ }
+
+ void setRBracketLoc(SourceLocation RBracketLoc) const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding();
+ else
+ ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ /// ClearExprs - Null out any expression references, which prevents them from
+ /// being 'delete'd later.
+ void ClearExprs(Action &Actions) {
+ switch (Kind) {
+ case FieldDesignator: return;
+ case ArrayDesignator:
+ ArrayInfo.Index = 0;
+ return;
+ case ArrayRangeDesignator:
+ ArrayRangeInfo.Start = 0;
+ ArrayRangeInfo.End = 0;
+ return;
+ }
+ }
+
+ /// FreeExprs - Release any unclaimed memory for the expressions in this
+ /// designator.
+ void FreeExprs(Action &Actions) {
+ switch (Kind) {
+ case FieldDesignator: return; // nothing to free.
+ case ArrayDesignator:
+ Actions.DeleteExpr(getArrayIndex());
+ return;
+ case ArrayRangeDesignator:
+ Actions.DeleteExpr(getArrayRangeStart());
+ Actions.DeleteExpr(getArrayRangeEnd());
+ return;
+ }
+ }
+};
+
+
+/// Designation - Represent a full designation, which is a sequence of
+/// designators. This class is mostly a helper for InitListDesignations.
+class Designation {
+ /// InitIndex - The index of the initializer expression this is for. For
+ /// example, if the initializer were "{ A, .foo=B, C }" a Designation would
+ /// exist with InitIndex=1, because element #1 has a designation.
+ unsigned InitIndex;
+
+ /// Designators - The actual designators for this initializer.
+ llvm::SmallVector<Designator, 2> Designators;
+
+ Designation(unsigned Idx) : InitIndex(Idx) {}
+public:
+ Designation() : InitIndex(4000) {}
+
+ /// AddDesignator - Add a designator to the end of this list.
+ void AddDesignator(Designator D) {
+ Designators.push_back(D);
+ }
+
+ bool empty() const { return Designators.empty(); }
+
+ unsigned getNumDesignators() const { return Designators.size(); }
+ const Designator &getDesignator(unsigned Idx) const {
+ assert(Idx < Designators.size());
+ return Designators[Idx];
+ }
+
+ /// ClearExprs - Null out any expression references, which prevents them from
+ /// being 'delete'd later.
+ void ClearExprs(Action &Actions) {
+ for (unsigned i = 0, e = Designators.size(); i != e; ++i)
+ Designators[i].ClearExprs(Actions);
+ }
+
+ /// FreeExprs - Release any unclaimed memory for the expressions in this
+ /// designation.
+ void FreeExprs(Action &Actions) {
+ for (unsigned i = 0, e = Designators.size(); i != e; ++i)
+ Designators[i].FreeExprs(Actions);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h
new file mode 100644
index 000000000000..59517930de95
--- /dev/null
+++ b/include/clang/Parse/Ownership.h
@@ -0,0 +1,830 @@
+//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains classes for managing ownership of Stmt and Expr nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H
+#define LLVM_CLANG_PARSE_OWNERSHIP_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+//===----------------------------------------------------------------------===//
+// OpaquePtr
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class ActionBase;
+
+ /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
+ /// Parser doesn't know about but that Sema or another client does. The UID
+ /// template argument is used to make sure that "Decl" pointers are not
+ /// compatible with "Type" pointers for example.
+ template<int UID>
+ class OpaquePtr {
+ void *Ptr;
+ public:
+ OpaquePtr() : Ptr(0) {}
+
+ template <typename T>
+ T* getAs() const {
+ return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr);
+ }
+
+ template <typename T>
+ T getAsVal() const {
+ return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr);
+ }
+
+ void *get() const { return Ptr; }
+
+ template<typename T>
+ static OpaquePtr make(T P) {
+ OpaquePtr R; R.set(P); return R;
+ }
+
+ template<typename T>
+ void set(T P) {
+ Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P);
+ }
+
+ operator bool() const { return Ptr != 0; }
+ };
+}
+
+namespace llvm {
+ template <int UID>
+ class PointerLikeTypeTraits<clang::OpaquePtr<UID> > {
+ public:
+ static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) {
+ // FIXME: Doesn't work? return P.getAs< void >();
+ return P.get();
+ }
+ static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) {
+ return clang::OpaquePtr<UID>::make(P);
+ }
+ enum { NumLowBitsAvailable = 3 };
+ };
+}
+
+
+
+// -------------------------- About Move Emulation -------------------------- //
+// The smart pointer classes in this file attempt to emulate move semantics
+// as they appear in C++0x with rvalue references. Since C++03 doesn't have
+// rvalue references, some tricks are needed to get similar results.
+// Move semantics in C++0x have the following properties:
+// 1) "Moving" means transferring the value of an object to another object,
+// similar to copying, but without caring what happens to the old object.
+// In particular, this means that the new object can steal the old object's
+// resources instead of creating a copy.
+// 2) Since moving can modify the source object, it must either be explicitly
+// requested by the user, or the modifications must be unnoticeable.
+// 3) As such, C++0x moving is only allowed in three contexts:
+// * By explicitly using std::move() to request it.
+// * From a temporary object, since that object cannot be accessed
+// afterwards anyway, thus making the state unobservable.
+// * On function return, since the object is not observable afterwards.
+//
+// To sum up: moving from a named object should only be possible with an
+// explicit std::move(), or on function return. Moving from a temporary should
+// be implicitly done. Moving from a const object is forbidden.
+//
+// The emulation is not perfect, and has the following shortcomings:
+// * move() is not in namespace std.
+// * move() is required on function return.
+// * There are difficulties with implicit conversions.
+// * Microsoft's compiler must be given the /Za switch to successfully compile.
+//
+// -------------------------- Implementation -------------------------------- //
+// The move emulation relies on the peculiar reference binding semantics of
+// C++03: as a rule, a non-const reference may not bind to a temporary object,
+// except for the implicit object parameter in a member function call, which
+// can refer to a temporary even when not being const.
+// The moveable object has five important functions to facilitate moving:
+// * A private, unimplemented constructor taking a non-const reference to its
+// own class. This constructor serves a two-fold purpose.
+// - It prevents the creation of a copy constructor that takes a const
+// reference. Temporaries would be able to bind to the argument of such a
+// constructor, and that would be bad.
+// - Named objects will bind to the non-const reference, but since it's
+// private, this will fail to compile. This prevents implicit moving from
+// named objects.
+// There's also a copy assignment operator for the same purpose.
+// * An implicit, non-const conversion operator to a special mover type. This
+// type represents the rvalue reference of C++0x. Being a non-const member,
+// its implicit this parameter can bind to temporaries.
+// * A constructor that takes an object of this mover type. This constructor
+// performs the actual move operation. There is an equivalent assignment
+// operator.
+// There is also a free move() function that takes a non-const reference to
+// an object and returns a temporary. Internally, this function uses explicit
+// constructor calls to move the value from the referenced object to the return
+// value.
+//
+// There are now three possible scenarios of use.
+// * Copying from a const object. Constructor overload resolution will find the
+// non-const copy constructor, and the move constructor. The first is not
+// viable because the const object cannot be bound to the non-const reference.
+// The second fails because the conversion to the mover object is non-const.
+// Moving from a const object fails as intended.
+// * Copying from a named object. Constructor overload resolution will select
+// the non-const copy constructor, but fail as intended, because this
+// constructor is private.
+// * Copying from a temporary. Constructor overload resolution cannot select
+// the non-const copy constructor, because the temporary cannot be bound to
+// the non-const reference. It thus selects the move constructor. The
+// temporary can be bound to the implicit this parameter of the conversion
+// operator, because of the special binding rule. Construction succeeds.
+// Note that the Microsoft compiler, as an extension, allows binding
+// temporaries against non-const references. The compiler thus selects the
+// non-const copy constructor and fails, because the constructor is private.
+// Passing /Za (disable extensions) disables this behaviour.
+// The free move() function is used to move from a named object.
+//
+// Note that when passing an object of a different type (the classes below
+// have OwningResult and OwningPtr, which should be mixable), you get a problem.
+// Argument passing and function return use copy initialization rules. The
+// effect of this is that, when the source object is not already of the target
+// type, the compiler will first seek a way to convert the source object to the
+// target type, and only then attempt to copy the resulting object. This means
+// that when passing an OwningResult where an OwningPtr is expected, the
+// compiler will first seek a conversion from OwningResult to OwningPtr, then
+// copy the OwningPtr. The resulting conversion sequence is:
+// OwningResult object -> ResultMover -> OwningResult argument to
+// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
+// This conversion sequence is too complex to be allowed. Thus the special
+// move_* functions, which help the compiler out with some explicit
+// conversions.
+
+// Flip this switch to measure performance impact of the smart pointers.
+//#define DISABLE_SMART_POINTERS
+
+namespace llvm {
+ template<>
+ class PointerLikeTypeTraits<clang::ActionBase*> {
+ typedef clang::ActionBase* PT;
+ public:
+ static inline void *getAsVoidPointer(PT P) { return P; }
+ static inline PT getFromVoidPointer(void *P) {
+ return static_cast<PT>(P);
+ }
+ enum { NumLowBitsAvailable = 2 };
+ };
+}
+
+namespace clang {
+ // Basic
+ class DiagnosticBuilder;
+
+ // Determines whether the low bit of the result pointer for the
+ // given UID is always zero. If so, ActionResult will use that bit
+ // for it's "invalid" flag.
+ template<unsigned UID>
+ struct IsResultPtrLowBitFree {
+ static const bool value = false;
+ };
+
+ /// ActionBase - A small part split from Action because of the horrible
+ /// definition order dependencies between Action and the smart pointers.
+ class ActionBase {
+ public:
+ /// Out-of-line virtual destructor to provide home for this class.
+ virtual ~ActionBase();
+
+ // Types - Though these don't actually enforce strong typing, they document
+ // what types are required to be identical for the actions.
+ typedef OpaquePtr<0> DeclPtrTy;
+ typedef OpaquePtr<1> DeclGroupPtrTy;
+ typedef OpaquePtr<2> TemplateTy;
+ typedef void AttrTy;
+ typedef void BaseTy;
+ typedef void MemInitTy;
+ typedef void ExprTy;
+ typedef void StmtTy;
+ typedef void TemplateParamsTy;
+ typedef void CXXScopeTy;
+ typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>.
+
+ /// ActionResult - This structure is used while parsing/acting on
+ /// expressions, stmts, etc. It encapsulates both the object returned by
+ /// the action, plus a sense of whether or not it is valid.
+ /// When CompressInvalid is true, the "invalid" flag will be
+ /// stored in the low bit of the Val pointer.
+ template<unsigned UID,
+ typename PtrTy = void*,
+ bool CompressInvalid = IsResultPtrLowBitFree<UID>::value>
+ class ActionResult {
+ PtrTy Val;
+ bool Invalid;
+
+ public:
+ ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
+ template<typename ActualExprTy>
+ ActionResult(ActualExprTy val) : Val(val), Invalid(false) {}
+ ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
+
+ PtrTy get() const { return Val; }
+ void set(PtrTy V) { Val = V; }
+ bool isInvalid() const { return Invalid; }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ Val = RHS;
+ Invalid = false;
+ return *this;
+ }
+ };
+
+ // This ActionResult partial specialization places the "invalid"
+ // flag into the low bit of the pointer.
+ template<unsigned UID, typename PtrTy>
+ class ActionResult<UID, PtrTy, true> {
+ // A pointer whose low bit is 1 if this result is invalid, 0
+ // otherwise.
+ uintptr_t PtrWithInvalid;
+ typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
+ public:
+ ActionResult(bool Invalid = false)
+ : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
+
+ template<typename ActualExprTy>
+ ActionResult(ActualExprTy *val) {
+ PtrTy V(val);
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ ActionResult(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
+
+ PtrTy get() const {
+ void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
+ return PtrTraits::getFromVoidPointer(VP);
+ }
+
+ void set(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ bool isInvalid() const { return PtrWithInvalid & 0x01; }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ void *VP = PtrTraits::getAsVoidPointer(RHS);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ return *this;
+ }
+ };
+
+ /// Deletion callbacks - Since the parser doesn't know the concrete types of
+ /// the AST nodes being generated, it must do callbacks to delete objects
+ /// when recovering from errors. These are in ActionBase because the smart
+ /// pointers need access to them.
+ virtual void DeleteExpr(ExprTy *E) {}
+ virtual void DeleteStmt(StmtTy *S) {}
+ virtual void DeleteTemplateParams(TemplateParamsTy *P) {}
+ };
+
+ /// ASTDestroyer - The type of an AST node destruction function pointer.
+ typedef void (ActionBase::*ASTDestroyer)(void *);
+
+ /// For the transition phase: translate from an ASTDestroyer to its
+ /// ActionResult UID.
+ template <ASTDestroyer Destroyer> struct DestroyerToUID;
+ template <> struct DestroyerToUID<&ActionBase::DeleteExpr> {
+ static const unsigned UID = 0;
+ };
+ template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
+ static const unsigned UID = 1;
+ };
+ /// ASTOwningResult - A moveable smart pointer for AST nodes that also
+ /// has an extra flag to indicate an additional success status.
+ template <ASTDestroyer Destroyer> class ASTOwningResult;
+
+ /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
+ /// the individual pointers, not the array holding them.
+ template <ASTDestroyer Destroyer> class ASTMultiPtr;
+
+#if !defined(DISABLE_SMART_POINTERS)
+ namespace moving {
+ /// Move emulation helper for ASTOwningResult. NEVER EVER use this class
+ /// directly if you don't know what you're doing.
+ template <ASTDestroyer Destroyer>
+ class ASTResultMover
+ {
+ ASTOwningResult<Destroyer> &Moved;
+
+ public:
+ ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
+
+ ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
+ };
+
+ /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class
+ /// directly if you don't know what you're doing.
+ template <ASTDestroyer Destroyer>
+ class ASTMultiMover
+ {
+ ASTMultiPtr<Destroyer> &Moved;
+
+ public:
+ ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
+
+ ASTMultiPtr<Destroyer> * operator ->() { return &Moved; }
+
+ /// Reset the moved object's internal structures.
+ void release();
+ };
+ }
+#else
+
+ /// Kept only as a type-safe wrapper for a void pointer, when smart pointers
+ /// are disabled. When they are enabled, ASTOwningResult takes over.
+ template <ASTDestroyer Destroyer>
+ class ASTOwningPtr
+ {
+ void *Node;
+
+ public:
+ explicit ASTOwningPtr(ActionBase &) : Node(0) {}
+ ASTOwningPtr(ActionBase &, void *node) : Node(node) {}
+ // Normal copying operators are defined implicitly.
+ ASTOwningPtr(const ASTOwningResult<Destroyer> &o);
+
+ ASTOwningPtr & operator =(void *raw) {
+ Node = raw;
+ return *this;
+ }
+
+ /// Access to the raw pointer.
+ void * get() const { return Node; }
+
+ /// Release the raw pointer.
+ void * take() {
+ return Node;
+ }
+
+ /// Take outside ownership of the raw pointer and cast it down.
+ template<typename T>
+ T *takeAs() {
+ return static_cast<T*>(Node);
+ }
+
+ /// Alias for interface familiarity with unique_ptr.
+ void * release() {
+ return take();
+ }
+ };
+#endif
+
+ // Important: There are two different implementations of
+ // ASTOwningResult below, depending on whether
+ // DISABLE_SMART_POINTERS is defined. If you make changes that
+ // affect the interface, be sure to compile and test both ways!
+
+#if !defined(DISABLE_SMART_POINTERS)
+ template <ASTDestroyer Destroyer>
+ class ASTOwningResult
+ {
+ llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv;
+ void *Ptr;
+
+ friend class moving::ASTResultMover<Destroyer>;
+
+ ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT
+ ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT
+
+ void destroy() {
+ if (Ptr) {
+ assert(ActionInv.getPointer() &&
+ "Smart pointer has node but no action.");
+ (ActionInv.getPointer()->*Destroyer)(Ptr);
+ Ptr = 0;
+ }
+ }
+
+ public:
+ typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
+
+ explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
+ : ActionInv(&actions, invalid), Ptr(0) {}
+ ASTOwningResult(ActionBase &actions, void *node)
+ : ActionInv(&actions, false), Ptr(node) {}
+ ASTOwningResult(ActionBase &actions, const DumbResult &res)
+ : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {}
+ /// Move from another owning result
+ ASTOwningResult(moving::ASTResultMover<Destroyer> mover)
+ : ActionInv(mover->ActionInv),
+ Ptr(mover->Ptr) {
+ mover->Ptr = 0;
+ }
+
+ ~ASTOwningResult() {
+ destroy();
+ }
+
+ /// Move assignment from another owning result
+ ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) {
+ destroy();
+ ActionInv = mover->ActionInv;
+ Ptr = mover->Ptr;
+ mover->Ptr = 0;
+ return *this;
+ }
+
+ /// Assignment from a raw pointer. Takes ownership - beware!
+ ASTOwningResult &operator=(void *raw) {
+ destroy();
+ Ptr = raw;
+ ActionInv.setInt(false);
+ return *this;
+ }
+
+ /// Assignment from an ActionResult. Takes ownership - beware!
+ ASTOwningResult &operator=(const DumbResult &res) {
+ destroy();
+ Ptr = res.get();
+ ActionInv.setInt(res.isInvalid());
+ return *this;
+ }
+
+ /// Access to the raw pointer.
+ void *get() const { return Ptr; }
+
+ bool isInvalid() const { return ActionInv.getInt(); }
+
+ /// Does this point to a usable AST node? To be usable, the node must be
+ /// valid and non-null.
+ bool isUsable() const { return !isInvalid() && get(); }
+
+ /// Take outside ownership of the raw pointer.
+ void *take() {
+ if (isInvalid())
+ return 0;
+ void *tmp = Ptr;
+ Ptr = 0;
+ return tmp;
+ }
+
+ /// Take outside ownership of the raw pointer and cast it down.
+ template<typename T>
+ T *takeAs() {
+ return static_cast<T*>(take());
+ }
+
+ /// Alias for interface familiarity with unique_ptr.
+ void *release() { return take(); }
+
+ /// Pass ownership to a classical ActionResult.
+ DumbResult result() {
+ if (isInvalid())
+ return true;
+ return take();
+ }
+
+ /// Move hook
+ operator moving::ASTResultMover<Destroyer>() {
+ return moving::ASTResultMover<Destroyer>(*this);
+ }
+ };
+#else
+ template <ASTDestroyer Destroyer>
+ class ASTOwningResult
+ {
+ public:
+ typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
+
+ private:
+ DumbResult Result;
+
+ public:
+ explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
+ : Result(invalid) { }
+ ASTOwningResult(ActionBase &actions, void *node) : Result(node) { }
+ ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { }
+ // Normal copying semantics are defined implicitly.
+ ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { }
+
+ /// Assignment from a raw pointer. Takes ownership - beware!
+ ASTOwningResult & operator =(void *raw)
+ {
+ Result = raw;
+ return *this;
+ }
+
+ /// Assignment from an ActionResult. Takes ownership - beware!
+ ASTOwningResult & operator =(const DumbResult &res) {
+ Result = res;
+ return *this;
+ }
+
+ /// Access to the raw pointer.
+ void * get() const { return Result.get(); }
+
+ bool isInvalid() const { return Result.isInvalid(); }
+
+ /// Does this point to a usable AST node? To be usable, the node must be
+ /// valid and non-null.
+ bool isUsable() const { return !Result.isInvalid() && get(); }
+
+ /// Take outside ownership of the raw pointer.
+ void * take() {
+ return Result.get();
+ }
+
+ /// Take outside ownership of the raw pointer and cast it down.
+ template<typename T>
+ T *takeAs() {
+ return static_cast<T*>(take());
+ }
+
+ /// Alias for interface familiarity with unique_ptr.
+ void * release() { return take(); }
+
+ /// Pass ownership to a classical ActionResult.
+ DumbResult result() { return Result; }
+ };
+#endif
+
+ template <ASTDestroyer Destroyer>
+ class ASTMultiPtr
+ {
+#if !defined(DISABLE_SMART_POINTERS)
+ ActionBase &Actions;
+#endif
+ void **Nodes;
+ unsigned Count;
+
+#if !defined(DISABLE_SMART_POINTERS)
+ friend class moving::ASTMultiMover<Destroyer>;
+
+ ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
+ // Reference member prevents copy assignment.
+
+ void destroy() {
+ assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
+ for (unsigned i = 0; i < Count; ++i) {
+ if (Nodes[i])
+ (Actions.*Destroyer)(Nodes[i]);
+ }
+ }
+#endif
+
+ public:
+#if !defined(DISABLE_SMART_POINTERS)
+ explicit ASTMultiPtr(ActionBase &actions)
+ : Actions(actions), Nodes(0), Count(0) {}
+ ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count)
+ : Actions(actions), Nodes(nodes), Count(count) {}
+ /// Move constructor
+ ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover)
+ : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
+ mover.release();
+ }
+#else
+ // Normal copying implicitly defined
+ explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {}
+ ASTMultiPtr(ActionBase &, void **nodes, unsigned count)
+ : Nodes(nodes), Count(count) {}
+ // Fake mover in Parse/AstGuard.h needs this:
+ ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {}
+#endif
+
+#if !defined(DISABLE_SMART_POINTERS)
+ /// Move assignment
+ ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) {
+ destroy();
+ Nodes = mover->Nodes;
+ Count = mover->Count;
+ mover.release();
+ return *this;
+ }
+#endif
+
+ /// Access to the raw pointers.
+ void ** get() const { return Nodes; }
+
+ /// Access to the count.
+ unsigned size() const { return Count; }
+
+ void ** release() {
+#if !defined(DISABLE_SMART_POINTERS)
+ void **tmp = Nodes;
+ Nodes = 0;
+ Count = 0;
+ return tmp;
+#else
+ return Nodes;
+#endif
+ }
+
+#if !defined(DISABLE_SMART_POINTERS)
+ /// Move hook
+ operator moving::ASTMultiMover<Destroyer>() {
+ return moving::ASTMultiMover<Destroyer>(*this);
+ }
+#endif
+ };
+
+ class ASTTemplateArgsPtr {
+#if !defined(DISABLE_SMART_POINTERS)
+ ActionBase &Actions;
+#endif
+ void **Args;
+ bool *ArgIsType;
+ mutable unsigned Count;
+
+#if !defined(DISABLE_SMART_POINTERS)
+ void destroy() {
+ if (!Count)
+ return;
+
+ for (unsigned i = 0; i != Count; ++i)
+ if (Args[i] && !ArgIsType[i])
+ Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
+
+ Count = 0;
+ }
+#endif
+
+ public:
+ ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
+ unsigned count) :
+#if !defined(DISABLE_SMART_POINTERS)
+ Actions(actions),
+#endif
+ Args(args), ArgIsType(argIsType), Count(count) { }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
+#if !defined(DISABLE_SMART_POINTERS)
+ Actions(Other.Actions),
+#endif
+ Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
+#if !defined(DISABLE_SMART_POINTERS)
+ Other.Count = 0;
+#endif
+ }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
+#if !defined(DISABLE_SMART_POINTERS)
+ Actions = Other.Actions;
+#endif
+ Args = Other.Args;
+ ArgIsType = Other.ArgIsType;
+ Count = Other.Count;
+#if !defined(DISABLE_SMART_POINTERS)
+ Other.Count = 0;
+#endif
+ return *this;
+ }
+
+#if !defined(DISABLE_SMART_POINTERS)
+ ~ASTTemplateArgsPtr() { destroy(); }
+#endif
+
+ void **getArgs() const { return Args; }
+ bool *getArgIsType() const {return ArgIsType; }
+ unsigned size() const { return Count; }
+
+ void reset(void **args, bool *argIsType, unsigned count) {
+#if !defined(DISABLE_SMART_POINTERS)
+ destroy();
+#endif
+ Args = args;
+ ArgIsType = argIsType;
+ Count = count;
+ }
+
+ void *operator[](unsigned Arg) const { return Args[Arg]; }
+
+ void **release() const {
+#if !defined(DISABLE_SMART_POINTERS)
+ Count = 0;
+#endif
+ return Args;
+ }
+ };
+
+ /// \brief A small vector that owns a set of AST nodes.
+ template <ASTDestroyer Destroyer, unsigned N = 8>
+ class ASTOwningVector : public llvm::SmallVector<void *, N> {
+#if !defined(DISABLE_SMART_POINTERS)
+ ActionBase &Actions;
+ bool Owned;
+#endif
+
+ ASTOwningVector(ASTOwningVector &); // do not implement
+ ASTOwningVector &operator=(ASTOwningVector &); // do not implement
+
+ public:
+ explicit ASTOwningVector(ActionBase &Actions)
+#if !defined(DISABLE_SMART_POINTERS)
+ : Actions(Actions), Owned(true)
+#endif
+ { }
+
+#if !defined(DISABLE_SMART_POINTERS)
+ ~ASTOwningVector() {
+ if (!Owned)
+ return;
+
+ for (unsigned I = 0, Last = this->size(); I != Last; ++I)
+ (Actions.*Destroyer)((*this)[I]);
+ }
+#endif
+
+ void **take() {
+#if !defined(DISABLE_SMART_POINTERS)
+ Owned = false;
+#endif
+ return &this->front();
+ }
+
+ template<typename T> T **takeAs() { return (T**)take(); }
+
+#if !defined(DISABLE_SMART_POINTERS)
+ ActionBase &getActions() const { return Actions; }
+#endif
+ };
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector;
+
+ template <ASTDestroyer Destroyer, unsigned N> inline
+ ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) {
+#if !defined(DISABLE_SMART_POINTERS)
+ return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size());
+#else
+ return ASTMultiPtr<Destroyer>(vec.take(), vec.size());
+#endif
+ }
+
+#if !defined(DISABLE_SMART_POINTERS)
+
+ // Out-of-line implementations due to definition dependencies
+
+ template <ASTDestroyer Destroyer> inline
+ void moving::ASTMultiMover<Destroyer>::release() {
+ Moved.Nodes = 0;
+ Moved.Count = 0;
+ }
+
+ // Move overloads.
+
+ template <ASTDestroyer Destroyer> inline
+ ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) {
+ return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr));
+ }
+
+ template <ASTDestroyer Destroyer> inline
+ ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) {
+ return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr));
+ }
+
+#else
+
+ template <ASTDestroyer Destroyer> inline
+ ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o)
+ : Node(o.get())
+ {}
+
+ // These versions are hopefully no-ops.
+ template <ASTDestroyer Destroyer> inline
+ ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) {
+ return ptr;
+ }
+
+ template <ASTDestroyer Destroyer> inline
+ ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) {
+ return ptr;
+ }
+
+ template <ASTDestroyer Destroyer> inline
+ ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) {
+ return ptr;
+ }
+#endif
+}
+
+#endif
diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h
new file mode 100644
index 000000000000..a85c6ad6ca7a
--- /dev/null
+++ b/include/clang/Parse/ParseDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICPARSE_H
+#define LLVM_CLANG_DIAGNOSTICPARSE_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define PARSESTART
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_PARSE_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
new file mode 100644
index 000000000000..26e37e2806a0
--- /dev/null
+++ b/include/clang/Parse/Parser.h
@@ -0,0 +1,1208 @@
+//===--- Parser.h - C Language Parser ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Parser interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_PARSER_H
+#define LLVM_CLANG_PARSE_PARSER_H
+
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/AccessSpecifier.h"
+#include "clang/Parse/Action.h"
+#include "clang/Parse/DeclSpec.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <stack>
+#include <list>
+
+namespace clang {
+ class AttributeList;
+ class PragmaHandler;
+ class Scope;
+ class DiagnosticBuilder;
+ class Parser;
+ class PragmaUnusedHandler;
+
+/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
+/// an entry is printed for it.
+class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
+ const Parser &P;
+public:
+ PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+
+/// Parser - This implements a parser for the C family of languages. After
+/// parsing units of the grammar, productions are invoked to handle whatever has
+/// been read.
+///
+class Parser {
+ friend class PragmaUnusedHandler;
+ PrettyStackTraceParserEntry CrashInfo;
+
+ Preprocessor &PP;
+
+ /// Tok - The current token we are peeking ahead. All parsing methods assume
+ /// that this is valid.
+ Token Tok;
+
+ // PrevTokLocation - The location of the token we previously
+ // consumed. This token is used for diagnostics where we expected to
+ // see a token following another token (e.g., the ';' at the end of
+ // a statement).
+ SourceLocation PrevTokLocation;
+
+ unsigned short ParenCount, BracketCount, BraceCount;
+
+ /// Actions - These are the callbacks we invoke as we parse various constructs
+ /// in the file. This refers to the common base class between MinimalActions
+ /// and SemaActions for those uses that don't matter.
+ Action &Actions;
+
+ Scope *CurScope;
+ Diagnostic &Diags;
+
+ /// ScopeCache - Cache scopes to reduce malloc traffic.
+ enum { ScopeCacheSize = 16 };
+ unsigned NumCachedScopes;
+ Scope *ScopeCache[ScopeCacheSize];
+
+ /// Ident_super - IdentifierInfo for "super", to support fast
+ /// comparison.
+ IdentifierInfo *Ident_super;
+
+ llvm::OwningPtr<PragmaHandler> PackHandler;
+ llvm::OwningPtr<PragmaHandler> UnusedHandler;
+
+ /// Whether the '>' token acts as an operator or not. This will be
+ /// true except when we are parsing an expression within a C++
+ /// template argument list, where the '>' closes the template
+ /// argument list.
+ bool GreaterThanIsOperator;
+
+ /// \brief RAII object that makes '>' behave either as an operator
+ /// or as the closing angle bracket for a template argument list.
+ struct GreaterThanIsOperatorScope {
+ bool &GreaterThanIsOperator;
+ bool OldGreaterThanIsOperator;
+
+ GreaterThanIsOperatorScope(bool &GTIO, bool Val)
+ : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
+ GreaterThanIsOperator = Val;
+ }
+
+ ~GreaterThanIsOperatorScope() {
+ GreaterThanIsOperator = OldGreaterThanIsOperator;
+ }
+ };
+
+public:
+ Parser(Preprocessor &PP, Action &Actions);
+ ~Parser();
+
+ const LangOptions &getLang() const { return PP.getLangOptions(); }
+ TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
+ Preprocessor &getPreprocessor() const { return PP; }
+ Action &getActions() const { return Actions; }
+
+ const Token &getCurToken() const { return Tok; }
+
+ // Type forwarding. All of these are statically 'void*', but they may all be
+ // different actual classes based on the actions in place.
+ typedef Action::ExprTy ExprTy;
+ typedef Action::StmtTy StmtTy;
+ typedef Action::DeclPtrTy DeclPtrTy;
+ typedef Action::DeclGroupPtrTy DeclGroupPtrTy;
+ typedef Action::TypeTy TypeTy;
+ typedef Action::BaseTy BaseTy;
+ typedef Action::MemInitTy MemInitTy;
+ typedef Action::CXXScopeTy CXXScopeTy;
+ typedef Action::TemplateParamsTy TemplateParamsTy;
+ typedef Action::TemplateTy TemplateTy;
+
+ typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
+
+ typedef Action::ExprResult ExprResult;
+ typedef Action::StmtResult StmtResult;
+ typedef Action::BaseResult BaseResult;
+ typedef Action::MemInitResult MemInitResult;
+ typedef Action::TypeResult TypeResult;
+
+ typedef Action::OwningExprResult OwningExprResult;
+ typedef Action::OwningStmtResult OwningStmtResult;
+
+ typedef Action::ExprArg ExprArg;
+ typedef Action::MultiStmtArg MultiStmtArg;
+ typedef Action::FullExprArg FullExprArg;
+
+ /// Adorns a ExprResult with Actions to make it an OwningExprResult
+ OwningExprResult Owned(ExprResult res) {
+ return OwningExprResult(Actions, res);
+ }
+ /// Adorns a StmtResult with Actions to make it an OwningStmtResult
+ OwningStmtResult Owned(StmtResult res) {
+ return OwningStmtResult(Actions, res);
+ }
+
+ OwningExprResult ExprError() { return OwningExprResult(Actions, true); }
+ OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); }
+
+ OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
+ OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
+
+ OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); }
+
+ // Parsing methods.
+
+ /// ParseTranslationUnit - All in one method that initializes parses, and
+ /// shuts down the parser.
+ void ParseTranslationUnit();
+
+ /// Initialize - Warm up the parser.
+ ///
+ void Initialize();
+
+ /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
+ /// the EOF was encountered.
+ bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
+
+private:
+ //===--------------------------------------------------------------------===//
+ // Low-Level token peeking and consumption methods.
+ //
+
+ /// isTokenParen - Return true if the cur token is '(' or ')'.
+ bool isTokenParen() const {
+ return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren;
+ }
+ /// isTokenBracket - Return true if the cur token is '[' or ']'.
+ bool isTokenBracket() const {
+ return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square;
+ }
+ /// isTokenBrace - Return true if the cur token is '{' or '}'.
+ bool isTokenBrace() const {
+ return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace;
+ }
+
+ /// isTokenStringLiteral - True if this token is a string-literal.
+ ///
+ bool isTokenStringLiteral() const {
+ return Tok.getKind() == tok::string_literal ||
+ Tok.getKind() == tok::wide_string_literal;
+ }
+
+ /// ConsumeToken - Consume the current 'peek token' and lex the next one.
+ /// This does not work with all kinds of tokens: strings and specific other
+ /// tokens must be consumed with custom methods below. This returns the
+ /// location of the consumed token.
+ SourceLocation ConsumeToken() {
+ assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
+ !isTokenBrace() &&
+ "Should consume special tokens with Consume*Token");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeAnyToken - Dispatch to the right Consume* method based on the
+ /// current token type. This should only be used in cases where the type of
+ /// the token really isn't known, e.g. in error recovery.
+ SourceLocation ConsumeAnyToken() {
+ if (isTokenParen())
+ return ConsumeParen();
+ else if (isTokenBracket())
+ return ConsumeBracket();
+ else if (isTokenBrace())
+ return ConsumeBrace();
+ else if (isTokenStringLiteral())
+ return ConsumeStringToken();
+ else
+ return ConsumeToken();
+ }
+
+ /// ConsumeParen - This consume method keeps the paren count up-to-date.
+ ///
+ SourceLocation ConsumeParen() {
+ assert(isTokenParen() && "wrong consume method");
+ if (Tok.getKind() == tok::l_paren)
+ ++ParenCount;
+ else if (ParenCount)
+ --ParenCount; // Don't let unbalanced )'s drive the count negative.
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeBracket - This consume method keeps the bracket count up-to-date.
+ ///
+ SourceLocation ConsumeBracket() {
+ assert(isTokenBracket() && "wrong consume method");
+ if (Tok.getKind() == tok::l_square)
+ ++BracketCount;
+ else if (BracketCount)
+ --BracketCount; // Don't let unbalanced ]'s drive the count negative.
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeBrace - This consume method keeps the brace count up-to-date.
+ ///
+ SourceLocation ConsumeBrace() {
+ assert(isTokenBrace() && "wrong consume method");
+ if (Tok.getKind() == tok::l_brace)
+ ++BraceCount;
+ else if (BraceCount)
+ --BraceCount; // Don't let unbalanced }'s drive the count negative.
+
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// ConsumeStringToken - Consume the current 'peek token', lexing a new one
+ /// and returning the token kind. This method is specific to strings, as it
+ /// handles string literal concatenation, as per C99 5.1.1.2, translation
+ /// phase #6.
+ SourceLocation ConsumeStringToken() {
+ assert(isTokenStringLiteral() &&
+ "Should only consume string literals with this method");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ /// GetLookAheadToken - This peeks ahead N tokens and returns that token
+ /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
+ /// returns the token after Tok, etc.
+ ///
+ /// Note that this differs from the Preprocessor's LookAhead method, because
+ /// the Parser always has one token lexed that the preprocessor doesn't.
+ ///
+ const Token &GetLookAheadToken(unsigned N) {
+ if (N == 0 || Tok.is(tok::eof)) return Tok;
+ return PP.LookAhead(N-1);
+ }
+
+ /// NextToken - This peeks ahead one token and returns it without
+ /// consuming it.
+ const Token &NextToken() {
+ return PP.LookAhead(0);
+ }
+
+ /// TryAnnotateTypeOrScopeToken - If the current token position is on a
+ /// typename (possibly qualified in C++) or a C++ scope specifier not followed
+ /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
+ /// with a single annotation token representing the typename or C++ scope
+ /// respectively.
+ /// This simplifies handling of C++ scope specifiers and allows efficient
+ /// backtracking without the need to re-parse and resolve nested-names and
+ /// typenames.
+ /// It will mainly be called when we expect to treat identifiers as typenames
+ /// (if they are typenames). For example, in C we do not expect identifiers
+ /// inside expressions to be treated as typenames so it will not be called
+ /// for expressions in C.
+ ///
+ /// This returns true if the token was annotated.
+ bool TryAnnotateTypeOrScopeToken();
+
+ /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but only
+ /// annotates C++ scope specifiers. This returns true if the token was
+ /// annotated.
+ bool TryAnnotateCXXScopeToken();
+
+ /// TentativeParsingAction - An object that is used as a kind of "tentative
+ /// parsing transaction". It gets instantiated to mark the token position and
+ /// after the token consumption is done, Commit() or Revert() is called to
+ /// either "commit the consumed tokens" or revert to the previously marked
+ /// token position. Example:
+ ///
+ /// TentativeParsingAction TPA;
+ /// ConsumeToken();
+ /// ....
+ /// TPA.Revert();
+ ///
+ class TentativeParsingAction {
+ Parser &P;
+ Token PrevTok;
+ bool isActive;
+
+ public:
+ explicit TentativeParsingAction(Parser& p) : P(p) {
+ PrevTok = P.Tok;
+ P.PP.EnableBacktrackAtThisPos();
+ isActive = true;
+ }
+ void Commit() {
+ assert(isActive && "Parsing action was finished!");
+ P.PP.CommitBacktrackedTokens();
+ isActive = false;
+ }
+ void Revert() {
+ assert(isActive && "Parsing action was finished!");
+ P.PP.Backtrack();
+ P.Tok = PrevTok;
+ isActive = false;
+ }
+ ~TentativeParsingAction() {
+ assert(!isActive && "Forgot to call Commit or Revert!");
+ }
+ };
+
+
+ /// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
+ /// this helper function matches and consumes the specified RHS token if
+ /// present. If not present, it emits the specified diagnostic indicating
+ /// that the parser failed to match the RHS of the token at LHSLoc. LHSName
+ /// should be the name of the unmatched LHS token. This returns the location
+ /// of the consumed token.
+ SourceLocation MatchRHSPunctuation(tok::TokenKind RHSTok,
+ SourceLocation LHSLoc);
+
+ /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
+ /// input. If so, it is consumed and false is returned.
+ ///
+ /// If the input is malformed, this emits the specified diagnostic. Next, if
+ /// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
+ /// returned.
+ bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag,
+ const char *DiagMsg = "",
+ tok::TokenKind SkipToTok = tok::unknown);
+
+ //===--------------------------------------------------------------------===//
+ // Scope manipulation
+
+ /// ParseScope - Introduces a new scope for parsing. The kind of
+ /// scope is determined by ScopeFlags. Objects of this type should
+ /// be created on the stack to coincide with the position where the
+ /// parser enters the new scope, and this object's constructor will
+ /// create that new scope. Similarly, once the object is destroyed
+ /// the parser will exit the scope.
+ class ParseScope {
+ Parser *Self;
+ ParseScope(const ParseScope&); // do not implement
+ ParseScope& operator=(const ParseScope&); // do not implement
+
+ public:
+ // ParseScope - Construct a new object to manage a scope in the
+ // parser Self where the new Scope is created with the flags
+ // ScopeFlags, but only when ManageScope is true (the default). If
+ // ManageScope is false, this object does nothing.
+ ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true)
+ : Self(Self) {
+ if (ManageScope)
+ Self->EnterScope(ScopeFlags);
+ else
+ this->Self = 0;
+ }
+
+ // Exit - Exit the scope associated with this object now, rather
+ // than waiting until the object is destroyed.
+ void Exit() {
+ if (Self) {
+ Self->ExitScope();
+ Self = 0;
+ }
+ }
+
+ ~ParseScope() {
+ Exit();
+ }
+ };
+
+ /// EnterScope - Start a new scope.
+ void EnterScope(unsigned ScopeFlags);
+
+ /// ExitScope - Pop a scope off the scope stack.
+ void ExitScope();
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic Emission and Error recovery.
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
+
+ void SuggestParentheses(SourceLocation Loc, unsigned DK,
+ SourceRange ParenRange);
+
+ /// SkipUntil - Read tokens until we get to the specified token, then consume
+ /// it (unless DontConsume is true). Because we cannot guarantee that the
+ /// token will ever occur, this skips to the next token, or to some likely
+ /// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
+ /// character.
+ ///
+ /// If SkipUntil finds the specified token, it returns true, otherwise it
+ /// returns false.
+ bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
+ bool DontConsume = false) {
+ return SkipUntil(&T, 1, StopAtSemi, DontConsume);
+ }
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
+ bool DontConsume = false) {
+ tok::TokenKind TokArray[] = {T1, T2};
+ return SkipUntil(TokArray, 2, StopAtSemi, DontConsume);
+ }
+ bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
+ bool StopAtSemi = true, bool DontConsume = false);
+
+ //===--------------------------------------------------------------------===//
+ // Lexing and parsing of C++ inline methods.
+
+ struct LexedMethod {
+ Action::DeclPtrTy D;
+ CachedTokens Toks;
+ explicit LexedMethod(Action::DeclPtrTy MD) : D(MD) {}
+ };
+
+ /// LateParsedDefaultArgument - Keeps track of a parameter that may
+ /// have a default argument that cannot be parsed yet because it
+ /// occurs within a member function declaration inside the class
+ /// (C++ [class.mem]p2).
+ struct LateParsedDefaultArgument {
+ explicit LateParsedDefaultArgument(Action::DeclPtrTy P,
+ CachedTokens *Toks = 0)
+ : Param(P), Toks(Toks) { }
+
+ /// Param - The parameter declaration for this parameter.
+ Action::DeclPtrTy Param;
+
+ /// Toks - The sequence of tokens that comprises the default
+ /// argument expression, not including the '=' or the terminating
+ /// ')' or ','. This will be NULL for parameters that have no
+ /// default argument.
+ CachedTokens *Toks;
+ };
+
+ /// LateParsedMethodDeclaration - A method declaration inside a class that
+ /// contains at least one entity whose parsing needs to be delayed
+ /// until the class itself is completely-defined, such as a default
+ /// argument (C++ [class.mem]p2).
+ struct LateParsedMethodDeclaration {
+ explicit LateParsedMethodDeclaration(Action::DeclPtrTy M) : Method(M) { }
+
+ /// Method - The method declaration.
+ Action::DeclPtrTy Method;
+
+ /// DefaultArgs - Contains the parameters of the function and
+ /// their default arguments. At least one of the parameters will
+ /// have a default argument, but all of the parameters of the
+ /// method will be stored so that they can be reintroduced into
+ /// scope at the appropriate times.
+ llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
+ };
+
+ /// LateParsedMethodDecls - During parsing of a top (non-nested) C++
+ /// class, its method declarations that contain parts that won't be
+ /// parsed until after the definiton is completed (C++ [class.mem]p2),
+ /// the method declarations will be stored here with the tokens that
+ /// will be parsed to create those entities.
+ typedef std::list<LateParsedMethodDeclaration> LateParsedMethodDecls;
+
+ /// LexedMethodsForTopClass - During parsing of a top (non-nested) C++ class,
+ /// its inline method definitions and the inline method definitions of its
+ /// nested classes are lexed and stored here.
+ typedef std::list<LexedMethod> LexedMethodsForTopClass;
+
+ /// \brief Representation of a class that has been parsed, including
+ /// any member function declarations or definitions that need to be
+ /// parsed after the corresponding top-level class is complete.
+ struct ParsingClass {
+ ParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass)
+ : TopLevelClass(TopLevelClass), TemplateScope(false),
+ TagOrTemplate(TagOrTemplate) { }
+
+ /// \brief Whether this is a "top-level" class, meaning that it is
+ /// not nested within another class.
+ bool TopLevelClass : 1;
+
+ /// \brief Whether this class had an associated template
+ /// scope. When true, TagOrTemplate is a template declaration;
+ /// othewise, it is a tag declaration.
+ bool TemplateScope : 1;
+
+ /// \brief The class or class template whose definition we are parsing.
+ DeclPtrTy TagOrTemplate;
+
+ /// MethodDecls - Method declarations that contain pieces whose
+ /// parsing will be delayed until the class is fully defined.
+ LateParsedMethodDecls MethodDecls;
+
+ /// MethodDefs - Methods whose definitions will be parsed once the
+ /// class has been fully defined.
+ LexedMethodsForTopClass MethodDefs;
+
+ /// \brief Nested classes inside this class.
+ llvm::SmallVector<ParsingClass*, 4> NestedClasses;
+ };
+
+ /// \brief The stack of classes that is currently being
+ /// parsed. Nested and local classes will be pushed onto this stack
+ /// when they are parsed, and removed afterward.
+ std::stack<ParsingClass *> ClassStack;
+
+ ParsingClass &getCurrentClass() {
+ assert(!ClassStack.empty() && "No lexed method stacks!");
+ return *ClassStack.top();
+ }
+
+ /// \brief RAII object used to
+ class ParsingClassDefinition {
+ Parser &P;
+ bool Popped;
+
+ public:
+ ParsingClassDefinition(Parser &P, DeclPtrTy TagOrTemplate, bool TopLevelClass)
+ : P(P), Popped(false) {
+ P.PushParsingClass(TagOrTemplate, TopLevelClass);
+ }
+
+ /// \brief Pop this class of the stack.
+ void Pop() {
+ assert(!Popped && "Nested class has already been popped");
+ Popped = true;
+ P.PopParsingClass();
+ }
+
+ ~ParsingClassDefinition() {
+ if (!Popped)
+ P.PopParsingClass();
+ }
+ };
+
+ void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
+ void DeallocateParsedClasses(ParsingClass *Class);
+ void PopParsingClass();
+
+ DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D);
+ void ParseLexedMethodDeclarations(ParsingClass &Class);
+ void ParseLexedMethodDefs(ParsingClass &Class);
+ bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
+ CachedTokens &Toks,
+ tok::TokenKind EarlyAbortIf = tok::unknown,
+ bool ConsumeFinalToken = true);
+
+ /// \brief Contains information about any template-specific
+ /// information that has been parsed prior to parsing declaration
+ /// specifiers.
+ struct ParsedTemplateInfo {
+ ParsedTemplateInfo()
+ : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
+
+ ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
+ bool isSpecialization)
+ : Kind(isSpecialization? ExplicitSpecialization : Template),
+ TemplateParams(TemplateParams) { }
+
+ explicit ParsedTemplateInfo(SourceLocation TemplateLoc)
+ : Kind(ExplicitInstantiation), TemplateParams(0),
+ TemplateLoc(TemplateLoc) { }
+
+ /// \brief The kind of template we are parsing.
+ enum {
+ /// \brief We are not parsing a template at all.
+ NonTemplate = 0,
+ /// \brief We are parsing a template declaration.
+ Template,
+ /// \brief We are parsing an explicit specialization.
+ ExplicitSpecialization,
+ /// \brief We are parsing an explicit instantiation.
+ ExplicitInstantiation
+ } Kind;
+
+ /// \brief The template parameter lists, for template declarations
+ /// and explicit specializations.
+ TemplateParameterLists *TemplateParams;
+
+ /// \brief The location of the 'template' keyword, for an explicit
+ /// instantiation.
+ SourceLocation TemplateLoc;
+ };
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.9: External Definitions.
+ DeclGroupPtrTy ParseExternalDeclaration();
+ bool isDeclarationAfterDeclarator();
+ bool isStartOfFunctionDefinition();
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
+ AccessSpecifier AS = AS_none);
+
+ DeclPtrTy ParseFunctionDefinition(Declarator &D);
+ void ParseKNRParamDeclarations(Declarator &D);
+ // EndLoc, if non-NULL, is filled with the location of the last token of
+ // the simple-asm.
+ OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
+ OwningExprResult ParseAsmStringLiteral();
+
+ // Objective-C External Declarations
+ DeclPtrTy ParseObjCAtDirectives();
+ DeclPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ AttributeList *prefixAttrs = 0);
+ void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
+ SourceLocation atLoc);
+ bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P,
+ bool WarnOnDeclarations,
+ SourceLocation &EndProtoLoc);
+ void ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
+ tok::ObjCKeywordKind contextKey);
+ DeclPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
+ AttributeList *prefixAttrs = 0);
+
+ DeclPtrTy ObjCImpDecl;
+
+ DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
+ DeclPtrTy ParseObjCAtEndDeclaration(SourceLocation atLoc);
+ DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc);
+ DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc);
+ DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc);
+
+ IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation);
+ // Definitions for Objective-c context sensitive keywords recognition.
+ enum ObjCTypeQual {
+ objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref,
+ objc_NumQuals
+ };
+ IdentifierInfo *ObjCTypeQuals[objc_NumQuals];
+
+ bool isTokIdentifier_in() const;
+
+ TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS);
+ void ParseObjCMethodRequirement();
+ DeclPtrTy ParseObjCMethodPrototype(DeclPtrTy classOrCat,
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
+ DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
+ DeclPtrTy classDecl,
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS);
+
+ DeclPtrTy ParseObjCMethodDefinition();
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.5: Expressions.
+
+ OwningExprResult ParseExpression();
+ OwningExprResult ParseConstantExpression();
+ // Expr that doesn't include commas.
+ OwningExprResult ParseAssignmentExpression();
+
+ OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
+
+ OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
+
+ OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS,
+ unsigned MinPrec);
+ OwningExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand,
+ bool &NotCastExpr);
+ OwningExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand = false);
+ OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS);
+ OwningExprResult ParseSizeofAlignofExpression();
+ OwningExprResult ParseBuiltinPrimaryExpression();
+
+ OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
+ bool &isCastExpr,
+ TypeTy *&CastTy,
+ SourceRange &CastRange);
+
+ static const unsigned ExprListSize = 12;
+ typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;
+ typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy;
+
+ /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
+ bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs);
+
+ /// ParenParseOption - Control what ParseParenExpression will parse.
+ enum ParenParseOption {
+ SimpleExpr, // Only parse '(' expression ')'
+ CompoundStmt, // Also allow '(' compound-statement ')'
+ CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
+ CastExpr // Also allow '(' type-name ')' <anything>
+ };
+ OwningExprResult ParseParenExpression(ParenParseOption &ExprType,
+ bool stopIfCastExpr,
+ TypeTy *&CastTy,
+ SourceLocation &RParenLoc);
+
+ OwningExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
+ TypeTy *&CastTy,
+ SourceLocation LParenLoc,
+ SourceLocation &RParenLoc);
+
+ OwningExprResult ParseCompoundLiteralExpression(TypeTy *Ty,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ OwningExprResult ParseStringLiteralExpression();
+
+ //===--------------------------------------------------------------------===//
+ // C++ Expressions
+ OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+
+ /// ParseOptionalCXXScopeSpecifier - Parse global scope or
+ /// nested-name-specifier if present. Returns true if a nested-name-specifier
+ /// was parsed from the token stream. Note that this routine will not parse
+ /// ::new or ::delete, it will just leave them in the token stream.
+ ///
+ bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Casts
+ OwningExprResult ParseCXXCasts();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2p1: C++ Type Identification
+ OwningExprResult ParseCXXTypeid();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9.3.2: C++ 'this' pointer
+ OwningExprResult ParseCXXThis();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 15: C++ Throw Expression
+ OwningExprResult ParseThrowExpression();
+ // EndLoc is filled with the location of the last token of the specification.
+ bool ParseExceptionSpecification(SourceLocation &EndLoc,
+ llvm::SmallVector<TypeTy*, 2> &Exceptions,
+ llvm::SmallVector<SourceRange, 2> &Ranges,
+ bool &hasAnyExceptionSpec);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 2.13.5: C++ Boolean Literals
+ OwningExprResult ParseCXXBoolLiteral();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2.3: Explicit type conversion (functional notation)
+ OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
+
+ /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
+ /// This should only be called when the current token is known to be part of
+ /// simple-type-specifier.
+ void ParseCXXSimpleTypeSpecifier(DeclSpec &DS);
+
+ bool ParseCXXTypeSpecifierSeq(DeclSpec &DS);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.3.4 and 5.3.5: C++ new and delete
+ bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D);
+ void ParseDirectNewDeclarator(Declarator &D);
+ OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
+ OwningExprResult ParseCXXDeleteExpression(bool UseGlobal,
+ SourceLocation Start);
+
+ //===--------------------------------------------------------------------===//
+ // C++ if/switch/while/for condition expression.
+ OwningExprResult ParseCXXCondition();
+
+ //===--------------------------------------------------------------------===//
+ // C++ types
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.7.8: Initialization.
+
+ /// ParseInitializer
+ /// initializer: [C99 6.7.8]
+ /// assignment-expression
+ /// '{' ...
+ OwningExprResult ParseInitializer() {
+ if (Tok.isNot(tok::l_brace))
+ return ParseAssignmentExpression();
+ return ParseBraceInitializer();
+ }
+ OwningExprResult ParseBraceInitializer();
+ OwningExprResult ParseInitializerWithPotentialDesignator();
+
+ //===--------------------------------------------------------------------===//
+ // clang Expressions
+
+ OwningExprResult ParseBlockLiteralExpression(); // ^{...}
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Expressions
+
+ bool isTokObjCMessageIdentifierReceiver() const {
+ if (!Tok.is(tok::identifier))
+ return false;
+
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (Actions.getTypeName(*II, Tok.getLocation(), CurScope))
+ return true;
+
+ return II == Ident_super;
+ }
+
+ OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation);
+ OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
+ OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
+ OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
+ OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
+ OwningExprResult ParseObjCMessageExpression();
+ OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
+ SourceLocation NameLoc,
+ IdentifierInfo *ReceiverName,
+ ExprArg ReceiverExpr);
+ OwningExprResult ParseAssignmentExprWithObjCMessageExprStart(
+ SourceLocation LBracloc, SourceLocation NameLoc,
+ IdentifierInfo *ReceiverName, ExprArg ReceiverExpr);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.8: Statements and Blocks.
+
+ OwningStmtResult ParseStatement() {
+ return ParseStatementOrDeclaration(true);
+ }
+ OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
+ OwningStmtResult ParseLabeledStatement();
+ OwningStmtResult ParseCaseStatement();
+ OwningStmtResult ParseDefaultStatement();
+ OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false);
+ OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(OwningExprResult &CondExp,
+ bool OnlyAllowCondition = false);
+ OwningStmtResult ParseIfStatement();
+ OwningStmtResult ParseSwitchStatement();
+ OwningStmtResult ParseWhileStatement();
+ OwningStmtResult ParseDoStatement();
+ OwningStmtResult ParseForStatement();
+ OwningStmtResult ParseGotoStatement();
+ OwningStmtResult ParseContinueStatement();
+ OwningStmtResult ParseBreakStatement();
+ OwningStmtResult ParseReturnStatement();
+ OwningStmtResult ParseAsmStatement(bool &msAsm);
+ OwningStmtResult FuzzyParseMicrosoftAsmStatement();
+ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
+ llvm::SmallVectorImpl<ExprTy*> &Constraints,
+ llvm::SmallVectorImpl<ExprTy*> &Exprs);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 6: Statements and Blocks
+
+ OwningStmtResult ParseCXXTryBlock();
+ OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
+ OwningStmtResult ParseCXXCatchBlock();
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Statements
+
+ OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc);
+ OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc);
+ OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.7: Declarations.
+
+ DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
+ DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
+ SourceLocation &DeclEnd,
+ bool RequireSemi = true);
+ DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D);
+ DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
+ DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
+ DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
+
+ bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS);
+ void ParseDeclarationSpecifiers(DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none);
+ bool ParseOptionalTypeSpecifier(DeclSpec &DS, int &isInvalid,
+ const char *&PrevSpec,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+
+ void ParseSpecifierQualifierList(DeclSpec &DS);
+
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
+
+ void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
+ AccessSpecifier AS = AS_none);
+ void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
+ void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
+ DeclPtrTy TagDecl);
+ void ParseStructDeclaration(DeclSpec &DS,
+ llvm::SmallVectorImpl<FieldDeclarator> &Fields);
+
+ bool isDeclarationSpecifier();
+ bool isTypeSpecifierQualifier();
+ bool isTypeQualifier() const;
+
+ /// isDeclarationStatement - Disambiguates between a declaration or an
+ /// expression statement, when parsing function bodies.
+ /// Returns true for declaration, false for expression.
+ bool isDeclarationStatement() {
+ if (getLang().CPlusPlus)
+ return isCXXDeclarationStatement();
+ return isDeclarationSpecifier();
+ }
+
+ /// isSimpleDeclaration - Disambiguates between a declaration or an
+ /// expression, mainly used for the C 'clause-1' or the C++
+ // 'for-init-statement' part of a 'for' statement.
+ /// Returns true for declaration, false for expression.
+ bool isSimpleDeclaration() {
+ if (getLang().CPlusPlus)
+ return isCXXSimpleDeclaration();
+ return isDeclarationSpecifier();
+ }
+
+ /// \brief Specifies the context in which type-id/expression
+ /// disambiguation will occur.
+ enum TentativeCXXTypeIdContext {
+ TypeIdInParens,
+ TypeIdAsTemplateArgument
+ };
+
+
+ /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know
+ /// whether the parens contain an expression or a type-id.
+ /// Returns true for a type-id and false for an expression.
+ bool isTypeIdInParens(bool &isAmbiguous) {
+ if (getLang().CPlusPlus)
+ return isCXXTypeId(TypeIdInParens, isAmbiguous);
+ isAmbiguous = false;
+ return isTypeSpecifierQualifier();
+ }
+ bool isTypeIdInParens() {
+ bool isAmbiguous;
+ return isTypeIdInParens(isAmbiguous);
+ }
+
+ /// isCXXDeclarationStatement - C++-specialized function that disambiguates
+ /// between a declaration or an expression statement, when parsing function
+ /// bodies. Returns true for declaration, false for expression.
+ bool isCXXDeclarationStatement();
+
+ /// isCXXSimpleDeclaration - C++-specialized function that disambiguates
+ /// between a simple-declaration or an expression-statement.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ /// Returns false if the statement is disambiguated as expression.
+ bool isCXXSimpleDeclaration();
+
+ /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
+ /// a constructor-style initializer, when parsing declaration statements.
+ /// Returns true for function declarator and false for constructor-style
+ /// initializer. If 'warnIfAmbiguous' is true a warning will be emitted to
+ /// indicate that the parens were disambiguated as function declarator.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ bool isCXXFunctionDeclarator(bool warnIfAmbiguous);
+
+ /// isCXXConditionDeclaration - Disambiguates between a declaration or an
+ /// expression for a condition of a if/switch/while/for statement.
+ /// If during the disambiguation process a parsing error is encountered,
+ /// the function returns true to let the declaration parsing code handle it.
+ bool isCXXConditionDeclaration();
+
+ bool isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous);
+ bool isCXXTypeId(TentativeCXXTypeIdContext Context) {
+ bool isAmbiguous;
+ return isCXXTypeId(Context, isAmbiguous);
+ }
+
+ /// TPResult - Used as the result value for functions whose purpose is to
+ /// disambiguate C++ constructs by "tentatively parsing" them.
+ /// This is a class instead of a simple enum because the implicit enum-to-bool
+ /// conversions may cause subtle bugs.
+ class TPResult {
+ enum Result {
+ TPR_true,
+ TPR_false,
+ TPR_ambiguous,
+ TPR_error
+ };
+ Result Res;
+ TPResult(Result result) : Res(result) {}
+ public:
+ static TPResult True() { return TPR_true; }
+ static TPResult False() { return TPR_false; }
+ static TPResult Ambiguous() { return TPR_ambiguous; }
+ static TPResult Error() { return TPR_error; }
+
+ bool operator==(const TPResult &RHS) const { return Res == RHS.Res; }
+ bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; }
+ };
+
+ /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a
+ /// declaration specifier, TPResult::False() if it is not,
+ /// TPResult::Ambiguous() if it could be either a decl-specifier or a
+ /// function-style cast, and TPResult::Error() if a parsing error was
+ /// encountered.
+ /// Doesn't consume tokens.
+ TPResult isCXXDeclarationSpecifier();
+
+ // "Tentative parsing" functions, used for disambiguation. If a parsing error
+ // is encountered they will return TPResult::Error().
+ // Returning TPResult::True()/False() indicates that the ambiguity was
+ // resolved and tentative parsing may stop. TPResult::Ambiguous() indicates
+ // that more tentative parsing is necessary for disambiguation.
+ // They all consume tokens, so backtracking should be used after calling them.
+
+ TPResult TryParseDeclarationSpecifier();
+ TPResult TryParseSimpleDeclaration();
+ TPResult TryParseTypeofSpecifier();
+ TPResult TryParseInitDeclaratorList();
+ TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
+ TPResult TryParseParameterDeclarationClause();
+ TPResult TryParseFunctionDeclarator();
+ TPResult TryParseBracketDeclarator();
+
+ TypeResult ParseTypeName(SourceRange *Range = 0);
+ void ParseBlockId();
+ // EndLoc, if non-NULL, is filled with the location of the last token of
+ // the attribute list.
+ AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
+ void FuzzyParseMicrosoftDeclSpec();
+ void ParseTypeofSpecifier(DeclSpec &DS);
+
+ /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
+ /// enter a new C++ declarator scope and exit it when the function is
+ /// finished.
+ class DeclaratorScopeObj {
+ Parser &P;
+ CXXScopeSpec &SS;
+ public:
+ DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss) : P(p), SS(ss) {}
+
+ void EnterDeclaratorScope() {
+ if (SS.isSet())
+ P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS);
+ }
+
+ ~DeclaratorScopeObj() {
+ if (SS.isSet())
+ P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS);
+ }
+ };
+
+ /// ParseDeclarator - Parse and verify a newly-initialized declarator.
+ void ParseDeclarator(Declarator &D);
+ /// A function that parses a variant of direct-declarator.
+ typedef void (Parser::*DirectDeclParseFunction)(Declarator&);
+ void ParseDeclaratorInternal(Declarator &D,
+ DirectDeclParseFunction DirectDeclParser);
+ void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true);
+ void ParseDirectDeclarator(Declarator &D);
+ void ParseParenDeclarator(Declarator &D);
+ void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
+ AttributeList *AttrList = 0,
+ bool RequiresArg = false);
+ void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
+ Declarator &D);
+ void ParseBracketDeclarator(Declarator &D);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 7: Declarations [dcl.dcl]
+
+ DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
+ DeclPtrTy ParseLinkage(unsigned Context);
+ DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
+ SourceLocation &DeclEnd);
+ DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
+ SourceLocation &DeclEnd);
+ DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
+ SourceLocation &DeclEnd);
+ DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceLocation &DeclEnd);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9: classes [class] and C structs/unions.
+ TypeResult ParseClassName(SourceLocation &EndLocation,
+ const CXXScopeSpec *SS = 0);
+ void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
+ DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none);
+ void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
+ DeclPtrTy TagDecl);
+ void ParseCXXClassMemberDeclaration(AccessSpecifier AS);
+ void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
+ MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 10: Derived classes [class.derived]
+ void ParseBaseClause(DeclPtrTy ClassDecl);
+ BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
+ AccessSpecifier getAccessSpecifierIfPresent() const;
+
+ //===--------------------------------------------------------------------===//
+ // C++ 13.5: Overloaded operators [over.oper]
+ // EndLoc, if non-NULL, is filled with the location of the last token of
+ // the ID.
+ OverloadedOperatorKind TryParseOperatorFunctionId(SourceLocation *EndLoc = 0);
+ TypeTy *ParseConversionFunctionId(SourceLocation *EndLoc = 0);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 14: Templates [temp]
+ typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList;
+
+ // C++ 14.1: Template Parameters [temp.param]
+ DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS);
+ DeclPtrTy ParseSingleDeclarationAfterTemplate(
+ unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS=AS_none);
+ bool ParseTemplateParameters(unsigned Depth,
+ TemplateParameterList &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc);
+ bool ParseTemplateParameterList(unsigned Depth,
+ TemplateParameterList &TemplateParams);
+ DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position);
+ DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position);
+ DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ // C++ 14.3: Template arguments [temp.arg]
+ typedef llvm::SmallVector<void *, 16> TemplateArgList;
+ typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList;
+ typedef llvm::SmallVector<SourceLocation, 16> TemplateArgLocationList;
+
+ bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ const CXXScopeSpec *SS,
+ bool ConsumeLastToken,
+ SourceLocation &LAngleLoc,
+ TemplateArgList &TemplateArgs,
+ TemplateArgIsTypeList &TemplateArgIsType,
+ TemplateArgLocationList &TemplateArgLocations,
+ SourceLocation &RAngleLoc);
+
+ void AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
+ const CXXScopeSpec *SS,
+ SourceLocation TemplateKWLoc = SourceLocation(),
+ bool AllowTypeAnnotation = true);
+ void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
+ TemplateArgIsTypeList &TemplateArgIsType,
+ TemplateArgLocationList &TemplateArgLocations);
+ void *ParseTemplateArgument(bool &ArgIsType);
+ DeclPtrTy ParseExplicitInstantiation(SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd);
+
+ //===--------------------------------------------------------------------===//
+ // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
+ OwningExprResult ParseUnaryTypeTrait();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h
new file mode 100644
index 000000000000..84cc5d5c3461
--- /dev/null
+++ b/include/clang/Parse/Scope.h
@@ -0,0 +1,310 @@
+//===--- Scope.h - Scope interface ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Scope interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_SCOPE_H
+#define LLVM_CLANG_PARSE_SCOPE_H
+
+#include "clang/Parse/Action.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+/// Scope - A scope is a transient data structure that is used while parsing the
+/// program. It assists with resolving identifiers to the appropriate
+/// declaration.
+///
+class Scope {
+public:
+ /// ScopeFlags - These are bitfields that are or'd together when creating a
+ /// scope, which defines the sorts of things the scope contains.
+ enum ScopeFlags {
+ /// FnScope - This indicates that the scope corresponds to a function, which
+ /// means that labels are set here.
+ FnScope = 0x01,
+
+ /// BreakScope - This is a while,do,switch,for, etc that can have break
+ /// stmts embedded into it.
+ BreakScope = 0x02,
+
+ /// ContinueScope - This is a while,do,for, which can have continue
+ /// stmt embedded into it.
+ ContinueScope = 0x04,
+
+ /// DeclScope - This is a scope that can contain a declaration. Some scopes
+ /// just contain loop constructs but don't contain decls.
+ DeclScope = 0x08,
+
+ /// ControlScope - The controlling scope in a if/switch/while/for statement.
+ ControlScope = 0x10,
+
+ /// ClassScope - The scope of a struct/union/class definition.
+ ClassScope = 0x20,
+
+ /// BlockScope - This is a scope that corresponds to a block object.
+ /// Blocks serve as top-level scopes for some objects like labels, they
+ /// also prevent things like break and continue. BlockScopes have the
+ /// other flags set as well.
+ BlockScope = 0x40,
+
+ /// TemplateParamScope - This is a scope that corresponds to the
+ /// template parameters of a C++ template. Template parameter
+ /// scope starts at the 'template' keyword and ends when the
+ /// template declaration ends.
+ TemplateParamScope = 0x80,
+
+ /// FunctionPrototypeScope - This is a scope that corresponds to the
+ /// parameters within a function prototype.
+ FunctionPrototypeScope = 0x100,
+
+ /// AtCatchScope - This is a scope that corresponds to the Objective-C
+ /// @catch statement.
+ AtCatchScope = 0x200
+ };
+private:
+ /// The parent scope for this scope. This is null for the translation-unit
+ /// scope.
+ Scope *AnyParent;
+
+ /// Depth - This is the depth of this scope. The translation-unit scope has
+ /// depth 0.
+ unsigned Depth : 16;
+
+ /// Flags - This contains a set of ScopeFlags, which indicates how the scope
+ /// interrelates with other control flow statements.
+ unsigned Flags : 10;
+
+ /// WithinElse - Whether this scope is part of the "else" branch in
+ /// its parent ControlScope.
+ bool WithinElse : 1;
+
+ /// FnParent - If this scope has a parent scope that is a function body, this
+ /// pointer is non-null and points to it. This is used for label processing.
+ Scope *FnParent;
+
+ /// BreakParent/ContinueParent - This is a direct link to the immediately
+ /// preceeding BreakParent/ContinueParent if this scope is not one, or null if
+ /// there is no containing break/continue scope.
+ Scope *BreakParent, *ContinueParent;
+
+ /// ControlParent - This is a direct link to the immediately
+ /// preceeding ControlParent if this scope is not one, or null if
+ /// there is no containing control scope.
+ Scope *ControlParent;
+
+ /// BlockParent - This is a direct link to the immediately containing
+ /// BlockScope if this scope is not one, or null if there is none.
+ Scope *BlockParent;
+
+ /// TemplateParamParent - This is a direct link to the
+ /// immediately containing template parameter scope. In the
+ /// case of nested templates, template parameter scopes can have
+ /// other template parameter scopes as parents.
+ Scope *TemplateParamParent;
+
+ /// DeclsInScope - This keeps track of all declarations in this scope. When
+ /// the declaration is added to the scope, it is set as the current
+ /// declaration for the identifier in the IdentifierTable. When the scope is
+ /// popped, these declarations are removed from the IdentifierTable's notion
+ /// of current declaration. It is up to the current Action implementation to
+ /// implement these semantics.
+ typedef llvm::SmallPtrSet<Action::DeclPtrTy, 32> DeclSetTy;
+ DeclSetTy DeclsInScope;
+
+ /// Entity - The entity with which this scope is associated. For
+ /// example, the entity of a class scope is the class itself, the
+ /// entity of a function scope is a function, etc. This field is
+ /// maintained by the Action implementation.
+ void *Entity;
+
+ typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy;
+ UsingDirectivesTy UsingDirectives;
+
+public:
+ Scope(Scope *Parent, unsigned ScopeFlags) {
+ Init(Parent, ScopeFlags);
+ }
+
+ /// getFlags - Return the flags for this scope.
+ ///
+ unsigned getFlags() const { return Flags; }
+
+ /// isBlockScope - Return true if this scope does not correspond to a
+ /// closure.
+ bool isBlockScope() const { return Flags & BlockScope; }
+
+ /// getParent - Return the scope that this is nested in.
+ ///
+ const Scope *getParent() const { return AnyParent; }
+ Scope *getParent() { return AnyParent; }
+
+ /// getFnParent - Return the closest scope that is a function body.
+ ///
+ const Scope *getFnParent() const { return FnParent; }
+ Scope *getFnParent() { return FnParent; }
+
+ /// getContinueParent - Return the closest scope that a continue statement
+ /// would be affected by. If the closest scope is a closure scope, we know
+ /// that there is no loop *inside* the closure.
+ Scope *getContinueParent() {
+ if (ContinueParent && !ContinueParent->isBlockScope())
+ return ContinueParent;
+ return 0;
+ }
+
+ const Scope *getContinueParent() const {
+ return const_cast<Scope*>(this)->getContinueParent();
+ }
+
+ /// getBreakParent - Return the closest scope that a break statement
+ /// would be affected by. If the closest scope is a block scope, we know
+ /// that there is no loop *inside* the block.
+ Scope *getBreakParent() {
+ if (BreakParent && !BreakParent->isBlockScope())
+ return BreakParent;
+ return 0;
+ }
+ const Scope *getBreakParent() const {
+ return const_cast<Scope*>(this)->getBreakParent();
+ }
+
+ Scope *getControlParent() { return ControlParent; }
+ const Scope *getControlParent() const { return ControlParent; }
+
+ Scope *getBlockParent() { return BlockParent; }
+ const Scope *getBlockParent() const { return BlockParent; }
+
+ Scope *getTemplateParamParent() { return TemplateParamParent; }
+ const Scope *getTemplateParamParent() const { return TemplateParamParent; }
+
+ typedef DeclSetTy::iterator decl_iterator;
+ decl_iterator decl_begin() const { return DeclsInScope.begin(); }
+ decl_iterator decl_end() const { return DeclsInScope.end(); }
+ bool decl_empty() const { return DeclsInScope.empty(); }
+
+ void AddDecl(Action::DeclPtrTy D) {
+ DeclsInScope.insert(D);
+ }
+
+ void RemoveDecl(Action::DeclPtrTy D) {
+ DeclsInScope.erase(D);
+ }
+
+ /// isDeclScope - Return true if this is the scope that the specified decl is
+ /// declared in.
+ bool isDeclScope(Action::DeclPtrTy D) {
+ return DeclsInScope.count(D) != 0;
+ }
+
+ void* getEntity() const { return Entity; }
+ void setEntity(void *E) { Entity = E; }
+
+ /// isClassScope - Return true if this scope is a class/struct/union scope.
+ bool isClassScope() const {
+ return (getFlags() & Scope::ClassScope);
+ }
+
+ /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline
+ /// method scope or is inside one.
+ bool isInCXXInlineMethodScope() const {
+ if (const Scope *FnS = getFnParent()) {
+ assert(FnS->getParent() && "TUScope not created?");
+ return FnS->getParent()->isClassScope();
+ }
+ return false;
+ }
+
+ /// isTemplateParamScope - Return true if this scope is a C++
+ /// template parameter scope.
+ bool isTemplateParamScope() const {
+ return getFlags() & Scope::TemplateParamScope;
+ }
+
+ /// isFunctionPrototypeScope - Return true if this scope is a
+ /// function prototype scope.
+ bool isFunctionPrototypeScope() const {
+ return getFlags() & Scope::FunctionPrototypeScope;
+ }
+
+ /// isAtCatchScope - Return true if this scope is @catch.
+ bool isAtCatchScope() const {
+ return getFlags() & Scope::AtCatchScope;
+ }
+
+ /// isWithinElse - Whether we are within the "else" of the
+ /// ControlParent (if any).
+ bool isWithinElse() const { return WithinElse; }
+
+ void setWithinElse(bool WE) { WithinElse = WE; }
+
+ typedef UsingDirectivesTy::iterator udir_iterator;
+ typedef UsingDirectivesTy::const_iterator const_udir_iterator;
+
+ void PushUsingDirective(Action::DeclPtrTy UDir) {
+ UsingDirectives.push_back(UDir);
+ }
+
+ udir_iterator using_directives_begin() {
+ return UsingDirectives.begin();
+ }
+
+ udir_iterator using_directives_end() {
+ return UsingDirectives.end();
+ }
+
+ const_udir_iterator using_directives_begin() const {
+ return UsingDirectives.begin();
+ }
+
+ const_udir_iterator using_directives_end() const {
+ return UsingDirectives.end();
+ }
+
+ /// Init - This is used by the parser to implement scope caching.
+ ///
+ void Init(Scope *Parent, unsigned ScopeFlags) {
+ AnyParent = Parent;
+ Depth = AnyParent ? AnyParent->Depth+1 : 0;
+ Flags = ScopeFlags;
+
+ if (AnyParent) {
+ FnParent = AnyParent->FnParent;
+ BreakParent = AnyParent->BreakParent;
+ ContinueParent = AnyParent->ContinueParent;
+ ControlParent = AnyParent->ControlParent;
+ BlockParent = AnyParent->BlockParent;
+ TemplateParamParent = AnyParent->TemplateParamParent;
+ WithinElse = AnyParent->WithinElse;
+
+ } else {
+ FnParent = BreakParent = ContinueParent = BlockParent = 0;
+ ControlParent = 0;
+ TemplateParamParent = 0;
+ WithinElse = false;
+ }
+
+ // If this scope is a function or contains breaks/continues, remember it.
+ if (Flags & FnScope) FnParent = this;
+ if (Flags & BreakScope) BreakParent = this;
+ if (Flags & ContinueScope) ContinueParent = this;
+ if (Flags & ControlScope) ControlParent = this;
+ if (Flags & BlockScope) BlockParent = this;
+ if (Flags & TemplateParamScope) TemplateParamParent = this;
+ DeclsInScope.clear();
+ UsingDirectives.clear();
+ Entity = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Rewrite/DeltaTree.h b/include/clang/Rewrite/DeltaTree.h
new file mode 100644
index 000000000000..7bf9305e2877
--- /dev/null
+++ b/include/clang/Rewrite/DeltaTree.h
@@ -0,0 +1,48 @@
+//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DeltaTree class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_REWRITE_DELTATREE_H
+#define CLANG_REWRITE_DELTATREE_H
+
+namespace clang {
+
+ /// DeltaTree - a multiway search tree (BTree) structure with some fancy
+ /// features. B-Trees are are generally more memory and cache efficient than
+ /// binary trees, because they store multiple keys/values in each node. This
+ /// implements a key/value mapping from index to delta, and allows fast lookup
+ /// on index. However, an added (important) bonus is that it can also
+ /// efficiently tell us the full accumulated delta for a specific file offset
+ /// as well, without traversing the whole tree.
+ class DeltaTree {
+ void *Root; // "DeltaTreeNode *"
+ void operator=(const DeltaTree&); // DO NOT IMPLEMENT
+ public:
+ DeltaTree();
+
+ // Note: Currently we only support copying when the RHS is empty.
+ DeltaTree(const DeltaTree &RHS);
+ ~DeltaTree();
+
+ /// getDeltaAt - Return the accumulated delta at the specified file offset.
+ /// This includes all insertions or delections that occurred *before* the
+ /// specified file index.
+ int getDeltaAt(unsigned FileIndex) const;
+
+ /// AddDelta - When a change is made that shifts around the text buffer,
+ /// this method is used to record that info. It inserts a delta of 'Delta'
+ /// into the current DeltaTree at offset FileIndex.
+ void AddDelta(unsigned FileIndex, int Delta);
+ };
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Rewrite/HTMLRewrite.h b/include/clang/Rewrite/HTMLRewrite.h
new file mode 100644
index 000000000000..f49d49e710c9
--- /dev/null
+++ b/include/clang/Rewrite/HTMLRewrite.h
@@ -0,0 +1,82 @@
+//==- HTMLRewrite.h - Translate source code into prettified HTML ---*- C++ -*-//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a set of functions used for translating source code
+// into beautified HTML.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_HTMLREWRITER_H
+#define LLVM_CLANG_HTMLREWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include <string>
+
+namespace clang {
+
+class Rewriter;
+class RewriteBuffer;
+class Preprocessor;
+class PreprocessorFactory;
+
+namespace html {
+
+ /// HighlightRange - Highlight a range in the source code with the specified
+ /// start/end tags. B/E must be in the same file. This ensures that
+ /// start/end tags are placed at the start/end of each line if the range is
+ /// multiline.
+ void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E,
+ const char *StartTag, const char *EndTag);
+
+ /// HighlightRange - Highlight a range in the source code with the specified
+ /// start/end tags. The Start/end of the range must be in the same file.
+ /// This ensures that start/end tags are placed at the start/end of each line
+ /// if the range is multiline.
+ inline void HighlightRange(Rewriter &R, SourceRange Range,
+ const char *StartTag, const char *EndTag) {
+ HighlightRange(R, Range.getBegin(), Range.getEnd(), StartTag, EndTag);
+ }
+
+ /// HighlightRange - This is the same as the above method, but takes
+ /// decomposed file locations.
+ void HighlightRange(RewriteBuffer &RB, unsigned B, unsigned E,
+ const char *BufferStart,
+ const char *StartTag, const char *EndTag);
+
+ /// EscapeText - HTMLize a specified file so that special characters are
+ /// are translated so that they are not interpreted as HTML tags.
+ void EscapeText(Rewriter& R, FileID FID,
+ bool EscapeSpaces = false, bool ReplaceTabs = false);
+
+ /// EscapeText - HTMLized the provided string so that special characters
+ /// in 's' are not interpreted as HTML tags. Unlike the version of
+ /// EscapeText that rewrites a file, this version by default replaces tabs
+ /// with spaces.
+ std::string EscapeText(const std::string& s,
+ bool EscapeSpaces = false, bool ReplaceTabs = false);
+
+ void AddLineNumbers(Rewriter& R, FileID FID);
+
+ void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
+ const char *title = NULL);
+
+ /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
+ /// information about keywords, comments, etc.
+ void SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP);
+
+ /// HighlightMacros - This uses the macro table state from the end of the
+ /// file, to reexpand macros and insert (into the HTML) information about the
+ /// macro expansions. This won't be perfectly perfect, but it will be
+ /// reasonably close.
+ void HighlightMacros(Rewriter &R, FileID FID, Preprocessor &PP);
+ void HighlightMacros(Rewriter &R, FileID FID, PreprocessorFactory &PPF);
+} // end html namespace
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Rewrite/RewriteRope.h b/include/clang/Rewrite/RewriteRope.h
new file mode 100644
index 000000000000..7faa451290e4
--- /dev/null
+++ b/include/clang/Rewrite/RewriteRope.h
@@ -0,0 +1,230 @@
+//===--- RewriteRope.h - Rope specialized for rewriter ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the RewriteRope class, which is a powerful string class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REWRITEROPE_H
+#define LLVM_CLANG_REWRITEROPE_H
+
+#include "llvm/ADT/iterator.h"
+#include <cstring>
+#include <cassert>
+
+namespace clang {
+ //===--------------------------------------------------------------------===//
+ // RopeRefCountString Class
+ //===--------------------------------------------------------------------===//
+
+ /// RopeRefCountString - This struct is allocated with 'new char[]' from the
+ /// heap, and represents a reference counted chunk of string data. When its
+ /// ref count drops to zero, it is delete[]'d. This is primarily managed
+ /// through the RopePiece class below.
+ struct RopeRefCountString {
+ unsigned RefCount;
+ char Data[1]; // Variable sized.
+
+ void addRef() {
+ if (this) ++RefCount;
+ }
+
+ void dropRef() {
+ if (this && --RefCount == 0)
+ delete [] (char*)this;
+ }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePiece Class
+ //===--------------------------------------------------------------------===//
+
+ /// RopePiece - This class represents a view into a RopeRefCountString object.
+ /// This allows references to string data to be efficiently chopped up and
+ /// moved around without having to push around the string data itself.
+ ///
+ /// For example, we could have a 1M RopePiece and want to insert something
+ /// into the middle of it. To do this, we split it into two RopePiece objects
+ /// that both refer to the same underlying RopeRefCountString (just with
+ /// different offsets) which is a nice constant time operation.
+ struct RopePiece {
+ RopeRefCountString *StrData;
+ unsigned StartOffs;
+ unsigned EndOffs;
+
+ RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {}
+
+ RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End)
+ : StrData(Str), StartOffs(Start), EndOffs(End) {
+ StrData->addRef();
+ }
+ RopePiece(const RopePiece &RP)
+ : StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) {
+ StrData->addRef();
+ }
+
+ ~RopePiece() {
+ StrData->dropRef();
+ }
+
+ void operator=(const RopePiece &RHS) {
+ if (StrData != RHS.StrData) {
+ StrData->dropRef();
+ StrData = RHS.StrData;
+ StrData->addRef();
+ }
+ StartOffs = RHS.StartOffs;
+ EndOffs = RHS.EndOffs;
+ }
+
+ const char &operator[](unsigned Offset) const {
+ return StrData->Data[Offset+StartOffs];
+ }
+ char &operator[](unsigned Offset) {
+ return StrData->Data[Offset+StartOffs];
+ }
+
+ unsigned size() const { return EndOffs-StartOffs; }
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePieceBTreeIterator Class
+ //===--------------------------------------------------------------------===//
+
+ /// RopePieceBTreeIterator - This class provides read-only forward iteration
+ /// over bytes that are in a RopePieceBTree. This first iterates over bytes
+ /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf,
+ /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree.
+ class RopePieceBTreeIterator :
+ public forward_iterator<const char, ptrdiff_t> {
+ /// CurNode - The current B+Tree node that we are inspecting.
+ const void /*RopePieceBTreeLeaf*/ *CurNode;
+ /// CurPiece - The current RopePiece in the B+Tree node that we're
+ /// inspecting.
+ const RopePiece *CurPiece;
+ /// CurChar - The current byte in the RopePiece we are pointing to.
+ unsigned CurChar;
+ public:
+ // begin iterator.
+ RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N);
+ // end iterator
+ RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {}
+
+ char operator*() const {
+ return (*CurPiece)[CurChar];
+ }
+
+ bool operator==(const RopePieceBTreeIterator &RHS) const {
+ return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar;
+ }
+ bool operator!=(const RopePieceBTreeIterator &RHS) const {
+ return !operator==(RHS);
+ }
+
+ RopePieceBTreeIterator& operator++() { // Preincrement
+ if (CurChar+1 < CurPiece->size())
+ ++CurChar;
+ else
+ MoveToNextPiece();
+ return *this;
+ }
+ inline RopePieceBTreeIterator operator++(int) { // Postincrement
+ RopePieceBTreeIterator tmp = *this; ++*this; return tmp;
+ }
+ private:
+ void MoveToNextPiece();
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePieceBTree Class
+ //===--------------------------------------------------------------------===//
+
+ class RopePieceBTree {
+ void /*RopePieceBTreeNode*/ *Root;
+ void operator=(const RopePieceBTree &); // DO NOT IMPLEMENT
+ public:
+ RopePieceBTree();
+ RopePieceBTree(const RopePieceBTree &RHS);
+ ~RopePieceBTree();
+
+ typedef RopePieceBTreeIterator iterator;
+ iterator begin() const { return iterator(Root); }
+ iterator end() const { return iterator(); }
+ unsigned size() const;
+ unsigned empty() const { return size() == 0; }
+
+ void clear();
+
+ void insert(unsigned Offset, const RopePiece &R);
+
+ void erase(unsigned Offset, unsigned NumBytes);
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RewriteRope Class
+ //===--------------------------------------------------------------------===//
+
+/// RewriteRope - A powerful string class. This class supports extremely
+/// efficient insertions and deletions into the middle of it, even for
+/// ridiculously long strings.
+class RewriteRope {
+ RopePieceBTree Chunks;
+
+ /// We allocate space for string data out of a buffer of size AllocChunkSize.
+ /// This keeps track of how much space is left.
+ RopeRefCountString *AllocBuffer;
+ unsigned AllocOffs;
+ enum { AllocChunkSize = 4080 };
+
+public:
+ RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {}
+ RewriteRope(const RewriteRope &RHS)
+ : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) {
+ }
+
+ ~RewriteRope() {
+ // If we had an allocation buffer, drop our reference to it.
+ AllocBuffer->dropRef();
+ }
+
+ typedef RopePieceBTree::iterator iterator;
+ typedef RopePieceBTree::iterator const_iterator;
+ iterator begin() const { return Chunks.begin(); }
+ iterator end() const { return Chunks.end(); }
+ unsigned size() const { return Chunks.size(); }
+
+ void clear() {
+ Chunks.clear();
+ }
+
+ void assign(const char *Start, const char *End) {
+ clear();
+ if (Start != End)
+ Chunks.insert(0, MakeRopeString(Start, End));
+ }
+
+ void insert(unsigned Offset, const char *Start, const char *End) {
+ assert(Offset <= size() && "Invalid position to insert!");
+ if (Start == End) return;
+ Chunks.insert(Offset, MakeRopeString(Start, End));
+ }
+
+ void erase(unsigned Offset, unsigned NumBytes) {
+ assert(Offset+NumBytes <= size() && "Invalid region to erase!");
+ if (NumBytes == 0) return;
+ Chunks.erase(Offset, NumBytes);
+ }
+
+private:
+ RopePiece MakeRopeString(const char *Start, const char *End);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h
new file mode 100644
index 000000000000..c3ee0175c36f
--- /dev/null
+++ b/include/clang/Rewrite/Rewriter.h
@@ -0,0 +1,238 @@
+//===--- Rewriter.h - Code rewriting interface ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Rewriter class, which is used for code
+// transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_REWRITER_H
+#define LLVM_CLANG_REWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Rewrite/RewriteRope.h"
+#include <map>
+#include <vector>
+#include <cstring>
+#include <string>
+#include "clang/Rewrite/DeltaTree.h"
+
+namespace clang {
+ class SourceManager;
+ class LangOptions;
+ class Rewriter;
+ class Stmt;
+
+/// RewriteBuffer - As code is rewritten, SourceBuffer's from the original
+/// input with modifications get a new RewriteBuffer associated with them. The
+/// RewriteBuffer captures the modified text itself as well as information used
+/// to map between SourceLocation's in the original input and offsets in the
+/// RewriteBuffer. For example, if text is inserted into the buffer, any
+/// locations after the insertion point have to be mapped.
+class RewriteBuffer {
+ friend class Rewriter;
+ /// Deltas - Keep track of all the deltas in the source code due to insertions
+ /// and deletions.
+ DeltaTree Deltas;
+
+ /// Buffer - This is the actual buffer itself. Note that using a vector or
+ /// string is a horribly inefficient way to do this, we should use a rope
+ /// instead.
+ typedef RewriteRope BufferTy;
+ BufferTy Buffer;
+public:
+ typedef BufferTy::const_iterator iterator;
+ iterator begin() const { return Buffer.begin(); }
+ iterator end() const { return Buffer.end(); }
+ unsigned size() const { return Buffer.size(); }
+
+ /// RemoveText - Remove the specified text.
+ void RemoveText(unsigned OrigOffset, unsigned Size);
+
+ /// InsertText - Insert some text at the specified point, where the offset in
+ /// the buffer is specified relative to the original SourceBuffer. The
+ /// text is inserted after the specified location.
+ ///
+ void InsertText(unsigned OrigOffset, const char *StrData, unsigned StrLen,
+ bool InsertAfter = true);
+
+
+ /// InsertTextBefore - Insert some text before the specified point,
+ /// where the offset in the buffer is specified relative to the original
+ /// SourceBuffer.
+ ///
+ void InsertTextBefore(unsigned OrigOffset, const char *StrData,
+ unsigned StrLen) {
+ InsertText(OrigOffset, StrData, StrLen, false);
+ }
+
+ /// InsertText - Insert some text at the specified point, where the offset in
+ /// the buffer is specified relative to the original SourceBuffer. The
+ /// text is inserted after the specified location. This is method is the
+ /// same as InsertText with "InsertAfter == false".
+ void InsertTextAfter(unsigned OrigOffset, const char *StrData,
+ unsigned StrLen) {
+ InsertText(OrigOffset, StrData, StrLen);
+ }
+
+ /// ReplaceText - This method replaces a range of characters in the input
+ /// buffer with a new string. This is effectively a combined "remove/insert"
+ /// operation.
+ void ReplaceText(unsigned OrigOffset, unsigned OrigLength,
+ const char *NewStr, unsigned NewLength);
+
+private: // Methods only usable by Rewriter.
+
+ /// Initialize - Start this rewrite buffer out with a copy of the unmodified
+ /// input buffer.
+ void Initialize(const char *BufStart, const char *BufEnd) {
+ Buffer.assign(BufStart, BufEnd);
+ }
+
+ /// getMappedOffset - Given an offset into the original SourceBuffer that this
+ /// RewriteBuffer is based on, map it into the offset space of the
+ /// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a
+ /// position where text is inserted, the location returned will be after any
+ /// inserted text at the position.
+ unsigned getMappedOffset(unsigned OrigOffset,
+ bool AfterInserts = false) const{
+ return Deltas.getDeltaAt(2*OrigOffset+AfterInserts)+OrigOffset;
+ }
+
+ /// AddInsertDelta - When an insertion is made at a position, this
+ /// method is used to record that information.
+ void AddInsertDelta(unsigned OrigOffset, int Change) {
+ return Deltas.AddDelta(2*OrigOffset, Change);
+ }
+
+ /// AddReplaceDelta - When a replacement/deletion is made at a position, this
+ /// method is used to record that information.
+ void AddReplaceDelta(unsigned OrigOffset, int Change) {
+ return Deltas.AddDelta(2*OrigOffset+1, Change);
+ }
+};
+
+
+/// Rewriter - This is the main interface to the rewrite buffers. Its primary
+/// job is to dispatch high-level requests to the low-level RewriteBuffers that
+/// are involved.
+class Rewriter {
+ SourceManager *SourceMgr;
+ const LangOptions *LangOpts;
+ std::map<FileID, RewriteBuffer> RewriteBuffers;
+public:
+ explicit Rewriter(SourceManager &SM, const LangOptions &LO)
+ : SourceMgr(&SM), LangOpts(&LO) {}
+ explicit Rewriter() : SourceMgr(0), LangOpts(0) {}
+
+ void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
+ SourceMgr = &SM;
+ LangOpts = &LO;
+ }
+ SourceManager &getSourceMgr() { return *SourceMgr; }
+ const LangOptions &getLangOpts() { return *LangOpts; }
+
+ /// isRewritable - Return true if this location is a raw file location, which
+ /// is rewritable. Locations from macros, etc are not rewritable.
+ static bool isRewritable(SourceLocation Loc) {
+ return Loc.isFileID();
+ }
+
+ /// getRangeSize - Return the size in bytes of the specified range if they
+ /// are in the same file. If not, this returns -1.
+ int getRangeSize(SourceRange Range) const;
+
+ /// getRewritenText - Return the rewritten form of the text in the specified
+ /// range. If the start or end of the range was unrewritable or if they are
+ /// in different buffers, this returns an empty string.
+ ///
+ /// Note that this method is not particularly efficient.
+ ///
+ std::string getRewritenText(SourceRange Range) const;
+
+ /// InsertText - Insert the specified string at the specified location in the
+ /// original buffer. This method returns true (and does nothing) if the input
+ /// location was not rewritable, false otherwise.
+ bool InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
+ bool InsertAfter = true);
+
+ /// InsertTextAfter - Insert the specified string at the specified location in
+ /// the original buffer. This method returns true (and does nothing) if
+ /// the input location was not rewritable, false otherwise. Text is
+ /// inserted after any other text that has been previously inserted
+ /// at the some point (the default behavior for InsertText).
+ bool InsertTextAfter(SourceLocation Loc, const char *StrData,
+ unsigned StrLen) {
+ return InsertText(Loc, StrData, StrLen);
+ }
+
+ /// InsertText - Insert the specified string at the specified location in the
+ /// original buffer. This method returns true (and does nothing) if the input
+ /// location was not rewritable, false otherwise. Text is
+ /// inserted before any other text that has been previously inserted
+ /// at the some point.
+ bool InsertTextBefore(SourceLocation Loc, const char *StrData,
+ unsigned StrLen) {
+ return InsertText(Loc, StrData, StrLen, false);
+ }
+
+
+ bool InsertCStrBefore(SourceLocation Loc, const char* Str) {
+ return InsertTextBefore(Loc, Str, strlen(Str));
+ }
+
+
+ bool InsertCStrAfter(SourceLocation Loc, const char* Str) {
+ return InsertTextAfter(Loc, Str, strlen(Str));
+ }
+
+ bool InsertStrBefore(SourceLocation Loc, const std::string& S) {
+ return S.empty() ? false : InsertTextBefore(Loc, &S[0], S.size());
+ }
+
+ bool InsertStrAfter(SourceLocation Loc, const std::string& S) {
+ return S.empty() ? false : InsertTextAfter(Loc, &S[0], S.size());
+ }
+
+
+ /// RemoveText - Remove the specified text region.
+ bool RemoveText(SourceLocation Start, unsigned Length);
+
+ /// ReplaceText - This method replaces a range of characters in the input
+ /// buffer with a new string. This is effectively a combined "remove/insert"
+ /// operation.
+ bool ReplaceText(SourceLocation Start, unsigned OrigLength,
+ const char *NewStr, unsigned NewLength);
+
+ /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
+ /// printer to generate the replacement code. This returns true if the input
+ /// could not be rewritten, or false if successful.
+ bool ReplaceStmt(Stmt *From, Stmt *To);
+
+ /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
+ /// If no modification has been made to it, return null.
+ const RewriteBuffer *getRewriteBufferFor(FileID FID) const {
+ std::map<FileID, RewriteBuffer>::const_iterator I =
+ RewriteBuffers.find(FID);
+ return I == RewriteBuffers.end() ? 0 : &I->second;
+ }
+
+ /// getEditBuffer - This is like getRewriteBufferFor, but always returns a
+ /// buffer, and allows you to write on it directly. This is useful if you
+ /// want efficient low-level access to apis for scribbling on one specific
+ /// FileID's buffer.
+ RewriteBuffer &getEditBuffer(FileID FID);
+
+private:
+ unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Rewrite/TokenRewriter.h b/include/clang/Rewrite/TokenRewriter.h
new file mode 100644
index 000000000000..c8fd0f532c25
--- /dev/null
+++ b/include/clang/Rewrite/TokenRewriter.h
@@ -0,0 +1,79 @@
+//===--- TokenRewriter.h - Token-based Rewriter -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenRewriter class, which is used for code
+// transformations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOKENREWRITER_H
+#define LLVM_CLANG_TOKENREWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/OwningPtr.h"
+#include <list>
+#include <map>
+
+namespace clang {
+ class Token;
+ class LangOptions;
+ class ScratchBuffer;
+
+ class TokenRewriter {
+ /// TokenList - This is the list of raw tokens that make up this file. Each
+ /// of these tokens has a unique SourceLocation, which is a FileID.
+ std::list<Token> TokenList;
+
+ /// TokenRefTy - This is the type used to refer to a token in the TokenList.
+ typedef std::list<Token>::iterator TokenRefTy;
+
+ /// TokenAtLoc - This map indicates which token exists at a specific
+ /// SourceLocation. Since each token has a unique SourceLocation, this is a
+ /// one to one map. The token can return its own location directly, to map
+ /// backwards.
+ std::map<SourceLocation, TokenRefTy> TokenAtLoc;
+
+ /// ScratchBuf - This is the buffer that we create scratch tokens from.
+ ///
+ llvm::OwningPtr<ScratchBuffer> ScratchBuf;
+
+ TokenRewriter(const TokenRewriter&); // DO NOT IMPLEMENT
+ void operator=(const TokenRewriter&); // DO NOT IMPLEMENT.
+ public:
+ /// TokenRewriter - This creates a TokenRewriter for the file with the
+ /// specified FileID.
+ TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO);
+ ~TokenRewriter();
+
+ typedef std::list<Token>::const_iterator token_iterator;
+ token_iterator token_begin() const { return TokenList.begin(); }
+ token_iterator token_end() const { return TokenList.end(); }
+
+
+ token_iterator AddTokenBefore(token_iterator I, const char *Val);
+ token_iterator AddTokenAfter(token_iterator I, const char *Val) {
+ assert(I != token_end() && "Cannot insert after token_end()!");
+ return AddTokenBefore(++I, Val);
+ }
+
+ private:
+ /// RemapIterator - Convert from token_iterator (a const iterator) to
+ /// TokenRefTy (a non-const iterator).
+ TokenRefTy RemapIterator(token_iterator I);
+
+ /// AddToken - Add the specified token into the Rewriter before the other
+ /// position.
+ TokenRefTy AddToken(const Token &T, TokenRefTy Where);
+ };
+
+
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
new file mode 100644
index 000000000000..0f0d375e9c30
--- /dev/null
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -0,0 +1,56 @@
+//===--- ExternalSemaSource.h - External Sema Interface ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalSemaSource interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
+#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
+
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ExternalASTSource.h"
+
+namespace clang {
+
+class Sema;
+
+/// \brief An abstract interface that should be implemented by
+/// external AST sources that also provide information for semantic
+/// analysis.
+class ExternalSemaSource : public ExternalASTSource {
+public:
+ ExternalSemaSource() {
+ ExternalASTSource::SemaSource = true;
+ }
+
+ /// \brief Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S) {}
+
+ /// \brief Load the contents of the global method pool for a given
+ /// selector.
+ ///
+ /// \returns a pair of Objective-C methods lists containing the
+ /// instance and factory methods, respectively, with this selector.
+ virtual std::pair<ObjCMethodList, ObjCMethodList>
+ ReadMethodPool(Selector Sel) {
+ return std::pair<ObjCMethodList, ObjCMethodList>();
+ }
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ExternalASTSource *Source) {
+ return Source->SemaSource;
+ }
+ static bool classof(const ExternalSemaSource *) { return true; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Sema/ParseAST.h
new file mode 100644
index 000000000000..bdce5e95effb
--- /dev/null
+++ b/include/clang/Sema/ParseAST.h
@@ -0,0 +1,37 @@
+//===--- ParseAST.h - Define the ParseAST method ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the clang::ParseAST method.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PARSEAST_H
+#define LLVM_CLANG_SEMA_PARSEAST_H
+
+namespace clang {
+ class Preprocessor;
+ class ASTConsumer;
+ class ASTContext;
+
+ /// \brief Parse the entire file specified, notifying the ASTConsumer as
+ /// the file is parsed.
+ ///
+ /// This operation inserts the parsed decls into the translation
+ /// unit held by Ctx.
+ ///
+ /// \param CompleteTranslationUnit When true, the parsed file is
+ /// considered to be a complete translation unit, and any
+ /// end-of-translation-unit wrapup will be performed.
+ void ParseAST(Preprocessor &pp, ASTConsumer *C,
+ ASTContext &Ctx, bool PrintStats = false,
+ bool CompleteTranslationUnit = true);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Sema/SemaConsumer.h b/include/clang/Sema/SemaConsumer.h
new file mode 100644
index 000000000000..e821947035c4
--- /dev/null
+++ b/include/clang/Sema/SemaConsumer.h
@@ -0,0 +1,45 @@
+//===--- SemaConsumer.h - Abstract interface for AST semantics --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SemaConsumer class, a subclass of
+// ASTConsumer that is used by AST clients that also require
+// additional semantic analysis.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_SEMACONSUMER_H
+#define LLVM_CLANG_SEMA_SEMACONSUMER_H
+
+#include "clang/AST/ASTConsumer.h"
+
+namespace clang {
+ class Sema;
+
+ /// \brief An abstract interface that should be implemented by
+ /// clients that read ASTs and then require further semantic
+ /// analysis of the entities in those ASTs.
+ class SemaConsumer : public ASTConsumer {
+ public:
+ SemaConsumer() {
+ ASTConsumer::SemaConsumer = true;
+ }
+
+ /// \brief Initialize the semantic consumer with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S) {}
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ASTConsumer *Consumer) {
+ return Consumer->SemaConsumer;
+ }
+ static bool classof(const SemaConsumer *) { return true; }
+ };
+}
+
+#endif
diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h
new file mode 100644
index 000000000000..e215ed48fbe5
--- /dev/null
+++ b/include/clang/Sema/SemaDiagnostic.h
@@ -0,0 +1,27 @@
+//===--- DiagnosticSema.h - Diagnostics for libsema -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DIAGNOSTICSEMA_H
+#define LLVM_CLANG_DIAGNOSTICSEMA_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM,
+#define SEMASTART
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_SEMA_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif