diff options
110 files changed, 3682 insertions, 2721 deletions
diff --git a/include/clang/AST/CFG.h b/include/clang/AST/CFG.h deleted file mode 100644 index e60e58e..0000000 --- a/include/clang/AST/CFG.h +++ /dev/null @@ -1,408 +0,0 @@ -//===--- 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 <list> -#include <vector> -#include <cassert> - -namespace llvm { - class raw_ostream; -} -namespace clang { - class Stmt; - class Expr; - class CFG; - class PrinterHelper; - class BlockEdge; - class LangOptions; - -/// 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 LangOptions &LO) const; - void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const; - void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) 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 LangOptions &LO) const; - void print(llvm::raw_ostream& OS, const LangOptions &LO) const; - void dump(const LangOptions &LO) 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/DeclObjC.h b/include/clang/AST/DeclObjC.h index 13193ff..897776c 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -808,7 +808,7 @@ public: /// - myMethod; /// @end /// -/// Cateogries also allow you to split the implementation of a class across +/// Categories 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 diff --git a/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h b/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h deleted file mode 100644 index 007ec09..0000000 --- a/include/clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h +++ /dev/null @@ -1,28 +0,0 @@ -//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines AttrNonNullChecker, a builtin check in GRExprEngine that -// performs checks for arguments declared to have nonnull attribute. -// -//===----------------------------------------------------------------------===// - -#include "clang/Analysis/PathSensitive/CheckerVisitor.h" - -namespace clang { - -class AttrNonNullChecker : public CheckerVisitor<AttrNonNullChecker> { - BugType *BT; - -public: - AttrNonNullChecker() : BT(0) {} - static void *getTag(); - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); -}; - -} diff --git a/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h b/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h deleted file mode 100644 index 70f3c44..0000000 --- a/include/clang/Analysis/PathSensitive/Checkers/BadCallChecker.h +++ /dev/null @@ -1,30 +0,0 @@ -//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines BadCallChecker, a builtin check in GRExprEngine that performs -// checks for bad callee at call sites. -// -//===----------------------------------------------------------------------===// - -#include "clang/Analysis/PathSensitive/CheckerVisitor.h" - -namespace clang { - -class BadCallChecker : public CheckerVisitor<BadCallChecker> { - BuiltinBug *BT; - -public: - BadCallChecker() : BT(0) {} - - static void *getTag(); - - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); -}; - -} diff --git a/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h deleted file mode 100644 index 317e43a..0000000 --- a/include/clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h +++ /dev/null @@ -1,28 +0,0 @@ -//== DivZeroChecker.h - Division by zero checker ----------------*- C++ -*--==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines DivZeroChecker, a builtin check in GRExprEngine that performs -// checks for division by zeros. -// -//===----------------------------------------------------------------------===// - -#include "clang/Analysis/PathSensitive/CheckerVisitor.h" - -namespace clang { - -class DivZeroChecker : public CheckerVisitor<DivZeroChecker> { - BuiltinBug *BT; -public: - DivZeroChecker() : BT(0) {} - - static void *getTag(); - void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); -}; - -} diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h deleted file mode 100644 index 7f4e7d5..0000000 --- a/include/clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h +++ /dev/null @@ -1,34 +0,0 @@ -//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines BadCallChecker, a builtin check in GRExprEngine that performs -// checks for undefined arguments. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNDEFARGCHECKER -#define LLVM_CLANG_UNDEFARGCHECKER - -#include "clang/Analysis/PathSensitive/CheckerVisitor.h" - -namespace clang { - -class UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> { - BugType *BT; - -public: - UndefinedArgChecker() : BT(0) {} - - static void *getTag(); - - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); -}; - -} -#endif diff --git a/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h b/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h deleted file mode 100644 index b339b3d..0000000 --- a/include/clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h +++ /dev/null @@ -1,39 +0,0 @@ -//=== VLASizeChecker.h - Undefined dereference checker ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines two VLASizeCheckers, a builtin check in GRExprEngine that -// performs checks for declaration of VLA of undefined or zero size. -// -//===----------------------------------------------------------------------===// - -#include "clang/Analysis/PathSensitive/Checker.h" - -namespace clang { - -class UndefSizedVLAChecker : public Checker { - BugType *BT; - -public: - UndefSizedVLAChecker() : BT(0) {} - static void *getTag(); - ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, - const GRState *state, Stmt *S, GRExprEngine &Eng); -}; - -class ZeroSizedVLAChecker : public Checker { - BugType *BT; - -public: - ZeroSizedVLAChecker() : BT(0) {} - static void *getTag(); - ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, - const GRState *state, Stmt *S, GRExprEngine &Eng); -}; - -} diff --git a/include/clang/Analysis/Visitors/CFGVarDeclVisitor.h b/include/clang/Analysis/Visitors/CFGVarDeclVisitor.h deleted file mode 100644 index 1bc798f..0000000 --- a/include/clang/Analysis/Visitors/CFGVarDeclVisitor.h +++ /dev/null @@ -1,63 +0,0 @@ -//==- 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" - -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/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 3a70e13..00a5bc6 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -235,8 +235,8 @@ public: // Diagnostic characterization methods, used by a client to customize how // - DiagnosticClient *getClient() { return Client; }; - const DiagnosticClient *getClient() const { return Client; }; + DiagnosticClient *getClient() { return Client; } + const DiagnosticClient *getClient() const { return Client; } /// pushMappings - Copies the current DiagMappings and pushes the new copy diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 28c46cd..3a8c5bf 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -117,8 +117,6 @@ 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_pointer_to_member_type : Error< - "invalid use of pointer to member type 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">; @@ -201,6 +199,8 @@ 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_synthesized_property_name : Error< + "expected a property name in @synthesize">; def warn_semicolon_before_method_body : Warning< "semicolon before method body is ignored">, InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 78a3ae5..a864d8a 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -979,6 +979,8 @@ 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">; +def err_pointer_to_member_type : Error< + "invalid use of pointer to member type after %select{.*|->*}0">; // C++ template specialization def err_template_spec_unknown_kind : Error< @@ -1811,6 +1813,8 @@ def err_typecheck_bool_condition : Error< "value of type %0 is not contextually convertible to 'bool'">; def err_typecheck_ambiguous_condition : Error< "conversion from %0 to %1 is ambiguous">; +def err_typecheck_nonviable_condition : Error< + "no viable conversion from %0 to %1 is possible">; 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">; diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt index 39e3698..61d2bf6 100644 --- a/include/clang/CMakeLists.txt +++ b/include/clang/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(Basic) +add_subdirectory(Driver) diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index dcb6038..5263108 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -10,8 +10,7 @@ #ifndef CLANG_DRIVER_ARGLIST_H_ #define CLANG_DRIVER_ARGLIST_H_ -#include "clang/Driver/Options.h" - +#include "clang/Driver/OptSpecifier.h" #include "clang/Driver/Util.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -26,6 +25,7 @@ namespace llvm { namespace clang { namespace driver { class Arg; + class Option; /// ArgList - Ordered collection of driver arguments. /// @@ -77,20 +77,26 @@ namespace driver { /// 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 hasArgNoClaim(OptSpecifier Id) const { + return getLastArgNoClaim(Id) != 0; + } + bool hasArg(OptSpecifier Id) const { + return getLastArg(Id) != 0; + } + bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const { + return getLastArg(Id0, Id1) != 0; } - bool hasArg(options::ID Id0, options::ID Id1, bool Claim=true) const { - return getLastArg(Id0, Id1, Claim) != 0; + bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { + return getLastArg(Id0, Id1, Id2) != 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; - Arg *getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, - bool Claim=true) const; + Arg *getLastArgNoClaim(OptSpecifier Id) const; + Arg *getLastArg(OptSpecifier Id) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; @@ -102,24 +108,24 @@ namespace driver { /// 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; + bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; /// AddLastArg - Render only the last argument match \arg Id0, if /// present. - void AddLastArg(ArgStringList &Output, options::ID Id0) const; + void AddLastArg(ArgStringList &Output, OptSpecifier 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; + void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const; + void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const; + void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1, + OptSpecifier 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; + void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const; + void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const; /// AddAllArgsTranslated - Render all the arguments matching the /// given ids, but forced to separate args and using the provided @@ -127,13 +133,13 @@ namespace driver { /// /// \param Joined - If true, render the argument as joined with /// the option specifier. - void AddAllArgsTranslated(ArgStringList &Output, options::ID Id0, + void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, const char *Translation, bool Joined = false) const; /// ClaimAllArgs - Claim all arguments which match the given /// option id. - void ClaimAllArgs(options::ID Id0) const; + void ClaimAllArgs(OptSpecifier Id0) const; /// @} /// @name Arg Synthesis diff --git a/include/clang/Driver/CC1Options.h b/include/clang/Driver/CC1Options.h new file mode 100644 index 0000000..057022c --- /dev/null +++ b/include/clang/Driver/CC1Options.h @@ -0,0 +1,34 @@ +//===--- CC1Options.h - Clang CC1 Options 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_CC1OPTIONS_H +#define CLANG_DRIVER_CC1OPTIONS_H + +namespace clang { +namespace driver { + class OptTable; + +namespace cc1options { + 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/CC1Options.inc" + LastOption +#undef OPTION + }; +} + + OptTable *createCC1OptTable(); +} +} + +#endif diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td new file mode 100644 index 0000000..ef8d847 --- /dev/null +++ b/include/clang/Driver/CC1Options.td @@ -0,0 +1,26 @@ +//===--- CC1Options.td - Options for clang -cc1 ---------------------------===// +// +// 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 options accepted by clang -cc1. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "OptParser.td" + +// Target Options + +def target_abi : Separate<"-target-abi">, + HelpText<"Target a particular ABI type">; +def target_cpu : Separate<"-mcpu">, + HelpText<"Target a specific cpu type (-mcpu=help for details)">; +def target_features : Separate<"-target-feature">, + HelpText<"Target specific attributes">; +def target_triple : Separate<"-triple">, + HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt new file mode 100644 index 0000000..f720d15 --- /dev/null +++ b/include/clang/Driver/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LLVM_TARGET_DEFINITIONS Options.td) +tablegen(Options.inc + -gen-opt-parser-defs) +add_custom_target(ClangDriverOptions + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Options.inc) + +set(LLVM_TARGET_DEFINITIONS CC1Options.td) +tablegen(CC1Options.inc + -gen-opt-parser-defs) +add_custom_target(ClangCC1Options + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/CC1Options.inc) diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile new file mode 100644 index 0000000..c0f2cc7 --- /dev/null +++ b/include/clang/Driver/Makefile @@ -0,0 +1,16 @@ +LEVEL = ../../../../.. +BUILT_SOURCES = Options.inc CC1Options.inc + +TABLEGEN_INC_FILES_COMMON = 1 + +include $(LEVEL)/Makefile.common + +$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(ObjDir)/.dir + $(Echo) "Building Clang Driver Option tables with tblgen" + $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< + +$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(ObjDir)/.dir + $(Echo) "Building Clang CC1 Option tables with tblgen" + $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< + + diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td new file mode 100644 index 0000000..70b59c6 --- /dev/null +++ b/include/clang/Driver/OptParser.td @@ -0,0 +1,116 @@ +//===--- OptParser.td - Common Option Parsing Interfaces ------------------===// +// +// 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 common interfaces used by the option parsing TableGen +// backend. +// +//===----------------------------------------------------------------------===// + +// Define the kinds of options. + +class OptionKind<string name, int predecence = 0> { + string Name = name; + // The kind precedence, kinds with lower precedence are matched first. + int Precedence = predecence; +} + +// An option group. +def KIND_GROUP : OptionKind<"Group">; +// A flag with no values. +def KIND_FLAG : OptionKind<"Flag">; +// An option which prefixes its (single) value. +def KIND_JOINED : OptionKind<"Joined", 1>; +// An option which is followed by its value. +def KIND_SEPARATE : OptionKind<"Separate">; +// An option followed by its values, which are separated by commas. +def KIND_COMMAJOINED : OptionKind<"CommaJoined">; +// An option which is which takes multiple (separate) arguments. +def KIND_MULTIARG : OptionKind<"MultiArg">; +// An option which is either joined to its (non-empty) value, or followed by its +// value. +def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">; +// An option which is both joined to its (first) value, and followed by its +// (second) value. +def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">; + +// Define the option flags. + +class OptionFlag {} + +// DriverOption - The option is a "driver" option, and should not be forwarded +// to gcc. +def DriverOption : OptionFlag; + +// LinkerInput - The option is a linker input. +def LinkerInput : OptionFlag; + +// NoArgumentUnused - 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. +def NoArgumentUnused : OptionFlag; + +// RenderAsInput - The option should not render the name when rendered as an +// input (i.e., the option is rendered as values). +def RenderAsInput : OptionFlag; + +// RenderJoined - The option should be rendered joined, even if separate (only +// sensible on single value separate options). +def RenderJoined : OptionFlag; + +// RenderSeparate - The option should be rendered separately, even if joined +// (only sensible on joined options). +def RenderSeparate : OptionFlag; + +// Unsupported - The option is unsupported, and the driver will reject command +// lines that use it. +def Unsupported : OptionFlag; + +// Define the option group class. + +class OptionGroup<string name> { + string EnumName = ?; // Uses the def name if undefined. + string Name = name; + OptionGroup Group = ?; +} + +// Define the option class. + +class Option<string name, OptionKind kind> { + string EnumName = ?; // Uses the def name if undefined. + string Name = name; + OptionKind Kind = kind; + // Used by MultiArg option kind. + int NumArgs = 0; + string HelpText = ?; + string MetaVarName = ?; + list<OptionFlag> Flags = []; + OptionGroup Group = ?; + Option Alias = ?; +} + +// Helpers for defining options. + +class Flag<string name> : Option<name, KIND_FLAG>; +class Joined<string name> : Option<name, KIND_JOINED>; +class Separate<string name> : Option<name, KIND_SEPARATE>; +class CommaJoined<string name> : Option<name, KIND_COMMAJOINED>; +class MultiArg<string name, int numargs> : Option<name, KIND_MULTIARG> { + int NumArgs = numargs; +} +class JoinedOrSeparate<string name> : Option<name, KIND_JOINED_OR_SEPARATE>; +class JoinedAndSeparate<string name> : Option<name, KIND_JOINED_AND_SEPARATE>; + +// Mix-ins for adding optional attributes. + +class Alias<Option alias> { Option Alias = alias; } +class EnumName<string name> { string EnumName = name; } +class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; } +class Group<OptionGroup group> { OptionGroup Group = group; } +class HelpText<string text> { string HelpText = text; } +class MetaVarName<string name> { string MetaVarName = name; } diff --git a/include/clang/Driver/OptSpecifier.h b/include/clang/Driver/OptSpecifier.h new file mode 100644 index 0000000..c38b36c --- /dev/null +++ b/include/clang/Driver/OptSpecifier.h @@ -0,0 +1,36 @@ +//===--- OptSpecifier.h - Option Specifiers ---------------------*- 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_OPTSPECIFIER_H +#define CLANG_DRIVER_OPTSPECIFIER_H + +namespace clang { +namespace driver { + class Option; + + /// OptSpecifier - Wrapper class for abstracting references to option IDs. + class OptSpecifier { + unsigned ID; + + private: + explicit OptSpecifier(bool); // DO NOT IMPLEMENT + + public: + /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {} + /*implicit*/ OptSpecifier(const Option *Opt); + + unsigned getID() const { return ID; } + + bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } + bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); } + }; +} +} + +#endif diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h new file mode 100644 index 0000000..faaeba6 --- /dev/null +++ b/include/clang/Driver/OptTable.h @@ -0,0 +1,163 @@ +//===--- OptTable.h - Option 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_OPTTABLE_H +#define CLANG_DRIVER_OPTTABLE_H + +#include "clang/Driver/OptSpecifier.h" +#include <cassert> + +namespace clang { +namespace driver { +namespace options { + enum DriverFlag { + DriverOption = (1 << 0), + LinkerInput = (1 << 1), + NoArgumentUnused = (1 << 2), + RenderAsInput = (1 << 3), + RenderJoined = (1 << 4), + RenderSeparate = (1 << 5), + Unsupported = (1 << 6) + }; +} + + 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 convenient. + class OptTable { + public: + /// Info - Entry for a single option instance in the option data table. + struct Info { + const char *Name; + const char *HelpText; + const char *MetaVar; + unsigned char Kind; + unsigned char Flags; + unsigned char Param; + unsigned short GroupID; + unsigned short AliasID; + }; + + private: + /// The static option information table. + const Info *OptionInfos; + unsigned NumOptionInfos; + + /// The lazily constructed options table, indexed by option::ID - 1. + mutable Option **Options; + + /// Prebound input option instance. + const Option *TheInputOption; + + /// Prebound unknown option instance. + const Option *TheUnknownOption; + + /// 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 FirstSearchableIndex; + + private: + const Info &getInfo(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID."); + return OptionInfos[id - 1]; + } + + Option *CreateOption(unsigned id) const; + + protected: + OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos); + public: + ~OptTable(); + + /// getNumOptions - Return the total number of option classes. + unsigned getNumOptions() const { return NumOptionInfos; } + + /// getOption - Get the given \arg id's Option instance, lazily creating it + /// if necessary. + /// + /// \return The option, or null for the INVALID option id. + const Option *getOption(OptSpecifier Opt) const { + unsigned id = Opt.getID(); + if (id == 0) + return 0; + + assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); + Option *&Entry = Options[id - 1]; + if (!Entry) + Entry = CreateOption(id); + return Entry; + } + + /// getOptionName - Lookup the name of the given option. + const char *getOptionName(OptSpecifier id) const { + return getInfo(id).Name; + } + + /// getOptionKind - Get the kind of the given option. + unsigned getOptionKind(OptSpecifier id) const { + return getInfo(id).Kind; + } + + /// getOptionHelpText - Get the help text to use to describe this option. + const char *getOptionHelpText(OptSpecifier id) const { + return getInfo(id).HelpText; + } + + /// getOptionMetaVar - Get the meta-variable name to use when describing + /// this options values in the help text. + const char *getOptionMetaVar(OptSpecifier id) const { + return getInfo(id).MetaVar; + } + + /// 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; + + /// ParseArgs - Parse an list of arguments into an InputArgList. + /// + /// The resulting InputArgList will reference the strings in [ArgBegin, + /// ArgEnd), and their lifetime should extend past that of the returned + /// InputArgList. + /// + /// The only error that can occur in this routine is if an argument is + /// missing values; in this case \arg MissingArgCount will be non-zero. + /// + /// \param ArgBegin - The beginning of the argument vector. + /// \param ArgEnd - The end of the argument vector. + /// \param MissingArgIndex - On error, the index of the option which could + /// not be parsed. + /// \param MissingArgCount - On error, the number of missing options. + /// \return - An InputArgList; on error this will contain all the options + /// which could be parsed. + InputArgList *ParseArgs(const char **ArgBegin, + const char **ArgEnd, + unsigned &MissingArgIndex, + unsigned &MissingArgCount) const; + }; +} +} + +#endif diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index c70b648..08b94b1 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -10,8 +10,7 @@ #ifndef CLANG_DRIVER_OPTION_H_ #define CLANG_DRIVER_OPTION_H_ -#include "Options.h" - +#include "clang/Driver/OptSpecifier.h" #include "llvm/Support/Casting.h" using llvm::isa; using llvm::cast; @@ -54,7 +53,8 @@ namespace driver { private: OptionClass Kind; - options::ID ID; + /// The option ID. + OptSpecifier ID; /// The option name. const char *Name; @@ -89,12 +89,12 @@ namespace driver { bool NoArgumentUnused : 1; protected: - Option(OptionClass Kind, options::ID ID, const char *Name, + Option(OptionClass Kind, OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); public: virtual ~Option(); - options::ID getId() const { return ID; } + unsigned getID() const { return ID.getID(); } OptionClass getKind() const { return Kind; } const char *getName() const { return Name; } const OptionGroup *getGroup() const { return Group; } @@ -138,8 +138,11 @@ namespace driver { /// 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; + /// + /// Note that matches against options which are an alias should never be + /// done -- aliases do not participate in matching and so such a query will + /// always be false. + bool matches(OptSpecifier ID) const; /// accept - Potentially accept the current argument, returning a /// new Arg instance, or 0 if the option does not accept this @@ -159,7 +162,7 @@ namespace driver { /// by the driver. class OptionGroup : public Option { public: - OptionGroup(options::ID ID, const char *Name, const OptionGroup *Group); + OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -174,7 +177,7 @@ namespace driver { /// InputOption - Dummy option class for representing driver inputs. class InputOption : public Option { public: - InputOption(); + InputOption(OptSpecifier ID); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -187,7 +190,7 @@ namespace driver { /// UnknownOption - Dummy option class for represent unknown arguments. class UnknownOption : public Option { public: - UnknownOption(); + UnknownOption(OptSpecifier ID); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -201,7 +204,7 @@ namespace driver { class FlagOption : public Option { public: - FlagOption(options::ID ID, const char *Name, const OptionGroup *Group, + FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -214,7 +217,7 @@ namespace driver { class JoinedOption : public Option { public: - JoinedOption(options::ID ID, const char *Name, const OptionGroup *Group, + JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -227,8 +230,8 @@ namespace driver { class SeparateOption : public Option { public: - SeparateOption(options::ID ID, const char *Name, const OptionGroup *Group, - const Option *Alias); + SeparateOption(OptSpecifier ID, const char *Name, + const OptionGroup *Group, const Option *Alias); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -240,7 +243,7 @@ namespace driver { class CommaJoinedOption : public Option { public: - CommaJoinedOption(options::ID ID, const char *Name, + CommaJoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -259,7 +262,7 @@ namespace driver { unsigned NumArgs; public: - MultiArgOption(options::ID ID, const char *Name, const OptionGroup *Group, + MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias, unsigned NumArgs); unsigned getNumArgs() const { return NumArgs; } @@ -276,7 +279,7 @@ namespace driver { /// prefixes its (non-empty) value, or is follwed by a value. class JoinedOrSeparateOption : public Option { public: - JoinedOrSeparateOption(options::ID ID, const char *Name, + JoinedOrSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; @@ -291,7 +294,7 @@ namespace driver { /// value and is followed by another value. class JoinedAndSeparateOption : public Option { public: - JoinedAndSeparateOption(options::ID ID, const char *Name, + JoinedAndSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def deleted file mode 100644 index 2b66b35..0000000 --- a/include/clang/Driver/Options.def +++ /dev/null @@ -1,661 +0,0 @@ -//===--- 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-undefined", _no_undefined, Flag, INVALID, INVALID, "l", 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("--relocatable-pch", _relocatable_pch, Flag, INVALID, INVALID, "", 0, - "Build a relocatable precompiled header", 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("--signed-char", _signed_char, Flag, INVALID, fsigned_char, "", 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("--unsigned-char", _unsigned_char, Flag, INVALID, funsigned_char, "", 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_errors_fatal", arch__errors__fatal, Flag, INVALID, 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-ast", emit_ast, Flag, INVALID, INVALID, "", 0, - "Emit Clang AST files for source inputs", 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("-fblock-introspection", fblock_introspection, 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-strcat", fbuiltin_strcat, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fbuiltin-strcpy", fbuiltin_strcpy, Flag, 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("-fcolor-diagnostics", fcolor_diagnostics, Flag, 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("-fconstant-string-class=", fconstant_string_class_EQ, Joined, 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("-fmerge-all-constants", fmerge_all_constants, 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-strcat", fno_builtin_strcat, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-builtin-strcpy", fno_builtin_strcpy, 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-color-diagnostics", fno_color_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-exceptions", fno_exceptions, 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-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-ms-extensions", fno_ms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-show-column", fno_show_column, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-show-source-location", fno_show_source_location, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-stack-protector", fno_stack_protector, Flag, 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", 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("-frtti", frtti, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fshort-wchar", fshort_wchar, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fstack-protector-all", fstack_protector_all, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fstack-protector", fstack_protector, Flag, 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("-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("-funsigned-char", funsigned_char, 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("-mabi=", mabi_EQ, Joined, m_Group, INVALID, "d", 0, 0, 0) -OPTION("-march=", march_EQ, Joined, m_Group, INVALID, "d", 0, 0, 0) -OPTION("-mcmodel=", mcmodel_EQ, Joined, m_Group, INVALID, "d", 0, 0, 0) -OPTION("-mconstant-cfstrings", mconstant_cfstrings, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0) -OPTION("-mcpu=", mcpu_EQ, Joined, m_Group, INVALID, "d", 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("-mfloat-abi=", mfloat_abi_EQ, Joined, m_Group, INVALID, "", 0, 0, 0) -OPTION("-mhard-float", mhard_float, Flag, 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("-mllvm", mllvm, Separate, INVALID, 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-thumb", mno_thumb, Flag, m_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("-mthumb", mthumb, Flag, m_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("-nobuiltininc", nobuiltininc, 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, "", 0, 0, 0) -OPTION("-print-multi-lib", print_multi_lib, Flag, INVALID, INVALID, "", 0, 0, 0) -OPTION("-print-multi-os-directory", print_multi_os_directory, Flag, INVALID, INVALID, "", 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("-rpath", rpath, Separate, INVALID, INVALID, "l", 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 index 7fcaf3f..b05d5af 100644 --- a/include/clang/Driver/Options.h +++ b/include/clang/Driver/Options.h @@ -7,11 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_OPTIONS_H_ -#define CLANG_DRIVER_OPTIONS_H_ +#ifndef CLANG_DRIVER_OPTIONS_H +#define CLANG_DRIVER_OPTIONS_H namespace clang { namespace driver { + class OptTable; + namespace options { enum ID { OPT_INVALID = 0, // This is not an option ID. @@ -19,71 +21,13 @@ namespace options { 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" +#include "clang/Driver/Options.inc" 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; - }; + OptTable *createDriverOptTable(); } } diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td new file mode 100644 index 0000000..ace1a3c --- /dev/null +++ b/include/clang/Driver/Options.td @@ -0,0 +1,607 @@ +//===--- DriverOptions.td - Options for clang -----------------------------===// +// +// 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 options accepted by clang. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "OptParser.td" + +///////// +// Groups + +def I_Group : OptionGroup<"<I group>">; +def M_Group : OptionGroup<"<M group>">; +def T_Group : OptionGroup<"<T group>">; +def O_Group : OptionGroup<"<O group>">; +def W_Group : OptionGroup<"<W group>">; +def X_Group : OptionGroup<"<X group>">; +def a_Group : OptionGroup<"<a group>">; +def d_Group : OptionGroup<"<d group>">; +def f_Group : OptionGroup<"<f group>">; +def g_Group : OptionGroup<"<g group>">; +def i_Group : OptionGroup<"<i group>">; +def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>; +def m_Group : OptionGroup<"<m group>">; +def m_x86_Features_Group : OptionGroup<"<m x86 features group>">; +def u_Group : OptionGroup<"<u group>">; + +def pedantic_Group : OptionGroup<"<pedantic group>">; + +// Temporary groups for clang options which we know we don't support, +// but don't want to verbosely warn the user about. +def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">, + Group<f_Group>; +def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">, + Group<m_Group>; + +///////// +// Options + +// The internal option ID 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 + +def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>, + HelpText<"Print the commands to run for this compilation">; +def A : JoinedOrSeparate<"-A">; +def B : JoinedOrSeparate<"-B">, Flags<[Unsupported]>; +def CC : Flag<"-CC">; +def C : Flag<"-C">; +def D : JoinedOrSeparate<"-D">; +def E : Flag<"-E">, Flags<[DriverOption]>, + HelpText<"Only run the preprocessor">; +def F : JoinedOrSeparate<"-F">; +def H : Flag<"-H">; +def I_ : Flag<"-I-">, Group<I_Group>; +def I : JoinedOrSeparate<"-I">, Group<I_Group>; +def L : JoinedOrSeparate<"-L">; +def MD : Flag<"-MD">, Group<M_Group>; +def MF : JoinedOrSeparate<"-MF">, Group<M_Group>; +def MG : Flag<"-MG">, Group<M_Group>; +def MMD : Flag<"-MMD">, Group<M_Group>; +def MM : Flag<"-MM">, Group<M_Group>; +def MP : Flag<"-MP">, Group<M_Group>; +def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>; +def MT : JoinedOrSeparate<"-MT">, Group<M_Group>; +def Mach : Flag<"-Mach">; +def M : Flag<"-M">, Group<M_Group>; +def O4 : Joined<"-O4">, Group<O_Group>; +def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>, + HelpText<"Treat source input files as Objective-C++ inputs">; +def ObjC : Flag<"-ObjC">, Flags<[DriverOption]>, + HelpText<"Treat source input files as Objective-C inputs">; +def O : Joined<"-O">, Group<O_Group>; +def P : Flag<"-P">; +def Qn : Flag<"-Qn">; +def Qunused_arguments : Flag<"-Qunused-arguments">, Flags<[DriverOption]>, + HelpText<"Don't emit warning for unused driver arguments">; +def Q : Flag<"-Q">; +def R : Flag<"-R">; +def S : Flag<"-S">, Flags<[DriverOption]>, + HelpText<"Only run preprocess and compilation steps">; +def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>; +def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>; +def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>; +def T : JoinedOrSeparate<"-T">, Group<T_Group>; +def U : JoinedOrSeparate<"-U">; +def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>; +def Wa_COMMA : CommaJoined<"-Wa,">, + HelpText<"Pass the comma separated arguments in <arg> to the assembler">, + MetaVarName<"<arg>">; +def Wall : Flag<"-Wall">, Group<W_Group>; +def Wextra : Flag<"-Wextra">, Group<W_Group>; +def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>, + HelpText<"Pass the comma separated arguments in <arg> to the linker">, + MetaVarName<"<arg>">; +def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>; +def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>; +def Wp_COMMA : CommaJoined<"-Wp,">, + HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">, + MetaVarName<"<arg>">; +def W_Joined : Joined<"-W">, Group<W_Group>; +def Xanalyzer : Separate<"-Xanalyzer">, + HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">; +def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>; +def Xassembler : Separate<"-Xassembler">, + HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">; +def Xclang : Separate<"-Xclang">, + HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">; +def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>, + HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">; +def Xpreprocessor : Separate<"-Xpreprocessor">, + HelpText<"Pass <arg> to the preprocessor">, MetaVarName<"<arg>">; +def X_Flag : Flag<"-X">; +def X_Joined : Joined<"-X">; +def Z_Flag : Flag<"-Z">; +def Z_Joined : Joined<"-Z">; +def all__load : Flag<"-all_load">; +def allowable__client : Separate<"-allowable_client">; +def ansi : Flag<"-ansi">, Group<a_Group>; +def arch__errors__fatal : Flag<"-arch_errors_fatal">; +def arch : Separate<"-arch">, Flags<[DriverOption]>; +def a : Joined<"-a">, Group<a_Group>; +def bind__at__load : Flag<"-bind_at_load">; +def bundle__loader : Separate<"-bundle_loader">; +def bundle : Flag<"-bundle">; +def b : JoinedOrSeparate<"-b">, Flags<[Unsupported]>; +def client__name : JoinedOrSeparate<"-client_name">; +def combine : Flag<"-combine">, Flags<[DriverOption, Unsupported]>; +def compatibility__version : JoinedOrSeparate<"-compatibility_version">; +def coverage : Flag<"-coverage">; +def cpp_precomp : Flag<"-cpp-precomp">; +def current__version : JoinedOrSeparate<"-current_version">; +def c : Flag<"-c">, Flags<[DriverOption]>, + HelpText<"Only run preprocess, compile, and assemble steps">; +def dA : Flag<"-dA">, Group<d_Group>; +def dD : Flag<"-dD">, Group<d_Group>; +def dM : Flag<"-dM">, Group<d_Group>; +def dead__strip : Flag<"-dead_strip">; +def dependency_file : Separate<"-dependency-file">; +def dumpmachine : Flag<"-dumpmachine">, Flags<[Unsupported]>; +def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>; +def dumpversion : Flag<"-dumpversion">; +def dylib__file : Separate<"-dylib_file">; +def dylinker__install__name : JoinedOrSeparate<"-dylinker_install_name">; +def dylinker : Flag<"-dylinker">; +def dynamiclib : Flag<"-dynamiclib">; +def dynamic : Flag<"-dynamic">, Flags<[NoArgumentUnused]>; +def d_Flag : Flag<"-d">, Group<d_Group>; +def d_Joined : Joined<"-d">, Group<d_Group>; +def emit_ast : Flag<"-emit-ast">, + HelpText<"Emit Clang AST files for source inputs">; +def emit_llvm : Flag<"-emit-llvm">, + HelpText<"Use the LLVM representation for assembler and object files">; +def exported__symbols__list : Separate<"-exported_symbols_list">; +def e : JoinedOrSeparate<"-e">; +def fPIC : Flag<"-fPIC">, Group<f_Group>; +def fPIE : Flag<"-fPIE">, Group<f_Group>; +def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>; +def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>; +def fastcp : Flag<"-fastcp">, Group<f_Group>; +def fastf : Flag<"-fastf">, Group<f_Group>; +def fast : Flag<"-fast">, Group<f_Group>; +def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>; +def fblock_introspection : Flag<"-fblock-introspection">, Group<f_Group>; +def fblocks : Flag<"-fblocks">, Group<f_Group>; +def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; +def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; +def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>; +def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>; +def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>; +def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>; +def fcommon : Flag<"-fcommon">, Group<f_Group>; +def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>; +def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<clang_ignored_f_Group>; +def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Group>; +def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; +def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; +def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; +def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>; +def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>; +def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; +def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>; +def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>; +def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>; +def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>; +def fexceptions : Flag<"-fexceptions">, Group<f_Group>; +def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; +def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; +def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; +def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; +def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; +def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Group<f_Group>; +def finline_functions : Flag<"-finline-functions">, Group<clang_ignored_f_Group>; +def finline : Flag<"-finline">, Group<clang_ignored_f_Group>; +def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>; +def flat__namespace : Flag<"-flat_namespace">; +def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>; +def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>; +def flto : Flag<"-flto">, Group<f_Group>; +def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; +def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>; +def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>; +def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>; +def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>; +def fmudflap : Flag<"-fmudflap">, Group<f_Group>; +def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>; +def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>; +def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>; +def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>; +def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>; +def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>; +def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>; +def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>; +def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group<f_Group>; +def fno_common : Flag<"-fno-common">, Group<f_Group>; +def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>; +def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>; +def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>; +def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; +def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; +def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; +def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>; +def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>; +def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>; +def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; +def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; +def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>; +def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>; +def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>; +def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>; +def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>; +def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>; +def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; +def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<clang_ignored_f_Group>; +def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; +def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; +def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; +def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; +def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; +def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; +def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; +def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>; +def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>; +def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>; +def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group<f_Group>; +def fobjc : Flag<"-fobjc">, Group<f_Group>; +def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>; +def fopenmp : Flag<"-fopenmp">, Group<f_Group>; +def force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">; +def force__flat__namespace : Flag<"-force_flat_namespace">; +def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group<f_Group>; +def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>; +def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>; +def fpic : Flag<"-fpic">, Group<f_Group>; +def fpie : Flag<"-fpie">, Group<f_Group>; +def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>; +def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>; +def framework : Separate<"-framework">, Flags<[LinkerInput]>; +def frtti : Flag<"-frtti">, Group<f_Group>; +def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>; +def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>; +def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>; +def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>; +def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>; +def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>; +def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<clang_ignored_f_Group>; +def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; +def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; +def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>; +def ftime_report : Flag<"-ftime-report">, Group<f_Group>; +def ftrapv : Flag<"-ftrapv">, Group<f_Group>; +def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; +def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>; +def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>; +def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>; +def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; +def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; +def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; +def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>; +def f : Joined<"-f">, Group<f_Group>; +def g0 : Joined<"-g0">, Group<g_Group>; +def g3 : Joined<"-g3">, Group<g_Group>; +def gfull : Joined<"-gfull">, Group<g_Group>; +def gstabs : Joined<"-gstabs">, Group<g_Group>; +def gused : Joined<"-gused">, Group<g_Group>; +def g_Flag : Flag<"-g">, Group<g_Group>; +def g_Joined : Joined<"-g">, Group<g_Group>; +def headerpad__max__install__names : Joined<"-headerpad_max_install_names">; +def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>; +def iframework : JoinedOrSeparate<"-iframework">, Group<clang_i_Group>; +def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>; +def image__base : Separate<"-image_base">; +def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">; +def init : Separate<"-init">; +def install__name : Separate<"-install_name">; +def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>; +def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>; +def isysroot : JoinedOrSeparate<"-isysroot">, Group<i_Group>; +def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>; +def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>; +def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>; +def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<i_Group>; +def i : Joined<"-i">, Group<i_Group>; +def keep__private__externs : Flag<"-keep_private_externs">; +def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput]>; +def m32 : Flag<"-m32">, Group<m_Group>, Flags<[DriverOption]>; +def m3dnowa : Flag<"-m3dnowa">, Group<m_x86_Features_Group>; +def m3dnow : Flag<"-m3dnow">, Group<m_x86_Features_Group>; +def m64 : Flag<"-m64">, Group<m_Group>, Flags<[DriverOption]>; +def mabi_EQ : Joined<"-mabi=">, Group<m_Group>, Flags<[DriverOption]>; +def march_EQ : Joined<"-march=">, Group<m_Group>, Flags<[DriverOption]>; +def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>, Flags<[DriverOption]>; +def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>; +def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>, Flags<[DriverOption]>; +def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>; +def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>; +def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; +def mhard_float : Flag<"-mhard-float">, Group<m_Group>; +def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>; +def mkernel : Flag<"-mkernel">, Group<m_Group>; +def mllvm : Separate<"-mllvm">; +def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>; +def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>; +def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>; +def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>; +def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group<m_Group>; +def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>; +def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>; +def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>; +def mno_soft_float : Flag<"-mno-soft-float">, Group<m_Group>; +def mno_sse2 : Flag<"-mno-sse2">, Group<m_x86_Features_Group>; +def mno_sse3 : Flag<"-mno-sse3">, Group<m_x86_Features_Group>; +def mno_sse4a : Flag<"-mno-sse4a">, Group<m_x86_Features_Group>; +def mno_sse4 : Flag<"-mno-sse4">, Group<m_x86_Features_Group>; +def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>; +def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; +def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; +def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>; +def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; +def mred_zone : Flag<"-mred-zone">, Group<m_Group>; +def msoft_float : Flag<"-msoft-float">, Group<m_Group>; +def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>; +def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>; +def msse4a : Flag<"-msse4a">, Group<m_x86_Features_Group>; +def msse4 : Flag<"-msse4">, Group<m_x86_Features_Group>; +def msse : Flag<"-msse">, Group<m_x86_Features_Group>; +def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>; +def mthumb : Flag<"-mthumb">, Group<m_Group>; +def mtune_EQ : Joined<"-mtune=">, Group<m_Group>; +def multi__module : Flag<"-multi_module">; +def multiply__defined__unused : Separate<"-multiply_defined_unused">; +def multiply__defined : Separate<"-multiply_defined">; +def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group<m_Group>; +def m_Separate : Separate<"-m">, Group<m_Group>; +def m_Joined : Joined<"-m">, Group<m_Group>; +def no_cpp_precomp : Flag<"-no-cpp-precomp">; +def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; +def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; +def nobuiltininc : Flag<"-nobuiltininc">; +def nodefaultlibs : Flag<"-nodefaultlibs">; +def nofixprebinding : Flag<"-nofixprebinding">; +def nolibc : Flag<"-nolibc">; +def nomultidefs : Flag<"-nomultidefs">; +def noprebind : Flag<"-noprebind">; +def noseglinkedit : Flag<"-noseglinkedit">; +def nostartfiles : Flag<"-nostartfiles">; +def nostdinc : Flag<"-nostdinc">; +def nostdlib : Flag<"-nostdlib">; +def object : Flag<"-object">; +def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>, + HelpText<"Write output to <file>">, MetaVarName<"<file>">; +def pagezero__size : JoinedOrSeparate<"-pagezero_size">; +def pass_exit_codes : Flag<"-pass-exit-codes">, Flags<[Unsupported]>; +def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>; +def pedantic : Flag<"-pedantic">, Group<pedantic_Group>; +def pg : Flag<"-pg">; +def pipe : Flag<"-pipe">, + HelpText<"Use pipes between commands, when possible">; +def prebind__all__twolevel__modules : Flag<"-prebind_all_twolevel_modules">; +def prebind : Flag<"-prebind">; +def preload : Flag<"-preload">; +def print_file_name_EQ : Joined<"-print-file-name=">, + HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">; +def print_ivar_layout : Flag<"-print-ivar-layout">; +def print_libgcc_file_name : Flag<"-print-libgcc-file-name">, + HelpText<"Print the library path for \"libgcc.a\"">; +def print_multi_directory : Flag<"-print-multi-directory">; +def print_multi_lib : Flag<"-print-multi-lib">; +def print_multi_os_directory : Flag<"-print-multi-os-directory">; +def print_prog_name_EQ : Joined<"-print-prog-name=">, + HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">; +def print_search_dirs : Flag<"-print-search-dirs">, + HelpText<"Print the paths used for finding libraries and programs">; +def private__bundle : Flag<"-private_bundle">; +def pthreads : Flag<"-pthreads">; +def pthread : Flag<"-pthread">; +def p : Flag<"-p">; +def read__only__relocs : Separate<"-read_only_relocs">; +def remap : Flag<"-remap">; +def rpath : Separate<"-rpath">, Flags<[LinkerInput]>; +def r : Flag<"-r">; +def save_temps : Flag<"-save-temps">, Flags<[DriverOption]>, + HelpText<"Save intermediate compilation results">; +def sectalign : MultiArg<"-sectalign", 3>; +def sectcreate : MultiArg<"-sectcreate", 3>; +def sectobjectsymbols : MultiArg<"-sectobjectsymbols", 2>; +def sectorder : MultiArg<"-sectorder", 3>; +def seg1addr : JoinedOrSeparate<"-seg1addr">; +def seg__addr__table__filename : Separate<"-seg_addr_table_filename">; +def seg__addr__table : Separate<"-seg_addr_table">; +def segaddr : MultiArg<"-segaddr", 2>; +def segcreate : MultiArg<"-segcreate", 3>; +def seglinkedit : Flag<"-seglinkedit">; +def segprot : MultiArg<"-segprot", 3>; +def segs__read__only__addr : Separate<"-segs_read_only_addr">; +def segs__read__write__addr : Separate<"-segs_read_write_addr">; +def segs__read__ : Joined<"-segs_read_">; +def shared_libgcc : Flag<"-shared-libgcc">; +def shared : Flag<"-shared">; +def single__module : Flag<"-single_module">; +def specs_EQ : Joined<"-specs=">; +def specs : Separate<"-specs">, Flags<[Unsupported]>; +def static_libgcc : Flag<"-static-libgcc">; +def static : Flag<"-static">, Flags<[NoArgumentUnused]>; +def std_default_EQ : Joined<"-std-default=">; +def std_EQ : Joined<"-std=">; +def sub__library : JoinedOrSeparate<"-sub_library">; +def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">; +def s : Flag<"-s">; +def time : Flag<"-time">, + HelpText<"Time individual commands">; +def traditional_cpp : Flag<"-traditional-cpp">; +def traditional : Flag<"-traditional">; +def trigraphs : Flag<"-trigraphs">; +def twolevel__namespace__hints : Flag<"-twolevel_namespace_hints">; +def twolevel__namespace : Flag<"-twolevel_namespace">; +def t : Flag<"-t">; +def umbrella : Separate<"-umbrella">; +def undefined : JoinedOrSeparate<"-undefined">, Group<u_Group>; +def undef : Flag<"-undef">, Group<u_Group>; +def unexported__symbols__list : Separate<"-unexported_symbols_list">; +def u : JoinedOrSeparate<"-u">, Group<u_Group>; +def v : Flag<"-v">, + HelpText<"Show commands to run and use verbose output">; +def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>; +def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>; +def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>; +def weak__reference__mismatches : Separate<"-weak_reference_mismatches">; +def whatsloaded : Flag<"-whatsloaded">; +def whyload : Flag<"-whyload">; +def w : Flag<"-w">; +def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>, + HelpText<"Treat subsequent input files as having type <language>">, + MetaVarName<"<language>">; +def y : Joined<"-y">; + +// Double dash options, which are usually an alias for one of the previous +// options. + +def _CLASSPATH_EQ : Joined<"--CLASSPATH=">, Alias<fclasspath_EQ>; +def _CLASSPATH : Separate<"--CLASSPATH">, Alias<fclasspath_EQ>, Flags<[RenderJoined]>; +def _all_warnings : Flag<"--all-warnings">, Alias<Wall>; +def _analyze_auto : Flag<"--analyze-auto">, Flags<[DriverOption]>; +def _analyzer_no_default_checks : Flag<"--analyzer-no-default-checks">, Flags<[DriverOption]>; +def _analyzer_output : JoinedOrSeparate<"--analyzer-output">, Flags<[DriverOption]>; +def _analyze : Flag<"--analyze">, Flags<[DriverOption]>, + HelpText<"Run the static analyzer">; +def _ansi : Flag<"--ansi">, Alias<ansi>; +def _assemble : Flag<"--assemble">, Alias<S>; +def _assert_EQ : Joined<"--assert=">, Alias<A>, Flags<[RenderSeparate]>; +def _assert : Separate<"--assert">, Alias<A>; +def _bootclasspath_EQ : Joined<"--bootclasspath=">, Alias<fbootclasspath_EQ>; +def _bootclasspath : Separate<"--bootclasspath">, Alias<fbootclasspath_EQ>, Flags<[RenderJoined]>; +def _classpath_EQ : Joined<"--classpath=">, Alias<fclasspath_EQ>; +def _classpath : Separate<"--classpath">, Alias<fclasspath_EQ>, Flags<[RenderJoined]>; +def _combine : Flag<"--combine">, Alias<combine>, Flags<[Unsupported]>; +def _comments_in_macros : Flag<"--comments-in-macros">, Alias<CC>; +def _comments : Flag<"--comments">, Alias<C>; +def _compile : Flag<"--compile">, Alias<c>; +def _constant_cfstrings : Flag<"--constant-cfstrings">; +def _coverage : Flag<"--coverage">, Alias<coverage>; +def _debug_EQ : Joined<"--debug=">, Alias<g_Flag>, Flags<[Unsupported]>; +def _debug : Flag<"--debug">, Alias<g_Flag>, Flags<[Unsupported]>; +def _define_macro_EQ : Joined<"--define-macro=">, Alias<D>; +def _define_macro : Separate<"--define-macro">, Alias<D>, Flags<[RenderJoined]>; +def _dependencies : Flag<"--dependencies">, Alias<M>; +def _encoding_EQ : Joined<"--encoding=">, Alias<fencoding_EQ>; +def _encoding : Separate<"--encoding">, Alias<fencoding_EQ>, Flags<[RenderJoined]>; +def _entry : Flag<"--entry">, Alias<e>; +def _extdirs_EQ : Joined<"--extdirs=">, Alias<fextdirs_EQ>; +def _extdirs : Separate<"--extdirs">, Alias<fextdirs_EQ>, Flags<[RenderJoined]>; +def _extra_warnings : Flag<"--extra-warnings">, Alias<W_Joined>; +def _for_linker_EQ : Joined<"--for-linker=">, Alias<Xlinker>, Flags<[LinkerInput, RenderAsInput, RenderSeparate]>; +def _for_linker : Separate<"--for-linker">, Alias<Xlinker>, Flags<[LinkerInput, RenderAsInput]>; +def _force_link_EQ : Joined<"--force-link=">, Alias<u>, Flags<[RenderSeparate]>; +def _force_link : Separate<"--force-link">, Alias<u>; +def _help_hidden : Flag<"--help-hidden">; +def _help : Flag<"--help">, + HelpText<"Display available options">; +def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>, Flags<[RenderSeparate]>; +def _imacros : Separate<"--imacros">, Alias<imacros>; +def _include_barrier : Flag<"--include-barrier">, Alias<I_>; +def _include_directory_after_EQ : Joined<"--include-directory-after=">, Alias<idirafter>, Flags<[RenderSeparate]>; +def _include_directory_after : Separate<"--include-directory-after">, Alias<idirafter>; +def _include_directory_EQ : Joined<"--include-directory=">, Alias<I>; +def _include_directory : Separate<"--include-directory">, Alias<I>, Flags<[RenderJoined]>; +def _include_prefix_EQ : Joined<"--include-prefix=">, Alias<iprefix>, Flags<[RenderSeparate]>; +def _include_prefix : Separate<"--include-prefix">, Alias<iprefix>; +def _include_with_prefix_after_EQ : Joined<"--include-with-prefix-after=">, Alias<iwithprefix>, Flags<[RenderSeparate]>; +def _include_with_prefix_after : Separate<"--include-with-prefix-after">, Alias<iwithprefix>; +def _include_with_prefix_before_EQ : Joined<"--include-with-prefix-before=">, Alias<iwithprefixbefore>, Flags<[RenderSeparate]>; +def _include_with_prefix_before : Separate<"--include-with-prefix-before">, Alias<iwithprefixbefore>; +def _include_with_prefix_EQ : Joined<"--include-with-prefix=">, Alias<iwithprefix>, Flags<[RenderSeparate]>; +def _include_with_prefix : Separate<"--include-with-prefix">, Alias<iwithprefix>; +def _include_EQ : Joined<"--include=">, Alias<include_>, Flags<[RenderSeparate]>; +def _include : Separate<"--include">, Alias<include_>; +def _language_EQ : Joined<"--language=">, Alias<x>, Flags<[RenderSeparate]>; +def _language : Separate<"--language">, Alias<x>; +def _library_directory_EQ : Joined<"--library-directory=">, Alias<L>, Flags<[RenderSeparate]>; +def _library_directory : Separate<"--library-directory">, Alias<L>; +def _machine__EQ : Joined<"--machine-=">, Alias<m_Joined>, Flags<[Unsupported]>; +def _machine_ : Joined<"--machine-">, Alias<m_Joined>, Flags<[Unsupported]>; +def _machine_EQ : Joined<"--machine=">, Alias<m_Joined>; +def _machine : Separate<"--machine">, Alias<m_Joined>, Flags<[RenderJoined]>; +def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>; +def _no_line_commands : Flag<"--no-line-commands">, Alias<P>; +def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>; +def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>; +def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>; +def _no_warnings : Flag<"--no-warnings">, Alias<w>; +def _optimize_EQ : Joined<"--optimize=">, Alias<O>, Flags<[Unsupported]>; +def _optimize : Flag<"--optimize">, Alias<O>, Flags<[Unsupported]>; +def _output_class_directory_EQ : Joined<"--output-class-directory=">, Alias<foutput_class_dir_EQ>; +def _output_class_directory : Separate<"--output-class-directory">, Alias<foutput_class_dir_EQ>, Flags<[RenderJoined]>; +def _output_EQ : Joined<"--output=">, Alias<o>, Flags<[RenderSeparate]>; +def _output : Separate<"--output">, Alias<o>; +def _param : Separate<"--param">; +def _param_EQ : Joined<"--param=">, Alias<_param>, Flags<[RenderSeparate]>; +def _pass_exit_codes : Flag<"--pass-exit-codes">, Alias<pass_exit_codes>; +def _pedantic_errors : Flag<"--pedantic-errors">, Alias<pedantic_errors>; +def _pedantic : Flag<"--pedantic">, Alias<pedantic>; +def _pipe : Flag<"--pipe">, Alias<pipe>, Flags<[DriverOption]>; +def _prefix_EQ : Joined<"--prefix=">, Alias<B>, Flags<[RenderSeparate]>; +def _prefix : Separate<"--prefix">, Alias<B>; +def _preprocess : Flag<"--preprocess">, Alias<E>; +def _print_file_name_EQ : Joined<"--print-file-name=">, Alias<print_file_name_EQ>; +def _print_file_name : Separate<"--print-file-name">, Alias<print_file_name_EQ>; +def _print_libgcc_file_name : Flag<"--print-libgcc-file-name">, Alias<print_libgcc_file_name>; +def _print_missing_file_dependencies : Flag<"--print-missing-file-dependencies">, Alias<MG>; +def _print_multi_directory : Flag<"--print-multi-directory">, Alias<print_multi_directory>; +def _print_multi_lib : Flag<"--print-multi-lib">, Alias<print_multi_lib>; +def _print_multi_os_directory : Flag<"--print-multi-os-directory">, Alias<print_multi_os_directory>; +def _print_prog_name_EQ : Joined<"--print-prog-name=">, Alias<print_prog_name_EQ>; +def _print_prog_name : Separate<"--print-prog-name">, Alias<print_prog_name_EQ>; +def _print_search_dirs : Flag<"--print-search-dirs">, Alias<print_search_dirs>; +def _profile_blocks : Flag<"--profile-blocks">, Alias<a>; +def _profile : Flag<"--profile">, Alias<p>; +def _relocatable_pch : Flag<"--relocatable-pch">, + HelpText<"Build a relocatable precompiled header">; +def _resource_EQ : Joined<"--resource=">, Alias<fcompile_resource_EQ>; +def _resource : Separate<"--resource">, Alias<fcompile_resource_EQ>, Flags<[RenderJoined]>; +def _save_temps : Flag<"--save-temps">, Alias<save_temps>; +def _shared : Flag<"--shared">, Alias<shared>; +def _signed_char : Flag<"--signed-char">, Alias<fsigned_char>; +def _specs_EQ : Joined<"--specs=">, Alias<specs_EQ>, Flags<[Unsupported]>; +def _specs : Separate<"--specs">, Alias<specs_EQ>, Flags<[RenderJoined, Unsupported]>; +def _static : Flag<"--static">, Alias<static>; +def _std_EQ : Joined<"--std=">, Alias<std_EQ>; +def _std : Separate<"--std">, Alias<std_EQ>, Flags<[RenderJoined]>; +def _sysroot_EQ : Joined<"--sysroot=">; +def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>, Flags<[RenderJoined]>; +def _target_help : Flag<"--target-help">; +def _trace_includes : Flag<"--trace-includes">, Alias<H>; +def _traditional_cpp : Flag<"--traditional-cpp">, Alias<traditional_cpp>; +def _traditional : Flag<"--traditional">, Alias<traditional>; +def _trigraphs : Flag<"--trigraphs">, Alias<trigraphs>; +def _undefine_macro_EQ : Joined<"--undefine-macro=">, Alias<U>; +def _undefine_macro : Separate<"--undefine-macro">, Alias<U>, Flags<[RenderJoined]>; +def _unsigned_char : Flag<"--unsigned-char">, Alias<funsigned_char>; +def _user_dependencies : Flag<"--user-dependencies">, Alias<MM>; +def _verbose : Flag<"--verbose">, Alias<v>; +def _version : Flag<"--version">; +def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>, Flags<[Unsupported]>; +def _warn_ : Joined<"--warn-">, Alias<W_Joined>, Flags<[Unsupported]>; +def _write_dependencies : Flag<"--write-dependencies">, Alias<MD>; +def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>; +def _ : Joined<"--">, Alias<f>, Flags<[Unsupported]>; diff --git a/include/clang/Frontend/CompileOptions.h b/include/clang/Frontend/CompileOptions.h deleted file mode 100644 index ad53a8d..0000000 --- a/include/clang/Frontend/CompileOptions.h +++ /dev/null @@ -1,77 +0,0 @@ -//===--- 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: - enum InliningMethod { - NoInlining, // Perform no inlining whatsoever. - NormalInlining, // Use the standard function inlining pass. - OnlyAlwaysInlining // Only run the always inlining pass. - }; - - 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 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. - unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. - unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. - unsigned MergeAllConstants : 1; // Merge identical constants. - - /// Inlining - The kind of inlining to perform. - InliningMethod Inlining; - - /// 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; - SimplifyLibCalls = UnrollLoops = 0; - VerifyModule = 1; - TimePasses = 0; - NoCommon = 0; - Inlining = NoInlining; - DisableRedZone = 0; - NoImplicitFloat = 0; - MergeAllConstants = 1; - } -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 2edc7e1..6712977 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -72,8 +72,8 @@ public: unsigned Verbose : 1; public: - HeaderSearchOptions(llvm::StringRef _Sysroot = "") - : Sysroot(_Sysroot), UseStandardIncludes(true) {} + HeaderSearchOptions(llvm::StringRef _Sysroot = "/") + : Sysroot(_Sysroot), UseStandardIncludes(true), Verbose(false) {} /// AddPath - Add the \arg Path path to the specified \arg Group list. void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, diff --git a/include/clang/Frontend/InitHeaderSearch.h b/include/clang/Frontend/InitHeaderSearch.h deleted file mode 100644 index 48c4268..0000000 --- a/include/clang/Frontend/InitHeaderSearch.h +++ /dev/null @@ -1,98 +0,0 @@ -//===--- 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 "clang/Lex/DirectoryLookup.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include <string> -#include <vector> - -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 llvm::StringRef &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); - - /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu - /// libstdc++. - void AddGnuCPlusPlusIncludePaths(const std::string &Base, const char *Dir32, - const char *Dir64, - const llvm::Triple &triple); - - /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW - /// libstdc++. - void AddMinGWCPlusPlusIncludePaths(const std::string &Base, - const char *Arch, - const char *Version); - - /// AddDefaultEnvVarPaths - Adds list of paths from default environment - /// variables such as CPATH. - void AddDefaultEnvVarPaths(const LangOptions &Lang); - - // AddDefaultCIncludePaths - Add paths that should always be searched. - void AddDefaultCIncludePaths(const llvm::Triple &triple); - - // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when - // compiling c++. - void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple); - - // AddDefaultFrameworkIncludePaths - Add the framework paths. Used on darwin. - void AddDefaultFrameworkIncludePaths(const llvm::Triple &triple); - - /// AddDefaultSystemIncludePaths - Adds the default system include paths so - /// that e.g. stdio.h is found. - void AddDefaultSystemIncludePaths(const LangOptions &Lang, - const llvm::Triple &triple); - - /// 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 deleted file mode 100644 index 415acea..0000000 --- a/include/clang/Frontend/InitPreprocessor.h +++ /dev/null @@ -1,79 +0,0 @@ -//===--- 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; - - unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler - /// and target specific predefines. - -public: - PreprocessorInitOptions() : UsePredefines(true) {} - - bool getUsePredefines() const { return UsePredefines; } - void setUsePredefines(bool Value) { - UsePredefines = Value; - } - - 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. -/// -void InitializePreprocessor(Preprocessor &PP, - const PreprocessorInitOptions& InitOptions); - -} // end namespace clang - -#endif diff --git a/include/clang/Frontend/ManagerRegistry.h b/include/clang/Frontend/ManagerRegistry.h deleted file mode 100644 index f05cfe6..0000000 --- a/include/clang/Frontend/ManagerRegistry.h +++ /dev/null @@ -1,53 +0,0 @@ -//===-- 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/Makefile b/include/clang/Makefile index 82a16d5..624292a 100644 --- a/include/clang/Makefile +++ b/include/clang/Makefile @@ -1,4 +1,4 @@ LEVEL = ../../../.. -DIRS := Basic +DIRS := Basic Driver include $(LEVEL)/Makefile.common diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index a9b3213..3d3232b 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -2329,29 +2329,75 @@ public: /// found after the left paren. /// /// \param S the scope in which the operator keyword occurs. - virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { } - + virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { } + + /// \brief Code completion for the getter of an Objective-C property + /// declaration. + /// + /// This code completion action is invoked when the code-completion + /// token is found after the "getter = " in a property declaration. + /// + /// \param S the scope in which the property is being declared. + /// + /// \param ClassDecl the Objective-C class or category in which the property + /// is being defined. + /// + /// \param Methods the set of methods declared thus far within \p ClassDecl. + /// + /// \param NumMethods the number of methods in \p Methods + virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { + } + + /// \brief Code completion for the setter of an Objective-C property + /// declaration. + /// + /// This code completion action is invoked when the code-completion + /// token is found after the "setter = " in a property declaration. + /// + /// \param S the scope in which the property is being declared. + /// + /// \param ClassDecl the Objective-C class or category in which the property + /// is being defined. + /// + /// \param Methods the set of methods declared thus far within \p ClassDecl. + /// + /// \param NumMethods the number of methods in \p Methods + virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { + } + /// \brief Code completion for an ObjC message expression that refers to /// a class method. /// /// This code completion action is invoked when the code-completion token is - /// found after the class name. + /// found after the class name and after each argument. /// /// \param S the scope in which the message expression occurs. /// \param FName the factory name. /// \param FNameLoc the source location of the factory name. + /// \param SelIdents the identifiers that describe the selector (thus far). + /// \param NumSelIdents the number of identifiers in \p SelIdents. virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, - SourceLocation FNameLoc){ } + SourceLocation FNameLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents){ } /// \brief Code completion for an ObjC message expression that refers to /// an instance method. /// /// This code completion action is invoked when the code-completion token is - /// found after the receiver expression. + /// found after the receiver expression and after each argument. /// /// \param S the scope in which the operator keyword occurs. /// \param Receiver an expression for the receiver of the message. - virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { } + /// \param SelIdents the identifiers that describe the selector (thus far). + /// \param NumSelIdents the number of identifiers in \p SelIdents. + virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { } /// \brief Code completion for a list of protocol references in Objective-C, /// such as P1 and P2 in \c id<P1,P2>. @@ -2371,6 +2417,61 @@ public: /// /// \param S the scope in which the protocol declaration occurs. virtual void CodeCompleteObjCProtocolDecl(Scope *S) { } + + /// \brief Code completion for an Objective-C interface, after the + /// @interface but before any identifier. + virtual void CodeCompleteObjCInterfaceDecl(Scope *S) { } + + /// \brief Code completion for the superclass of an Objective-C + /// interface, after the ':'. + /// + /// \param S the scope in which the interface declaration occurs. + /// + /// \param ClassName the name of the class being defined. + virtual void CodeCompleteObjCSuperclass(Scope *S, + IdentifierInfo *ClassName) { + } + + /// \brief Code completion for an Objective-C implementation, after the + /// @implementation but before any identifier. + virtual void CodeCompleteObjCImplementationDecl(Scope *S) { } + + /// \brief Code completion for the category name in an Objective-C interface + /// declaration. + /// + /// This code completion action is invoked after the '(' that indicates + /// a category name within an Objective-C interface declaration. + virtual void CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName) { + } + + /// \brief Code completion for the category name in an Objective-C category + /// implementation. + /// + /// This code completion action is invoked after the '(' that indicates + /// the category name within an Objective-C category implementation. + virtual void CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName) { + } + + /// \brief Code completion for the property names when defining an + /// Objective-C property. + /// + /// This code completion action is invoked after @synthesize or @dynamic and + /// after each "," within one of those definitions. + virtual void CodeCompleteObjCPropertyDefinition(Scope *S, + DeclPtrTy ObjCImpDecl) { + } + + /// \brief Code completion for the instance variable name that should + /// follow an '=' when synthesizing an Objective-C property. + /// + /// This code completion action is invoked after each '=' that occurs within + /// an @synthesized definition. + virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName, + DeclPtrTy ObjCImpDecl) { + } //@} }; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e7dabdb..f7cccca 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -810,7 +810,8 @@ private: DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, DeclPtrTy classDecl, tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); - void ParseObjCPropertyAttribute(ObjCDeclSpec &DS); + void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, unsigned NumMethods); DeclPtrTy ParseObjCMethodDefinition(); diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 43ff686..ed74761 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -123,6 +123,9 @@ public: /// \brief Create a new current-parameter chunk. static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter); + /// \brief Clone the given chunk. + Chunk Clone() const; + /// \brief Destroy this chunk, deallocating any memory it owns. void Destroy(); }; @@ -192,15 +195,21 @@ public: /// \brief Add a new chunk. void AddChunk(Chunk C) { Chunks.push_back(C); } + /// \brief Returns the text in the TypedText chunk. + const char *getTypedText() const; + /// \brief Retrieve a string representation of the code completion string, /// which is mainly useful for debugging. std::string getAsString() const; + /// \brief Clone this code-completion string. + CodeCompletionString *Clone() const; + /// \brief Serialize this code-completion string to the given stream. void Serialize(llvm::raw_ostream &OS) const; /// \brief Deserialize a code-completion string from the given string. - static CodeCompletionString *Deserialize(llvm::StringRef &Str); + static CodeCompletionString *Deserialize(llvm::StringRef &Str); }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, @@ -220,7 +229,8 @@ public: enum ResultKind { RK_Declaration = 0, //< Refers to a declaration RK_Keyword, //< Refers to a keyword or symbol. - RK_Macro //< Refers to a macro + RK_Macro, //< Refers to a macro + RK_Pattern //< Refers to a precomputed pattern. }; /// \brief The kind of result stored here. @@ -235,6 +245,10 @@ public: /// or symbol's spelling. const char *Keyword; + /// \brief When Kind == RK_Pattern, the code-completion string that + /// describes the completion text to insert. + CodeCompletionString *Pattern; + /// \brief When Kind == RK_Macro, the identifier that refers to a macro. IdentifierInfo *Macro; }; @@ -243,6 +257,10 @@ public: /// result and progressively higher numbers representing poorer results. unsigned Rank; + /// \brief Specifiers which parameter (of a function, Objective-C method, + /// macro, etc.) we should start with when formatting the result. + unsigned StartParameter; + /// \brief Whether this result is hidden by another name. bool Hidden : 1; @@ -252,7 +270,11 @@ public: /// \brief Whether this declaration is the beginning of a /// nested-name-specifier and, therefore, should be followed by '::'. bool StartsNestedNameSpecifier : 1; - + + /// \brief Whether all parameters (of a function, Objective-C + /// method, etc.) should be considered "informative". + bool AllParametersAreInformative : 1; + /// \brief If the result should have a nested-name-specifier, this is it. /// When \c QualifierIsInformative, the nested-name-specifier is /// informative rather than required. @@ -263,20 +285,31 @@ public: NestedNameSpecifier *Qualifier = 0, bool QualifierIsInformative = false) : Kind(RK_Declaration), Declaration(Declaration), Rank(Rank), - Hidden(false), QualifierIsInformative(QualifierIsInformative), - StartsNestedNameSpecifier(false), Qualifier(Qualifier) { } + StartParameter(0), Hidden(false), + QualifierIsInformative(QualifierIsInformative), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + Qualifier(Qualifier) { } /// \brief Build a result that refers to a keyword or symbol. Result(const char *Keyword, unsigned Rank) - : Kind(RK_Keyword), Keyword(Keyword), Rank(Rank), Hidden(false), - QualifierIsInformative(0), StartsNestedNameSpecifier(false), + : Kind(RK_Keyword), Keyword(Keyword), Rank(Rank), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), Qualifier(0) { } /// \brief Build a result that refers to a macro. Result(IdentifierInfo *Macro, unsigned Rank) - : Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false), - QualifierIsInformative(0), StartsNestedNameSpecifier(false), + : Kind(RK_Macro), Macro(Macro), Rank(Rank), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), Qualifier(0) { } + + /// \brief Build a result that refers to a pattern. + Result(CodeCompletionString *Pattern, unsigned Rank) + : Kind(RK_Pattern), Pattern(Pattern), Rank(Rank), StartParameter(0), + Hidden(false), QualifierIsInformative(0), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + Qualifier(0) { } /// \brief Retrieve the declaration stored in this result. NamedDecl *getDeclaration() const { @@ -293,6 +326,8 @@ public: /// \brief Create a new code-completion string that describes how to insert /// this result into a program. CodeCompletionString *CreateCodeCompletionString(Sema &S); + + void Destroy(); }; class OverloadCandidate { diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 8f5cff4..b1d30a6 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -603,8 +603,8 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, EmitBlock(AfterFor, true); } -/// GenerateCXXAggrDestructorHelper - Generates a helper function which when invoked, -/// calls the default destructor on array elements in reverse order of +/// GenerateCXXAggrDestructorHelper - Generates a helper function which when +/// invoked, calls the default destructor on array elements in reverse order of /// construction. llvm::Constant * CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 1d2040b..349ede5 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -611,4 +611,3 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder); } } - diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 8e0864b..a63c832 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -345,6 +345,11 @@ static const CXXMethodDecl *GetKeyFunction(const RecordDecl *D) { if (MD->isPure()) continue; + // FIXME: This doesn't work. If we have an out of line body, that body will + // set the MD to have a body, what we want to know is, was the body present + // inside the declaration of the class. For now, we just avoid the problem + // by pretending there is no key function. + return 0; if (MD->getBody()) continue; diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp index e18843d..79d8664 100644 --- a/lib/CodeGen/CGRtti.cpp +++ b/lib/CodeGen/CGRtti.cpp @@ -47,21 +47,35 @@ public: return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } - llvm::Constant *BuildName(QualType Ty, bool Hidden) { + llvm::Constant *BuildName(QualType Ty, bool Hidden, bool Extern) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRttiName(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; + + llvm::GlobalVariable *GV; + GV = CGM.getModule().getGlobalVariable(Name); + if (GV && !GV->isDeclaration()) + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); llvm::Constant *C; - C = llvm::ConstantArray::get(VMContext, Out.str().substr(4)); + C = llvm::ConstantArray::get(VMContext, Name.substr(4)); - llvm::GlobalVariable * GV = new llvm::GlobalVariable(CGM.getModule(), - C->getType(), - true, linktype, C, - Out.str()); + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Name); + if (OGV) { + GV->takeName(OGV); + llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, + OGV->getType()); + OGV->replaceAllUsesWith(NewPtr); + OGV->eraseFromParent(); + } if (Hidden) GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); @@ -87,8 +101,9 @@ public: llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); - C = CGM.getModule().getGlobalVariable(Out.str()); + C = CGM.getModule().getGlobalVariable(Name); if (C) return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); @@ -96,7 +111,7 @@ public: linktype = llvm::GlobalValue::ExternalLinkage;; C = new llvm::GlobalVariable(CGM.getModule(), Int8PtrTy, true, linktype, - 0, Out.str()); + 0, Name); return llvm::ConstantExpr::getBitCast(C, Int8PtrTy); } @@ -147,20 +162,19 @@ public: llvm::Constant *finish(std::vector<llvm::Constant *> &info, llvm::GlobalVariable *GV, - llvm::StringRef Name, bool Hidden) { + llvm::StringRef Name, bool Hidden, bool Extern) { llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; llvm::Constant *C; C = llvm::ConstantStruct::get(VMContext, &info[0], info.size(), false); - if (GV == 0) - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, - linktype, C, Name); - else { - llvm::GlobalVariable *OGV = GV; - GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, - linktype, C, Name); + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, linktype, + C, Name); + if (OGV) { GV->takeName(OGV); llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, OGV->getType()); @@ -183,15 +197,17 @@ public: llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), CGM.getContext().getTagDeclType(RD), Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector<llvm::Constant *> info; bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + bool Extern = !RD->isInAnonymousNamespace(); bool simple = false; if (RD->getNumBases() == 0) @@ -202,7 +218,8 @@ public: } else C = BuildVtableRef("_ZTVN10__cxxabiv121__vmi_class_type_infoE"); info.push_back(C); - info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden)); + info.push_back(BuildName(CGM.getContext().getTagDeclType(RD), Hidden, + Extern)); // If we have no bases, there are no more fields. if (RD->getNumBases()) { @@ -235,7 +252,7 @@ public: } } - return finish(info, GV, Out.str(), Hidden); + return finish(info, GV, Name, Hidden, Extern); } /// - BuildFlags - Build a __flags value for __pbase_type_info. @@ -250,23 +267,49 @@ public: return BuildType(Ty); } + bool DecideExtern(QualType Ty) { + // For this type, see if all components are never in an anonymous namespace. + if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) + return (DecideExtern(MPT->getPointeeType()) + && DecideExtern(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs<PointerType>()) + return DecideExtern(PT->getPointeeType()); + if (const RecordType *RT = Ty->getAs<RecordType>()) + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) + return !RD->isInAnonymousNamespace(); + return true; + } + + bool DecideHidden(QualType Ty) { + // For this type, see if all components are never hidden. + if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) + return (DecideHidden(MPT->getPointeeType()) + && DecideHidden(QualType(MPT->getClass(), 0))); + if (const PointerType *PT = Ty->getAs<PointerType>()) + return DecideHidden(PT->getPointeeType()); + if (const RecordType *RT = Ty->getAs<RecordType>()) + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) + return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + return false; + } + llvm::Constant *BuildPointerType(QualType Ty) { llvm::Constant *C; llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector<llvm::Constant *> info; - // FIXME: pointer to hidden should be hidden, we should be able to - // grab a bit off the type for this. - bool Hidden = false; + bool Extern = DecideExtern(Ty); + bool Hidden = DecideHidden(Ty); QualType PTy = Ty->getPointeeType(); QualType BTy; @@ -282,7 +325,7 @@ public: else C = BuildVtableRef("_ZTVN10__cxxabiv119__pointer_type_infoE"); info.push_back(C); - info.push_back(BuildName(Ty, Hidden)); + info.push_back(BuildName(Ty, Hidden, Extern)); Qualifiers Q = PTy.getQualifiers(); PTy = CGM.getContext().getCanonicalType(PTy).getUnqualifiedType(); int flags = 0; @@ -300,7 +343,8 @@ public: if (PtrMem) info.push_back(BuildType2(BTy)); - return finish(info, GV, Out.str(), true); + // We always generate these as hidden, only the name isn't hidden. + return finish(info, GV, Name, true, Extern); } llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) { @@ -309,23 +353,24 @@ public: llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXRtti(CGM.getMangleContext(), Ty, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable *GV; - GV = CGM.getModule().getGlobalVariable(Out.str()); + GV = CGM.getModule().getGlobalVariable(Name); if (GV && !GV->isDeclaration()) return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); std::vector<llvm::Constant *> info; - // FIXME: pointer to hidden should be hidden, we should be able to - // grab a bit off the type for this. - bool Hidden = false; + bool Extern = DecideExtern(Ty); + bool Hidden = DecideHidden(Ty); C = BuildVtableRef(vtbl); info.push_back(C); - info.push_back(BuildName(Ty, Hidden)); + info.push_back(BuildName(Ty, Hidden, Extern)); - return finish(info, GV, Out.str(), true); + // We always generate these as hidden, only the name isn't hidden. + return finish(info, GV, Name, true, Extern); } llvm::Constant *BuildType(QualType Ty) { diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 4c97a9b..9be1a3b 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -69,7 +69,6 @@ private: llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints; typedef CXXRecordDecl::method_iterator method_iter; - // FIXME: Linkage should follow vtable const bool Extern; const uint32_t LLVMPointerWidth; Index_t extra; @@ -82,7 +81,7 @@ public: BLayout(cgm.getContext().getASTRecordLayout(l)), rtti(cgm.GenerateRttiRef(c)), VMContext(cgm.getModule().getContext()), CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>), - Extern(true), + Extern(!l->isInAnonymousNamespace()), LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); @@ -788,37 +787,73 @@ llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass, mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out); else mangleCXXVtable(getMangleContext(), RD, Out); + llvm::StringRef Name = Out.str(); - llvm::GlobalVariable::LinkageTypes linktype; - linktype = llvm::GlobalValue::LinkOnceODRLinkage; std::vector<llvm::Constant *> methods; llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); int64_t AddressPoint; - VtableBuilder b(methods, RD, LayoutClass, Offset, *this); + llvm::GlobalVariable *GV = getModule().getGlobalVariable(Name); + if (GV && AddressPoints[LayoutClass] && !GV->isDeclaration()) + AddressPoint=(*(*(AddressPoints[LayoutClass]))[RD])[std::make_pair(RD, + Offset)]; + else { + VtableBuilder b(methods, RD, LayoutClass, Offset, *this); - D1(printf("vtable %s\n", RD->getNameAsCString())); - // First comes the vtables for all the non-virtual bases... - AddressPoint = b.GenerateVtableForBase(RD, Offset); + D1(printf("vtable %s\n", RD->getNameAsCString())); + // First comes the vtables for all the non-virtual bases... + AddressPoint = b.GenerateVtableForBase(RD, Offset); - // then the vtables for all the virtual bases. - b.GenerateVtableForVBases(RD, Offset); + // then the vtables for all the virtual bases. + b.GenerateVtableForVBases(RD, Offset); - CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass]; - if (ref == 0) - ref = new CodeGenModule::AddrMap_t; + CodeGenModule::AddrMap_t *&ref = AddressPoints[LayoutClass]; + if (ref == 0) + ref = new CodeGenModule::AddrMap_t; - (*ref)[RD] = b.getAddressPoints(); + (*ref)[RD] = b.getAddressPoints(); + + bool CreateDefinition = true; + if (LayoutClass != RD) + CreateDefinition = true; + else { + // We have to convert it to have a record layout. + Types.ConvertTagDeclType(LayoutClass); + const CGRecordLayout &CGLayout = Types.getCGRecordLayout(LayoutClass); + if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) { + if (!KeyFunction->getBody()) { + // If there is a KeyFunction, and it isn't defined, just build a + // reference to the vtable. + CreateDefinition = false; + } + } + } - llvm::Constant *C; - llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); - C = llvm::ConstantArray::get(type, methods); - llvm::GlobalVariable *GV = new llvm::GlobalVariable(getModule(), type, - true, linktype, C, - Out.str()); - bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; - if (Hidden) - GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); + llvm::Constant *C = 0; + llvm::Type *type = Ptr8Ty; + llvm::GlobalVariable::LinkageTypes linktype + = llvm::GlobalValue::ExternalLinkage; + if (CreateDefinition) { + llvm::ArrayType *ntype = llvm::ArrayType::get(Ptr8Ty, methods.size()); + C = llvm::ConstantArray::get(ntype, methods); + linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (LayoutClass->isInAnonymousNamespace()) + linktype = llvm::GlobalValue::InternalLinkage; + type = ntype; + } + llvm::GlobalVariable *OGV = GV; + GV = new llvm::GlobalVariable(getModule(), type, true, linktype, C, Name); + if (OGV) { + GV->takeName(OGV); + llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, + OGV->getType()); + OGV->replaceAllUsesWith(NewPtr); + OGV->eraseFromParent(); + } + bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; + if (Hidden) + GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); + } llvm::Constant *vtable = llvm::ConstantExpr::getBitCast(GV, Ptr8Ty); llvm::Constant *AddressPointC; uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0); @@ -1001,9 +1036,12 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); mangleCXXVTT(getMangleContext(), RD, Out); + llvm::StringRef Name = Out.str(); llvm::GlobalVariable::LinkageTypes linktype; linktype = llvm::GlobalValue::LinkOnceODRLinkage; + if (RD->isInAnonymousNamespace()) + linktype = llvm::GlobalValue::InternalLinkage; std::vector<llvm::Constant *> inits; llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); @@ -1015,20 +1053,41 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size()); C = llvm::ConstantArray::get(type, inits); llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true, - linktype, C, Out.str()); + linktype, C, Name); bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; if (Hidden) vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility); return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty); } +void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) { + Vtables[RD] = CGM.GenerateVtable(RD, RD); + CGM.GenerateRtti(RD); + CGM.GenerateVTT(RD); +} + llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { llvm::Constant *&vtbl = Vtables[RD]; if (vtbl) return vtbl; vtbl = CGM.GenerateVtable(RD, RD); - CGM.GenerateRtti(RD); - CGM.GenerateVTT(RD); + + bool CreateDefinition = true; + // We have to convert it to have a record layout. + CGM.getTypes().ConvertTagDeclType(RD); + const CGRecordLayout &CGLayout = CGM.getTypes().getCGRecordLayout(RD); + if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) { + if (!KeyFunction->getBody()) { + // If there is a KeyFunction, and it isn't defined, just build a + // reference to the vtable. + CreateDefinition = false; + } + } + + if (CreateDefinition) { + CGM.GenerateRtti(RD); + CGM.GenerateVTT(RD); + } return vtbl; } diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index f9ddf44..78ae670 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -61,6 +61,10 @@ public: llvm::Constant *getVtable(const CXXRecordDecl *RD); llvm::Constant *getCtorVtable(const CXXRecordDecl *RD, const CXXRecordDecl *Class, uint64_t Offset); + /// GenerateClassData - Generate all the class data requires to be generated + /// upon definition of a KeyFunction. This includes the vtable, the + /// rtti data structure and the VTT. + void GenerateClassData(const CXXRecordDecl *RD); }; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0e6f4a6..195acc5 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -616,6 +616,16 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { Context.getSourceManager(), "Generating code for declaration"); + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + const CXXRecordDecl *RD = MD->getParent(); + // We have to convert it to have a record layout. + Types.ConvertTagDeclType(RD); + const CGRecordLayout &CGLayout = Types.getCGRecordLayout(RD); + // A definition of a KeyFunction, generates all the class data, such + // as vtable, rtti and the VTT. + if (CGLayout.getKeyFunction() == MD) + getVtableInfo().GenerateClassData(RD); + } if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) EmitCXXConstructor(CD, GD.getCtorType()); else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp index 8d2138d..ea75c34 100644 --- a/lib/Driver/ArgList.cpp +++ b/lib/Driver/ArgList.cpp @@ -27,38 +27,41 @@ void ArgList::append(Arg *A) { Args.push_back(A); } -Arg *ArgList::getLastArg(options::ID Id, bool Claim) const { +Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { // FIXME: Make search efficient? - for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) { - if ((*it)->getOption().matches(Id)) { - if (Claim) (*it)->claim(); + for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) + if ((*it)->getOption().matches(Id)) return *it; - } - } - return 0; } -Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const { - Arg *Res, *A0 = getLastArg(Id0, false), *A1 = getLastArg(Id1, false); +Arg *ArgList::getLastArg(OptSpecifier Id) const { + Arg *A = getLastArgNoClaim(Id); + if (A) + A->claim(); + return A; +} + +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const { + Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1); if (A0 && A1) Res = A0->getIndex() > A1->getIndex() ? A0 : A1; else Res = A0 ? A0 : A1; - if (Claim && Res) + if (Res) Res->claim(); return Res; } -Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, - bool Claim) const { +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, + OptSpecifier Id2) const { Arg *Res = 0; - Arg *A0 = getLastArg(Id0, false); - Arg *A1 = getLastArg(Id1, false); - Arg *A2 = getLastArg(Id2, false); + Arg *A0 = getLastArgNoClaim(Id0); + Arg *A1 = getLastArgNoClaim(Id1); + Arg *A2 = getLastArgNoClaim(Id2); int A0Idx = A0 ? A0->getIndex() : -1; int A1Idx = A1 ? A1->getIndex() : -1; @@ -76,26 +79,26 @@ Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, Res = A2; } - if (Claim && Res) + if (Res) Res->claim(); return Res; } -bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const { +bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { if (Arg *A = getLastArg(Pos, Neg)) return A->getOption().matches(Pos); return Default; } -void ArgList::AddLastArg(ArgStringList &Output, options::ID Id) const { +void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { if (Arg *A = getLastArg(Id)) { A->claim(); A->render(*this, Output); } } -void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const { +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -106,8 +109,8 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const { } } -void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, - options::ID Id1) const { +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -118,8 +121,8 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, } } -void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, - options::ID Id1, options::ID Id2) const { +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1, OptSpecifier Id2) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -131,7 +134,7 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0, } } -void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const { +void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -143,8 +146,8 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const { } } -void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0, - options::ID Id1) const { +void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; @@ -156,7 +159,7 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0, } } -void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0, +void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, const char *Translation, bool Joined) const { // FIXME: Make fast. @@ -177,7 +180,7 @@ void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0, } } -void ArgList::ClaimAllArgs(options::ID Id0) const { +void ArgList::ClaimAllArgs(OptSpecifier Id0) const { // FIXME: Make fast. for (const_iterator it = begin(), ie = end(); it != ie; ++it) { const Arg *A = *it; diff --git a/lib/Driver/CC1Options.cpp b/lib/Driver/CC1Options.cpp new file mode 100644 index 0000000..672fe04 --- /dev/null +++ b/lib/Driver/CC1Options.cpp @@ -0,0 +1,43 @@ +//===--- CC1Options.cpp - Clang CC1 Options Table -----------------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/CC1Options.h" +#include "clang/Driver/OptTable.h" +#include "clang/Driver/Option.h" + +using namespace clang::driver; +using namespace clang::driver::options; +using namespace clang::driver::cc1options; + +static OptTable::Info CC1InfoTable[] = { + // The InputOption info + { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID }, + // The UnknownOption info + { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID }, + +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + OPT_##GROUP, OPT_##ALIAS }, +#include "clang/Driver/CC1Options.inc" +}; + +namespace { + +class CC1OptTable : public OptTable { +public: + CC1OptTable() + : OptTable(CC1InfoTable, sizeof(CC1InfoTable) / sizeof(CC1InfoTable[0])) {} +}; + +} + +OptTable *clang::driver::createCC1OptTable() { + return new CC1OptTable(); +} diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index b6998ab..60d8e9c 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -4,8 +4,10 @@ add_clang_library(clangDriver Action.cpp Arg.cpp ArgList.cpp + CC1Options.cpp Compilation.cpp Driver.cpp + DriverOptions.cpp HostInfo.cpp Job.cpp OptTable.cpp @@ -18,4 +20,4 @@ add_clang_library(clangDriver Types.cpp ) -add_dependencies(clangDriver ClangDiagnosticDriver) +add_dependencies(clangDriver ClangDiagnosticDriver ClangDriverOptions ClangCC1Options) diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index c12f5aa..ffa627a 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index b4693f2..b40dc27 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -16,6 +16,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/HostInfo.h" #include "clang/Driver/Job.h" +#include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" @@ -44,7 +45,7 @@ Driver::Driver(const char *_Name, const char *_Dir, const char *_DefaultHostTriple, const char *_DefaultImageName, bool IsProduction, Diagnostic &_Diags) - : Opts(new OptTable()), Diags(_Diags), + : Opts(createDriverOptTable()), Diags(_Diags), Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple), DefaultImageName(_DefaultImageName), Host(0), @@ -75,40 +76,23 @@ Driver::~Driver() { InputArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); - InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); + unsigned MissingArgIndex, MissingArgCount; + InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd, + MissingArgIndex, MissingArgCount); - // FIXME: Handle '@' args (or at least error on them). - - unsigned Index = 0, End = ArgEnd - ArgBegin; - while (Index < End) { - // gcc's handling of empty arguments doesn't make sense, but this is not a - // common use case. :) - // - // We just ignore them here (note that other things may still take them as - // arguments). - if (Args->getArgString(Index)[0] == '\0') { - ++Index; - continue; - } - - unsigned Prev = Index; - Arg *A = getOpts().ParseOneArg(*Args, Index); - assert(Index > Prev && "Parser failed to consume argument."); - - // Check for missing argument error. - if (!A) { - assert(Index >= End && "Unexpected parser error."); - Diag(clang::diag::err_drv_missing_argument) - << Args->getArgString(Prev) - << (Index - Prev - 1); - break; - } + // Check for missing argument error. + if (MissingArgCount) + Diag(clang::diag::err_drv_missing_argument) + << Args->getArgString(MissingArgIndex) << MissingArgCount; + // Check for unsupported options. + for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); + it != ie; ++it) { + Arg *A = *it; if (A->getOption().isUnsupported()) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } - Args->append(A); } return Args; @@ -340,8 +324,8 @@ void Driver::PrintHelp(bool ShowHidden) const { // Render help text into (option, help) pairs. std::vector< std::pair<std::string, const char*> > OptionHelp; - for (unsigned i = options::OPT_INPUT, e = options::LastOption; i != e; ++i) { - options::ID Id = (options::ID) i; + for (unsigned i = 0, e = getOpts().getNumOptions(); i != e; ++i) { + options::ID Id = (options::ID) (i + 1); if (const char *Text = getOpts().getOptionHelpText(Id)) OptionHelp.push_back(std::make_pair(getOptionHelpName(getOpts(), Id), Text)); @@ -591,7 +575,7 @@ void Driver::BuildUniversalActions(const ArgList &Args, it != ie; ++it) { Arg *A = *it; - if (A->getOption().getId() == options::OPT_arch) { + if (A->getOption().matches(options::OPT_arch)) { // Validate the option here; we don't save the type here because its // particular spelling may participate in other driver choices. llvm::Triple::ArchType Arch = @@ -686,7 +670,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const { // // Otherwise emit an error but still use a valid type to avoid // spurious errors (e.g., no inputs). - if (!Args.hasArg(options::OPT_E, false)) + if (!Args.hasArgNoClaim(options::OPT_E)) Diag(clang::diag::err_drv_unknown_stdin_type); Ty = types::TY_C; } else { @@ -730,7 +714,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const { // necessary. Inputs.push_back(std::make_pair(types::TY_Object, A)); - } else if (A->getOption().getId() == options::OPT_x) { + } else if (A->getOption().matches(options::OPT_x)) { InputTypeArg = A; InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args)); @@ -984,7 +968,7 @@ void Driver::BuildJobs(Compilation &C) const { // FIXME: Use iterator. for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { - if ((*it)->isClaimed() && (*it)->getOption().matches(Opt.getId())) { + if ((*it)->isClaimed() && (*it)->getOption().matches(&Opt)) { DuplicateClaimed = true; break; } diff --git a/lib/Driver/DriverOptions.cpp b/lib/Driver/DriverOptions.cpp new file mode 100644 index 0000000..eddaee0 --- /dev/null +++ b/lib/Driver/DriverOptions.cpp @@ -0,0 +1,42 @@ +//===--- DriverOptions.cpp - Driver Options Table -----------------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/Options.h" +#include "clang/Driver/OptTable.h" +#include "clang/Driver/Option.h" + +using namespace clang::driver; +using namespace clang::driver::options; + +static OptTable::Info InfoTable[] = { + // The InputOption info + { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID }, + // The UnknownOption info + { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID }, + +#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ + HELPTEXT, METAVAR) \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + OPT_##GROUP, OPT_##ALIAS }, +#include "clang/Driver/Options.inc" +}; + +namespace { + +class DriverOptTable : public OptTable { +public: + DriverOptTable() + : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {} +}; + +} + +OptTable *clang::driver::createDriverOptTable() { + return new DriverOptTable(); +} diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 08c4ef4..ed73b17 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -122,7 +122,7 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, // // FIXME: Should this information be in llvm::Triple? if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (A->getOption().getId() == options::OPT_m32) { + if (A->getOption().matches(options::OPT_m32)) { if (Arch == llvm::Triple::x86_64) Arch = llvm::Triple::x86; if (Arch == llvm::Triple::ppc64) @@ -205,11 +205,11 @@ ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64"; + (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64"; + (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } @@ -478,11 +478,11 @@ ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args, if (Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::x86_64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64"; + (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; } else if (Triple.getArch() == llvm::Triple::ppc || Triple.getArch() == llvm::Triple::ppc64) { ArchName = - (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64"; + (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; } } diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp index affd1c5..f68a1d8 100644 --- a/lib/Driver/OptTable.cpp +++ b/lib/Driver/OptTable.cpp @@ -1,4 +1,4 @@ -//===--- Options.cpp - Option info table --------------------------------*-===// +//===--- OptTable.cpp - Option Table Implementation ---------------------*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/Driver/Options.h" - +#include "clang/Driver/OptTable.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Option.h" @@ -18,18 +17,6 @@ using namespace clang::driver; using namespace clang::driver::options; -struct Info { - const char *Name; - const char *Flags; - const char *HelpText; - const char *MetaVar; - - Option::OptionClass Kind; - unsigned GroupID; - unsigned AliasID; - unsigned Param; -}; - // Ordering on Info. 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 @@ -56,7 +43,9 @@ static int StrCmpOptionName(const char *A, const char *B) { return (a < b) ? -1 : 1; } -static inline bool operator<(const Info &A, const Info &B) { +namespace clang { +namespace driver { +static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { if (&A == &B) return false; @@ -70,57 +59,62 @@ static inline bool operator<(const Info &A, const Info &B) { return B.Kind == Option::JoinedClass; } +// Support lower_bound between info and an option name. +static inline bool operator<(const OptTable::Info &I, const char *Name) { + return StrCmpOptionName(I.Name, Name) == -1; +} +static inline bool operator<(const char *Name, const OptTable::Info &I) { + return StrCmpOptionName(Name, I.Name) == -1; +} +} +} + // -static Info OptionInfos[] = { - // The InputOption info - { "<input>", "d", 0, 0, Option::InputClass, OPT_INVALID, OPT_INVALID, 0 }, - // The UnknownOption info - { "<unknown>", "", 0, 0, Option::UnknownClass, OPT_INVALID, OPT_INVALID, 0 }, - -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ - { NAME, FLAGS, HELPTEXT, METAVAR, \ - Option::KIND##Class, OPT_##GROUP, OPT_##ALIAS, PARAM }, -#include "clang/Driver/Options.def" -}; -static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]); - -static Info &getInfo(unsigned id) { - assert(id > 0 && id - 1 < numOptions && "Invalid Option ID."); - return OptionInfos[id - 1]; -} +OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} -OptTable::OptTable() : Options(new Option*[numOptions]) { +// + +OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos) + : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos), + Options(new Option*[NumOptionInfos]), + TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0) +{ // Explicitly zero initialize the error to work around a bug in array // value-initialization on MinGW with gcc 4.3.5. - memset(Options, 0, sizeof(*Options) * numOptions); + memset(Options, 0, sizeof(*Options) * NumOptionInfos); // Find start of normal options. - FirstSearchableOption = 0; - for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) { - if (getInfo(i).Kind != Option::GroupClass) { - FirstSearchableOption = i; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + unsigned Kind = getInfo(i + 1).Kind; + if (Kind == Option::InputClass) { + assert(!TheInputOption && "Cannot have multiple input options!"); + TheInputOption = getOption(i + 1); + } else if (Kind == Option::UnknownClass) { + assert(!TheUnknownOption && "Cannot have multiple input options!"); + TheUnknownOption = getOption(i + 1); + } else if (Kind != Option::GroupClass) { + FirstSearchableIndex = i; break; } } - assert(FirstSearchableOption != 0 && "No searchable options?"); + assert(FirstSearchableIndex != 0 && "No searchable options?"); #ifndef NDEBUG // Check that everything after the first searchable option is a // regular option class. - for (unsigned i = FirstSearchableOption; i < LastOption; ++i) { - Option::OptionClass Kind = getInfo(i).Kind; + for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) { + Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind; assert((Kind != Option::InputClass && Kind != Option::UnknownClass && Kind != Option::GroupClass) && "Special options should be defined first!"); } // Check that options are in order. - for (unsigned i = FirstSearchableOption + 1; i < LastOption; ++i) { - if (!(getInfo(i - 1) < getInfo(i))) { - getOption((options::ID) (i - 1))->dump(); - getOption((options::ID) i)->dump(); + for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) { + if (!(getInfo(i) < getInfo(i + 1))) { + getOption(i)->dump(); + getOption(i + 1)->dump(); assert(0 && "Options are not in order!"); } } @@ -128,56 +122,23 @@ OptTable::OptTable() : Options(new Option*[numOptions]) { } OptTable::~OptTable() { - for (unsigned i = 0; i < numOptions; ++i) + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) delete Options[i]; delete[] Options; } -unsigned OptTable::getNumOptions() const { - return numOptions; -} - -const char *OptTable::getOptionName(options::ID id) const { - return getInfo(id).Name; -} - -unsigned OptTable::getOptionKind(options::ID id) const { - return getInfo(id).Kind; -} - -const char *OptTable::getOptionHelpText(options::ID id) const { - return getInfo(id).HelpText; -} - -const char *OptTable::getOptionMetaVar(options::ID id) const { - return getInfo(id).MetaVar; -} - -const Option *OptTable::getOption(options::ID id) const { - if (id == OPT_INVALID) - return 0; - - assert((unsigned) (id - 1) < numOptions && "Invalid ID."); - - Option *&Entry = Options[id - 1]; - if (!Entry) - Entry = constructOption(id); - - return Entry; -} - -Option *OptTable::constructOption(options::ID id) const { - Info &info = getInfo(id); +Option *OptTable::CreateOption(unsigned id) const { + const Info &info = getInfo(id); const OptionGroup *Group = - cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID)); - const Option *Alias = getOption((options::ID) info.AliasID); + cast_or_null<OptionGroup>(getOption(info.GroupID)); + const Option *Alias = getOption(info.AliasID); Option *Opt = 0; switch (info.Kind) { case Option::InputClass: - Opt = new InputOption(); break; + Opt = new InputOption(id); break; case Option::UnknownClass: - Opt = new UnknownOption(); break; + Opt = new UnknownOption(id); break; case Option::GroupClass: Opt = new OptionGroup(id, info.Name, Group); break; case Option::FlagClass: @@ -196,44 +157,38 @@ Option *OptTable::constructOption(options::ID id) const { Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break; } - for (const char *s = info.Flags; *s; ++s) { - switch (*s) { - default: assert(0 && "Invalid option flag."); - case 'J': - assert(info.Kind == Option::SeparateClass && "Invalid option."); - Opt->setForceJoinedRender(true); break; - case 'S': - assert(info.Kind == Option::JoinedClass && "Invalid option."); - Opt->setForceSeparateRender(true); break; - case 'd': Opt->setDriverOption(true); break; - case 'i': Opt->setNoOptAsInput(true); break; - case 'l': Opt->setLinkerInput(true); break; - case 'q': Opt->setNoArgumentUnused(true); break; - case 'u': Opt->setUnsupported(true); break; - } + if (info.Flags & DriverOption) + Opt->setDriverOption(true); + if (info.Flags & LinkerInput) + Opt->setLinkerInput(true); + if (info.Flags & NoArgumentUnused) + Opt->setNoArgumentUnused(true); + if (info.Flags & RenderAsInput) + Opt->setNoOptAsInput(true); + if (info.Flags & RenderJoined) { + assert(info.Kind == Option::SeparateClass && "Invalid option."); + Opt->setForceJoinedRender(true); } + if (info.Flags & RenderSeparate) { + assert(info.Kind == Option::JoinedClass && "Invalid option."); + Opt->setForceSeparateRender(true); + } + if (info.Flags & Unsupported) + Opt->setUnsupported(true); return Opt; } -// Support lower_bound between info and an option name. -static inline bool operator<(struct Info &I, const char *Name) { - return StrCmpOptionName(I.Name, Name) == -1; -} -static inline bool operator<(const char *Name, struct Info &I) { - return StrCmpOptionName(Name, I.Name) == -1; -} - Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const { unsigned Prev = Index; const char *Str = Args.getArgString(Index); // Anything that doesn't start with '-' is an input, as is '-' itself. if (Str[0] != '-' || Str[1] == '\0') - return new PositionalArg(getOption(OPT_INPUT), Index++); + return new PositionalArg(TheInputOption, Index++); - struct Info *Start = OptionInfos + FirstSearchableOption - 1; - struct Info *End = OptionInfos + LastOption - 1; + const Info *Start = OptionInfos + FirstSearchableIndex; + const Info *End = OptionInfos + getNumOptions(); // Search for the first next option which could be a prefix. Start = std::lower_bound(Start, End, Str); @@ -255,8 +210,7 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const { break; // See if this option matches. - options::ID id = (options::ID) (Start - OptionInfos + 1); - if (Arg *A = getOption(id)->accept(Args, Index)) + if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index)) return A; // Otherwise, see if this argument was missing values. @@ -264,6 +218,40 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const { return 0; } - return new PositionalArg(getOption(OPT_UNKNOWN), Index++); + return new PositionalArg(TheUnknownOption, Index++); } +InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd, + unsigned &MissingArgIndex, + unsigned &MissingArgCount) const { + InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); + + // FIXME: Handle '@' args (or at least error on them). + + MissingArgIndex = MissingArgCount = 0; + unsigned Index = 0, End = ArgEnd - ArgBegin; + while (Index < End) { + // Ignore empty arguments (other things may still take them as arguments). + if (Args->getArgString(Index)[0] == '\0') { + ++Index; + continue; + } + + unsigned Prev = Index; + Arg *A = ParseOneArg(*Args, Index); + assert(Index > Prev && "Parser failed to consume argument."); + + // Check for missing argument error. + if (!A) { + assert(Index >= End && "Unexpected parser error."); + assert(Index - Prev - 1 && "No missing arguments!"); + MissingArgIndex = Prev; + MissingArgCount = Index - Prev - 1; + break; + } + + Args->append(A); + } + + return Args; +} diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp index c2ace05..17d00f5 100644 --- a/lib/Driver/Option.cpp +++ b/lib/Driver/Option.cpp @@ -16,9 +16,9 @@ #include <algorithm> using namespace clang::driver; -Option::Option(OptionClass _Kind, options::ID _ID, const char *_Name, +Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name, const OptionGroup *_Group, const Option *_Alias) - : Kind(_Kind), ID(_ID), Name(_Name), Group(_Group), Alias(_Alias), + : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias), Unsupported(false), LinkerInput(false), NoOptAsInput(false), ForceSeparateRender(false), ForceJoinedRender(false), DriverOption(false), NoArgumentUnused(false) { @@ -70,14 +70,13 @@ void Option::dump() const { llvm::errs() << ">\n"; } -bool Option::matches(const Option *Opt) const { - // Aliases are never considered in matching. - if (Opt->getAlias()) - return matches(Opt->getAlias()); +bool Option::matches(OptSpecifier Opt) const { + // Aliases are never considered in matching, look through them. if (Alias) return Alias->matches(Opt); - if (this == Opt) + // Check exact match. + if (ID == Opt) return true; if (Group) @@ -85,23 +84,7 @@ bool Option::matches(const Option *Opt) const { return false; } -bool Option::matches(options::ID Id) const { - // FIXME: Decide what to do here; we should either pull out the - // handling of alias on the option for Id from the other matches, or - // find some other solution (which hopefully doesn't require using - // the option table). - if (Alias) - return Alias->matches(Id); - - if (ID == Id) - return true; - - if (Group) - return Group->matches(Id); - return false; -} - -OptionGroup::OptionGroup(options::ID ID, const char *Name, +OptionGroup::OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group) : Option(Option::GroupClass, ID, Name, Group, 0) { } @@ -111,8 +94,8 @@ Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const { return 0; } -InputOption::InputOption() - : Option(Option::InputClass, options::OPT_INPUT, "<input>", 0, 0) { +InputOption::InputOption(OptSpecifier ID) + : Option(Option::InputClass, ID, "<input>", 0, 0) { } Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const { @@ -120,8 +103,8 @@ Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const { return 0; } -UnknownOption::UnknownOption() - : Option(Option::UnknownClass, options::OPT_UNKNOWN, "<unknown>", 0, 0) { +UnknownOption::UnknownOption(OptSpecifier ID) + : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) { } Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const { @@ -129,7 +112,7 @@ Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const { return 0; } -FlagOption::FlagOption(options::ID ID, const char *Name, +FlagOption::FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::FlagClass, ID, Name, Group, Alias) { } @@ -143,7 +126,7 @@ Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const { return new FlagArg(this, Index++); } -JoinedOption::JoinedOption(options::ID ID, const char *Name, +JoinedOption::JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::JoinedClass, ID, Name, Group, Alias) { } @@ -153,7 +136,7 @@ Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const { return new JoinedArg(this, Index++); } -CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name, +CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) { @@ -170,7 +153,7 @@ Arg *CommaJoinedOption::accept(const InputArgList &Args, return new CommaJoinedArg(this, Index++, Suffix); } -SeparateOption::SeparateOption(options::ID ID, const char *Name, +SeparateOption::SeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::SeparateClass, ID, Name, Group, Alias) { } @@ -188,7 +171,7 @@ Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const { return new SeparateArg(this, Index - 2, 1); } -MultiArgOption::MultiArgOption(options::ID ID, const char *Name, +MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias, unsigned _NumArgs) : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) { @@ -208,7 +191,7 @@ Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const { return new SeparateArg(this, Index - 1 - NumArgs, NumArgs); } -JoinedOrSeparateOption::JoinedOrSeparateOption(options::ID ID, const char *Name, +JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) { @@ -229,7 +212,7 @@ Arg *JoinedOrSeparateOption::accept(const InputArgList &Args, return new SeparateArg(this, Index - 2, 1); } -JoinedAndSeparateOption::JoinedAndSeparateOption(options::ID ID, +JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias) diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index ae8119d..af63952 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -14,7 +14,9 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/HostInfo.h" +#include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" +#include "clang/Driver/Options.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -303,9 +305,9 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args, // and try to push it down into tool specific logic. Arg *OSXVersion = - Args.getLastArg(options::OPT_mmacosx_version_min_EQ, false); + Args.getLastArgNoClaim(options::OPT_mmacosx_version_min_EQ); Arg *iPhoneVersion = - Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false); + Args.getLastArgNoClaim(options::OPT_miphoneos_version_min_EQ); if (OSXVersion && iPhoneVersion) { getHost().getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) @@ -365,8 +367,7 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args, // Sob. These is strictly gcc compatible for the time being. Apple // gcc translates options twice, which means that self-expanding // options add duplicates. - options::ID id = A->getOption().getId(); - switch (id) { + switch ((options::ID) A->getOption().getID()) { default: DAL->append(A); break; @@ -440,7 +441,7 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args, if (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64) - if (!Args.hasArg(options::OPT_mtune_EQ, false)) + if (!Args.hasArgNoClaim(options::OPT_mtune_EQ)) DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), "core2")); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 34154f3..5f0551b 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -18,6 +18,7 @@ #include "clang/Driver/Job.h" #include "clang/Driver/HostInfo.h" #include "clang/Driver/Option.h" +#include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" @@ -81,8 +82,8 @@ void Clang::AddPreprocessingOptions(const Driver &D, DepFile = Output.getFilename(); } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(Args); - } else if (A->getOption().getId() == options::OPT_M || - A->getOption().getId() == options::OPT_MM) { + } else if (A->getOption().matches(options::OPT_M) || + A->getOption().matches(options::OPT_MM)) { DepFile = "-"; } else { DepFile = darwin::CC1::getDependencyFileName(Args, Inputs); @@ -116,8 +117,8 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back(DepTarget); } - if (A->getOption().getId() == options::OPT_M || - A->getOption().getId() == options::OPT_MD) + if (A->getOption().matches(options::OPT_M) || + A->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); } @@ -778,12 +779,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; } - if (Args.hasFlag(options::OPT_fmath_errno, + // -fmath-errno is default. + if (!Args.hasFlag(options::OPT_fmath_errno, options::OPT_fno_math_errno, getToolChain().IsMathErrnoDefault())) - CmdArgs.push_back("--fmath-errno=1"); - else - CmdArgs.push_back("--fmath-errno=0"); + CmdArgs.push_back("-fno-math-errno"); if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("--limit-float-precision"); @@ -822,7 +822,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Manually translate -O to -O2 and -O4 to -O3; let clang reject // others. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { - if (A->getOption().getId() == options::OPT_O4) + if (A->getOption().matches(options::OPT_O4)) CmdArgs.push_back("-O3"); else if (A->getValue(Args)[0] == '\0') CmdArgs.push_back("-O2"); @@ -864,7 +864,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - if (Args.hasArg(options::OPT__relocatable_pch, true)) + if (Args.hasArg(options::OPT__relocatable_pch)) CmdArgs.push_back("--relocatable-pch"); if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) { @@ -922,7 +922,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fbuiltin is default. if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) - CmdArgs.push_back("-fbuiltin=0"); + CmdArgs.push_back("-fno-builtin"); // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, @@ -938,7 +938,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -frtti is default. if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti)) - CmdArgs.push_back("-frtti=0"); + CmdArgs.push_back("-fno-rtti"); // -fsigned-char is default. if (!Args.hasFlag(options::OPT_fsigned_char, @@ -2609,6 +2609,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // the default system libraries. Just mimic this for now. CmdArgs.push_back("-lgcc"); + if (D.CCCIsCXX) + CmdArgs.push_back("-lstdc++"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-lgcc_eh"); } else { @@ -2638,10 +2640,6 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o"))); - // FIXME: g++ is more complicated here, it tries to put -lstdc++ - // before -lm, for example. - if (D.CCCIsCXX) - CmdArgs.push_back("-lstdc++"); } const char *Exec = diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp index 30893e7..750286b 100644 --- a/lib/Driver/Types.cpp +++ b/lib/Driver/Types.cpp @@ -16,14 +16,14 @@ using namespace clang::driver; using namespace clang::driver::types; -struct Info { +struct TypeInfo { const char *Name; const char *Flags; const char *TempSuffix; ID PreprocessedType; }; -static Info TypeInfos[] = { +static TypeInfo TypeInfos[] = { #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \ { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, }, #include "clang/Driver/Types.def" @@ -31,7 +31,7 @@ static Info TypeInfos[] = { }; static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]); -static Info &getInfo(unsigned id) { +static TypeInfo &getInfo(unsigned id) { assert(id > 0 && id - 1 < numTypes && "Invalid Type ID."); return TypeInfos[id - 1]; } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index ed6d0b7..b4a79c6 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -14,7 +14,6 @@ using namespace clang; void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, const llvm::SmallVectorImpl<llvm::StringRef> &Args) { - llvm::llvm_report_error("FIXME: Not yet implemented!"); } static const char *getAnalysisName(Analyses Kind) { @@ -83,8 +82,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyzer-display-progress"); if (Opts.EagerlyAssume) Res.push_back("-analyzer-eagerly-assume"); - if (Opts.PurgeDead) - Res.push_back("-analyzer-purge-dead"); + if (!Opts.PurgeDead) + Res.push_back("-analyzer-no-purge-dead"); if (Opts.TrimGraph) Res.push_back("-trim-egraph"); if (Opts.VisualizeEGDot) @@ -238,7 +237,7 @@ static const char *getActionName(frontend::ActionKind Kind) { static void FrontendOptsToArgs(const FrontendOptions &Opts, std::vector<std::string> &Res) { if (!Opts.DebugCodeCompletionPrinter) - Res.push_back("-code-completion-debug-printer=0"); + Res.push_back("-no-code-completion-debug-printer"); if (Opts.DisableFree) Res.push_back("-disable-free"); if (Opts.EmptyInputOnly) @@ -298,7 +297,7 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, std::vector<std::string> &Res) { - if (Opts.Sysroot.empty()) { + if (Opts.Sysroot != "/") { Res.push_back("-isysroot"); Res.push_back(Opts.Sysroot); } @@ -394,8 +393,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-faltivec"); Res.push_back("-fexceptions"); Res.push_back(Opts.Exceptions ? "1" : "0"); - Res.push_back("-frtti"); - Res.push_back(Opts.Rtti ? "1" : "0"); + if (!Opts.Rtti) + Res.push_back("-fno-rtti"); if (!Opts.NeXTRuntime) Res.push_back("-fgnu-runtime"); if (Opts.Freestanding) @@ -411,7 +410,7 @@ static void LangOptsToArgs(const LangOptions &Opts, if (Opts.EmitAllDecls) Res.push_back("-femit-all-decls"); if (!Opts.MathErrno) - Res.push_back("-fmath-errno=0"); + Res.push_back("-fno-math-errno"); if (Opts.OverflowChecking) Res.push_back("-ftrapv"); if (Opts.HeinousExtensions) diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 4ee286d..b77c240 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -237,6 +237,13 @@ static void DefineType(const char *MacroName, TargetInfo::IntType Ty, DefineBuiltinMacro(Buf, MacroBuf); } +static void DefineTypeWidth(const char *MacroName, TargetInfo::IntType Ty, + const TargetInfo &TI, std::vector<char> &Buf) { + char MacroBuf[60]; + sprintf(MacroBuf, "%s=%d", MacroName, TI.getTypeWidth(Ty)); + DefineBuiltinMacro(Buf, MacroBuf); +} + static void DefineExactWidthIntType(TargetInfo::IntType Ty, const TargetInfo &TI, std::vector<char> &Buf) { char MacroBuf[60]; @@ -381,10 +388,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Buf); DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Buf); - DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Buf); - DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Buf); + DefineTypeWidth("__INTMAX_WIDTH__", TI.getIntMaxType(), TI, Buf); DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Buf); DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Buf); + DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Buf); DefineType("__SIZE_TYPE__", TI.getSizeType(), Buf); DefineType("__WCHAR_TYPE__", TI.getWCharType(), Buf); DefineType("__WINT_TYPE__", TI.getWIntType(), Buf); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index ca7aa32..c9679b7 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/System/Path.h" #include <algorithm> #include <iterator> #include <cstdio> @@ -1086,11 +1087,9 @@ void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) { if (!RelocatablePCH) return; - if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<') + if (Filename.empty() || llvm::sys::Path(Filename).isAbsolute()) return; - std::string FIXME = Filename; - if (isysroot == 0) { // If no system root was given, default to '/' Filename.insert(Filename.begin(), '/'); diff --git a/lib/Headers/stdint.h b/lib/Headers/stdint.h index bb81a6a..ccaf349 100644 --- a/lib/Headers/stdint.h +++ b/lib/Headers/stdint.h @@ -213,16 +213,19 @@ typedef __uint_least8_t uint_fast8_t; /* C99 7.18.1.4 Integer types capable of holding object pointers. */ +#define __stdint_join3(a,b,c) a ## b ## c +#define __stdint_exjoin3(a,b,c) __stdint_join3(a,b,c) + #ifndef __intptr_t_defined -typedef __INTPTR_TYPE__ intptr_t; +typedef __stdint_exjoin3( int, __INTPTR_WIDTH__, _t) intptr_t; #define __intptr_t_defined #endif -typedef unsigned __INTPTR_TYPE__ uintptr_t; +typedef __stdint_exjoin3(uint, __INTPTR_WIDTH__, _t) uintptr_t; /* C99 7.18.1.5 Greatest-width integer types. */ -typedef __INTMAX_TYPE__ intmax_t; -typedef __UINTMAX_TYPE__ uintmax_t; +typedef __stdint_exjoin3( int, __INTMAX_WIDTH__, _t) intmax_t; +typedef __stdint_exjoin3(uint, __INTMAX_WIDTH__, _t) uintmax_t; /* C99 7.18.4 Macros for minimum-width integer constants. * @@ -600,29 +603,24 @@ typedef __UINTMAX_TYPE__ uintmax_t; /* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */ /* C99 7.18.3 Limits of other integer types. */ +#define INTPTR_MIN __stdint_exjoin3( INT, __INTPTR_WIDTH__, _MIN) +#define INTPTR_MAX __stdint_exjoin3( INT, __INTPTR_WIDTH__, _MAX) +#define UINTPTR_MAX __stdint_exjoin3(UINT, __INTPTR_WIDTH__, _MAX) + #if __POINTER_WIDTH__ == 64 -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#define UINTPTR_MAX UINT64_MAX #define PTRDIFF_MIN INT64_MIN #define PTRDIFF_MAX INT64_MAX #define SIZE_MAX UINT64_MAX #elif __POINTER_WIDTH__ == 32 -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#define UINTPTR_MAX UINT32_MAX #define PTRDIFF_MIN INT32_MIN #define PTRDIFF_MAX INT32_MAX #define SIZE_MAX UINT32_MAX #elif __POINTER_WIDTH__ == 16 -#define INTPTR_MIN INT16_MIN -#define INTPTR_MAX INT16_MAX -#define UINTPTR_MAX UINT16_MAX #define PTRDIFF_MIN INT16_MIN #define PTRDIFF_MAX INT16_MAX #define SIZE_MAX UINT16_MAX @@ -632,9 +630,9 @@ typedef __UINTMAX_TYPE__ uintmax_t; #endif /* C99 7.18.2.5 Limits of greatest-width integer types. */ -#define INTMAX_MIN (-__INTMAX_MAX__-1) -#define INTMAX_MAX __INTMAX_MAX__ -#define UINTMAX_MAX (__INTMAX_MAX__*2ULL+1ULL) +#define INTMAX_MIN __stdint_exjoin3( INT, __INTMAX_WIDTH__, _MIN) +#define INTMAX_MAX __stdint_exjoin3( INT, __INTMAX_WIDTH__, _MAX) +#define UINTMAX_MAX __stdint_exjoin3(UINT, __INTMAX_WIDTH__, _MAX) /* C99 7.18.3 Limits of other integer types. */ #define SIG_ATOMIC_MIN INT32_MIN @@ -653,8 +651,8 @@ typedef __UINTMAX_TYPE__ uintmax_t; #endif /* 7.18.4.2 Macros for greatest-width integer constants. */ -#define INTMAX_C(v) v##LL -#define UINTMAX_C(v) v##ULL +#define INTMAX_C(v) __stdint_exjoin3( INT, __INTMAX_WIDTH__, _C(v)) +#define UINTMAX_C(v) __stdint_exjoin3(UINT, __INTMAX_WIDTH__, _C(v)) #endif /* __STDC_HOSTED__ */ #endif /* __CLANG_STDINT_H */ diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 95a0e98..d2b3b84 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -341,17 +341,6 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) { ColonLoc = ConsumeToken(); } - if ((OpToken.is(tok::periodstar) || OpToken.is(tok::arrowstar)) - && Tok.is(tok::identifier)) { - CXXScopeSpec SS; - if (Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope, &SS)) { - const char *Opc = OpToken.is(tok::periodstar) ? "'.*'" : "'->*'"; - Diag(OpToken, diag::err_pointer_to_member_type) << Opc; - return ExprError(); - } - - } // Parse another leaf here for the RHS of the operator. // ParseCastExpression works here because all RHS expressions in C have it // as a prefix, at least. However, in C++, an assignment-expression could diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 65bd79d..5ba1dd1 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -123,6 +123,12 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( "ParseObjCAtInterfaceDeclaration(): Expected @interface"); ConsumeToken(); // the "interface" identifier + // Code completion after '@interface'. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCInterfaceDecl(CurScope); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing class or category name. return DeclPtrTy(); @@ -137,6 +143,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( SourceLocation categoryLoc, rparenLoc; IdentifierInfo *categoryId = 0; + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId); + ConsumeToken(); + } + // For ObjC2, the category name is optional (not an error). if (Tok.is(tok::identifier)) { categoryId = Tok.getIdentifierInfo(); @@ -181,6 +192,13 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration( if (Tok.is(tok::colon)) { // a super class is specified. ConsumeToken(); + + // Code completion of superclass names. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCSuperclass(CurScope, nameId); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing super class name. return DeclPtrTy(); @@ -308,7 +326,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, ObjCDeclSpec OCDS; // Parse property attribute list, if any. if (Tok.is(tok::l_paren)) - ParseObjCPropertyAttribute(OCDS); + ParseObjCPropertyAttribute(OCDS, interfaceDecl, + allMethods.data(), allMethods.size()); struct ObjCPropertyCallback : FieldCallback { Parser &P; @@ -407,13 +426,15 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, /// copy /// nonatomic /// -void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { +void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { assert(Tok.getKind() == tok::l_paren); SourceLocation LHSLoc = ConsumeParen(); // consume '(' while (1) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCProperty(CurScope, DS); + Actions.CodeCompleteObjCPropertyFlags(CurScope, DS); ConsumeToken(); } const IdentifierInfo *II = Tok.getIdentifierInfo(); @@ -444,6 +465,16 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { tok::r_paren)) return; + if (Tok.is(tok::code_completion)) { + if (II->getNameStart()[0] == 's') + Actions.CodeCompleteObjCPropertySetter(CurScope, ClassDecl, + Methods, NumMethods); + else + Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl, + Methods, NumMethods); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); SkipUntil(tok::r_paren); @@ -1078,6 +1109,12 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( "ParseObjCAtImplementationDeclaration(): Expected @implementation"); ConsumeToken(); // the "implementation" identifier + // Code completion after '@implementation'. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCImplementationDecl(CurScope); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); // missing class or category name. return DeclPtrTy(); @@ -1092,6 +1129,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration( SourceLocation categoryLoc, rparenLoc; IdentifierInfo *categoryId = 0; + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId); + ConsumeToken(); + } + if (Tok.is(tok::identifier)) { categoryId = Tok.getIdentifierInfo(); categoryLoc = ConsumeToken(); @@ -1202,18 +1244,32 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { assert(Tok.isObjCAtKeyword(tok::objc_synthesize) && "ParseObjCPropertyDynamic(): Expected '@synthesize'"); SourceLocation loc = ConsumeToken(); // consume synthesize - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - return DeclPtrTy(); - } - while (Tok.is(tok::identifier)) { + while (true) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl); + ConsumeToken(); + } + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_synthesized_property_name); + SkipUntil(tok::semi); + return DeclPtrTy(); + } + IdentifierInfo *propertyIvar = 0; IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name if (Tok.is(tok::equal)) { // property '=' ivar-name ConsumeToken(); // consume '=' + + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId, + ObjCImpDecl); + ConsumeToken(); + } + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); break; @@ -1227,8 +1283,10 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { break; ConsumeToken(); // consume ',' } - if (Tok.isNot(tok::semi)) + if (Tok.isNot(tok::semi)) { Diag(Tok, diag::err_expected_semi_after) << "@synthesize"; + SkipUntil(tok::semi); + } else ConsumeToken(); // consume ';' return DeclPtrTy(); @@ -1245,11 +1303,18 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { assert(Tok.isObjCAtKeyword(tok::objc_dynamic) && "ParseObjCPropertyDynamic(): Expected '@dynamic'"); SourceLocation loc = ConsumeToken(); // consume dynamic - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - return DeclPtrTy(); - } - while (Tok.is(tok::identifier)) { + while (true) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl); + ConsumeToken(); + } + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_expected_ident); + SkipUntil(tok::semi); + return DeclPtrTy(); + } + IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl, @@ -1580,11 +1645,14 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, ExprArg ReceiverExpr) { if (Tok.is(tok::code_completion)) { if (ReceiverName) - Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc); + Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, + 0, 0); else - Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get()); + Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), + 0, 0); ConsumeToken(); } + // Parse objc-selector SourceLocation Loc; IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc); @@ -1622,6 +1690,19 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, // We have a valid expression. KeyExprs.push_back(Res.release()); + // Code completion after each argument. + if (Tok.is(tok::code_completion)) { + if (ReceiverName) + Actions.CodeCompleteObjCClassMessage(CurScope, ReceiverName, NameLoc, + KeyIdents.data(), + KeyIdents.size()); + else + Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(), + KeyIdents.data(), + KeyIdents.size()); + ConsumeToken(); + } + // Check for another keyword selector. selIdent = ParseObjCSelectorPiece(Loc); if (!selIdent && Tok.isNot(tok::colon)) diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 88ac4e4..a9d8301 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -117,6 +117,33 @@ CodeCompletionString::Chunk::CreateCurrentParameter( return Chunk(CK_CurrentParameter, CurrentParameter); } +CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const { + switch (Kind) { + case CK_TypedText: + case CK_Text: + case CK_Placeholder: + case CK_Informative: + case CK_CurrentParameter: + case CK_LeftParen: + case CK_RightParen: + case CK_LeftBracket: + case CK_RightBracket: + case CK_LeftBrace: + case CK_RightBrace: + case CK_LeftAngle: + case CK_RightAngle: + case CK_Comma: + return Chunk(Kind, Text); + + case CK_Optional: { + std::auto_ptr<CodeCompletionString> Opt(Optional->Clone()); + return CreateOptional(Opt); + } + } + + // Silence GCC warning. + return Chunk(); +} void CodeCompletionString::Chunk::Destroy() { @@ -168,6 +195,20 @@ std::string CodeCompletionString::getAsString() const { return Result; } +const char *CodeCompletionString::getTypedText() const { + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) + if (C->Kind == CK_TypedText) + return C->Text; + + return 0; +} + +CodeCompletionString *CodeCompletionString::Clone() const { + CodeCompletionString *Result = new CodeCompletionString; + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) + Result->AddChunk(C->Clone()); + return Result; +} namespace { // Escape a string for XML-like formatting. @@ -473,6 +514,13 @@ CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) { return Result; } +void CodeCompleteConsumer::Result::Destroy() { + if (Kind == RK_Pattern) { + delete Pattern; + Pattern = 0; + } +} + //===----------------------------------------------------------------------===// // Code completion overload candidate implementation //===----------------------------------------------------------------------===// @@ -545,6 +593,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, OS << '\n'; break; } + + case Result::RK_Pattern: { + OS << "Pattern : " << Results[I].Rank << " : " + << Results[I].Pattern->getAsString() << '\n'; + break; + } } } @@ -627,6 +681,13 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, OS << '\n'; break; } + + case Result::RK_Pattern: { + OS << "Pattern:"; + Results[I].Pattern->Serialize(OS); + OS << '\n'; + break; + } } } diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index 6e72dce..10cc818 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -201,6 +201,13 @@ public: return getResultKind() == Ambiguous; } + /// Determines if this names a single result which is not an + /// unresolved value using decl. If so, it is safe to call + /// getFoundDecl(). + bool isSingleResult() const { + return getResultKind() == Found; + } + LookupResultKind getResultKind() const { sanity(); return ResultKind; @@ -248,12 +255,24 @@ public: Decls.set_size(N); } - /// \brief Resolves the kind of the lookup, possibly hiding decls. + /// \brief Resolves the result kind of the lookup, possibly hiding + /// decls. /// /// This should be called in any environment where lookup might /// generate multiple lookup results. void resolveKind(); + /// \brief Re-resolves the result kind of the lookup after a set of + /// removals has been performed. + void resolveKindAfterFilter() { + if (Decls.empty()) + ResultKind = NotFound; + else { + ResultKind = Found; + resolveKind(); + } + } + /// \brief Fetch this as an unambiguous single declaration /// (possibly an overloaded one). /// @@ -272,6 +291,12 @@ public: return Decls[0]->getUnderlyingDecl(); } + /// Fetches a representative decl. Useful for lazy diagnostics. + NamedDecl *getRepresentativeDecl() const { + assert(!Decls.empty() && "cannot get representative of empty set"); + return Decls[0]; + } + /// \brief Asks if the result is a single tag decl. bool isSingleTagDecl() const { return getResultKind() == Found && isa<TagDecl>(getFoundDecl()); @@ -337,6 +362,65 @@ public: return NameLoc; } + /// A class for iterating through a result set and possibly + /// filtering out results. The results returned are possibly + /// sugared. + class Filter { + LookupResult &Results; + unsigned I; + bool ErasedAny; +#ifndef NDEBUG + bool CalledDone; +#endif + + friend class LookupResult; + Filter(LookupResult &Results) + : Results(Results), I(0), ErasedAny(false) +#ifndef NDEBUG + , CalledDone(false) +#endif + {} + + public: +#ifndef NDEBUG + ~Filter() { + assert(CalledDone && + "LookupResult::Filter destroyed without done() call"); + } +#endif + + bool hasNext() const { + return I != Results.Decls.size(); + } + + NamedDecl *next() { + assert(I < Results.Decls.size() && "next() called on empty filter"); + return Results.Decls[I++]; + } + + /// Erase the last element returned from this iterator. + void erase() { + Results.Decls[--I] = Results.Decls.back(); + Results.Decls.pop_back(); + ErasedAny = true; + } + + void done() { +#ifndef NDEBUG + assert(!CalledDone && "done() called twice"); + CalledDone = true; +#endif + + if (ErasedAny) + Results.resolveKindAfterFilter(); + } + }; + + /// Create a filter for this result set. + Filter makeFilter() { + return Filter(*this); + } + private: void diagnose() { if (isAmbiguous()) diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index b2bbac8..fe2d744 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -319,7 +319,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { &Context.Idents.get("Protocol"), SourceLocation(), true); Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); - PushOnScopeChains(ProtocolDecl, TUScope); + PushOnScopeChains(ProtocolDecl, TUScope, false); } // Create the built-in typedef for 'id'. if (Context.getObjCIdType().isNull()) { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3e186b2..ad4c90b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -548,26 +548,32 @@ public: DeclPtrTy HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, bool IsFunctionDefinition); - void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, + void RegisterLocallyScopedExternCDecl(NamedDecl *ND, + const LookupResult &Previous, Scope *S); void DiagnoseFunctionSpecifiers(Declarator& D); + bool CheckRedeclaration(DeclContext *DC, + DeclarationName Name, + SourceLocation NameLoc, + unsigned Diagnostic); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, DeclaratorInfo *DInfo, - NamedDecl* PrevDecl, bool &Redeclaration); + LookupResult &Previous, bool &Redeclaration); NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, DeclaratorInfo *DInfo, - NamedDecl* PrevDecl, + LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &Redeclaration); - void CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, + void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous, bool &Redeclaration); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, DeclaratorInfo *DInfo, - NamedDecl* PrevDecl, + LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, bool &Redeclaration); - void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, + void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); + void CheckFunctionDeclaration(FunctionDecl *NewFD, LookupResult &Previous, bool IsExplicitSpecialization, bool &Redeclaration, bool &OverloadableAttrRequired); @@ -779,15 +785,17 @@ public: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, DeclaratorInfo *DInfo); - void MergeTypeDefDecl(TypedefDecl *New, Decl *Old); + void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); - void MergeVarDecl(VarDecl *New, Decl *Old); + void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); /// C++ Overloading. - bool IsOverload(FunctionDecl *New, Decl* OldD, - OverloadedFunctionDecl::function_iterator &MatchedDecl); + bool IsOverload(FunctionDecl *New, LookupResult &OldDecls, + NamedDecl *&OldDecl); + bool IsOverload(FunctionDecl *New, FunctionDecl *Old); + ImplicitConversionSequence TryImplicitConversion(Expr* From, QualType ToType, bool SuppressUserConversions, @@ -822,7 +830,7 @@ public: bool AllowConversionFunctions, bool AllowExplicit, bool ForceRValue, bool UserCast = false); - bool DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType); + bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); ImplicitConversionSequence::CompareKind @@ -2324,8 +2332,8 @@ public: const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation RAngleLoc, - NamedDecl *&PrevDecl); - bool CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl); + LookupResult &Previous); + bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); virtual DeclResult ActOnExplicitInstantiation(Scope *S, @@ -3638,14 +3646,38 @@ public: virtual void CodeCompleteNamespaceAliasDecl(Scope *S); virtual void CodeCompleteOperatorName(Scope *S); - virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS); + virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); + virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods); + virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods); + virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, - SourceLocation FNameLoc); - virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver); + SourceLocation FNameLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, unsigned NumProtocols); virtual void CodeCompleteObjCProtocolDecl(Scope *S); - //@} + virtual void CodeCompleteObjCInterfaceDecl(Scope *S); + virtual void CodeCompleteObjCSuperclass(Scope *S, + IdentifierInfo *ClassName); + virtual void CodeCompleteObjCImplementationDecl(Scope *S); + virtual void CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName); + virtual void CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName); + virtual void CodeCompleteObjCPropertyDefinition(Scope *S, + DeclPtrTy ObjCImpDecl); + virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName, + DeclPtrTy ObjCImpDecl); + //@} //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index e5ad338..6b4f87e 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -175,6 +175,30 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return ExprError(); } +/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, +/// this removes one level of indirection from both types, provided that they're +/// the same kind of pointer (plain or to-member). Unlike the Sema function, +/// this one doesn't care if the two pointers-to-member don't point into the +/// same class. This is because CastsAwayConstness doesn't care. +bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { + const PointerType *T1PtrType = T1->getAs<PointerType>(), + *T2PtrType = T2->getAs<PointerType>(); + if (T1PtrType && T2PtrType) { + T1 = T1PtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + + const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), + *T2MPType = T2->getAs<MemberPointerType>(); + if (T1MPType && T2MPType) { + T1 = T1MPType->getPointeeType(); + T2 = T2MPType->getPointeeType(); + return true; + } + return false; +} + /// CastsAwayConstness - Check if the pointer conversion from SrcType to /// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by /// the cast checkers. Both arguments must denote pointer (possibly to member) @@ -195,7 +219,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { llvm::SmallVector<Qualifiers, 8> cv1, cv2; // Find the qualifications. - while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { + while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { cv1.push_back(UnwrappedSrcType.getQualifiers()); cv2.push_back(UnwrappedDestType.getQualifiers()); } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 9cecdad..6dbb442 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -944,26 +944,50 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { return Result; } - Result->AddTypedTextChunk( - Sel.getIdentifierInfoForSlot(0)->getName().str() + std::string(":")); + std::string SelName = Sel.getIdentifierInfoForSlot(0)->getName().str(); + SelName += ':'; + if (StartParameter == 0) + Result->AddTypedTextChunk(SelName); + else { + Result->AddInformativeChunk(SelName); + + // If there is only one parameter, and we're past it, add an empty + // typed-text chunk since there is nothing to type. + if (Method->param_size() == 1) + Result->AddTypedTextChunk(""); + } unsigned Idx = 0; for (ObjCMethodDecl::param_iterator P = Method->param_begin(), PEnd = Method->param_end(); P != PEnd; (void)++P, ++Idx) { if (Idx > 0) { - std::string Keyword = " "; + std::string Keyword; + if (Idx > StartParameter) + Keyword = " "; if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) Keyword += II->getName().str(); Keyword += ":"; - Result->AddTextChunk(Keyword); + if (Idx < StartParameter || AllParametersAreInformative) { + Result->AddInformativeChunk(Keyword); + } else if (Idx == StartParameter) + Result->AddTypedTextChunk(Keyword); + else + Result->AddTextChunk(Keyword); } + + // If we're before the starting parameter, skip the placeholder. + if (Idx < StartParameter) + continue; std::string Arg; (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy); Arg = "(" + Arg + ")"; if (IdentifierInfo *II = (*P)->getIdentifier()) Arg += II->getName().str(); - Result->AddPlaceholderChunk(Arg); + if (AllParametersAreInformative) + Result->AddInformativeChunk(Arg); + else + Result->AddPlaceholderChunk(Arg); } return Result; @@ -1066,6 +1090,17 @@ namespace { else if (X.Rank > Y.Rank) return false; + // We use a special ordering for keywords and patterns, based on the + // typed text. + if ((X.Kind == Result::RK_Keyword || X.Kind == Result::RK_Pattern) && + (Y.Kind == Result::RK_Keyword || Y.Kind == Result::RK_Pattern)) { + const char *XStr = (X.Kind == Result::RK_Keyword)? X.Keyword + : X.Pattern->getTypedText(); + const char *YStr = (Y.Kind == Result::RK_Keyword)? Y.Keyword + : Y.Pattern->getTypedText(); + return strcmp(XStr, YStr) < 0; + } + // Result kinds are ordered by decreasing importance. if (X.Kind < Y.Kind) return true; @@ -1087,12 +1122,14 @@ namespace { return isEarlierDeclarationName(X.Declaration->getDeclName(), Y.Declaration->getDeclName()); - case Result::RK_Keyword: - return strcmp(X.Keyword, Y.Keyword) < 0; - case Result::RK_Macro: return llvm::LowercaseString(X.Macro->getName()) < llvm::LowercaseString(Y.Macro->getName()); + + case Result::RK_Keyword: + case Result::RK_Pattern: + llvm::llvm_unreachable("Result kinds handled above"); + break; } // Silence GCC warning. @@ -1120,6 +1157,9 @@ static void HandleCodeCompleteResults(Sema *S, if (CodeCompleter) CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults); + + for (unsigned I = 0; I != NumResults; ++I) + Results[I].Destroy(); } void Sema::CodeCompleteOrdinaryName(Scope *S) { @@ -1132,6 +1172,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S) { } static void AddObjCProperties(ObjCContainerDecl *Container, + bool AllowCategories, DeclContext *CurContext, ResultBuilder &Results) { typedef CodeCompleteConsumer::Result Result; @@ -1148,29 +1189,32 @@ static void AddObjCProperties(ObjCContainerDecl *Container, for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), PEnd = Protocol->protocol_end(); P != PEnd; ++P) - AddObjCProperties(*P, CurContext, Results); + AddObjCProperties(*P, AllowCategories, CurContext, Results); } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ - // Look through categories. - for (ObjCCategoryDecl *Category = IFace->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - AddObjCProperties(Category, CurContext, Results); + if (AllowCategories) { + // Look through categories. + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + AddObjCProperties(Category, AllowCategories, CurContext, Results); + } // Look through protocols. for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), E = IFace->protocol_end(); I != E; ++I) - AddObjCProperties(*I, CurContext, Results); + AddObjCProperties(*I, AllowCategories, CurContext, Results); // Look in the superclass. if (IFace->getSuperClass()) - AddObjCProperties(IFace->getSuperClass(), CurContext, Results); + AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext, + Results); } else if (const ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { // Look through protocols. for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(), PEnd = Category->protocol_end(); P != PEnd; ++P) - AddObjCProperties(*P, CurContext, Results); + AddObjCProperties(*P, AllowCategories, CurContext, Results); } } @@ -1234,13 +1278,13 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, const ObjCObjectPointerType *ObjCPtr = BaseType->getAsObjCInterfacePointerType(); assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); - AddObjCProperties(ObjCPtr->getInterfaceDecl(), CurContext, Results); + AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext, Results); // Add properties from the protocols in a qualified interface. for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(), E = ObjCPtr->qual_end(); I != E; ++I) - AddObjCProperties(*I, CurContext, Results); + AddObjCProperties(*I, true, CurContext, Results); // FIXME: We could (should?) also look for "implicit" properties, identified // only by the presence of nullary and unary selectors. @@ -1611,34 +1655,104 @@ void Sema::CodeCompleteOperatorName(Scope *S) { HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } -void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { +/// \brief Determine whether the addition of the given flag to an Objective-C +/// property's attributes will cause a conflict. +static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { + // Check if we've already added this flag. + if (Attributes & NewFlag) + return true; + + Attributes |= NewFlag; + + // Check for collisions with "readonly". + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | + ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain))) + return true; + + // Check for more than one of { assign, copy, retain }. + unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain); + if (AssignCopyRetMask && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain) + return true; + + return false; +} + +void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { if (!CodeCompleter) return; + unsigned Attributes = ODS.getPropertyAttributes(); typedef CodeCompleteConsumer::Result Result; ResultBuilder Results(*this); Results.EnterNewScope(); - if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) Results.MaybeAddResult(CodeCompleteConsumer::Result("readonly", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_assign)) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) Results.MaybeAddResult(CodeCompleteConsumer::Result("assign", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_readwrite)) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) Results.MaybeAddResult(CodeCompleteConsumer::Result("readwrite", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_retain)) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) Results.MaybeAddResult(CodeCompleteConsumer::Result("retain", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) Results.MaybeAddResult(CodeCompleteConsumer::Result("copy", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) Results.MaybeAddResult(CodeCompleteConsumer::Result("nonatomic", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_setter)) - Results.MaybeAddResult(CodeCompleteConsumer::Result("setter", 0)); - if (!(Attributes & ObjCDeclSpec::DQ_PR_getter)) - Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0)); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { + CodeCompletionString *Setter = new CodeCompletionString; + Setter->AddTypedTextChunk("setter"); + Setter->AddTextChunk(" = "); + Setter->AddPlaceholderChunk("method"); + Results.MaybeAddResult(CodeCompleteConsumer::Result(Setter, 0)); + } + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { + CodeCompletionString *Getter = new CodeCompletionString; + Getter->AddTypedTextChunk("getter"); + Getter->AddTextChunk(" = "); + Getter->AddPlaceholderChunk("method"); + Results.MaybeAddResult(CodeCompleteConsumer::Result(Getter, 0)); + } Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } +/// \brief Descripts the kind of Objective-C method that we want to find +/// via code completion. +enum ObjCMethodKind { + MK_Any, //< Any kind of method, provided it means other specified criteria. + MK_ZeroArgSelector, //< Zero-argument (unary) selector. + MK_OneArgSelector //< One-argument selector. +}; + +static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + Selector Sel = Method->getSelector(); + if (NumSelIdents > Sel.getNumArgs()) + return false; + + switch (WantKind) { + case MK_Any: break; + case MK_ZeroArgSelector: return Sel.isUnarySelector(); + case MK_OneArgSelector: return Sel.getNumArgs() == 1; + } + + for (unsigned I = 0; I != NumSelIdents; ++I) + if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I)) + return false; + + return true; +} + /// \brief Add all of the Objective-C methods in the given Objective-C /// container to the set of results. /// @@ -1658,14 +1772,26 @@ void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { /// \param Results the structure into which we'll add results. static void AddObjCMethods(ObjCContainerDecl *Container, bool WantInstanceMethods, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, DeclContext *CurContext, ResultBuilder &Results) { typedef CodeCompleteConsumer::Result Result; for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), MEnd = Container->meth_end(); M != MEnd; ++M) { - if ((*M)->isInstanceMethod() == WantInstanceMethods) - Results.MaybeAddResult(Result(*M, 0), CurContext); + if ((*M)->isInstanceMethod() == WantInstanceMethods) { + // Check whether the selector identifiers we've been given are a + // subset of the identifiers for this particular method. + if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents)) + continue; + + Result R = Result(*M, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = (WantKind != MK_Any); + Results.MaybeAddResult(R, CurContext); + } } ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); @@ -1677,12 +1803,14 @@ static void AddObjCMethods(ObjCContainerDecl *Container, for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, CurContext, Results); + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, + CurContext, Results); // Add methods in categories. for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; CatDecl = CatDecl->getNextClassCategory()) { - AddObjCMethods(CatDecl, WantInstanceMethods, CurContext, Results); + AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Results); // Add a categories protocol methods. const ObjCList<ObjCProtocolDecl> &Protocols @@ -1690,25 +1818,110 @@ static void AddObjCMethods(ObjCContainerDecl *Container, for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, CurContext, Results); + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Results); // Add methods in category implementations. if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) - AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results); + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Results); } // Add methods in superclass. if (IFace->getSuperClass()) - AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, CurContext, - Results); + AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, + SelIdents, NumSelIdents, CurContext, Results); // Add methods in our implementation, if any. if (ObjCImplementationDecl *Impl = IFace->getImplementation()) - AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results); + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Results); +} + + +void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { + typedef CodeCompleteConsumer::Result Result; + + // Try to find the interface where getters might live. + ObjCInterfaceDecl *Class + = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl.getAs<Decl>()); + if (!Class) { + if (ObjCCategoryDecl *Category + = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl.getAs<Decl>())) + Class = Category->getClassInterface(); + + if (!Class) + return; + } + + // Find all of the potential getters. + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // FIXME: We need to do this because Objective-C methods don't get + // pushed into DeclContexts early enough. Argh! + for (unsigned I = 0; I != NumMethods; ++I) { + if (ObjCMethodDecl *Method + = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>())) + if (Method->isInstanceMethod() && + isAcceptableObjCMethod(Method, MK_ZeroArgSelector, 0, 0)) { + Result R = Result(Method, 0); + R.AllParametersAreInformative = true; + Results.MaybeAddResult(R, CurContext); + } + } + + AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Results); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl, + DeclPtrTy *Methods, + unsigned NumMethods) { + typedef CodeCompleteConsumer::Result Result; + + // Try to find the interface where setters might live. + ObjCInterfaceDecl *Class + = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl.getAs<Decl>()); + if (!Class) { + if (ObjCCategoryDecl *Category + = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl.getAs<Decl>())) + Class = Category->getClassInterface(); + + if (!Class) + return; + } + + // Find all of the potential getters. + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // FIXME: We need to do this because Objective-C methods don't get + // pushed into DeclContexts early enough. Argh! + for (unsigned I = 0; I != NumMethods; ++I) { + if (ObjCMethodDecl *Method + = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>())) + if (Method->isInstanceMethod() && + isAcceptableObjCMethod(Method, MK_OneArgSelector, 0, 0)) { + Result R = Result(Method, 0); + R.AllParametersAreInformative = true; + Results.MaybeAddResult(R, CurContext); + } + } + + AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size()); } void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, - SourceLocation FNameLoc) { + SourceLocation FNameLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { typedef CodeCompleteConsumer::Result Result; ObjCInterfaceDecl *CDecl = 0; @@ -1734,7 +1947,8 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, SuperTy = Context.getObjCObjectPointerType(SuperTy); OwningExprResult Super = Owned(new (Context) ObjCSuperExpr(FNameLoc, SuperTy)); - return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get()); + return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), + SelIdents, NumSelIdents); } // Okay, we're calling a factory method in our superclass. @@ -1756,21 +1970,25 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, // probably calling an instance method. OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName, false, 0, false); - return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get()); + return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), + SelIdents, NumSelIdents); } // Add all of the factory methods in this Objective-C class, its protocols, // superclasses, categories, implementation, etc. ResultBuilder Results(*this); Results.EnterNewScope(); - AddObjCMethods(CDecl, false, CurContext, Results); + AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext, + Results); Results.ExitScope(); // This also suppresses remaining diagnostics. HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } -void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { +void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { typedef CodeCompleteConsumer::Result Result; Expr *RecExpr = static_cast<Expr *>(Receiver); @@ -1798,7 +2016,8 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { ReceiverType->isObjCQualifiedClassType()) { if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) - AddObjCMethods(ClassDecl, false, CurContext, Results); + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, + CurContext, Results); } } // Handle messages to a qualified ID ("id<foo>"). @@ -1808,19 +2027,22 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(), E = QualID->qual_end(); I != E; ++I) - AddObjCMethods(*I, true, CurContext, Results); + AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + Results); } // Handle messages to a pointer to interface type. else if (const ObjCObjectPointerType *IFacePtr = ReceiverType->getAsObjCInterfacePointerType()) { // Search the class, its superclasses, etc., for instance methods. - AddObjCMethods(IFacePtr->getInterfaceDecl(), true, CurContext, Results); + AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, + NumSelIdents, CurContext, Results); // Search protocols for instance methods. for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(), E = IFacePtr->qual_end(); I != E; ++I) - AddObjCMethods(*I, true, CurContext, Results); + AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + Results); } Results.ExitScope(); @@ -1885,3 +2107,210 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) { Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } + +/// \brief Add all of the Objective-C interface declarations that we find in +/// the given (translation unit) context. +static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, + bool OnlyForwardDeclarations, + bool OnlyUnimplemented, + ResultBuilder &Results) { + typedef CodeCompleteConsumer::Result Result; + + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); + D != DEnd; ++D) { + // Record any interfaces we find. + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) + if ((!OnlyForwardDeclarations || Class->isForwardDecl()) && + (!OnlyUnimplemented || !Class->getImplementation())) + Results.MaybeAddResult(Result(Class, 0), CurContext); + + // Record any forward-declared interfaces we find. + if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) { + for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end(); + C != CEnd; ++C) + if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) && + (!OnlyUnimplemented || !C->getInterface()->getImplementation())) + Results.MaybeAddResult(Result(C->getInterface(), 0), CurContext); + } + } +} + +void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Add all classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true, + false, Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Make sure that we ignore the class we're currently defining. + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, LookupOrdinaryName); + if (CurClass && isa<ObjCInterfaceDecl>(CurClass)) + Results.Ignore(CurClass); + + // Add all classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + false, Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { + ResultBuilder Results(*this); + Results.EnterNewScope(); + + // Add all unimplemented classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + true, Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName) { + typedef CodeCompleteConsumer::Result Result; + + ResultBuilder Results(*this); + + // Ignore any categories we find that have already been implemented by this + // interface. + llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, LookupOrdinaryName); + if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + CategoryNames.insert(Category->getIdentifier()); + + // Add all of the categories we know about. + Results.EnterNewScope(); + TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + for (DeclContext::decl_iterator D = TU->decls_begin(), + DEnd = TU->decls_end(); + D != DEnd; ++D) + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D)) + if (CategoryNames.insert(Category->getIdentifier())) + Results.MaybeAddResult(Result(Category, 0), CurContext); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName) { + typedef CodeCompleteConsumer::Result Result; + + // Find the corresponding interface. If we couldn't find the interface, the + // program itself is ill-formed. However, we'll try to be helpful still by + // providing the list of all of the categories we know about. + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, LookupOrdinaryName); + ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass); + if (!Class) + return CodeCompleteObjCInterfaceCategory(S, ClassName); + + ResultBuilder Results(*this); + + // Add all of the categories that have have corresponding interface + // declarations in this class and any of its superclasses, except for + // already-implemented categories in the class itself. + llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; + Results.EnterNewScope(); + bool IgnoreImplemented = true; + while (Class) { + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + if ((!IgnoreImplemented || !Category->getImplementation()) && + CategoryNames.insert(Category->getIdentifier())) + Results.MaybeAddResult(Result(Category, 0), CurContext); + + Class = Class->getSuperClass(); + IgnoreImplemented = false; + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) { + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + + // Figure out where this @synthesize lives. + ObjCContainerDecl *Container + = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>()); + if (!Container || + (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) + return; + + // Ignore any properties that have already been implemented. + for (DeclContext::decl_iterator D = Container->decls_begin(), + DEnd = Container->decls_end(); + D != DEnd; ++D) + if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D)) + Results.Ignore(PropertyImpl->getPropertyDecl()); + + // Add any properties that we find. + Results.EnterNewScope(); + if (ObjCImplementationDecl *ClassImpl + = dyn_cast<ObjCImplementationDecl>(Container)) + AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext, + Results); + else + AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(), + false, CurContext, Results); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName, + DeclPtrTy ObjCImpDecl) { + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + + // Figure out where this @synthesize lives. + ObjCContainerDecl *Container + = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>()); + if (!Container || + (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) + return; + + // Figure out which interface we're looking into. + ObjCInterfaceDecl *Class = 0; + if (ObjCImplementationDecl *ClassImpl + = dyn_cast<ObjCImplementationDecl>(Container)) + Class = ClassImpl->getClassInterface(); + else + Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl() + ->getClassInterface(); + + // Add all of the instance variables in this class and its superclasses. + Results.EnterNewScope(); + for(; Class; Class = Class->getSuperClass()) { + // FIXME: We could screen the type of each ivar for compatibility with + // the property, but is that being too paternal? + for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(), + IVarEnd = Class->ivar_end(); + IVar != IVarEnd; ++IVar) + Results.MaybeAddResult(Result(*IVar, 0), CurContext); + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 57c101b..b5109f8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -311,14 +311,16 @@ void Sema::ExitDeclaratorContext(Scope *S) { /// extension, in C when the previous function is already an /// overloaded function declaration or has the "overloadable" /// attribute. -static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) { +static bool AllowOverloadingOfFunction(LookupResult &Previous, + ASTContext &Context) { if (Context.getLangOptions().CPlusPlus) return true; - if (isa<OverloadedFunctionDecl>(PrevDecl)) + if (Previous.getResultKind() == LookupResult::FoundOverloaded) return true; - return PrevDecl->getAttr<OverloadableAttr>() != 0; + return (Previous.getResultKind() == LookupResult::Found + && Previous.getFoundDecl()->hasAttr<OverloadableAttr>()); } /// Add this decl to the scope shadowed decl chains. @@ -396,6 +398,48 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) { return IdResolver.isDeclInScope(D, Ctx, Context, S); } +static bool isOutOfScopePreviousDeclaration(NamedDecl *, + DeclContext*, + ASTContext&); + +/// Filters out lookup results that don't fall within the given scope +/// as determined by isDeclInScope. +static void FilterLookupForScope(Sema &SemaRef, LookupResult &R, + DeclContext *Ctx, Scope *S, + bool ConsiderLinkage) { + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + + if (SemaRef.isDeclInScope(D, Ctx, S)) + continue; + + if (ConsiderLinkage && + isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context)) + continue; + + F.erase(); + } + + F.done(); +} + +static bool isUsingDecl(NamedDecl *D) { + return isa<UsingShadowDecl>(D) || + isa<UnresolvedUsingTypenameDecl>(D) || + isa<UnresolvedUsingValueDecl>(D); +} + +/// Removes using shadow declarations from the lookup results. +static void RemoveUsingDecls(LookupResult &R) { + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) + if (isUsingDecl(F.next())) + F.erase(); + + F.done(); +} + static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { if (D->isUsed() || D->hasAttr<UnusedAttr>()) return false; @@ -572,11 +616,10 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, /// how to resolve this situation, merging decls or emitting /// diagnostics as appropriate. If there was an error, set New to be invalid. /// -void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { - // If either decl is known invalid already, set the new one to be invalid and - // don't bother doing any merging checks. - if (New->isInvalidDecl() || OldD->isInvalidDecl()) - return New->setInvalidDecl(); +void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { + // If the new decl is known invalid already, don't bother doing any + // merging checks. + if (New->isInvalidDecl()) return; // Allow multiple definitions for ObjC built-in typedefs. // FIXME: Verify the underlying types are equivalent! @@ -611,16 +654,25 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { } // Fall through - the typedef name was not a builtin type. } + // Verify the old decl was also a type. - TypeDecl *Old = dyn_cast<TypeDecl>(OldD); - if (!Old) { + TypeDecl *Old = 0; + if (!OldDecls.isSingleResult() || + !(Old = dyn_cast<TypeDecl>(OldDecls.getFoundDecl()))) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); + + NamedDecl *OldD = OldDecls.getRepresentativeDecl(); if (OldD->getLocation().isValid()) Diag(OldD->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); } + // If the old declaration is invalid, just give up here. + if (Old->isInvalidDecl()) + return New->setInvalidDecl(); + // Determine the "old" type we'll use for checking and diagnostics. QualType OldType; if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old)) @@ -977,18 +1029,19 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. /// -void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { - // If either decl is invalid, make sure the new one is marked invalid and - // don't do any other checking. - if (New->isInvalidDecl() || OldD->isInvalidDecl()) - return New->setInvalidDecl(); +void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { + // If the new decl is already invalid, don't do any other checking. + if (New->isInvalidDecl()) + return; // Verify the old decl was also a variable. - VarDecl *Old = dyn_cast<VarDecl>(OldD); - if (!Old) { + VarDecl *Old = 0; + if (!Previous.isSingleResult() || + !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); - Diag(OldD->getLocation(), diag::note_previous_definition); + Diag(Previous.getRepresentativeDecl()->getLocation(), + diag::note_previous_definition); return New->setInvalidDecl(); } @@ -1403,6 +1456,33 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { return DeclPtrTy::make(Tag); } +/// We are trying to introduce the given name into the given context; +/// check if there's an existing declaration that can't be overloaded. +/// +/// \return true if this is a forbidden redeclaration +bool Sema::CheckRedeclaration(DeclContext *DC, + DeclarationName Name, + SourceLocation NameLoc, + unsigned diagnostic) { + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName, + ForRedeclaration); + LookupQualifiedName(R, DC); + + if (R.empty()) return false; + + if (R.getResultKind() == LookupResult::Found && + isa<TagDecl>(R.getFoundDecl())) + return false; + + // Pick a representative declaration. + NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl(); + + Diag(NameLoc, diagnostic) << Name; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + + return true; +} + /// InjectAnonymousStructOrUnionMembers - Inject the members of the /// anonymous struct or union AnonRecord into the owning context Owner /// and scope S. This routine will be invoked just after we realize @@ -1421,26 +1501,21 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { /// structs/unions into the owning context and scope as well. bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, RecordDecl *AnonRecord) { + unsigned diagKind + = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl + : diag::err_anonymous_struct_member_redecl; + bool Invalid = false; for (RecordDecl::field_iterator F = AnonRecord->field_begin(), FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - LookupResult R(*this, (*F)->getDeclName(), SourceLocation(), - LookupOrdinaryName, ForRedeclaration); - LookupQualifiedName(R, Owner); - NamedDecl *PrevDecl = R.getAsSingleDecl(Context); - if (PrevDecl && !isa<TagDecl>(PrevDecl)) { + if (CheckRedeclaration(Owner, (*F)->getDeclName(), + (*F)->getLocation(), diagKind)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be // distinct from the names of any other entity in the // scope in which the anonymous union is declared. - unsigned diagKind - = AnonRecord->isUnion()? diag::err_anonymous_union_member_redecl - : diag::err_anonymous_struct_member_redecl; - Diag((*F)->getLocation(), diagKind) - << (*F)->getDeclName(); - Diag(PrevDecl->getLocation(), diag::note_previous_declaration); Invalid = true; } else { // C++ [class.union]p2: @@ -1765,19 +1840,20 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, } DeclContext *DC; - NamedDecl *PrevDecl; NamedDecl *New; DeclaratorInfo *DInfo = 0; QualType R = GetTypeForDeclarator(D, S, &DInfo); + LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, + ForRedeclaration); + // See if this is a redefinition of a variable in the same scope. if (D.getCXXScopeSpec().isInvalid()) { DC = CurContext; - PrevDecl = 0; D.setInvalidType(); } else if (!D.getCXXScopeSpec().isSet()) { - LookupNameKind NameKind = LookupOrdinaryName; + bool IsLinkageLookup = false; // If the declaration we're planning to build will be a function // or object with linkage, then look for another declaration with @@ -1787,19 +1863,18 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, else if (R->isFunctionType()) { if (CurContext->isFunctionOrMethod() || D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) - NameKind = LookupRedeclarationWithLinkage; + IsLinkageLookup = true; } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) - NameKind = LookupRedeclarationWithLinkage; + IsLinkageLookup = true; else if (CurContext->getLookupContext()->isTranslationUnit() && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) - NameKind = LookupRedeclarationWithLinkage; + IsLinkageLookup = true; - DC = CurContext; - LookupResult R(*this, Name, D.getIdentifierLoc(), NameKind, - ForRedeclaration); + if (IsLinkageLookup) + Previous.clear(LookupRedeclarationWithLinkage); - LookupName(R, S, NameKind == LookupRedeclarationWithLinkage); - PrevDecl = R.getAsSingleDecl(Context); + DC = CurContext; + LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup); } else { // Something like "int foo::x;" DC = computeDeclContext(D.getCXXScopeSpec(), true); @@ -1819,10 +1894,11 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, RequireCompleteDeclContext(D.getCXXScopeSpec())) return DeclPtrTy(); - LookupResult Res(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, - ForRedeclaration); - LookupQualifiedName(Res, DC); - PrevDecl = Res.getAsSingleDecl(Context); + LookupQualifiedName(Previous, DC); + + // Don't consider using declarations as previous declarations for + // out-of-line members. + RemoveUsingDecls(Previous); // C++ 7.3.1.2p2: // Members (including explicit specializations of templates) of a named @@ -1870,23 +1946,25 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, } } - if (PrevDecl && PrevDecl->isTemplateParameter()) { + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. if (!D.isInvalidType()) - if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl)) + if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), + Previous.getFoundDecl())) D.setInvalidType(); // Just pretend that we didn't see the previous declaration. - PrevDecl = 0; + Previous.clear(); } // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). - if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag && + if (Previous.isSingleTagDecl() && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) - PrevDecl = 0; + Previous.clear(); bool Redeclaration = false; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -1895,13 +1973,13 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, return DeclPtrTy(); } - New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, PrevDecl, Redeclaration); + New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, Previous, Redeclaration); } else if (R->isFunctionType()) { - New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, PrevDecl, + New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, Previous, move(TemplateParamLists), IsFunctionDefinition, Redeclaration); } else { - New = ActOnVariableDeclarator(S, D, DC, R, DInfo, PrevDecl, + New = ActOnVariableDeclarator(S, D, DC, R, DInfo, Previous, move(TemplateParamLists), Redeclaration); } @@ -1970,16 +2048,19 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, /// \brief Register the given locally-scoped external C declaration so /// that it can be found later for redeclarations void -Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, +Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, + const LookupResult &Previous, Scope *S) { assert(ND->getLexicalDeclContext()->isFunctionOrMethod() && "Decl is not a locally-scoped decl!"); // Note that we have a locally-scoped external with this name. LocallyScopedExternalDecls[ND->getDeclName()] = ND; - if (!PrevDecl) + if (!Previous.isSingleResult()) return; + NamedDecl *PrevDecl = Previous.getFoundDecl(); + // If there was a previous declaration of this variable, it may be // in our identifier chain. Update the identifier chain with the new // declaration. @@ -2015,7 +2096,7 @@ void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, DeclaratorInfo *DInfo, - NamedDecl* PrevDecl, bool &Redeclaration) { + LookupResult &Previous, bool &Redeclaration) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) @@ -2040,11 +2121,13 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); + // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. - if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) { + FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false); + if (!Previous.empty()) { Redeclaration = true; - MergeTypeDefDecl(NewTD, PrevDecl); + MergeTypeDefDecl(NewTD, Previous); } // C99 6.7.7p2: If a typedef name specifies a variably modified type @@ -2155,7 +2238,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, NamedDecl* Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, DeclaratorInfo *DInfo, - NamedDecl* PrevDecl, + LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &Redeclaration) { DeclarationName Name = GetNameForDeclarator(D); @@ -2285,22 +2368,21 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, SE->getByteLength()))); } - // If name lookup finds a previous declaration that is not in the - // same scope as the new declaration, this may still be an - // acceptable redeclaration. - if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) && - !(NewVD->hasLinkage() && - isOutOfScopePreviousDeclaration(PrevDecl, DC, Context))) - PrevDecl = 0; + // Don't consider existing declarations that are in a different + // scope and are out-of-semantic-context declarations (if the new + // declaration has linkage). + FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage()); // Merge the decl with the existing one if appropriate. - if (PrevDecl) { - if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) { + if (!Previous.empty()) { + if (Previous.isSingleResult() && + isa<FieldDecl>(Previous.getFoundDecl()) && + D.getCXXScopeSpec().isSet()) { // The user tried to define a non-static data member // out-of-line (C++ [dcl.meaning]p1). Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line) << D.getCXXScopeSpec().getRange(); - PrevDecl = 0; + Previous.clear(); NewVD->setInvalidDecl(); } } else if (D.getCXXScopeSpec().isSet()) { @@ -2311,17 +2393,18 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewVD->setInvalidDecl(); } - CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration); + CheckVariableDeclaration(NewVD, Previous, Redeclaration); // This is an explicit specialization of a static data member. Check it. if (isExplicitSpecialization && !NewVD->isInvalidDecl() && - CheckMemberSpecialization(NewVD, PrevDecl)) + CheckMemberSpecialization(NewVD, Previous)) NewVD->setInvalidDecl(); - + // attributes declared post-definition are currently ignored - if (PrevDecl) { - const VarDecl *Def = 0, *PrevVD = dyn_cast<VarDecl>(PrevDecl); - if (PrevVD->getDefinition(Def) && D.hasAttributes()) { + if (Previous.isSingleResult()) { + const VarDecl *Def = 0; + VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl()); + if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) { Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); Diag(Def->getLocation(), diag::note_previous_definition); } @@ -2331,7 +2414,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // such variables. if (CurContext->isFunctionOrMethod() && NewVD->isExternC() && !NewVD->isInvalidDecl()) - RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S); + RegisterLocallyScopedExternCDecl(NewVD, Previous, S); return NewVD; } @@ -2346,7 +2429,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, /// that have been instantiated from a template. /// /// Sets NewVD->isInvalidDecl() if an error was encountered. -void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, +void Sema::CheckVariableDeclaration(VarDecl *NewVD, + LookupResult &Previous, bool &Redeclaration) { // If the decl is already known invalid, don't check it. if (NewVD->isInvalidDecl()) @@ -2419,14 +2503,14 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, NewVD->setType(FixedTy); } - if (!PrevDecl && NewVD->isExternC()) { + if (Previous.empty() && NewVD->isExternC()) { // Since we did not find anything by this name and we're declaring // an extern "C" variable, look for a non-visible extern "C" // declaration with the same name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos = LocallyScopedExternalDecls.find(NewVD->getDeclName()); if (Pos != LocallyScopedExternalDecls.end()) - PrevDecl = Pos->second; + Previous.addDecl(Pos->second); } if (T->isVoidType() && !NewVD->hasExternalStorage()) { @@ -2445,18 +2529,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, return NewVD->setInvalidDecl(); } - if (PrevDecl) { + if (!Previous.empty()) { Redeclaration = true; - MergeVarDecl(NewVD, PrevDecl); + MergeVarDecl(NewVD, Previous); } } -static bool isUsingDecl(Decl *D) { - return isa<UsingDecl>(D) || - isa<UnresolvedUsingTypenameDecl>(D) || - isa<UnresolvedUsingValueDecl>(D); -} - /// \brief Data used with FindOverriddenMethod struct FindOverriddenMethodData { Sema *S; @@ -2477,8 +2555,7 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, Path.Decls.first != Path.Decls.second; ++Path.Decls.first) { if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) { - OverloadedFunctionDecl::function_iterator MatchedDecl; - if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, MatchedDecl)) + if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD)) return true; } } @@ -2486,10 +2563,30 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, return false; } +/// AddOverriddenMethods - See if a method overrides any in the base classes, +/// and if so, check that it's a valid override and remember it. +void Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { + // Look for virtual methods in base classes that this method might override. + CXXBasePaths Paths; + FindOverriddenMethodData Data; + Data.Method = MD; + Data.S = this; + if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) { + for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(), + E = Paths.found_decls_end(); I != E; ++I) { + if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) { + if (!CheckOverridingFunctionReturnType(MD, OldMD) && + !CheckOverridingFunctionExceptionSpec(MD, OldMD)) + MD->addOverriddenMethod(OldMD); + } + } + } +} + NamedDecl* Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, DeclaratorInfo *DInfo, - NamedDecl* PrevDecl, + LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); @@ -2554,10 +2651,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionDecl *NewFD; if (isFriend) { - // DC is the namespace in which the function is being declared. - assert((DC->isFileContext() || PrevDecl) && "previously-undeclared " - "friend function being created in a non-namespace context"); - // C++ [class.friend]p5 // A function can be defined in a friend declaration of a // class . . . . Such a function is implicitly inline. @@ -2733,37 +2826,29 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } + // Filter out previous declarations that don't match the scope. + FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); + if (isFriend) { + // DC is the namespace in which the function is being declared. + assert((DC->isFileContext() || !Previous.empty()) && + "previously-undeclared friend function being created " + "in a non-namespace context"); + if (FunctionTemplate) { FunctionTemplate->setObjectOfFriendDecl( - /* PreviouslyDeclared= */ PrevDecl != NULL); + /* PreviouslyDeclared= */ !Previous.empty()); FunctionTemplate->setAccess(AS_public); } else - NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL); + NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ !Previous.empty()); NewFD->setAccess(AS_public); } - if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) { - // Look for virtual methods in base classes that this method might override. - CXXBasePaths Paths; - FindOverriddenMethodData Data; - Data.Method = NewMD; - Data.S = this; - if (cast<CXXRecordDecl>(DC)->lookupInBases(&FindOverriddenMethod, &Data, - Paths)) { - for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(), - E = Paths.found_decls_end(); I != E; ++I) { - if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) { - if (!CheckOverridingFunctionReturnType(NewMD, OldMD) && - !CheckOverridingFunctionExceptionSpec(NewMD, OldMD)) - NewMD->addOverriddenMethod(OldMD); - } - } - } - } + if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) + AddOverriddenMethods(cast<CXXRecordDecl>(DC), NewMD); if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) { @@ -2847,14 +2932,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Finally, we know we have the right number of parameters, install them. NewFD->setParams(Context, Params.data(), Params.size()); - // If name lookup finds a previous declaration that is not in the - // same scope as the new declaration, this may still be an - // acceptable redeclaration. - if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) && - !(NewFD->hasLinkage() && - isOutOfScopePreviousDeclaration(PrevDecl, DC, Context))) - PrevDecl = 0; - // If the declarator is a template-id, translate the parser's template // argument list into our AST format. bool HasExplicitTemplateArgs = false; @@ -2891,22 +2968,26 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isFunctionTemplateSpecialization = true; } } - + if (isFunctionTemplateSpecialization) { if (CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), RAngleLoc, - PrevDecl)) + Previous)) NewFD->setInvalidDecl(); } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) && - CheckMemberSpecialization(NewFD, PrevDecl)) + CheckMemberSpecialization(NewFD, Previous)) NewFD->setInvalidDecl(); // Perform semantic checking on the function declaration. bool OverloadableAttrRequired = false; // FIXME: HACK! - CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization, + CheckFunctionDeclaration(NewFD, Previous, isExplicitSpecialization, Redeclaration, /*FIXME:*/OverloadableAttrRequired); + assert((NewFD->isInvalidDecl() || !Redeclaration || + Previous.getResultKind() != LookupResult::FoundOverloaded) && + "previous declaration set still overloaded"); + if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) { // An out-of-line member function declaration must also be a // definition (C++ [dcl.meaning]p1). @@ -2918,7 +2999,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(NewFD->getLocation(), diag::err_out_of_line_declaration) << D.getCXXScopeSpec().getRange(); NewFD->setInvalidDecl(); - } else if (!Redeclaration && (!PrevDecl || !isUsingDecl(PrevDecl))) { + } else if (!Redeclaration) { // The user tried to provide an out-of-line definition for a // function that is a member of a class or namespace, but there // was no such member function declared (C++ [class.mfct]p2, @@ -2948,8 +3029,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD)) Diag((*Func)->getLocation(), diag::note_member_def_close_match); } - - PrevDecl = 0; } } @@ -2960,8 +3039,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, ProcessDeclAttributes(S, NewFD, D); // attributes declared post-definition are currently ignored - if (Redeclaration && PrevDecl) { - const FunctionDecl *Def, *PrevFD = dyn_cast<FunctionDecl>(PrevDecl); + if (Redeclaration && Previous.isSingleResult()) { + const FunctionDecl *Def; + FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl()); if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) { Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition); Diag(Def->getLocation(), diag::note_previous_definition); @@ -2975,8 +3055,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // with that name must be marked "overloadable". Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) << Redeclaration << NewFD; - if (PrevDecl) - Diag(PrevDecl->getLocation(), + if (!Previous.empty()) + Diag(Previous.getRepresentativeDecl()->getLocation(), diag::note_attribute_overloadable_prev_overload); NewFD->addAttr(::new (Context) OverloadableAttr()); } @@ -2985,7 +3065,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // map of such names. if (CurContext->isFunctionOrMethod() && NewFD->isExternC() && !NewFD->isInvalidDecl()) - RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S); + RegisterLocallyScopedExternCDecl(NewFD, Previous, S); // Set this FunctionDecl's range up to the right paren. NewFD->setLocEnd(D.getSourceRange().getEnd()); @@ -3013,7 +3093,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, /// an explicit specialization of the previous declaration. /// /// This sets NewFD->isInvalidDecl() to true if there was an error. -void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, +void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, + LookupResult &Previous, bool IsExplicitSpecialization, bool &Redeclaration, bool &OverloadableAttrRequired) { @@ -3032,27 +3113,26 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, CheckMain(NewFD); // Check for a previous declaration of this name. - if (!PrevDecl && NewFD->isExternC()) { + if (Previous.empty() && NewFD->isExternC()) { // Since we did not find anything by this name and we're declaring // an extern "C" function, look for a non-visible extern "C" // declaration with the same name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos = LocallyScopedExternalDecls.find(NewFD->getDeclName()); if (Pos != LocallyScopedExternalDecls.end()) - PrevDecl = Pos->second; + Previous.addDecl(Pos->second); } // Merge or overload the declaration with an existing declaration of // the same name, if appropriate. - if (PrevDecl) { + if (!Previous.empty()) { // Determine whether NewFD is an overload of PrevDecl or // a declaration that requires merging. If it's an overload, // there's no more work to do here; we'll just add the new // function to the scope. - OverloadedFunctionDecl::function_iterator MatchedDecl; if (!getLangOptions().CPlusPlus && - AllowOverloadingOfFunction(PrevDecl, Context)) { + AllowOverloadingOfFunction(Previous, Context)) { OverloadableAttrRequired = true; // Functions marked "overloadable" must have a prototype (that @@ -3071,22 +3151,26 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, } } - if (PrevDecl && - (!AllowOverloadingOfFunction(PrevDecl, Context) || - !IsOverload(NewFD, PrevDecl, MatchedDecl)) && !isUsingDecl(PrevDecl)) { - Redeclaration = true; - Decl *OldDecl = PrevDecl; - - // If PrevDecl was an overloaded function, extract the - // FunctionDecl that matched. - if (isa<OverloadedFunctionDecl>(PrevDecl)) - OldDecl = *MatchedDecl; + NamedDecl *OldDecl = 0; + if (!Previous.empty()) { + if (!AllowOverloadingOfFunction(Previous, Context)) { + Redeclaration = true; + OldDecl = Previous.getFoundDecl(); + } else if (!IsOverload(NewFD, Previous, OldDecl)) { + if (!isUsingDecl(OldDecl)) + Redeclaration = true; + } + } + if (Redeclaration) { // NewFD and OldDecl represent declarations that need to be // merged. if (MergeFunctionDecl(NewFD, OldDecl)) return NewFD->setInvalidDecl(); + Previous.clear(); + Previous.addDecl(OldDecl); + if (FunctionTemplateDecl *OldTemplateDecl = dyn_cast<FunctionTemplateDecl>(OldDecl)) { NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); @@ -4313,11 +4397,13 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; - NamedDecl *PrevDecl = 0; bool isStdBadAlloc = false; bool Invalid = false; - RedeclarationKind Redecl = (RedeclarationKind) (TUK != TUK_Reference); + RedeclarationKind Redecl = (TUK != TUK_Reference ? ForRedeclaration + : NotForRedeclaration); + + LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). @@ -4344,17 +4430,13 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DC = computeDeclContext(SS, true); SearchDC = DC; // Look-up name inside 'foo::'. - LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl); - LookupQualifiedName(R, DC); + LookupQualifiedName(Previous, DC); - if (R.isAmbiguous()) + if (Previous.isAmbiguous()) return DeclPtrTy(); - if (R.getResultKind() == LookupResult::Found) - PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl()); - // A tag 'foo::bar' must already exist. - if (!PrevDecl) { + if (Previous.empty()) { Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange(); Name = 0; Invalid = true; @@ -4366,19 +4448,11 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: We're looking into outer scopes here, even when we // shouldn't be. Doing so can result in ambiguities that we // shouldn't be diagnosing. - LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl); - LookupName(R, S); - if (R.isAmbiguous()) { - // FIXME: This is not best way to recover from case like: - // - // struct S s; - // - // causes needless "incomplete type" error later. - Name = 0; - PrevDecl = 0; - Invalid = true; - } else - PrevDecl = R.getAsSingleDecl(Context); + LookupName(Previous, S); + + // Note: there used to be some attempt at recovery here. + if (Previous.isAmbiguous()) + return DeclPtrTy(); if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) { // FIXME: This makes sure that we ignore the contexts associated @@ -4390,11 +4464,12 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } } - if (PrevDecl && PrevDecl->isTemplateParameter()) { + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. - DiagnoseTemplateParameterShadow(NameLoc, PrevDecl); + DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl()); // Just pretend that we didn't see the previous declaration. - PrevDecl = 0; + Previous.clear(); } if (getLangOptions().CPlusPlus && Name && DC && StdNamespace && @@ -4402,15 +4477,17 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // This is a declaration of or a reference to "std::bad_alloc". isStdBadAlloc = true; - if (!PrevDecl && StdBadAlloc) { + if (Previous.empty() && StdBadAlloc) { // std::bad_alloc has been implicitly declared (but made invisible to // name lookup). Fill in this implicit declaration as the previous // declaration, so that the declarations get chained appropriately. - PrevDecl = StdBadAlloc; + Previous.addDecl(StdBadAlloc); } } - - if (PrevDecl) { + + if (!Previous.empty()) { + assert(Previous.isSingleResult()); + NamedDecl *PrevDecl = Previous.getFoundDecl(); if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or @@ -4430,14 +4507,14 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, PrevTagDecl->getKindName()); else Diag(KWLoc, diag::err_use_with_wrong_tag) << Name; - Diag(PrevDecl->getLocation(), diag::note_previous_use); + Diag(PrevTagDecl->getLocation(), diag::note_previous_use); if (SafeToContinue) Kind = PrevTagDecl->getTagKind(); else { // Recover by making this an anonymous redefinition. Name = 0; - PrevDecl = 0; + Previous.clear(); Invalid = true; } } @@ -4450,7 +4527,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // For our current ASTs this shouldn't be a problem, but will // need to be changed with DeclGroups. if (TUK == TUK_Reference || TUK == TUK_Friend) - return DeclPtrTy::make(PrevDecl); + return DeclPtrTy::make(PrevTagDecl); // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { @@ -4468,7 +4545,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // struct be anonymous, which will make any later // references get the previous definition. Name = 0; - PrevDecl = 0; + Previous.clear(); Invalid = true; } } else { @@ -4480,7 +4557,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Diag(PrevTagDecl->getLocation(), diag::note_previous_definition); Name = 0; - PrevDecl = 0; + Previous.clear(); Invalid = true; } } @@ -4497,7 +4574,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // scope, e.g. "struct foo; void bar() { struct foo; }", just create a // new decl/type. We set PrevDecl to NULL so that the entities // have distinct types. - PrevDecl = 0; + Previous.clear(); } // If we get here, we're going to create a new Decl. If PrevDecl // is non-NULL, it's a definition of the tag declared by @@ -4511,12 +4588,12 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, Diag(NameLoc, diag::err_redefinition_different_kind) << Name; Diag(PrevDecl->getLocation(), diag::note_previous_definition); Name = 0; - PrevDecl = 0; + Previous.clear(); Invalid = true; } else { // The existing declaration isn't relevant to us; we're in a // new scope, so clear out the previous declaration. - PrevDecl = 0; + Previous.clear(); } } } else if (TUK == TUK_Reference && SS.isEmpty() && Name && @@ -4570,6 +4647,10 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, CreateNewDecl: + TagDecl *PrevDecl = 0; + if (Previous.isSingleResult()) + PrevDecl = cast<TagDecl>(Previous.getFoundDecl()); + // If there is an identifier, use the location of the identifier as the // location of the decl, otherwise use the location of the struct/union // keyword. @@ -4651,7 +4732,7 @@ CreateNewDecl: // If this is a specialization of a member class (of a class template), // check the specialization. - if (isExplicitSpecialization && CheckMemberSpecialization(New, PrevDecl)) + if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) Invalid = true; if (Invalid) @@ -4671,7 +4752,7 @@ CreateNewDecl: // Mark this as a friend decl if applicable. if (TUK == TUK_Friend) - New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL); + New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty()); // Set the access specifier. if (!Invalid && TUK != TUK_Friend) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 237a869..bda1a69 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4668,7 +4668,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // FIXME: handle local classes // Recover from invalid scope qualifiers as if they just weren't there. - NamedDecl *PrevDecl = 0; + LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, + ForRedeclaration); if (!ScopeQual.isInvalid() && ScopeQual.isSet()) { // FIXME: RequireCompleteDeclContext DC = computeDeclContext(ScopeQual); @@ -4676,15 +4677,15 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // FIXME: handle dependent contexts if (!DC) return DeclPtrTy(); - LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration); - LookupQualifiedName(R, DC); - PrevDecl = R.getAsSingleDecl(Context); + LookupQualifiedName(Previous, DC); // If searching in that context implicitly found a declaration in // a different context, treat it like it wasn't found at all. // TODO: better diagnostics for this case. Suggesting the right // qualified scope would be nice... - if (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) { + // FIXME: getRepresentativeDecl() is not right here at all + if (Previous.empty() || + !Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) { D.setInvalidType(); Diag(Loc, diag::err_qualified_friend_not_found) << Name << T; return DeclPtrTy(); @@ -4711,12 +4712,10 @@ Sema::ActOnFriendFunctionDecl(Scope *S, while (DC->isRecord()) DC = DC->getParent(); - LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration); - LookupQualifiedName(R, DC); - PrevDecl = R.getAsSingleDecl(Context); + LookupQualifiedName(Previous, DC); // TODO: decide what we think about using declarations. - if (PrevDecl) + if (!Previous.empty()) break; if (DC->isFileContext()) break; @@ -4728,7 +4727,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, // C++0x changes this for both friend types and functions. // Most C++ 98 compilers do seem to give an error here, so // we do, too. - if (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x) + if (!Previous.empty() && DC->Equals(CurContext) + && !getLangOptions().CPlusPlus0x) Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); } @@ -4745,7 +4745,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S, } bool Redeclaration = false; - NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl, + NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, Previous, move(TemplateParams), IsDefinition, Redeclaration); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 0c5569c..7da37af 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -828,9 +828,10 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); IM != EM; ++IM, ++IF) { - if (Context.typesAreCompatible((*IF)->getType(), (*IM)->getType()) || - Context.QualifiedIdConformsQualifiedId((*IF)->getType(), - (*IM)->getType())) + QualType ParmDeclTy = (*IF)->getType().getUnqualifiedType(); + QualType ParmImpTy = (*IM)->getType().getUnqualifiedType(); + if (Context.typesAreCompatible(ParmDeclTy, ParmImpTy) || + Context.QualifiedIdConformsQualifiedId(ParmDeclTy, ParmImpTy)) continue; Diag((*IM)->getLocation(), diag::warn_conflicting_param_types) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 0eea169..462bf13 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1445,6 +1445,12 @@ QualType Sema::CheckPointerToMemberOperands( } } + if (isa<CXXZeroInitValueExpr>(rex->IgnoreParens())) { + // Diagnose use of pointer-to-member type which when used as + // the functional cast in a pointer-to-member expression. + Diag(Loc, diag::err_pointer_to_member_type) << isIndirect; + return QualType(); + } // C++ 5.5p2 // The result is an object or a function of the type specified by the // second operand. diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1f49b78..1957d7f 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -246,7 +246,11 @@ void LookupResult::resolveKind() { unsigned N = Decls.size(); // Fast case: no possible ambiguity. - if (N == 0) return; + if (N == 0) { + assert(ResultKind == NotFound); + return; + } + if (N == 1) { if (isa<UnresolvedUsingValueDecl>(Decls[0])) ResultKind = FoundUnresolvedValue; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index adcd977..daf5b7f 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -284,100 +284,102 @@ void ImplicitConversionSequence::DebugPrint() const { // signature), IsOverload returns false and MatchedDecl will be set to // point to the FunctionDecl for #2. bool -Sema::IsOverload(FunctionDecl *New, Decl* OldD, - OverloadedFunctionDecl::function_iterator& MatchedDecl) { - if (OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(OldD)) { - // Is this new function an overload of every function in the - // overload set? - OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), - FuncEnd = Ovl->function_end(); - for (; Func != FuncEnd; ++Func) { - if (!IsOverload(New, *Func, MatchedDecl)) { - MatchedDecl = Func; +Sema::IsOverload(FunctionDecl *New, LookupResult &Previous, NamedDecl *&Match) { + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *Old = (*I)->getUnderlyingDecl(); + if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(Old)) { + if (!IsOverload(New, OldT->getTemplatedDecl())) { + Match = Old; return false; } + } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(Old)) { + if (!IsOverload(New, OldF)) { + Match = Old; + return false; + } + } else { + // (C++ 13p1): + // Only function declarations can be overloaded; object and type + // declarations cannot be overloaded. + Match = Old; + return false; } + } - // This function overloads every function in the overload set. - return true; - } else if (FunctionTemplateDecl *Old = dyn_cast<FunctionTemplateDecl>(OldD)) - return IsOverload(New, Old->getTemplatedDecl(), MatchedDecl); - else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) { - FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); - FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); - - // C++ [temp.fct]p2: - // A function template can be overloaded with other function templates - // and with normal (non-template) functions. - if ((OldTemplate == 0) != (NewTemplate == 0)) - return true; + return true; +} - // Is the function New an overload of the function Old? - QualType OldQType = Context.getCanonicalType(Old->getType()); - QualType NewQType = Context.getCanonicalType(New->getType()); +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) { + FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); + FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); - // Compare the signatures (C++ 1.3.10) of the two functions to - // determine whether they are overloads. If we find any mismatch - // in the signature, they are overloads. + // C++ [temp.fct]p2: + // A function template can be overloaded with other function templates + // and with normal (non-template) functions. + if ((OldTemplate == 0) != (NewTemplate == 0)) + return true; - // If either of these functions is a K&R-style function (no - // prototype), then we consider them to have matching signatures. - if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) || - isa<FunctionNoProtoType>(NewQType.getTypePtr())) - return false; + // Is the function New an overload of the function Old? + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); - FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType); - FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType); - - // The signature of a function includes the types of its - // parameters (C++ 1.3.10), which includes the presence or absence - // of the ellipsis; see C++ DR 357). - if (OldQType != NewQType && - (OldType->getNumArgs() != NewType->getNumArgs() || - OldType->isVariadic() != NewType->isVariadic() || - !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(), - NewType->arg_type_begin()))) - return true; + // Compare the signatures (C++ 1.3.10) of the two functions to + // determine whether they are overloads. If we find any mismatch + // in the signature, they are overloads. - // C++ [temp.over.link]p4: - // The signature of a function template consists of its function - // signature, its return type and its template parameter list. The names - // of the template parameters are significant only for establishing the - // relationship between the template parameters and the rest of the - // signature. - // - // We check the return type and template parameter lists for function - // templates first; the remaining checks follow. - if (NewTemplate && - (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), - OldTemplate->getTemplateParameters(), - false, TPL_TemplateMatch) || - OldType->getResultType() != NewType->getResultType())) - return true; + // If either of these functions is a K&R-style function (no + // prototype), then we consider them to have matching signatures. + if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) || + isa<FunctionNoProtoType>(NewQType.getTypePtr())) + return false; - // If the function is a class member, its signature includes the - // cv-qualifiers (if any) on the function itself. - // - // As part of this, also check whether one of the member functions - // is static, in which case they are not overloads (C++ - // 13.1p2). While not part of the definition of the signature, - // this check is important to determine whether these functions - // can be overloaded. - CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); - CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); - if (OldMethod && NewMethod && - !OldMethod->isStatic() && !NewMethod->isStatic() && - OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers()) - return true; + FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType); + FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType); + + // The signature of a function includes the types of its + // parameters (C++ 1.3.10), which includes the presence or absence + // of the ellipsis; see C++ DR 357). + if (OldQType != NewQType && + (OldType->getNumArgs() != NewType->getNumArgs() || + OldType->isVariadic() != NewType->isVariadic() || + !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(), + NewType->arg_type_begin()))) + return true; - // The signatures match; this is not an overload. - return false; - } else { - // (C++ 13p1): - // Only function declarations can be overloaded; object and type - // declarations cannot be overloaded. - return false; - } + // C++ [temp.over.link]p4: + // The signature of a function template consists of its function + // signature, its return type and its template parameter list. The names + // of the template parameters are significant only for establishing the + // relationship between the template parameters and the rest of the + // signature. + // + // We check the return type and template parameter lists for function + // templates first; the remaining checks follow. + if (NewTemplate && + (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + false, TPL_TemplateMatch) || + OldType->getResultType() != NewType->getResultType())) + return true; + + // If the function is a class member, its signature includes the + // cv-qualifiers (if any) on the function itself. + // + // As part of this, also check whether one of the member functions + // is static, in which case they are not overloads (C++ + // 13.1p2). While not part of the definition of the signature, + // this check is important to determine whether these functions + // can be overloaded. + CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); + CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); + if (OldMethod && NewMethod && + !OldMethod->isStatic() && !NewMethod->isStatic() && + OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers()) + return true; + + // The signatures match; this is not an overload. + return false; } /// TryImplicitConversion - Attempt to perform an implicit conversion @@ -1545,18 +1547,23 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( } bool -Sema::DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType) { +Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { ImplicitConversionSequence ICS; OverloadCandidateSet CandidateSet; OverloadingResult OvResult = IsUserDefinedConversion(From, ToType, ICS.UserDefined, CandidateSet, true, false, false); - if (OvResult != OR_Ambiguous) + if (OvResult == OR_Ambiguous) + Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_ambiguous_condition) + << From->getType() << ToType << From->getSourceRange(); + else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) + Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_nonviable_condition) + << From->getType() << ToType << From->getSourceRange(); + else return false; - Diag(From->getSourceRange().getBegin(), - diag::err_typecheck_ambiguous_condition) - << From->getType() << ToType << From->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); return true; } @@ -2072,7 +2079,7 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, if (!PerformImplicitConversion(From, ToType, Flavor, /*AllowExplicit=*/false, Elidable)) return false; - if (!DiagnoseAmbiguousUserDefinedConversion(From, ToType)) + if (!DiagnoseMultipleUserDefinedConversion(From, ToType)) return Diag(From->getSourceRange().getBegin(), diag::err_typecheck_convert_incompatible) << ToType << From->getType() << Flavor << From->getSourceRange(); @@ -2085,8 +2092,11 @@ bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, ImplicitConversionSequence Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { QualType ClassType = Context.getTypeDeclType(Method->getParent()); - QualType ImplicitParamType - = Context.getCVRQualifiedType(ClassType, Method->getTypeQualifiers()); + // [class.dtor]p2: A destructor can be invoked for a const, volatile or + // const volatile object. + unsigned Quals = isa<CXXDestructorDecl>(Method) ? + Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers(); + QualType ImplicitParamType = Context.getCVRQualifiedType(ClassType, Quals); // Set up the conversion sequence as a "bad" conversion, to allow us // to exit early. @@ -2101,7 +2111,7 @@ Sema::TryObjectArgumentInitialization(Expr *From, CXXMethodDecl *Method) { assert(FromType->isRecordType()); - // The implicit object parmeter is has the type "reference to cv X", + // The implicit object parameter is has the type "reference to cv X", // where X is the class of which the function is a member // (C++ [over.match.funcs]p4). However, when finding an implicit // conversion sequence for the argument, we are not allowed to @@ -2192,7 +2202,7 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { if (!PerformImplicitConversion(From, Context.BoolTy, ICS, "converting")) return false; - if (!DiagnoseAmbiguousUserDefinedConversion(From, Context.BoolTy)) + if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) return Diag(From->getSourceRange().getBegin(), diag::err_typecheck_bool_condition) << From->getType() << From->getSourceRange(); @@ -3017,6 +3027,12 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, assert(PointerTy && "type was not a pointer type!"); QualType PointeeTy = PointerTy->getPointeeType(); + // Don't add qualified variants of arrays. For one, they're not allowed + // (the qualifier would sink to the element type), and for another, the + // only overload situation where it matters is subscript or pointer +- int, + // and those shouldn't have qualifier variants anyway. + if (PointeeTy->isArrayType()) + return true; unsigned BaseCVR = PointeeTy.getCVRQualifiers(); if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy)) BaseCVR = Array->getElementType().getCVRQualifiers(); @@ -3057,6 +3073,12 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( assert(PointerTy && "type was not a member pointer type!"); QualType PointeeTy = PointerTy->getPointeeType(); + // Don't add qualified variants of arrays. For one, they're not allowed + // (the qualifier would sink to the element type), and for another, the + // only overload situation where it matters is subscript or pointer +- int, + // and those shouldn't have qualifier variants anyway. + if (PointeeTy->isArrayType()) + return true; const Type *ClassTy = PointerTy->getClass(); // Iterate through all strict supersets of the pointee type's CVR @@ -4873,11 +4895,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Opc == BinaryOperator::PtrMemD) return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); - // If this is one of the assignment operators, we only perform - // overload resolution if the left-hand side is a class or - // enumeration type (C++ [expr.ass]p3). - if (Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign && - !Args[0]->getType()->isOverloadableType()) + // If this is the assignment operator, we only perform overload resolution + // if the left-hand side is a class or enumeration type. This is actually + // a hack. The standard requires that we do overload resolution between the + // various built-in candidates, but as DR507 points out, this can lead to + // problems. So we do it this way, which pretty much follows what GCC does. + // Note that we go the traditional code path for compound assignment forms. + if (Opc==BinaryOperator::Assign && !Args[0]->getType()->isOverloadableType()) return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); // Build an empty overload set. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 466a0e3..31cd300 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3538,15 +3538,17 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation RAngleLoc, - NamedDecl *&PrevDecl) { + LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet; CandidateSet Candidates; DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext(); - for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) { - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)) { + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *Ovl = (*I)->getUnderlyingDecl(); + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) { // Only consider templates found within the same semantic lookup scope as // FD. if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext())) @@ -3637,7 +3639,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // The "previous declaration" for this function template specialization is // the prior function template specialization. - PrevDecl = Specialization; + Previous.clear(); + Previous.addDecl(Specialization); return false; } @@ -3652,10 +3655,11 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, /// \param Member the member declaration, which will be updated to become a /// specialization. /// -/// \param PrevDecl the set of declarations, one of which may be specialized -/// by this function specialization. +/// \param Previous the set of declarations, one of which may be specialized +/// by this function specialization; the set will be modified to contain the +/// redeclared member. bool -Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { +Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { assert(!isa<TemplateDecl>(Member) && "Only for non-template members"); // Try to find the member we are instantiating. @@ -3663,11 +3667,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { NamedDecl *InstantiatedFrom = 0; MemberSpecializationInfo *MSInfo = 0; - if (!PrevDecl) { + if (Previous.empty()) { // Nowhere to look anyway. } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) { - for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) { - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) { + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { if (Context.hasSameType(Function->getType(), Method->getType())) { Instantiation = Method; InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); @@ -3677,15 +3683,19 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { } } } else if (isa<VarDecl>(Member)) { - if (VarDecl *PrevVar = dyn_cast<VarDecl>(PrevDecl)) + VarDecl *PrevVar; + if (Previous.isSingleResult() && + (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl()))) if (PrevVar->isStaticDataMember()) { - Instantiation = PrevDecl; + Instantiation = PrevVar; InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember(); MSInfo = PrevVar->getMemberSpecializationInfo(); } } else if (isa<RecordDecl>(Member)) { - if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) { - Instantiation = PrevDecl; + CXXRecordDecl *PrevRecord; + if (Previous.isSingleResult() && + (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) { + Instantiation = PrevRecord; InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass(); MSInfo = PrevRecord->getMemberSpecializationInfo(); } @@ -3774,7 +3784,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { // Save the caller the trouble of having to figure out which declaration // this specialization matches. - PrevDecl = Instantiation; + Previous.clear(); + Previous.addDecl(Instantiation); return false; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7e618cd..3f40ffc 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -175,7 +175,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // FIXME: In theory, we could have a previous declaration for variables that // are not static data members. bool Redeclaration = false; - SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration); + // FIXME: having to fake up a LookupResult is dumb. + LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(), + Sema::LookupOrdinaryName); + SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration); if (D->isOutOfLine()) { D->getLexicalDeclContext()->addDecl(Var); @@ -680,27 +683,24 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { bool Redeclaration = false; bool OverloadableAttrRequired = false; - NamedDecl *PrevDecl = 0; + LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + if (TemplateParams || !FunctionTemplate) { // Look only into the namespace where the friend would be declared to // find a previous declaration. This is the innermost enclosing namespace, // as described in ActOnFriendFunctionDecl. - LookupResult R(SemaRef, Function->getDeclName(), SourceLocation(), - Sema::LookupOrdinaryName, - Sema::ForRedeclaration); - SemaRef.LookupQualifiedName(R, DC); + SemaRef.LookupQualifiedName(Previous, DC); - PrevDecl = R.getAsSingleDecl(SemaRef.Context); - // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). - if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag) - PrevDecl = 0; + if (Previous.isSingleTagDecl()) + Previous.clear(); } - SemaRef.CheckFunctionDeclaration(Function, PrevDecl, false, Redeclaration, + SemaRef.CheckFunctionDeclaration(Function, Previous, false, Redeclaration, /*FIXME:*/OverloadableAttrRequired); // If the original function was part of a friend declaration, @@ -709,6 +709,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { = TemplateParams? cast<NamedDecl>(D->getDescribedFunctionTemplate()) : D; if (FromFriendD->getFriendObjectKind()) { NamedDecl *ToFriendD = 0; + NamedDecl *PrevDecl; if (TemplateParams) { ToFriendD = cast<NamedDecl>(FunctionTemplate); PrevDecl = FunctionTemplate->getPreviousDeclaration(); @@ -843,32 +844,31 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, if (InitMethodInstantiation(Method, D)) Method->setInvalidDecl(); - NamedDecl *PrevDecl = 0; + LookupResult Previous(SemaRef, Name, SourceLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); if (!FunctionTemplate || TemplateParams) { - LookupResult R(SemaRef, Name, SourceLocation(), - Sema::LookupOrdinaryName, - Sema::ForRedeclaration); - SemaRef.LookupQualifiedName(R, Owner); - PrevDecl = R.getAsSingleDecl(SemaRef.Context); + SemaRef.LookupQualifiedName(Previous, Owner); // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). - if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag) - PrevDecl = 0; + if (Previous.isSingleTagDecl()) + Previous.clear(); } bool Redeclaration = false; bool OverloadableAttrRequired = false; - SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration, + SemaRef.CheckFunctionDeclaration(Method, Previous, false, Redeclaration, /*FIXME:*/OverloadableAttrRequired); - if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl) && + if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) && !Method->getFriendObjectKind()) Owner->addDecl(Method); + SemaRef.AddOverriddenMethods(Record, Method); + return Method; } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 2bee32a..ca680c2 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -3037,18 +3037,21 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, template<typename Derived> Sema::OwningStmtResult TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { - // The case value expressions are not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + OwningExprResult LHS(SemaRef), RHS(SemaRef); + { + // The case value expressions are not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - // Transform the left-hand case value. - OwningExprResult LHS = getDerived().TransformExpr(S->getLHS()); - if (LHS.isInvalid()) - return SemaRef.StmtError(); + // Transform the left-hand case value. + LHS = getDerived().TransformExpr(S->getLHS()); + if (LHS.isInvalid()) + return SemaRef.StmtError(); - // Transform the right-hand case value (for the GNU case-range extension). - OwningExprResult RHS = getDerived().TransformExpr(S->getRHS()); - if (RHS.isInvalid()) - return SemaRef.StmtError(); + // Transform the right-hand case value (for the GNU case-range extension). + RHS = getDerived().TransformExpr(S->getRHS()); + if (RHS.isInvalid()) + return SemaRef.StmtError(); + } // Build the case statement. // Case statements are always rebuilt so that they will attached to their diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index 4604db5..f5c6a10 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -1,6 +1,6 @@ // RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=basic // RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=basic -// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -analyzer-purge-dead=false -verify %s +// RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -analyzer-no-purge-dead -verify %s // RUN: clang-cc -triple i386-apple-darwin10 -analyze -analyzer-experimental-internal-checks -std=gnu99 -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s typedef unsigned uintptr_t; diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp index b32948b..88bc813 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp @@ -31,7 +31,7 @@ void test() { } namespace Numbers { - struct Number { + struct Number { // expected-note 2 {{candidate}} explicit Number(double d) : d(d) {} double d; }; @@ -57,9 +57,9 @@ void test3() { int i = Ints::zero; Numbers2::f(i); - Numbers2::g(i); // expected-error {{incompatible type passing 'int'}} + Numbers2::g(i); // expected-error {{no viable conversion from 'int' to 'struct Numbers::Number' is possible}} float f = Floats::zero; Numbers2::f(f); - Numbers2::g(f); // expected-error {{incompatible type passing 'float'}} + Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'struct Numbers::Number' is possible}} } diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp index 35e8c08..9528c4b 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp @@ -4,7 +4,7 @@ template <unsigned N> class test {}; -class foo {}; +class foo {}; // expected-note {{candidate}} test<0> foo(foo); // expected-note {{candidate}} namespace Test0 { @@ -38,7 +38,7 @@ namespace Test0 { test<2> _1 = (foo)(a); class Test0::foo b; - test<2> _2 = (foo)(b); // expected-error {{incompatible type passing}} + test<2> _2 = (foo)(b); // expected-error {{no viable conversion from 'class Test0::foo' to 'class foo' is possible}} } } } diff --git a/test/CXX/special/class.dtor/p2.cpp b/test/CXX/special/class.dtor/p2.cpp new file mode 100644 index 0000000..c0e878f --- /dev/null +++ b/test/CXX/special/class.dtor/p2.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR5548 +struct A {~A();}; +void a(const A* x) { + x->~A(); +} diff --git a/test/CodeGen/libcalls.c b/test/CodeGen/libcalls.c index cbbde8a..32fc59f 100644 --- a/test/CodeGen/libcalls.c +++ b/test/CodeGen/libcalls.c @@ -1,7 +1,7 @@ -// RUN: clang-cc -fmath-errno=1 -emit-llvm -o %t %s -triple i386-unknown-unknown +// RUN: clang-cc -emit-llvm -o %t %s -triple i386-unknown-unknown // RUN: grep "declare " %t | count 6 // RUN: grep "declare " %t | grep "@llvm." | count 1 -// RUN: clang-cc -fmath-errno=0 -emit-llvm -o %t %s -triple i386-unknown-unknown +// RUN: clang-cc -fno-math-errno -emit-llvm -o %t %s -triple i386-unknown-unknown // RUN: grep "declare " %t | count 6 // RUN: grep "declare " %t | grep -v "@llvm." | count 0 diff --git a/test/Driver/analyze.c b/test/Driver/analyze.c index ff35cc5..bdbfbbf 100644 --- a/test/Driver/analyze.c +++ b/test/Driver/analyze.c @@ -6,4 +6,4 @@ // CHECK: "-analyze" // CHECK: "-target-feature" "+sse" -// CHECK: "--fmath-errno=0" +// CHECK: "-fno-math-errno" diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c index c57a2b7..fe35184 100644 --- a/test/Driver/clang-translation.c +++ b/test/Driver/clang-translation.c @@ -5,7 +5,6 @@ // RUN: grep '"--relocation-model" "static"' %t.log // RUN: grep '"--disable-fp-elim"' %t.log // RUN: grep '"--unwind-tables=0"' %t.log -// RUN: grep '"--fmath-errno=1"' %t.log // RUN: grep '"-Os"' %t.log // RUN: grep '"-o" .*clang-translation.*' %t.log // RUN: grep '"--asm-verbose"' %t.log diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c index b18f147..3756a2f 100644 --- a/test/Driver/clang_f_opts.c +++ b/test/Driver/clang_f_opts.c @@ -1,10 +1,9 @@ // RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings %s 2> %t // RUN: grep -F '"-fblocks"' %t -// RUN: grep -F '"--fmath-errno=1"' %t // RUN: grep -F '"-fpascal-strings"' %t // RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fno-show-source-location -fshort-wchar %s 2> %t -// RUN: grep -F '"-fbuiltin=0"' %t +// RUN: grep -F '"-fno-builtin"' %t // RUN: grep -F '"-fno-common"' %t -// RUN: grep -F '"--fmath-errno=0"' %t +// RUN: grep -F '"-fno-math-errno"' %t // RUN: grep -F '"-fno-show-source-location"' %t // RUN: grep -F '"-fshort-wchar"' %t diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m index 7256d2b..9009f78 100644 --- a/test/Index/TestClassDecl.m +++ b/test/Index/TestClassDecl.m @@ -32,20 +32,20 @@ void function(Foo * arg) // CHECK-scan: {start_line=13 start_col=24 end_line=16 end_col=1} FunctionDecl=function:13:6 // CHECK-scan: {start_line=16 start_col=2 end_line=52 end_col=1} Invalid Cursor => NoDeclFound -// CHECK-load: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:0:0: StructDecl=objc_selector:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=SEL:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:0:0: ObjCInterfaceDecl=Protocol:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=id:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=Class:0:0 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:80:16: StructDecl=__va_list_tag:80:16 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:80:42: FieldDecl=gp_offset:80:42 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:63: FieldDecl=fp_offset:80:63 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:81: FieldDecl=overflow_arg_area:80:81 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:107: FieldDecl=reg_save_area:80:107 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:123: TypedefDecl=__va_list_tag:80:123 [Context=TestClassDecl.m] -// CHECK-load: <invalid loc>:80:159: TypedefDecl=__builtin_va_list:80:159 [Context=TestClassDecl.m] + + + + + + + + + + + + + + // CHECK-load: TestClassDecl.m:10:12: ObjCInterfaceDecl=Foo:10:1 [Context=TestClassDecl.m] // CHECK-load: TestClassDecl.m:13:6: FunctionDefn=function [Context=TestClassDecl.m] // CHECK-load: TestClassDecl.m:13:21: ParmDecl=arg:13:21 [Context=function] diff --git a/test/Index/TestClassForwardDecl.m b/test/Index/TestClassForwardDecl.m index 4584445..31b7c6c 100644 --- a/test/Index/TestClassForwardDecl.m +++ b/test/Index/TestClassForwardDecl.m @@ -27,20 +27,20 @@ void function(Foo * arg) // CHECK-scan: {start_line=10 start_col=24 end_line=13 end_col=1} FunctionDecl=function:10:6 // CHECK-scan: {start_line=13 start_col=2 end_line=46 end_col=1} Invalid Cursor => NoDeclFound -// CHECK-load: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:0:0: StructDecl=objc_selector:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=SEL:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:0:0: ObjCInterfaceDecl=Protocol:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=id:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:0:0: TypedefDecl=Class:0:0 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:80:16: StructDecl=__va_list_tag:80:16 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:80:42: FieldDecl=gp_offset:80:42 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:63: FieldDecl=fp_offset:80:63 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:81: FieldDecl=overflow_arg_area:80:81 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:107: FieldDecl=reg_save_area:80:107 [Context=__va_list_tag] -// CHECK-load: <invalid loc>:80:123: TypedefDecl=__va_list_tag:80:123 [Context=TestClassForwardDecl.m] -// CHECK-load: <invalid loc>:80:159: TypedefDecl=__builtin_va_list:80:159 [Context=TestClassForwardDecl.m] + + + + + + + + + + + + + + // CHECK-load: TestClassForwardDecl.m:10:6: FunctionDefn=function [Context=TestClassForwardDecl.m] // CHECK-load: TestClassForwardDecl.m:10:21: ParmDecl=arg:10:21 [Context=function] diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m index 5427764..7ab1435 100644 --- a/test/Index/c-index-api-loadTU-test.m +++ b/test/Index/c-index-api-loadTU-test.m @@ -1,21 +1,21 @@ // RUN: clang-cc -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast // RUN: c-index-test -test-load-tu %t.ast all | FileCheck %s -// CHECK: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:0:0: StructDecl=objc_selector:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:0:0: TypedefDecl=SEL:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:0:0: ObjCInterfaceDecl=Protocol:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:0:0: TypedefDecl=id:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:0:0: TypedefDecl=Class:0:0 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:80:16: StructDecl=__va_list_tag:80:16 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:80:42: FieldDecl=gp_offset:80:42 [Context=__va_list_tag] -// CHECK: <invalid loc>:80:63: FieldDecl=fp_offset:80:63 [Context=__va_list_tag] -// CHECK: <invalid loc>:80:81: FieldDecl=overflow_arg_area:80:81 [Context=__va_list_tag] -// CHECK: <invalid loc>:80:107: FieldDecl=reg_save_area:80:107 [Context=__va_list_tag] -// CHECK: <invalid loc>:80:123: TypedefDecl=__va_list_tag:80:123 [Context=c-index-api-loadTU-test.m] -// CHECK: <invalid loc>:80:159: TypedefDecl=__builtin_va_list:80:159 [Context=c-index-api-loadTU-test.m] -// + + + + + + + + + + + + + + + @interface Foo { diff --git a/test/Index/complete-categories.m b/test/Index/complete-categories.m new file mode 100644 index 0000000..92b14db --- /dev/null +++ b/test/Index/complete-categories.m @@ -0,0 +1,39 @@ +/* Note: the RUN lines are near the end of the file, since line/column + matter for this test. */ + +@interface I1 @end +@interface I2 @end +@interface I3 : I2 @end + +@interface I1(Cat1) @end +@interface I1(Cat2) @end +@interface I1(Cat3) @end + +@interface I2 (Cat2) @end +@interface I2 (Cat3) @end +@interface I2 (Cat2) @end +@interface I3 (Cat1) @end +@interface I3 (Cat2) @end + +@implementation I1(Cat2) @end +@implementation I1(Cat3) @end +@implementation I3(Cat2) @end + +// RUN: c-index-test -code-completion-at=%s:12:16 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: ObjCCategoryDecl:{TypedText Cat1} +// CHECK-CC1: ObjCCategoryDecl:{TypedText Cat2} +// CHECK-CC1: ObjCCategoryDecl:{TypedText Cat3} +// RUN: c-index-test -code-completion-at=%s:13:16 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: ObjCCategoryDecl:{TypedText Cat1} +// CHECK-CC2-NEXT: ObjCCategoryDecl:{TypedText Cat3} +// RUN: c-index-test -code-completion-at=%s:18:20 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: ObjCCategoryDecl:{TypedText Cat1} +// CHECK-CC3: ObjCCategoryDecl:{TypedText Cat2} +// CHECK-CC3: ObjCCategoryDecl:{TypedText Cat3} +// RUN: c-index-test -code-completion-at=%s:19:20 %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: ObjCCategoryDecl:{TypedText Cat1} +// CHECK-CC4-NEXT: ObjCCategoryDecl:{TypedText Cat3} +// RUN: c-index-test -code-completion-at=%s:20:20 %s | FileCheck -check-prefix=CHECK-CC5 %s +// CHECK-CC5: ObjCCategoryDecl:{TypedText Cat1} +// CHECK-CC5-NEXT: ObjCCategoryDecl:{TypedText Cat2} +// CHECK-CC5-NEXT: ObjCCategoryDecl:{TypedText Cat3} diff --git a/test/Index/complete-interfaces.m b/test/Index/complete-interfaces.m new file mode 100644 index 0000000..229ec2d --- /dev/null +++ b/test/Index/complete-interfaces.m @@ -0,0 +1,43 @@ +/* Note: the RUN lines are near the end of the file, since line/column + matter for this test. */ + +@class Int1, Int2, Int3, Int4; + +@interface Int3 +{ +} +@end + +@interface Int2 : Int3 +{ +} +@end + +@implementation Int2 +@end + +@implementation Int3 +@end + +// RUN: c-index-test -code-completion-at=%s:6:12 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: ObjCInterfaceDecl:{TypedText Int1} +// CHECK-CC1: ObjCInterfaceDecl:{TypedText Int2} +// CHECK-CC1: ObjCInterfaceDecl:{TypedText Int3} +// CHECK-CC1: ObjCInterfaceDecl:{TypedText Int4} +// RUN: c-index-test -code-completion-at=%s:11:12 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: ObjCInterfaceDecl:{TypedText Int1} +// CHECK-CC2-NEXT: ObjCInterfaceDecl:{TypedText Int2} +// CHECK-CC2-NEXT: ObjCInterfaceDecl:{TypedText Int4} +// RUN: c-index-test -code-completion-at=%s:11:19 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: ObjCInterfaceDecl:{TypedText Int1} +// CHECK-CC3-NEXT: ObjCInterfaceDecl:{TypedText Int3} +// CHECK-CC3-NEXT: ObjCInterfaceDecl:{TypedText Int4} +// RUN: c-index-test -code-completion-at=%s:16:17 %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: ObjCInterfaceDecl:{TypedText Int1} +// CHECK-CC4-NEXT: ObjCInterfaceDecl:{TypedText Int2} +// CHECK-CC4-NEXT: ObjCInterfaceDecl:{TypedText Int3} +// CHECK-CC4-NEXT: ObjCInterfaceDecl:{TypedText Int4} +// RUN: c-index-test -code-completion-at=%s:19:17 %s | FileCheck -check-prefix=CHECK-CC5 %s +// CHECK-CC5: ObjCInterfaceDecl:{TypedText Int1} +// CHECK-CC5-NEXT: ObjCInterfaceDecl:{TypedText Int3} +// CHECK-CC5-NEXT: ObjCInterfaceDecl:{TypedText Int4} diff --git a/test/Index/complete-objc-message.m b/test/Index/complete-objc-message.m index 8f235d3..b692986c 100644 --- a/test/Index/complete-objc-message.m +++ b/test/Index/complete-objc-message.m @@ -82,6 +82,19 @@ void test_qual_id(id<FooTestProtocol,FooTestProtocol2> ptr) { [ptr protocolInstanceMethod:1]; } +@interface Overload +- (int)Method:(int)i; +- (int)Method; +- (int)Method:(float)f Arg1:(int)i1 Arg2:(int)i2; +- (int)Method:(float)f Arg1:(int)i1 OtherArg:(id)obj; +- (int)Method:(float)f SomeArg:(int)i1 OtherArg:(id)obj; +- (int)OtherMethod:(float)f Arg1:(int)i1 Arg2:(int)i2; +@end + +void test_overload(Overload *ovl) { + [ovl Method:1 Arg1:1 OtherArg:ovl]; +} + // RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: {TypedText categoryClassMethod} // CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)a}{Text withKeyword:}{Placeholder (int)b} @@ -104,4 +117,18 @@ void test_qual_id(id<FooTestProtocol,FooTestProtocol2> ptr) { // RUN: c-index-test -code-completion-at=%s:82:8 %s | FileCheck -check-prefix=CHECK-CC6 %s // CHECK-CC6: ObjCInstanceMethodDecl:{TypedText protocolInstanceMethod:}{Placeholder (int)value} // CHECK-CC6: ObjCInstanceMethodDecl:{TypedText secondProtocolInstanceMethod} - +// RUN: c-index-test -code-completion-at=%s:95:8 %s | FileCheck -check-prefix=CHECK-CC7 %s +// CHECK-CC7: ObjCInstanceMethodDecl:{TypedText Method} +// CHECK-CC7: ObjCInstanceMethodDecl:{TypedText Method:}{Placeholder (int)i} +// CHECK-CC7: ObjCInstanceMethodDecl:{TypedText Method:}{Placeholder (float)f}{Text Arg1:}{Placeholder (int)i1}{Text Arg2:}{Placeholder (int)i2} +// CHECK-CC7: ObjCInstanceMethodDecl:{TypedText Method:}{Placeholder (float)f}{Text Arg1:}{Placeholder (int)i1}{Text OtherArg:}{Placeholder (id)obj} +// CHECK-CC7: ObjCInstanceMethodDecl:{TypedText Method:}{Placeholder (float)f}{Text SomeArg:}{Placeholder (int)i1}{Text OtherArg:}{Placeholder (id)obj} +// CHECK-CC7: ObjCInstanceMethodDecl:{TypedText OtherMethod:}{Placeholder (float)f}{Text Arg1:}{Placeholder (int)i1}{Text Arg2:}{Placeholder (int)i2} +// RUN: c-index-test -code-completion-at=%s:95:17 %s | FileCheck -check-prefix=CHECK-CC8 %s +// CHECK-CC8: ObjCInstanceMethodDecl:{Informative Method:}{TypedText } +// CHECK-CC8: ObjCInstanceMethodDecl:{Informative Method:}{TypedText Arg1:}{Placeholder (int)i1}{Text Arg2:}{Placeholder (int)i2} +// CHECK-CC8: ObjCInstanceMethodDecl:{Informative Method:}{TypedText Arg1:}{Placeholder (int)i1}{Text OtherArg:}{Placeholder (id)obj} +// CHECK-CC8: ObjCInstanceMethodDecl:{Informative Method:}{TypedText SomeArg:}{Placeholder (int)i1}{Text OtherArg:}{Placeholder (id)obj} +// RUN: c-index-test -code-completion-at=%s:95:24 %s | FileCheck -check-prefix=CHECK-CC9 %s +// CHECK-CC9: ObjCInstanceMethodDecl:{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2} +// CHECK-CC9: ObjCInstanceMethodDecl:{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj} diff --git a/test/Index/complete-properties.m b/test/Index/complete-properties.m new file mode 100644 index 0000000..a99b1d1 --- /dev/null +++ b/test/Index/complete-properties.m @@ -0,0 +1,40 @@ +/* Note: the RUN lines are near the end of the file, since line/column + matter for this test. */ + +@interface I1 +{ + id StoredProp3; + int RandomIVar; +} +@property int Prop0; +@property int Prop1; +@property float Prop2; +@end + +@interface I2 : I1 +@property id Prop3; +@property id Prop4; +@end + +@implementation I2 +@synthesize Prop2, Prop1, Prop3 = StoredProp3; +@dynamic Prop4; +@end + +// RUN: c-index-test -code-completion-at=%s:20:13 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop0} +// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop1} +// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop2} +// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop3} +// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop4} +// RUN: c-index-test -code-completion-at=%s:20:20 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: ObjCPropertyDecl:{TypedText Prop0} +// CHECK-CC2: ObjCPropertyDecl:{TypedText Prop1} +// CHECK-CC2-NEXT: ObjCPropertyDecl:{TypedText Prop3} +// CHECK-CC2: ObjCPropertyDecl:{TypedText Prop4} +// RUN: c-index-test -code-completion-at=%s:20:35 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: ObjCIvarDecl:{TypedText RandomIVar} +// CHECK-CC3: ObjCIvarDecl:{TypedText StoredProp3} +// RUN: c-index-test -code-completion-at=%s:21:10 %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: ObjCPropertyDecl:{TypedText Prop0} +// CHECK-CC4-NEXT: ObjCPropertyDecl:{TypedText Prop4} diff --git a/test/Index/complete-property-flags.m b/test/Index/complete-property-flags.m new file mode 100644 index 0000000..cd3696f --- /dev/null +++ b/test/Index/complete-property-flags.m @@ -0,0 +1,23 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +@interface Foo { + void *isa; +} +@property(copy) Foo *myprop; +@property(retain, nonatomic) id xx; +// RUN: c-index-test -code-completion-at=%s:7:11 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: {TypedText assign} +// CHECK-CC1-NEXT: {TypedText copy} +// CHECK-CC1-NEXT: {TypedText getter}{Text = }{Placeholder method} +// CHECK-CC1-NEXT: {TypedText nonatomic} +// CHECK-CC1-NEXT: {TypedText readonly} +// CHECK-CC1-NEXT: {TypedText readwrite} +// CHECK-CC1-NEXT: {TypedText retain} +// CHECK-CC1-NEXT: {TypedText setter}{Text = }{Placeholder method} +// RUN: c-index-test -code-completion-at=%s:8:18 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: {TypedText getter}{Text = }{Placeholder method} +// CHECK-CC2-NEXT: {TypedText nonatomic} +// CHECK-CC2-NEXT: {TypedText readwrite} +// CHECK-CC2-NEXT: {TypedText setter}{Text = }{Placeholder method} +@end diff --git a/test/Index/complete-property-getset.m b/test/Index/complete-property-getset.m new file mode 100644 index 0000000..a2a8053 --- /dev/null +++ b/test/Index/complete-property-getset.m @@ -0,0 +1,41 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +@interface Super { } +- (int)getter1; ++ (int)getter2_not_instance; +- (int)getter2_not:(int)x; +- (int)getter3; +- (void)setter1:(int)x; ++ (void)setter2_not_inst:(int)x; ++ (void)setter2_many_args:(int)x second:(int)y; +- (void)setter3:(int)y; +@property (getter = getter1, setter = setter1:) int blah; +@end + +@interface Sub : Super { } +- (int)getter4; +- (void)setter4:(int)x; +@property (getter = getter4, setter = setter1:) int blarg; +@end + +// RUN: c-index-test -code-completion-at=%s:13:21 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: ObjCInstanceMethodDecl:{TypedText getter1} +// CHECK-CC1-NOT: getter2 +// CHECK-CC1: ObjCInstanceMethodDecl:{TypedText getter3} +// RUN: c-index-test -code-completion-at=%s:13:39 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText getter2_not:} +// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText setter1:} +// CHECK-CC2-NOT: setter2 +// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText setter3:} +// RUN: c-index-test -code-completion-at=%s:19:21 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText getter1} +// CHECK-CC3-NOT: getter2 +// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText getter3} +// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText getter4} +// RUN: c-index-test -code-completion-at=%s:19:39 %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText getter2_not:}{Informative (int)x} +// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText setter1:}{Informative (int)x} +// CHECK-CC4-NOT: setter2 +// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText setter3:}{Informative (int)y} +// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText setter4:}{Informative (int)x} diff --git a/test/Parser/objc-synthesized-recover.m b/test/Parser/objc-synthesized-recover.m new file mode 100644 index 0000000..7de1a57 --- /dev/null +++ b/test/Parser/objc-synthesized-recover.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface I1 +{ + int value; + int value2; +} +@property int value; +@property int value2; +@end + +@implementation I1 +@synthesize value, - value2; // expected-error{{expected a property name}} +@synthesize value2; +@end diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c index 2926900..aae218d 100644 --- a/test/Preprocessor/init.c +++ b/test/Preprocessor/init.c @@ -155,8 +155,9 @@ // ARM:#define __INT64_TYPE__ long long int // ARM:#define __INT8_TYPE__ char // ARM:#define __INTMAX_MAX__ 9223372036854775807LL -// ARM:#define __INTMAX_TYPE__ long long int +// ARM:#define __INTMAX_WIDTH__ 64 // ARM:#define __INTPTR_TYPE__ long int +// ARM:#define __INTPTR_WIDTH__ 32 // ARM:#define __INT_MAX__ 2147483647 // ARM:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // ARM:#define __LDBL_DIG__ 15 @@ -181,7 +182,6 @@ // ARM:#define __SHRT_MAX__ 32767 // ARM:#define __SIZE_TYPE__ unsigned int // ARM:#define __THUMB_INTERWORK__ 1 -// ARM:#define __UINTMAX_TYPE__ long long unsigned int // ARM:#define __USER_LABEL_PREFIX__ _ // ARM:#define __VFP_FP__ 1 // ARM:#define __WCHAR_MAX__ 2147483647 @@ -233,8 +233,9 @@ // BFIN:#define __INT64_TYPE__ long long int // BFIN:#define __INT8_TYPE__ char // BFIN:#define __INTMAX_MAX__ 9223372036854775807LL -// BFIN:#define __INTMAX_TYPE__ long long int +// BFIN:#define __INTMAX_WIDTH__ 64 // BFIN:#define __INTPTR_TYPE__ long int +// BFIN:#define __INTPTR_WIDTH__ 32 // BFIN:#define __INT_MAX__ 2147483647 // BFIN:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // BFIN:#define __LDBL_DIG__ 15 @@ -257,7 +258,6 @@ // BFIN:#define __SCHAR_MAX__ 127 // BFIN:#define __SHRT_MAX__ 32767 // BFIN:#define __SIZE_TYPE__ long unsigned int -// BFIN:#define __UINTMAX_TYPE__ long long unsigned int // BFIN:#define __USER_LABEL_PREFIX__ _ // BFIN:#define __WCHAR_MAX__ 2147483647 // BFIN:#define __WCHAR_TYPE__ int @@ -304,8 +304,9 @@ // I386:#define __INT64_TYPE__ long long int // I386:#define __INT8_TYPE__ char // I386:#define __INTMAX_MAX__ 9223372036854775807LL -// I386:#define __INTMAX_TYPE__ long long int +// I386:#define __INTMAX_WIDTH__ 64 // I386:#define __INTPTR_TYPE__ int +// I386:#define __INTPTR_WIDTH__ 32 // I386:#define __INT_MAX__ 2147483647 // I386:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L // I386:#define __LDBL_DIG__ 18 @@ -331,7 +332,6 @@ // I386:#define __SCHAR_MAX__ 127 // I386:#define __SHRT_MAX__ 32767 // I386:#define __SIZE_TYPE__ unsigned int -// I386:#define __UINTMAX_TYPE__ long long unsigned int // I386:#define __USER_LABEL_PREFIX__ _ // I386:#define __WCHAR_MAX__ 2147483647 // I386:#define __WCHAR_TYPE__ int @@ -381,8 +381,9 @@ // MSP430:#define __INT32_TYPE__ long int // MSP430:#define __INT8_TYPE__ char // MSP430:#define __INTMAX_MAX__ 2147483647L -// MSP430:#define __INTMAX_TYPE__ long int +// MSP430:#define __INTMAX_WIDTH__ 32 // MSP430:#define __INTPTR_TYPE__ short +// MSP430:#define __INTPTR_WIDTH__ 16 // MSP430:#define __INT_MAX__ 32767 // MSP430:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // MSP430:#define __LDBL_DIG__ 15 @@ -406,7 +407,6 @@ // MSP430:#define __SCHAR_MAX__ 127 // MSP430:#define __SHRT_MAX__ 32767 // MSP430:#define __SIZE_TYPE__ unsigned int -// MSP430:#define __UINTMAX_TYPE__ long unsigned int // MSP430:#define __USER_LABEL_PREFIX__ _ // MSP430:#define __WCHAR_MAX__ 32767 // MSP430:#define __WCHAR_TYPE__ int @@ -451,8 +451,9 @@ // PIC16:#define __INT32_TYPE__ long int // PIC16:#define __INT8_TYPE__ char // PIC16:#define __INTMAX_MAX__ 2147483647L -// PIC16:#define __INTMAX_TYPE__ long int +// PIC16:#define __INTMAX_WIDTH__ 32 // PIC16:#define __INTPTR_TYPE__ short +// PIC16:#define __INTPTR_WIDTH__ 16 // PIC16:#define __INT_MAX__ 32767 // PIC16:#define __LDBL_DENORM_MIN__ 1.40129846e-45F // PIC16:#define __LDBL_DIG__ 6 @@ -475,7 +476,6 @@ // PIC16:#define __SCHAR_MAX__ 127 // PIC16:#define __SHRT_MAX__ 32767 // PIC16:#define __SIZE_TYPE__ unsigned int -// PIC16:#define __UINTMAX_TYPE__ long unsigned int // PIC16:#define __USER_LABEL_PREFIX__ _ // PIC16:#define __WCHAR_MAX__ 32767 // PIC16:#define __WCHAR_TYPE__ int @@ -533,8 +533,9 @@ // PPC64:#define __INT64_TYPE__ long int // PPC64:#define __INT8_TYPE__ char // PPC64:#define __INTMAX_MAX__ 9223372036854775807L -// PPC64:#define __INTMAX_TYPE__ long int +// PPC64:#define __INTMAX_WIDTH__ 64 // PPC64:#define __INTPTR_TYPE__ long int +// PPC64:#define __INTPTR_WIDTH__ 64 // PPC64:#define __INT_MAX__ 2147483647 // PPC64:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // PPC64:#define __LDBL_DIG__ 15 @@ -562,7 +563,6 @@ // PPC64:#define __SCHAR_MAX__ 127 // PPC64:#define __SHRT_MAX__ 32767 // PPC64:#define __SIZE_TYPE__ long unsigned int -// PPC64:#define __UINTMAX_TYPE__ long unsigned int // PPC64:#define __USER_LABEL_PREFIX__ _ // PPC64:#define __WCHAR_MAX__ 2147483647 // PPC64:#define __WCHAR_TYPE__ int @@ -612,8 +612,9 @@ // PPC:#define __INT64_TYPE__ long long int // PPC:#define __INT8_TYPE__ char // PPC:#define __INTMAX_MAX__ 9223372036854775807LL -// PPC:#define __INTMAX_TYPE__ long long int +// PPC:#define __INTMAX_WIDTH__ 64 // PPC:#define __INTPTR_TYPE__ long int +// PPC:#define __INTPTR_WIDTH__ 32 // PPC:#define __INT_MAX__ 2147483647 // PPC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // PPC:#define __LDBL_DIG__ 15 @@ -640,7 +641,6 @@ // PPC:#define __SCHAR_MAX__ 127 // PPC:#define __SHRT_MAX__ 32767 // PPC:#define __SIZE_TYPE__ long unsigned int -// PPC:#define __UINTMAX_TYPE__ long long unsigned int // PPC:#define __USER_LABEL_PREFIX__ _ // PPC:#define __WCHAR_MAX__ 2147483647 // PPC:#define __WCHAR_TYPE__ int @@ -686,8 +686,9 @@ // S390X:#define __INT64_TYPE__ long int // S390X:#define __INT8_TYPE__ char // S390X:#define __INTMAX_MAX__ 9223372036854775807LL -// S390X:#define __INTMAX_TYPE__ long long int +// S390X:#define __INTMAX_WIDTH__ 64 // S390X:#define __INTPTR_TYPE__ long int +// S390X:#define __INTPTR_WIDTH__ 64 // S390X:#define __INT_MAX__ 2147483647 // S390X:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // S390X:#define __LDBL_DIG__ 15 @@ -710,7 +711,6 @@ // S390X:#define __SCHAR_MAX__ 127 // S390X:#define __SHRT_MAX__ 32767 // S390X:#define __SIZE_TYPE__ long unsigned int -// S390X:#define __UINTMAX_TYPE__ long long unsigned int // S390X:#define __USER_LABEL_PREFIX__ _ // S390X:#define __WCHAR_MAX__ 2147483647 // S390X:#define __WCHAR_TYPE__ int @@ -756,8 +756,9 @@ // SPARC:#define __INT64_TYPE__ long long int // SPARC:#define __INT8_TYPE__ char // SPARC:#define __INTMAX_MAX__ 9223372036854775807LL -// SPARC:#define __INTMAX_TYPE__ long long int +// SPARC:#define __INTMAX_WIDTH__ 64 // SPARC:#define __INTPTR_TYPE__ long int +// SPARC:#define __INTPTR_WIDTH__ 32 // SPARC:#define __INT_MAX__ 2147483647 // SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324 // SPARC:#define __LDBL_DIG__ 15 @@ -781,7 +782,6 @@ // SPARC:#define __SCHAR_MAX__ 127 // SPARC:#define __SHRT_MAX__ 32767 // SPARC:#define __SIZE_TYPE__ long unsigned int -// SPARC:#define __UINTMAX_TYPE__ long long unsigned int // SPARC:#define __USER_LABEL_PREFIX__ _ // SPARC:#define __VERSION__ "4.2.1 Compatible Clang Compiler" // SPARC:#define __WCHAR_MAX__ 2147483647 @@ -828,8 +828,9 @@ // TCE:#define __INT32_TYPE__ int // TCE:#define __INT8_TYPE__ char // TCE:#define __INTMAX_MAX__ 2147483647L -// TCE:#define __INTMAX_TYPE__ long int +// TCE:#define __INTMAX_WIDTH__ 32 // TCE:#define __INTPTR_TYPE__ int +// TCE:#define __INTPTR_WIDTH__ 32 // TCE:#define __INT_MAX__ 2147483647 // TCE:#define __LDBL_DENORM_MIN__ 1.40129846e-45F // TCE:#define __LDBL_DIG__ 6 @@ -854,7 +855,6 @@ // TCE:#define __SIZE_TYPE__ unsigned int // TCE:#define __TCE_V1__ 1 // TCE:#define __TCE__ 1 -// TCE:#define __UINTMAX_TYPE__ long unsigned int // TCE:#define __USER_LABEL_PREFIX__ _ // TCE:#define __WCHAR_MAX__ 2147483647 // TCE:#define __WCHAR_TYPE__ int @@ -902,8 +902,9 @@ // X86_64:#define __INT64_TYPE__ long int // X86_64:#define __INT8_TYPE__ char // X86_64:#define __INTMAX_MAX__ 9223372036854775807L -// X86_64:#define __INTMAX_TYPE__ long int +// X86_64:#define __INTMAX_WIDTH__ 64 // X86_64:#define __INTPTR_TYPE__ long int +// X86_64:#define __INTPTR_WIDTH__ 64 // X86_64:#define __INT_MAX__ 2147483647 // X86_64:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L // X86_64:#define __LDBL_DIG__ 18 @@ -935,7 +936,6 @@ // X86_64:#define __SSE2__ 1 // X86_64:#define __SSE_MATH__ 1 // X86_64:#define __SSE__ 1 -// X86_64:#define __UINTMAX_TYPE__ long unsigned int // X86_64:#define __USER_LABEL_PREFIX__ _ // X86_64:#define __WCHAR_MAX__ 2147483647 // X86_64:#define __WCHAR_TYPE__ int diff --git a/test/Preprocessor/stdint.c b/test/Preprocessor/stdint.c index 641f704..9c98e29 100644 --- a/test/Preprocessor/stdint.c +++ b/test/Preprocessor/stdint.c @@ -28,11 +28,11 @@ // ARM:typedef int8_t int_fast8_t; // ARM:typedef uint8_t uint_fast8_t; // -// ARM:typedef long int intptr_t; -// ARM:typedef unsigned long int uintptr_t; +// ARM:typedef int32_t intptr_t; +// ARM:typedef uint32_t uintptr_t; // -// ARM:typedef long long int intmax_t; -// ARM:typedef long long unsigned int uintmax_t; +// ARM:typedef int64_t intmax_t; +// ARM:typedef uint64_t uintmax_t; // // ARM:INT8_MAX_ 127 // ARM:INT8_MIN_ (-127 -1) @@ -83,7 +83,7 @@ // // ARM:INTMAX_MIN_ (-9223372036854775807LL -1) // ARM:INTMAX_MAX_ 9223372036854775807LL -// ARM:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL) +// ARM:UINTMAX_MAX_ 18446744073709551615ULL // // ARM:SIG_ATOMIC_MIN_ (-2147483647 -1) // ARM:SIG_ATOMIC_MAX_ 2147483647 @@ -136,11 +136,11 @@ // BFIN:typedef int8_t int_fast8_t; // BFIN:typedef uint8_t uint_fast8_t; // -// BFIN:typedef long int intptr_t; -// BFIN:typedef unsigned long int uintptr_t; +// BFIN:typedef int32_t intptr_t; +// BFIN:typedef uint32_t uintptr_t; // -// BFIN:typedef long long int intmax_t; -// BFIN:typedef long long unsigned int uintmax_t; +// BFIN:typedef int64_t intmax_t; +// BFIN:typedef uint64_t uintmax_t; // // BFIN:INT8_MAX_ 127 // BFIN:INT8_MIN_ (-127 -1) @@ -191,7 +191,7 @@ // // BFIN:INTMAX_MIN_ (-9223372036854775807LL -1) // BFIN:INTMAX_MAX_ 9223372036854775807LL -// BFIN:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL) +// BFIN:UINTMAX_MAX_ 18446744073709551615ULL // // BFIN:SIG_ATOMIC_MIN_ (-2147483647 -1) // BFIN:SIG_ATOMIC_MAX_ 2147483647 @@ -244,11 +244,11 @@ // I386:typedef int8_t int_fast8_t; // I386:typedef uint8_t uint_fast8_t; // -// I386:typedef int intptr_t; -// I386:typedef unsigned int uintptr_t; +// I386:typedef int32_t intptr_t; +// I386:typedef uint32_t uintptr_t; // -// I386:typedef long long int intmax_t; -// I386:typedef long long unsigned int uintmax_t; +// I386:typedef int64_t intmax_t; +// I386:typedef uint64_t uintmax_t; // // I386:INT8_MAX_ 127 // I386:INT8_MIN_ (-127 -1) @@ -299,7 +299,7 @@ // // I386:INTMAX_MIN_ (-9223372036854775807LL -1) // I386:INTMAX_MAX_ 9223372036854775807LL -// I386:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL) +// I386:UINTMAX_MAX_ 18446744073709551615ULL // // I386:SIG_ATOMIC_MIN_ (-2147483647 -1) // I386:SIG_ATOMIC_MAX_ 2147483647 @@ -344,11 +344,11 @@ // MSP430:typedef int8_t int_fast8_t; // MSP430:typedef uint8_t uint_fast8_t; // -// MSP430:typedef short intptr_t; -// MSP430:typedef unsigned short uintptr_t; +// MSP430:typedef int16_t intptr_t; +// MSP430:typedef uint16_t uintptr_t; // -// MSP430:typedef long int intmax_t; -// MSP430:typedef long unsigned int uintmax_t; +// MSP430:typedef int32_t intmax_t; +// MSP430:typedef uint32_t uintmax_t; // // MSP430:INT8_MAX_ 127 // MSP430:INT8_MIN_ (-127 -1) @@ -399,7 +399,7 @@ // // MSP430:INTMAX_MIN_ (-2147483647L -1) // MSP430:INTMAX_MAX_ 2147483647L -// MSP430:UINTMAX_MAX_ (2147483647L*2ULL +1ULL) +// MSP430:UINTMAX_MAX_ 4294967295UL // // MSP430:SIG_ATOMIC_MIN_ (-2147483647L -1) // MSP430:SIG_ATOMIC_MAX_ 2147483647L @@ -418,8 +418,8 @@ // MSP430:INT64_C_(0) INT64_C(0) // MSP430:UINT64_C_(0) UINT64_C(0) // -// MSP430:INTMAX_C_(0) 0LL -// MSP430:UINTMAX_C_(0) 0ULL +// MSP430:INTMAX_C_(0) 0L +// MSP430:UINTMAX_C_(0) 0UL // // RUN: clang-cc -E -ffreestanding -triple=pic16-none-none %s | FileCheck -check-prefix PIC16 %s // @@ -444,11 +444,11 @@ // PIC16:typedef int8_t int_fast8_t; // PIC16:typedef uint8_t uint_fast8_t; // -// PIC16:typedef short intptr_t; -// PIC16:typedef unsigned short uintptr_t; +// PIC16:typedef int16_t intptr_t; +// PIC16:typedef uint16_t uintptr_t; // -// PIC16:typedef long int intmax_t; -// PIC16:typedef long unsigned int uintmax_t; +// PIC16:typedef int32_t intmax_t; +// PIC16:typedef uint32_t uintmax_t; // // PIC16:INT8_MAX_ 127 // PIC16:INT8_MIN_ (-127 -1) @@ -499,7 +499,7 @@ // // PIC16:INTMAX_MIN_ (-2147483647L -1) // PIC16:INTMAX_MAX_ 2147483647L -// PIC16:UINTMAX_MAX_ (2147483647L*2ULL +1ULL) +// PIC16:UINTMAX_MAX_ 4294967295UL // // PIC16:SIG_ATOMIC_MIN_ (-2147483647L -1) // PIC16:SIG_ATOMIC_MAX_ 2147483647L @@ -518,8 +518,8 @@ // PIC16:INT64_C_(0) INT64_C(0) // PIC16:UINT64_C_(0) UINT64_C(0) // -// PIC16:INTMAX_C_(0) 0LL -// PIC16:UINTMAX_C_(0) 0ULL +// PIC16:INTMAX_C_(0) 0L +// PIC16:UINTMAX_C_(0) 0UL // // RUN: clang-cc -E -ffreestanding -triple=powerpc64-none-none %s | FileCheck -check-prefix PPC64 %s // @@ -551,11 +551,11 @@ // PPC64:typedef int8_t int_fast8_t; // PPC64:typedef uint8_t uint_fast8_t; // -// PPC64:typedef long int intptr_t; -// PPC64:typedef unsigned long int uintptr_t; +// PPC64:typedef int64_t intptr_t; +// PPC64:typedef uint64_t uintptr_t; // -// PPC64:typedef long int intmax_t; -// PPC64:typedef long unsigned int uintmax_t; +// PPC64:typedef int64_t intmax_t; +// PPC64:typedef uint64_t uintmax_t; // // PPC64:INT8_MAX_ 127 // PPC64:INT8_MIN_ (-127 -1) @@ -606,7 +606,7 @@ // // PPC64:INTMAX_MIN_ (-9223372036854775807L -1) // PPC64:INTMAX_MAX_ 9223372036854775807L -// PPC64:UINTMAX_MAX_ (9223372036854775807L*2ULL +1ULL) +// PPC64:UINTMAX_MAX_ 18446744073709551615UL // // PPC64:SIG_ATOMIC_MIN_ (-2147483647 -1) // PPC64:SIG_ATOMIC_MAX_ 2147483647 @@ -625,8 +625,8 @@ // PPC64:INT64_C_(0) 0L // PPC64:UINT64_C_(0) 0UL // -// PPC64:INTMAX_C_(0) 0LL -// PPC64:UINTMAX_C_(0) 0ULL +// PPC64:INTMAX_C_(0) 0L +// PPC64:UINTMAX_C_(0) 0UL // // RUN: clang-cc -E -ffreestanding -triple=powerpc-none-none %s | FileCheck -check-prefix PPC %s // @@ -659,11 +659,11 @@ // PPC:typedef int8_t int_fast8_t; // PPC:typedef uint8_t uint_fast8_t; // -// PPC:typedef long int intptr_t; -// PPC:typedef unsigned long int uintptr_t; +// PPC:typedef int32_t intptr_t; +// PPC:typedef uint32_t uintptr_t; // -// PPC:typedef long long int intmax_t; -// PPC:typedef long long unsigned int uintmax_t; +// PPC:typedef int64_t intmax_t; +// PPC:typedef uint64_t uintmax_t; // // PPC:INT8_MAX_ 127 // PPC:INT8_MIN_ (-127 -1) @@ -714,7 +714,7 @@ // // PPC:INTMAX_MIN_ (-9223372036854775807LL -1) // PPC:INTMAX_MAX_ 9223372036854775807LL -// PPC:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL) +// PPC:UINTMAX_MAX_ 18446744073709551615ULL // // PPC:SIG_ATOMIC_MIN_ (-2147483647 -1) // PPC:SIG_ATOMIC_MAX_ 2147483647 @@ -766,11 +766,11 @@ // S390X:typedef int8_t int_fast8_t; // S390X:typedef uint8_t uint_fast8_t; // -// S390X:typedef long int intptr_t; -// S390X:typedef unsigned long int uintptr_t; +// S390X:typedef int64_t intptr_t; +// S390X:typedef uint64_t uintptr_t; // -// S390X:typedef long long int intmax_t; -// S390X:typedef long long unsigned int uintmax_t; +// S390X:typedef int64_t intmax_t; +// S390X:typedef uint64_t uintmax_t; // // S390X:INT8_MAX_ 127 // S390X:INT8_MIN_ (-127 -1) @@ -819,9 +819,9 @@ // S390X:PTRDIFF_MAX_ 9223372036854775807L // S390X:SIZE_MAX_ 18446744073709551615UL // -// S390X:INTMAX_MIN_ (-9223372036854775807LL -1) -// S390X:INTMAX_MAX_ 9223372036854775807LL -// S390X:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL) +// S390X:INTMAX_MIN_ (-9223372036854775807L -1) +// S390X:INTMAX_MAX_ 9223372036854775807L +// S390X:UINTMAX_MAX_ 18446744073709551615UL // // S390X:SIG_ATOMIC_MIN_ (-2147483647 -1) // S390X:SIG_ATOMIC_MAX_ 2147483647 @@ -840,8 +840,8 @@ // S390X:INT64_C_(0) 0L // S390X:UINT64_C_(0) 0UL // -// S390X:INTMAX_C_(0) 0LL -// S390X:UINTMAX_C_(0) 0ULL +// S390X:INTMAX_C_(0) 0L +// S390X:UINTMAX_C_(0) 0UL // // RUN: clang-cc -E -ffreestanding -triple=sparc-none-none %s | FileCheck -check-prefix SPARC %s // @@ -873,11 +873,11 @@ // SPARC:typedef int8_t int_fast8_t; // SPARC:typedef uint8_t uint_fast8_t; // -// SPARC:typedef long int intptr_t; -// SPARC:typedef unsigned long int uintptr_t; +// SPARC:typedef int32_t intptr_t; +// SPARC:typedef uint32_t uintptr_t; // -// SPARC:typedef long long int intmax_t; -// SPARC:typedef long long unsigned int uintmax_t; +// SPARC:typedef int64_t intmax_t; +// SPARC:typedef uint64_t uintmax_t; // // SPARC:INT8_MAX_ 127 // SPARC:INT8_MIN_ (-127 -1) @@ -928,7 +928,7 @@ // // SPARC:INTMAX_MIN_ (-9223372036854775807LL -1) // SPARC:INTMAX_MAX_ 9223372036854775807LL -// SPARC:UINTMAX_MAX_ (9223372036854775807LL*2ULL +1ULL) +// SPARC:UINTMAX_MAX_ 18446744073709551615ULL // // SPARC:SIG_ATOMIC_MIN_ (-2147483647 -1) // SPARC:SIG_ATOMIC_MAX_ 2147483647 @@ -973,11 +973,11 @@ // TCE:typedef int8_t int_fast8_t; // TCE:typedef uint8_t uint_fast8_t; // -// TCE:typedef int intptr_t; -// TCE:typedef unsigned int uintptr_t; +// TCE:typedef int32_t intptr_t; +// TCE:typedef uint32_t uintptr_t; // -// TCE:typedef long int intmax_t; -// TCE:typedef long unsigned int uintmax_t; +// TCE:typedef int32_t intmax_t; +// TCE:typedef uint32_t uintmax_t; // // TCE:INT8_MAX_ 127 // TCE:INT8_MIN_ (-127 -1) @@ -1026,9 +1026,9 @@ // TCE:PTRDIFF_MAX_ 2147483647 // TCE:SIZE_MAX_ 4294967295U // -// TCE:INTMAX_MIN_ (-2147483647L -1) -// TCE:INTMAX_MAX_ 2147483647L -// TCE:UINTMAX_MAX_ (2147483647L*2ULL +1ULL) +// TCE:INTMAX_MIN_ (-2147483647 -1) +// TCE:INTMAX_MAX_ 2147483647 +// TCE:UINTMAX_MAX_ 4294967295U // // TCE:SIG_ATOMIC_MIN_ (-2147483647 -1) // TCE:SIG_ATOMIC_MAX_ 2147483647 @@ -1047,8 +1047,8 @@ // TCE:INT64_C_(0) INT64_C(0) // TCE:UINT64_C_(0) UINT64_C(0) // -// TCE:INTMAX_C_(0) 0LL -// TCE:UINTMAX_C_(0) 0ULL +// TCE:INTMAX_C_(0) 0 +// TCE:UINTMAX_C_(0) 0U // // RUN: clang-cc -E -ffreestanding -triple=x86_64-none-none %s | FileCheck -check-prefix X86_64 %s // @@ -1081,11 +1081,11 @@ // X86_64:typedef int8_t int_fast8_t; // X86_64:typedef uint8_t uint_fast8_t; // -// X86_64:typedef long int intptr_t; -// X86_64:typedef unsigned long int uintptr_t; +// X86_64:typedef int64_t intptr_t; +// X86_64:typedef uint64_t uintptr_t; // -// X86_64:typedef long int intmax_t; -// X86_64:typedef long unsigned int uintmax_t; +// X86_64:typedef int64_t intmax_t; +// X86_64:typedef uint64_t uintmax_t; // // X86_64:INT8_MAX_ 127 // X86_64:INT8_MIN_ (-127 -1) @@ -1136,7 +1136,7 @@ // // X86_64:INTMAX_MIN_ (-9223372036854775807L -1) // X86_64:INTMAX_MAX_ 9223372036854775807L -// X86_64:UINTMAX_MAX_ (9223372036854775807L*2ULL +1ULL) +// X86_64:UINTMAX_MAX_ 18446744073709551615UL // // X86_64:SIG_ATOMIC_MIN_ (-2147483647 -1) // X86_64:SIG_ATOMIC_MAX_ 2147483647 @@ -1155,8 +1155,8 @@ // X86_64:INT64_C_(0) 0L // X86_64:UINT64_C_(0) 0UL // -// X86_64:INTMAX_C_(0) 0LL -// X86_64:UINTMAX_C_(0) 0ULL +// X86_64:INTMAX_C_(0) 0L +// X86_64:UINTMAX_C_(0) 0UL // #include <stdint.h> diff --git a/test/Sema/unused-expr.c b/test/Sema/unused-expr.c index acf4887..522fda4 100644 --- a/test/Sema/unused-expr.c +++ b/test/Sema/unused-expr.c @@ -1,4 +1,4 @@ -// RUN: clang-cc -fsyntax-only -verify -fmath-errno=0 %s +// RUN: clang-cc -fsyntax-only -verify -fno-math-errno %s int foo(int X, int Y); diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index 42b8d7f..3db607a 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -138,3 +138,20 @@ namespace PR5222 { C c; } + +// PR5550 - instantiating template didn't track overridden methods +namespace PR5550 { + struct A { + virtual void a() = 0; + virtual void b() = 0; + }; + template<typename T> struct B : public A { + virtual void b(); + virtual void c() = 0; + }; + struct C : public B<int> { + virtual void a(); + virtual void c(); + }; + C x; +} diff --git a/test/SemaCXX/cxx-member-pointer-op.cpp b/test/SemaCXX/cxx-member-pointer-op.cpp new file mode 100644 index 0000000..63b29c72 --- /dev/null +++ b/test/SemaCXX/cxx-member-pointer-op.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +struct C { + static int (C::* a); +}; + +typedef void (C::*pmfc)(); + +void g(pmfc) { + C *c; + c->*pmfc(); // expected-error {{invalid use of pointer to member type after ->*}} + C c1; + c1.*pmfc(); // expected-error {{invalid use of pointer to member type after .*}} + c->*(pmfc()); // expected-error {{invalid use of pointer to member type after ->*}} + c1.*((pmfc())); // expected-error {{invalid use of pointer to member type after .*}} +} + +int a(C* x) { + return x->*C::a; +} + diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 7762667..16d3704 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -286,3 +286,41 @@ class RegAlloc { } int usepri[LastReg + 1]; }; + +// PR5546: Don't generate incorrect and ambiguous overloads for multi-level +// arrays. +namespace pr5546 +{ + enum { X }; + extern const char *const sMoveCommands[][2][2]; + const char* a() { return sMoveCommands[X][0][0]; } + const char* b() { return (*(sMoveCommands+X))[0][0]; } +} + +// PR5512 and its discussion +namespace pr5512 { + struct Y { + operator short(); + operator float(); + }; + void g_test(Y y) { + short s = 0; + // DR507, this should be ambiguous, but we special-case assignment + s = y; + // Note: DR507, this is ambiguous as specified + //s += y; + } + + struct S {}; + void operator +=(int&, S); + void f(S s) { + int i = 0; + i += s; + } + + struct A {operator int();}; + int a; + void b(A x) { + a += x; + } +} diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp index 91b72cc..be960a3 100644 --- a/test/SemaCXX/reinterpret-cast.cpp +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -88,3 +88,9 @@ void memptrs() (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)()' is not allowed}} (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}} } + +// PR5545 +class A; +class B; +void (A::*a)(); +void (B::*b)() = reinterpret_cast<void (B::*)()>(a); diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp index a7d26bb..5132c2a 100644 --- a/test/SemaCXX/rval-references.cpp +++ b/test/SemaCXX/rval-references.cpp @@ -65,9 +65,9 @@ int&& should_not_warn(int&& i) { // But GCC 4.4 does // Test the return dance. This also tests IsReturnCopyElidable. struct MoveOnly { MoveOnly(); - MoveOnly(const MoveOnly&) = delete; - MoveOnly(MoveOnly&&); - MoveOnly(int&&); + MoveOnly(const MoveOnly&) = delete; // expected-note {{candidate function}} + MoveOnly(MoveOnly&&); // expected-note {{candidate function}} + MoveOnly(int&&); // expected-note {{candidate function}} }; MoveOnly returning() { @@ -87,5 +87,5 @@ MoveOnly returningNonEligible() { else if (0) // Copy from reference can't be elided return r; // expected-error {{incompatible type returning}} else // Construction from different type can't be elided - return i; // expected-error {{incompatible type returning}} + return i; // expected-error {{no viable conversion from 'int' to 'struct MoveOnly'}} } diff --git a/test/SemaCXX/using-directive.cpp b/test/SemaCXX/using-directive.cpp index 78ad0429..3b67c7a 100644 --- a/test/SemaCXX/using-directive.cpp +++ b/test/SemaCXX/using-directive.cpp @@ -45,22 +45,18 @@ namespace A { using namespace E; // expected-error{{reference to 'E' is ambiguous}} } - struct K2 {}; // expected-note{{candidate found by name lookup is 'A::K2'}} + struct K2 {}; // expected-note 2{{candidate found by name lookup is 'A::K2'}} } -struct K2 {}; // expected-note{{candidate found by name lookup is 'K2'}} +struct K2 {}; // expected-note 2{{candidate found by name lookup is 'K2'}} using namespace A; void K1::foo() {} // okay -// FIXME: Do we want err_ovl_no_viable_function_in_init here? -struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \ - expected-error{{incomplete type}} - -// FIXME: This case is incorrectly diagnosed! -//K2 k3; +struct K2 *k2; // expected-error{{reference to 'K2' is ambiguous}} +K2 *k3; // expected-error{{reference to 'K2' is ambiguous}} class X { // expected-note{{candidate found by name lookup is 'X'}} // FIXME: produce a suitable error message for this diff --git a/test/SemaObjC/class-protocol.m b/test/SemaObjC/class-protocol.m new file mode 100644 index 0000000..12b6381 --- /dev/null +++ b/test/SemaObjC/class-protocol.m @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// pr5552 + +@interface Protocol +@end + diff --git a/test/SemaObjC/no-warn-qual-mismatch.m b/test/SemaObjC/no-warn-qual-mismatch.m new file mode 100644 index 0000000..3bd4dba --- /dev/null +++ b/test/SemaObjC/no-warn-qual-mismatch.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// radar 7211563 + +@interface X + ++ (void)prototypeWithScalar:(int)aParameter; ++ (void)prototypeWithPointer:(void *)aParameter; + +@end + +@implementation X + ++ (void)prototypeWithScalar:(const int)aParameter {} ++ (void)prototypeWithPointer:(void * const)aParameter {} + +@end diff --git a/test/SemaTemplate/constructor-template.cpp b/test/SemaTemplate/constructor-template.cpp index 12c6f8b9..203977e 100644 --- a/test/SemaTemplate/constructor-template.cpp +++ b/test/SemaTemplate/constructor-template.cpp @@ -53,7 +53,7 @@ struct B { A<int> x; B(B& a) : x(a.x) {} }; struct X2 { X2(); - X2(X2&); + X2(X2&); // expected-note {{candidate function}} template<typename T> X2(T); }; @@ -61,7 +61,7 @@ X2 test(bool Cond, X2 x2) { if (Cond) return x2; // okay, uses copy constructor - return X2(); // expected-error{{incompatible type}} + return X2(); // expected-error{{no viable conversion from 'struct X2' to 'struct X2' is possible}} } struct X3 { @@ -73,12 +73,12 @@ template<> X3::X3(X3); // expected-error{{must pass its first argument by refere struct X4 { X4(); ~X4(); - X4(X4&); + X4(X4&); // expected-note {{candidate function}} template<typename T> X4(const T&, int = 17); }; X4 test_X4(bool Cond, X4 x4) { X4 a(x4, 17); // okay, constructor template X4 b(x4); // okay, copy constructor - return X4(); // expected-error{{incompatible type}} + return X4(); // expected-error{{no viable conversion}} } diff --git a/test/SemaTemplate/instantiate-case.cpp b/test/SemaTemplate/instantiate-case.cpp new file mode 100644 index 0000000..bed39d7 --- /dev/null +++ b/test/SemaTemplate/instantiate-case.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<class T> +static int alpha(T c) +{ + return *c; // expected-error{{indirection requires pointer operand}} +} + +template<class T> +static void +_shexp_match() +{ + switch(1) { + case 1: + alpha(1); // expected-note{{instantiation of function template}} + } +} +int main() { + _shexp_match<char>(); // expected-note{{instantiation of function template}} + return 0; +} diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index ebdba29..46732de 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -1219,7 +1219,7 @@ void clang_codeComplete(CXIndex CIdx, argv.push_back("-Xclang"); argv.push_back(code_complete_at.c_str()); argv.push_back("-Xclang"); - argv.push_back("-code-completion-debug-printer=0"); + argv.push_back("-no-code-completion-debug-printer"); // Add the source file name (FIXME: later, we'll want to build temporary // file from the buffer, or just feed the source text via standard input). diff --git a/tools/clang-cc/Options.cpp b/tools/clang-cc/Options.cpp index b5190eb..584f957 100644 --- a/tools/clang-cc/Options.cpp +++ b/tools/clang-cc/Options.cpp @@ -100,14 +100,12 @@ AnalyzeSpecificFunction("analyze-function", static llvm::cl::opt<bool> EagerlyAssume("analyzer-eagerly-assume", - llvm::cl::init(false), llvm::cl::desc("Eagerly assume the truth/falseness of some " "symbolic constraints")); static llvm::cl::opt<bool> -PurgeDead("analyzer-purge-dead", - llvm::cl::init(true), - llvm::cl::desc("Remove dead symbols, bindings, and constraints before" +NoPurgeDead("analyzer-no-purge-dead", + llvm::cl::desc("Don't remove dead symbols, bindings, and constraints before" " processing a statement")); static llvm::cl::opt<bool> @@ -136,8 +134,7 @@ DisableLLVMOptimizations("disable-llvm-optzns", static llvm::cl::opt<bool> DisableRedZone("disable-red-zone", - llvm::cl::desc("Do not emit code that uses the red zone."), - llvm::cl::init(false)); + llvm::cl::desc("Do not emit code that uses the red zone.")); static llvm::cl::opt<bool> GenerateDebugInfo("g", @@ -150,8 +147,7 @@ NoCommon("fno-common", static llvm::cl::opt<bool> NoImplicitFloat("no-implicit-float", - llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)"), - llvm::cl::init(false)); + llvm::cl::desc("Don't generate implicit floating point instructions (x86-only)")); static llvm::cl::opt<bool> NoMergeConstants("fno-merge-all-constants", @@ -170,8 +166,7 @@ struct OptLevelParser : public llvm::cl::parser<unsigned> { }; static llvm::cl::opt<unsigned, false, OptLevelParser> OptLevel("O", llvm::cl::Prefix, - llvm::cl::desc("Optimization level"), - llvm::cl::init(0)); + llvm::cl::desc("Optimization level")); static llvm::cl::opt<bool> OptSize("Os", llvm::cl::desc("Optimize for size")); @@ -264,7 +259,7 @@ PrintColorDiagnostic("fcolor-diagnostics", llvm::cl::desc("Use colors in diagnostics")); static llvm::cl::opt<bool> -SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false), +SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::desc("Silence ObjC rewriting warnings")); static llvm::cl::opt<bool> @@ -287,9 +282,8 @@ CodeCompletionAt("code-completion-at", llvm::cl::desc("Dump code-completion information at a location")); static llvm::cl::opt<bool> -CodeCompletionDebugPrinter("code-completion-debug-printer", - llvm::cl::desc("Use the \"debug\" code-completion print"), - llvm::cl::init(true)); +NoCodeCompletionDebugPrinter("no-code-completion-debug-printer", + llvm::cl::desc("Don't the \"debug\" code-completion print")); static llvm::cl::opt<bool> CodeCompletionWantsMacros("code-completion-macros", @@ -297,8 +291,7 @@ CodeCompletionWantsMacros("code-completion-macros", static llvm::cl::opt<bool> DisableFree("disable-free", - llvm::cl::desc("Disable freeing of memory on exit"), - llvm::cl::init(false)); + llvm::cl::desc("Disable freeing of memory on exit")); static llvm::cl::opt<bool> EmptyInputOnly("empty-input-only", @@ -444,12 +437,11 @@ TimeReport("ftime-report", namespace langoptions { static llvm::cl::opt<bool> -AllowBuiltins("fbuiltin", llvm::cl::init(true), - llvm::cl::desc("Disable implicit builtin knowledge of functions")); +NoBuiltin("fno-builtin", + llvm::cl::desc("Disable implicit builtin knowledge of functions")); static llvm::cl::opt<bool> -AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax"), - llvm::cl::init(false)); +AltiVec("faltivec", llvm::cl::desc("Enable AltiVec vector initializer syntax")); static llvm::cl::opt<bool> AccessControl("faccess-control", @@ -537,8 +529,8 @@ MainFileName("main-file-name", llvm::cl::desc("Main file name to use for debug info")); static llvm::cl::opt<bool> -MathErrno("fmath-errno", llvm::cl::init(true), - llvm::cl::desc("Require math functions to respect errno")); +NoMathErrno("fno-math-errno", + llvm::cl::desc("Don't require math functions to respect errno")); static llvm::cl::opt<bool> NoElideConstructors("fno-elide-constructors", @@ -581,15 +573,13 @@ ObjCNonFragileABI("fobjc-nonfragile-abi", static llvm::cl::opt<bool> OverflowChecking("ftrapv", - llvm::cl::desc("Trap on integer overflow"), - llvm::cl::init(false)); + llvm::cl::desc("Trap on integer overflow")); static llvm::cl::opt<unsigned> PICLevel("pic-level", llvm::cl::desc("Value for __PIC__")); static llvm::cl::opt<bool> -PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code"), - llvm::cl::init(false)); +PThread("pthread", llvm::cl::desc("Support POSIX threads in generated code")); static llvm::cl::opt<bool> PascalStrings("fpascal-strings", @@ -597,8 +587,8 @@ PascalStrings("fpascal-strings", "string literals")); static llvm::cl::opt<bool> -Rtti("frtti", llvm::cl::init(true), - llvm::cl::desc("Enable generation of rtti information")); +NoRtti("fno-rtti", + llvm::cl::desc("Disable generation of rtti information")); static llvm::cl::opt<bool> ShortWChar("fshort-wchar", @@ -609,8 +599,7 @@ StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined")); static llvm::cl::opt<int> StackProtector("stack-protector", - llvm::cl::desc("Enable stack protectors"), - llvm::cl::init(-1)); + llvm::cl::desc("Enable stack protectors")); static llvm::cl::opt<LangOptions::VisibilityMode> SymbolVisibility("fvisibility", @@ -625,7 +614,7 @@ SymbolVisibility("fvisibility", clEnumValEnd)); static llvm::cl::opt<unsigned> -TemplateDepth("ftemplate-depth", llvm::cl::init(99), +TemplateDepth("ftemplate-depth", llvm::cl::desc("Maximum depth of recursive template " "instantiation")); @@ -724,7 +713,7 @@ iwithprefixbefore_vals("iwithprefixbefore", llvm::cl::value_desc("dir"), llvm::cl::desc("Set directory to include search path with prefix")); static llvm::cl::opt<std::string> -isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"), +isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::desc("Set the system root directory (usually /)")); static llvm::cl::opt<bool> @@ -793,7 +782,7 @@ void clang::InitializeAnalyzerOptions(AnalyzerOptions &Opts) { Opts.VisualizeEGUbi = VisualizeEGUbi; Opts.AnalyzeAll = AnalyzeAll; Opts.AnalyzerDisplayProgress = AnalyzerDisplayProgress; - Opts.PurgeDead = PurgeDead; + Opts.PurgeDead = !NoPurgeDead; Opts.EagerlyAssume = EagerlyAssume; Opts.AnalyzeSpecificFunction = AnalyzeSpecificFunction; Opts.EnableExperimentalChecks = AnalyzerExperimentalChecks; @@ -807,7 +796,8 @@ void clang::InitializeCodeGenOptions(CodeGenOptions &Opts, using namespace codegenoptions; // -Os implies -O2 - Opts.OptimizationLevel = OptSize ? 2 : OptLevel; + unsigned Opt = OptLevel.getPosition() ? OptLevel : 0; + Opts.OptimizationLevel = OptSize ? 2 : Opt; // We must always run at least the always inlining pass. Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining @@ -875,7 +865,7 @@ void clang::InitializeFrontendOptions(FrontendOptions &Opts) { } Opts.CodeCompletionAt = CodeCompletionAt; - Opts.DebugCodeCompletionPrinter = CodeCompletionDebugPrinter; + Opts.DebugCodeCompletionPrinter = !NoCodeCompletionDebugPrinter; Opts.DisableFree = DisableFree; Opts.EmptyInputOnly = EmptyInputOnly; Opts.FixItLocations = FixItAtLocations; @@ -907,7 +897,8 @@ void clang::InitializeHeaderSearchOptions(HeaderSearchOptions &Opts, llvm::StringRef BuiltinIncludePath) { using namespace headersearchoptions; - Opts.Sysroot = isysroot; + if (isysroot.getPosition()) + Opts.Sysroot = isysroot; Opts.Verbose = Verbose; // Handle -I... and -F... options, walking the lists in parallel. @@ -1231,7 +1222,7 @@ void clang::InitializeLangOptions(LangOptions &Options, if (NoLaxVectorConversions.getPosition()) Options.LaxVectorConversions = 0; Options.Exceptions = Exceptions; - Options.Rtti = Rtti; + Options.Rtti = !NoRtti; if (EnableBlocks.getPosition()) Options.Blocks = EnableBlocks; if (CharIsSigned.getPosition()) @@ -1239,8 +1230,7 @@ void clang::InitializeLangOptions(LangOptions &Options, if (ShortWChar.getPosition()) Options.ShortWChar = ShortWChar; - if (!AllowBuiltins) - Options.NoBuiltin = 1; + Options.NoBuiltin = NoBuiltin; if (Freestanding) Options.Freestanding = Options.NoBuiltin = 1; @@ -1255,9 +1245,10 @@ void clang::InitializeLangOptions(LangOptions &Options, // OpenCL and C++ both have bool, true, false keywords. Options.Bool = Options.OpenCL | Options.CPlusPlus; - Options.MathErrno = MathErrno; + Options.MathErrno = !NoMathErrno; - Options.InstantiationDepth = TemplateDepth; + if (TemplateDepth.getPosition()) + Options.InstantiationDepth = TemplateDepth; // Override the default runtime if the user requested it. if (GNURuntime) @@ -1273,8 +1264,10 @@ void clang::InitializeLangOptions(LangOptions &Options, Options.EmitAllDecls = 1; // The __OPTIMIZE_SIZE__ define is tied to -Oz, which we don't support. + unsigned Opt = + codegenoptions::OptLevel.getPosition() ? codegenoptions::OptLevel : 0; Options.OptimizeSize = 0; - Options.Optimize = codegenoptions::OptSize || codegenoptions::OptLevel; + Options.Optimize = codegenoptions::OptSize || Opt; assert(PICLevel <= 2 && "Invalid value for -pic-level"); Options.PICLevel = PICLevel; @@ -1286,17 +1279,18 @@ void clang::InitializeLangOptions(LangOptions &Options, // inlining enabled. // // FIXME: This is affected by other options (-fno-inline). - Options.NoInline = !codegenoptions::OptLevel; + Options.NoInline = !Opt; Options.Static = StaticDefine; - switch (StackProtector) { - default: - assert(StackProtector <= 2 && "Invalid value for -stack-protector"); - case -1: break; - case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break; - case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break; - case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break; + if (StackProtector.getPosition()) { + switch (StackProtector) { + default: + assert(0 && "Invalid value for -stack-protector"); + case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break; + case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break; + case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break; + } } if (MainFileName.getPosition()) diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index 1ad04c8..1a95380 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -3,15 +3,27 @@ set(LLVM_NO_RTTI 1) set( LLVM_USED_LIBS clangDriver clangBasic + clangFrontend ) set(LLVM_LINK_COMPONENTS system support bitreader bitwriter) add_clang_executable(clang driver.cpp + cc1_main.cpp ) add_dependencies(clang clang-cc) +# Create the clang++ symlink in the build directory. +add_custom_target(clang++ ALL + ${CMAKE_COMMAND} -E create_symlink + "${LLVM_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX}" + "${LLVM_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}" + DEPENDS clang) + install(TARGETS clang RUNTIME DESTINATION bin) + +# Create the clang++ symlink at installation time. +install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink \"${CMAKE_INSTALL_PREFIX}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}\" \"${CMAKE_INSTALL_PREFIX}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}\")") diff --git a/tools/driver/Makefile b/tools/driver/Makefile index 4b2fb44..19f93a2 100644 --- a/tools/driver/Makefile +++ b/tools/driver/Makefile @@ -9,6 +9,7 @@ LEVEL = ../../../.. TOOLNAME = clang +TOOLALIAS = clang++ CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include CXXFLAGS = -fno-rtti @@ -18,7 +19,7 @@ TOOL_NO_EXPORTS = 1 # FIXME: It is unfortunate we need to pull in the bitcode reader and # writer just to get the serializer stuff used by clangBasic. LINK_COMPONENTS := system support bitreader bitwriter -USEDLIBS = clangDriver.a clangBasic.a +USEDLIBS = clangDriver.a clangBasic.a clangFrontend.a include $(LEVEL)/Makefile.common diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp new file mode 100644 index 0000000..c516359 --- /dev/null +++ b/tools/driver/cc1_main.cpp @@ -0,0 +1,88 @@ +//===-- cc1_main.cpp - Clang CC1 Driver -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the entry point to the clang -cc1 functionality. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/Arg.h" +#include "clang/Driver/ArgList.h" +#include "clang/Driver/CC1Options.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/OptTable.h" +#include "clang/Driver/Option.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdlib> +#include <vector> + +using namespace clang; +using namespace clang::driver; + +int cc1_main(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd) { + llvm::errs() << "cc1 argv:"; + for (const char **i = ArgBegin; i != ArgEnd; ++i) + llvm::errs() << " \"" << *i << '"'; + llvm::errs() << "\n"; + + // Parse the arguments. + OptTable *Opts = createCC1OptTable(); + unsigned MissingArgIndex, MissingArgCount; + InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd, + MissingArgIndex, MissingArgCount); + + // Check for missing argument error. + if (MissingArgCount) + Diags.Report(clang::diag::err_drv_missing_argument) + << Args->getArgString(MissingArgIndex) << MissingArgCount; + + // Dump the parsed arguments. + llvm::errs() << "cc1 parsed options:\n"; + for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); + it != ie; ++it) + (*it)->dump(); + + // Create a compiler invocation. + llvm::errs() << "cc1 creating invocation.\n"; + CompilerInvocation Invocation; + CompilerInvocation::CreateFromArgs(Invocation, + llvm::SmallVector<llvm::StringRef, 32>(ArgBegin, ArgEnd)); + + // Convert the invocation back to argument strings. + std::vector<std::string> InvocationArgs; + Invocation.toArgs(InvocationArgs); + + // Dump the converted arguments. + llvm::SmallVector<llvm::StringRef, 32> Invocation2Args; + llvm::errs() << "invocation argv:"; + for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { + Invocation2Args.push_back(InvocationArgs[i]); + llvm::errs() << " \"" << InvocationArgs[i] << '"'; + } + llvm::errs() << "\n"; + + // Convert those arguments to another invocation, and check that we got the + // same thing. + CompilerInvocation Invocation2; + CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args); + + // FIXME: Implement CompilerInvocation comparison. + if (memcmp(&Invocation, &Invocation2, sizeof(Invocation)) != 0) { + llvm::errs() << "warning: Invocations differ!\n"; + + std::vector<std::string> Invocation2Args; + Invocation2.toArgs(Invocation2Args); + llvm::errs() << "invocation argv:"; + for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i) + llvm::errs() << " \"" << Invocation2Args[i] << '"'; + llvm::errs() << "\n"; + } + + return 0; +} diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index fb7c6cc..dbfc293 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -15,7 +15,6 @@ #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/Option.h" -#include "clang/Driver/Options.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/OwningPtr.h" @@ -179,6 +178,9 @@ void ApplyQAOverride(std::vector<const char*> &Args, const char *OverrideStr, } } +extern int cc1_main(Diagnostic &Diags, + const char **ArgBegin, const char **ArgEnd); + int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); @@ -188,6 +190,10 @@ int main(int argc, const char **argv) { Diagnostic Diags(&DiagClient); + // Dispatch to cc1_main if appropriate. + if (argc > 1 && llvm::StringRef(argv[1]) == "-cc1") + return cc1_main(Diags, argv+2, argv+argc); + #ifdef CLANG_IS_PRODUCTION bool IsProduction = true; #else |