diff --git a/clang/AST/ASTStreamer.cpp b/clang/AST/ASTStreamer.cpp deleted file mode 100644 index 25319ea2a18e..000000000000 --- a/clang/AST/ASTStreamer.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===--- ASTStreamer.cpp - Provide streaming interface to ASTs ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the ASTStreamer interface. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ASTStreamer.h" -#include "clang/AST/ASTContext.h" -#include "Sema.h" -#include "clang/Parse/Action.h" -#include "clang/Parse/Parser.h" -using namespace llvm; -using namespace clang; - -namespace { - class ASTStreamer { - Parser P; - std::vector LastInGroupList; - public: - ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID) - : P(pp, *new Sema(pp, ctxt, LastInGroupList)) { - pp.EnterSourceFile(MainFileID, 0, true); - - // Initialize the parser. - P.Initialize(); - } - - /// ReadTopLevelDecl - Parse and return the next top-level declaration. - Decl *ReadTopLevelDecl(); - - void PrintStats() const; - - ~ASTStreamer() { - P.Finalize(); - delete &P.getActions(); - } - }; -} - -/// ReadTopLevelDecl - Parse and return the next top-level declaration. -/// -Decl *ASTStreamer::ReadTopLevelDecl() { - Parser::DeclTy *Result; - - /// If the previous time through we read something like 'int X, Y', return - /// the next declarator. - if (!LastInGroupList.empty()) { - Result = LastInGroupList.back(); - LastInGroupList.pop_back(); - return static_cast(Result); - } - - do { - if (P.ParseTopLevelDecl(Result)) - return 0; // End of file. - - // If we got a null return and something *was* parsed, try again. This - // is due to a top-level semicolon, an action override, or a parse error - // skipping something. - } while (Result == 0); - - // If we parsed a declspec with multiple declarators, reverse the list and - // return the first one. - if (!LastInGroupList.empty()) { - LastInGroupList.push_back((Decl*)Result); - std::reverse(LastInGroupList.begin(), LastInGroupList.end()); - Result = LastInGroupList.back(); - LastInGroupList.pop_back(); - } - - return static_cast(Result); -} - -void ASTStreamer::PrintStats() const { -} - -//===----------------------------------------------------------------------===// -// Public interface to the file -//===----------------------------------------------------------------------===// - -/// ASTStreamer_Init - Create an ASTStreamer with the specified preprocessor -/// and FileID. -ASTStreamerTy *llvm::clang::ASTStreamer_Init(Preprocessor &pp, - ASTContext &ctxt, - unsigned MainFileID) { - return new ASTStreamer(pp, ctxt, MainFileID); -} - -/// ASTStreamer_ReadTopLevelDecl - Parse and return one top-level declaration. This -/// returns null at end of file. -Decl *llvm::clang::ASTStreamer_ReadTopLevelDecl(ASTStreamerTy *Streamer) { - return static_cast(Streamer)->ReadTopLevelDecl(); -} - - -/// ASTStreamer_PrintStats - Emit statistic information to stderr. -/// -void llvm::clang::ASTStreamer_PrintStats(ASTStreamerTy *Streamer) { - return static_cast(Streamer)->PrintStats(); -} - -/// ASTStreamer_Terminate - Gracefully shut down the streamer. -/// -void llvm::clang::ASTStreamer_Terminate(ASTStreamerTy *Streamer) { - delete static_cast(Streamer); -} diff --git a/clang/AST/Sema.cpp b/clang/AST/Sema.cpp deleted file mode 100644 index 91d0ec6d26da..000000000000 --- a/clang/AST/Sema.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the actions class which performs semantic analysis and -// builds an AST out of a parse stream. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Basic/Diagnostic.h" -using namespace llvm; -using namespace clang; - -Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector &prevInGroup) - : PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) { -} - -//===----------------------------------------------------------------------===// -// Helper functions. -//===----------------------------------------------------------------------===// - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID) { - PP.getDiagnostics().Report(Loc, DiagID); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) { - PP.getDiagnostics().Report(Loc, DiagID, &Msg, 1); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, - const std::string &Msg2) { - std::string MsgArr[] = { Msg1, Msg2 }; - PP.getDiagnostics().Report(Loc, DiagID, MsgArr, 2); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, SourceRange Range) { - PP.getDiagnostics().Report(Loc, DiagID, 0, 0, &Range, 1); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg, - SourceRange Range) { - PP.getDiagnostics().Report(Loc, DiagID, &Msg, 1, &Range, 1); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, - const std::string &Msg2, SourceRange Range) { - std::string MsgArr[] = { Msg1, Msg2 }; - PP.getDiagnostics().Report(Loc, DiagID, MsgArr, 2, &Range, 1); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, - SourceRange R1, SourceRange R2) { - SourceRange RangeArr[] = { R1, R2 }; - PP.getDiagnostics().Report(Loc, DiagID, 0, 0, RangeArr, 2); - return true; -} - -bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg, - SourceRange R1, SourceRange R2) { - SourceRange RangeArr[] = { R1, R2 }; - PP.getDiagnostics().Report(Loc, DiagID, &Msg, 1, RangeArr, 2); - return true; -} - -bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1, - const std::string &Msg2, SourceRange R1, SourceRange R2) { - std::string MsgArr[] = { Msg1, Msg2 }; - SourceRange RangeArr[] = { R1, R2 }; - PP.getDiagnostics().Report(Range, DiagID, MsgArr, 2, RangeArr, 2); - return true; -} - -const LangOptions &Sema::getLangOptions() const { - return PP.getLangOptions(); -} diff --git a/clang/AST/Sema.h b/clang/AST/Sema.h deleted file mode 100644 index 63d33a439c75..000000000000 --- a/clang/AST/Sema.h +++ /dev/null @@ -1,311 +0,0 @@ -//===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the Sema class, which performs semantic analysis and -// builds ASTs. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_SEMA_H -#define LLVM_CLANG_AST_SEMA_H - -#include "clang/Parse/Action.h" -#include -#include - -namespace llvm { -namespace clang { - class ASTContext; - class Preprocessor; - class Decl; - class Expr; - class VarDecl; - class TypedefDecl; - class FunctionDecl; - class QualType; - class LangOptions; - class DeclaratorChunk; - class LexerToken; - class IntegerLiteral; - class ArrayType; - -/// Sema - This implements semantic analysis and AST building for C. -class Sema : public Action { - Preprocessor &PP; - - ASTContext &Context; - - /// CurFunctionDecl - If inside of a function body, this contains a pointer to - /// the function decl for the function being parsed. - FunctionDecl *CurFunctionDecl; - - /// LastInGroupList - This vector is populated when there are multiple - /// declarators in a single decl group (e.g. "int A, B, C"). In this case, - /// all but the last decl will be entered into this. This is used by the - /// ASTStreamer. - std::vector &LastInGroupList; -public: - Sema(Preprocessor &pp, ASTContext &ctxt, std::vector &prevInGroup); - - const LangOptions &getLangOptions() const; - - /// The primitive diagnostic helpers - always returns true, which simplifies - /// error handling (i.e. less code). - bool Diag(SourceLocation Loc, unsigned DiagID); - bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg); - bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, - const std::string &Msg2); - - /// More expressive diagnostic helpers for expressions (say that 6 times:-) - bool Diag(SourceLocation Loc, unsigned DiagID, SourceRange R1); - bool Diag(SourceLocation Loc, unsigned DiagID, - SourceRange R1, SourceRange R2); - bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg, - SourceRange R1); - bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg, - SourceRange R1, SourceRange R2); - bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, - const std::string &Msg2, SourceRange R1); - bool Diag(SourceLocation Loc, unsigned DiagID, - const std::string &Msg1, const std::string &Msg2, - SourceRange R1, SourceRange R2); - - //===--------------------------------------------------------------------===// - // Type Analysis / Processing: SemaType.cpp. - // - QualType GetTypeForDeclarator(Declarator &D, Scope *S); - - virtual TypeResult ParseTypeName(Scope *S, Declarator &D); - - virtual TypeResult ParseParamDeclaratorType(Scope *S, Declarator &D); -private: - //===--------------------------------------------------------------------===// - // Symbol table / Decl tracking callbacks: SemaDecl.cpp. - // - virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const; - virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, - DeclTy *LastInGroup); - virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D); - virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body); - virtual void PopScope(SourceLocation Loc, Scope *S); - - /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with - /// no declarator (e.g. "struct foo;") is parsed. - virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS); - - virtual DeclTy *ParseTag(Scope *S, unsigned TagType, TagKind TK, - SourceLocation KWLoc, IdentifierInfo *Name, - SourceLocation NameLoc); - virtual DeclTy *ParseField(Scope *S, DeclTy *TagDecl,SourceLocation DeclStart, - Declarator &D, ExprTy *BitfieldWidth); - virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl, - DeclTy **Fields, unsigned NumFields); - virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl, - SourceLocation IdLoc, IdentifierInfo *Id, - SourceLocation EqualLoc, ExprTy *Val); - virtual void ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl, - DeclTy **Elements, unsigned NumElements); -private: - /// Subroutines of ParseDeclarator()... - TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D); - TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old); - FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old); - VarDecl *MergeVarDecl(VarDecl *New, Decl *Old); - /// AddTopLevelDecl - called after the decl has been fully processed. - /// Allows for bookkeeping and post-processing of each declaration. - void AddTopLevelDecl(Decl *current, Decl *last); - - /// More parsing and symbol table subroutines... - VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo, - Scope *FnBodyScope); - Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, SourceLocation IdLoc, - Scope *S); - Decl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S); - Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, - Scope *S); - - //===--------------------------------------------------------------------===// - // Statement Parsing Callbacks: SemaStmt.cpp. -public: - virtual StmtResult ParseCompoundStmt(SourceLocation L, SourceLocation R, - StmtTy **Elts, unsigned NumElts); - virtual StmtResult ParseExprStmt(ExprTy *Expr) { - return Expr; // Exprs are Stmts. - } - virtual StmtResult ParseCaseStmt(SourceLocation CaseLoc, ExprTy *LHSVal, - SourceLocation DotDotDotLoc, ExprTy *RHSVal, - SourceLocation ColonLoc, StmtTy *SubStmt); - virtual StmtResult ParseDefaultStmt(SourceLocation DefaultLoc, - SourceLocation ColonLoc, StmtTy *SubStmt); - virtual StmtResult ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, - SourceLocation ColonLoc, StmtTy *SubStmt); - virtual StmtResult ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal, - StmtTy *ThenVal, SourceLocation ElseLoc, - StmtTy *ElseVal); - virtual StmtResult ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond, - StmtTy *Body); - virtual StmtResult ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond, - StmtTy *Body); - virtual StmtResult ParseDoStmt(SourceLocation DoLoc, StmtTy *Body, - SourceLocation WhileLoc, ExprTy *Cond); - - virtual StmtResult ParseForStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - StmtTy *First, ExprTy *Second, ExprTy *Third, - SourceLocation RParenLoc, StmtTy *Body); - virtual StmtResult ParseGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - IdentifierInfo *LabelII); - virtual StmtResult ParseIndirectGotoStmt(SourceLocation GotoLoc, - SourceLocation StarLoc, - ExprTy *DestExp); - virtual StmtResult ParseContinueStmt(SourceLocation ContinueLoc, - Scope *CurScope); - virtual StmtResult ParseBreakStmt(SourceLocation GotoLoc, Scope *CurScope); - - virtual StmtResult ParseReturnStmt(SourceLocation ReturnLoc, - ExprTy *RetValExp); - - //===--------------------------------------------------------------------===// - // Expression Parsing Callbacks: SemaExpr.cpp. - - // Primary Expressions. - virtual ExprResult ParseIdentifierExpr(Scope *S, SourceLocation Loc, - IdentifierInfo &II, - bool HasTrailingLParen); - virtual ExprResult ParseSimplePrimaryExpr(SourceLocation Loc, - tok::TokenKind Kind); - virtual ExprResult ParseNumericConstant(const LexerToken &); - virtual ExprResult ParseCharacterConstant(const LexerToken &); - virtual ExprResult ParseParenExpr(SourceLocation L, SourceLocation R, - ExprTy *Val); - - /// ParseStringLiteral - The specified tokens were lexed as pasted string - /// fragments (e.g. "foo" "bar" L"baz"). - virtual ExprResult ParseStringLiteral(const LexerToken *Toks, unsigned NumToks); - - // Binary/Unary Operators. 'Tok' is the token for the operator. - virtual ExprResult ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op, - ExprTy *Input); - virtual ExprResult - ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, - SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc); - - virtual ExprResult ParsePostfixUnaryOp(SourceLocation OpLoc, - tok::TokenKind Kind, ExprTy *Input); - - virtual ExprResult ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, - ExprTy *Idx, SourceLocation RLoc); - virtual ExprResult ParseMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation MemberLoc, - IdentifierInfo &Member); - - /// ParseCallExpr - Handle a call to Fn with the specified array of arguments. - /// This provides the location of the left/right parens and a list of comma - /// locations. - virtual ExprResult ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, - ExprTy **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc); - - virtual ExprResult ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc, ExprTy *Op); - - virtual ExprResult ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind, - ExprTy *LHS,ExprTy *RHS); - - /// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null - /// in the case of a the GNU conditional expr extension. - virtual ExprResult ParseConditionalOp(SourceLocation QuestionLoc, - SourceLocation ColonLoc, - ExprTy *Cond, ExprTy *LHS, ExprTy *RHS); - - /// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's. - virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, TypeTy *Ty, - SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, ExprTy *E, - SourceLocation RParenLoc); - - /// ParseCXXBoolLiteral - Parse {true,false} literals. - virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc, - tok::TokenKind Kind); -private: - QualType UsualUnaryConversion(QualType t); // C99 6.3 - QualType UsualArithmeticConversions(QualType t1, QualType t2); // C99 6.3.1.8 - - enum AssignmentConversionResult { - Compatible, - Incompatible, - PointerFromInt, - IntFromPointer, - IncompatiblePointer, - CompatiblePointerDiscardsQualifiers - }; - // Conversions for assignment, argument passing, initialization, and - // function return values. UsualAssignmentConversions is currently used by - // CheckSimpleAssignment, CheckCompoundAssignment and ParseCallExpr. - QualType UsualAssignmentConversions(QualType lhs, QualType rhs, // C99 6.5.16 - AssignmentConversionResult &r); - // Helper function for UsualAssignmentConversions (C99 6.5.16.1p1) - QualType CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType, - AssignmentConversionResult &r); - - /// the following "Check" methods will return a valid/converted QualType - /// or a null QualType (indicating an error diagnostic was issued). - - /// type checking binary operators (subroutines of ParseBinOp). - inline QualType CheckMultiplyDivideOperands( // C99 6.5.5 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckRemainderOperands( // C99 6.5.5 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckAdditionOperands( // C99 6.5.6 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckSubtractionOperands( // C99 6.5.6 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckShiftOperands( // C99 6.5.7 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckRelationalOperands( // C99 6.5.8 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckEqualityOperands( // C99 6.5.9 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckBitwiseOperands( // C99 6.5.[10...12] - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckLogicalOperands( // C99 6.5.[13,14] - Expr *lex, Expr *rex, SourceLocation OpLoc); - // CheckAssignmentOperands is used for both simple and compound assignment. - // For simple assignment, pass both expressions and a null converted type. - // For compound assignment, pass both expressions and the converted type. - inline QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] - Expr *lex, Expr *rex, SourceLocation OpLoc, QualType convertedType); - inline QualType CheckCommaOperands( // C99 6.5.17 - Expr *lex, Expr *rex, SourceLocation OpLoc); - inline QualType CheckConditionalOperands( // C99 6.5.15 - Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc); - - /// type checking unary operators (subroutines of ParseUnaryOp). - // C99 6.5.3.1, 6.5.3.2, 6.5.3.4 - QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc); - QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc); - QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc); - QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation loc, - bool isSizeof); - - // C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have - // a constant expression of type int with a value greater than zero. - bool isConstantArrayType(ArrayType *ary, SourceLocation loc); -}; - - -} // end namespace clang -} // end namespace llvm - -#endif diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp deleted file mode 100644 index e5fafa2673c2..000000000000 --- a/clang/AST/SemaDecl.cpp +++ /dev/null @@ -1,825 +0,0 @@ -//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements semantic analysis for declarations. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Builtins.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Scope.h" -#include "clang/Lex/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallSet.h" - -using namespace llvm; -using namespace clang; - -// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have -// a constant expression of type int with a value greater than zero. -bool Sema::isConstantArrayType(ArrayType *ary, SourceLocation loc) { - if (Expr *size = ary->getSize()) { - SourceLocation expLoc; - if (!size->isConstantExpr(expLoc)) { - Diag(expLoc, diag::err_typecheck_illegal_vla); - return false; - } - if (!size->getType()->isIntegerType()) { - Diag(size->getLocStart(), diag::err_array_size_non_int, - size->getType().getAsString()); - return false; - } - // We have a constant expression with an integer type, now make sure - // value greater than zero (C99 6.7.5.2p1). - // FIXME: evaluate constant expression. - } - return true; -} - -Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const { - return dyn_cast_or_null(II.getFETokenInfo()); -} - -void Sema::PopScope(SourceLocation Loc, Scope *S) { - for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); - I != E; ++I) { - Decl *D = static_cast(*I); - assert(D && "This decl didn't get pushed??"); - IdentifierInfo *II = D->getIdentifier(); - if (!II) continue; - - // Unlink this decl from the identifier. Because the scope contains decls - // in an unordered collection, and because we have multiple identifier - // namespaces (e.g. tag, normal, label),the decl may not be the first entry. - if (II->getFETokenInfo() == D) { - // Normal case, no multiple decls in different namespaces. - II->setFETokenInfo(D->getNext()); - } else { - // Scan ahead. There are only three namespaces in C, so this loop can - // never execute more than 3 times. - Decl *SomeDecl = II->getFETokenInfo(); - while (SomeDecl->getNext() != D) { - SomeDecl = SomeDecl->getNext(); - assert(SomeDecl && "Didn't find this decl on its identifier's chain!"); - } - SomeDecl->setNext(D->getNext()); - } - - // This will have to be revisited for C++: there we want to nest stuff in - // namespace decls etc. Even for C, we might want a top-level translation - // unit decl or something. - if (!CurFunctionDecl) - continue; - - // Chain this decl to the containing function, it now owns the memory for - // the decl. - D->setNext(CurFunctionDecl->getDeclChain()); - CurFunctionDecl->setDeclChain(D); - } -} - -/// LookupScopedDecl - Look up the inner-most declaration in the specified -/// namespace. -Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI, - SourceLocation IdLoc, Scope *S) { - if (II == 0) return 0; - Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI; - - // Scan up the scope chain looking for a decl that matches this identifier - // that is in the appropriate namespace. This search should not take long, as - // shadowing of names is uncommon, and deep shadowing is extremely uncommon. - for (Decl *D = II->getFETokenInfo(); D; D = D->getNext()) - if (D->getIdentifierNamespace() == NS) - return D; - - // If we didn't find a use of this identifier, and if the identifier - // corresponds to a compiler builtin, create the decl object for the builtin - // now, injecting it into translation unit scope, and return it. - if (NS == Decl::IDNS_Ordinary) { - // If this is a builtin on some other target, or if this builtin varies - // across targets (e.g. in type), emit a diagnostic and mark the translation - // unit non-portable for using it. - if (II->isNonPortableBuiltin()) { - // Only emit this diagnostic once for this builtin. - II->setNonPortableBuiltin(false); - Context.Target.DiagnoseNonPortability(IdLoc, - diag::port_target_builtin_use); - } - // If this is a builtin on this (or all) targets, create the decl. - if (unsigned BuiltinID = II->getBuiltinID()) - return LazilyCreateBuiltin(II, BuiltinID, S); - } - return 0; -} - -/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope. -/// lazily create a decl for it. -Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) { - Builtin::ID BID = (Builtin::ID)bid; - - QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context); - FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R); - - // Find translation-unit scope to insert this function into. - while (S->getParent()) - S = S->getParent(); - S->AddDecl(New); - - // Add this decl to the end of the identifier info. - if (Decl *LastDecl = II->getFETokenInfo()) { - // Scan until we find the last (outermost) decl in the id chain. - while (LastDecl->getNext()) - LastDecl = LastDecl->getNext(); - // Insert before (outside) it. - LastDecl->setNext(New); - } else { - II->setFETokenInfo(New); - } - // Make sure clients iterating over decls see this. - LastInGroupList.push_back(New); - - return New; -} - -/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the same name -/// and scope as a previous declaration 'Old'. Figure out how to resolve this -/// situation, merging decls or emitting diagnostics as appropriate. -/// -TypedefDecl *Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { - // Verify the old decl was also a typedef. - TypedefDecl *Old = dyn_cast(OldD); - if (!Old) { - Diag(New->getLocation(), diag::err_redefinition_different_kind, - New->getName()); - Diag(OldD->getLocation(), diag::err_previous_definition); - return New; - } - - // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. - // TODO: This is totally simplistic. It should handle merging functions - // together etc, merging extern int X; int X; ... - Diag(New->getLocation(), diag::err_redefinition, New->getName()); - Diag(Old->getLocation(), diag::err_previous_definition); - return New; -} - -/// MergeFunctionDecl - We just parsed a function 'New' which has the same name -/// and scope as a previous declaration 'Old'. Figure out how to resolve this -/// situation, merging decls or emitting diagnostics as appropriate. -/// -FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { - // Verify the old decl was also a function. - FunctionDecl *Old = dyn_cast(OldD); - if (!Old) { - Diag(New->getLocation(), diag::err_redefinition_different_kind, - New->getName()); - Diag(OldD->getLocation(), diag::err_previous_definition); - return New; - } - - // This is not right, but it's a start. If 'Old' is a function prototype with - // the same type as 'New', silently allow this. FIXME: We should link up decl - // objects here. - if (Old->getBody() == 0 && - Old->getCanonicalType() == New->getCanonicalType()) { - return New; - } - - // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. - // TODO: This is totally simplistic. It should handle merging functions - // together etc, merging extern int X; int X; ... - Diag(New->getLocation(), diag::err_redefinition, New->getName()); - Diag(Old->getLocation(), diag::err_previous_definition); - return New; -} - -/// MergeVarDecl - We just parsed a variable 'New' which has the same name -/// and scope as a previous declaration 'Old'. Figure out how to resolve this -/// situation, merging decls or emitting diagnostics as appropriate. -/// -/// FIXME: Need to carefully consider tentative definition rules (C99 6.9.2p2). -/// For example, we incorrectly complain about i1, i4 from C99 6.9.2p4. -/// -VarDecl *Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { - // Verify the old decl was also a variable. - VarDecl *Old = dyn_cast(OldD); - if (!Old) { - Diag(New->getLocation(), diag::err_redefinition_different_kind, - New->getName()); - Diag(OldD->getLocation(), diag::err_previous_definition); - return New; - } - // Verify the types match. - if (Old->getCanonicalType() != New->getCanonicalType()) { - Diag(New->getLocation(), diag::err_redefinition, New->getName()); - Diag(Old->getLocation(), diag::err_previous_definition); - return New; - } - // We've verified the types match, now check if Old is "extern". - if (Old->getStorageClass() != VarDecl::Extern) { - Diag(New->getLocation(), diag::err_redefinition, New->getName()); - Diag(Old->getLocation(), diag::err_previous_definition); - } - return New; -} - -/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with -/// no declarator (e.g. "struct foo;") is parsed. -Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { - // TODO: emit error on 'int;' or 'const enum foo;'. - // TODO: emit error on 'typedef int;' - // if (!DS.isMissingDeclaratorOk()) Diag(...); - - return 0; -} - -Action::DeclTy * -Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, - DeclTy *LastInGroup) { - IdentifierInfo *II = D.getIdentifier(); - - // See if this is a redefinition of a variable in the same scope. - Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary, - D.getIdentifierLoc(), S); - if (!S->isDeclScope(PrevDecl)) - PrevDecl = 0; // If in outer scope, it isn't the same thing. - - Decl *New; - if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { - TypedefDecl *NewTD = ParseTypedefDecl(S, D); - if (!NewTD) return 0; - - // Merge the decl with the existing one if appropriate. - if (PrevDecl) { - NewTD = MergeTypeDefDecl(NewTD, PrevDecl); - if (NewTD == 0) return 0; - } - New = NewTD; - if (S->getParent() == 0) { - // C99 6.7.7p2: If a typedef name specifies a variably modified type - // then it shall have block scope. - if (ArrayType *ary = dyn_cast(NewTD->getUnderlyingType())) { - if (!isConstantArrayType(ary, D.getIdentifierLoc())) - return 0; - } - } - } else if (D.isFunctionDeclarator()) { - QualType R = GetTypeForDeclarator(D, S); - if (R.isNull()) return 0; // FIXME: "auto func();" passes through... - - FunctionDecl::StorageClass SC; - switch (D.getDeclSpec().getStorageClassSpec()) { - default: assert(0 && "Unknown storage class!"); - case DeclSpec::SCS_auto: - case DeclSpec::SCS_register: - Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func, - R.getAsString()); - return 0; - case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break; - case DeclSpec::SCS_extern: SC = FunctionDecl::Extern; break; - case DeclSpec::SCS_static: SC = FunctionDecl::Static; break; - } - - FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC); - - // Merge the decl with the existing one if appropriate. - if (PrevDecl) { - NewFD = MergeFunctionDecl(NewFD, PrevDecl); - if (NewFD == 0) return 0; - } - New = NewFD; - } else { - QualType R = GetTypeForDeclarator(D, S); - if (R.isNull()) return 0; - - VarDecl *NewVD; - VarDecl::StorageClass SC; - switch (D.getDeclSpec().getStorageClassSpec()) { - default: assert(0 && "Unknown storage class!"); - case DeclSpec::SCS_unspecified: SC = VarDecl::None; break; - case DeclSpec::SCS_extern: SC = VarDecl::Extern; break; - case DeclSpec::SCS_static: SC = VarDecl::Static; break; - case DeclSpec::SCS_auto: SC = VarDecl::Auto; break; - case DeclSpec::SCS_register: SC = VarDecl::Register; break; - } - if (S->getParent() == 0) { - // File scope. C99 6.9.2p2: A declaration of an identifier for and - // object that has file scope without an initializer, and without a - // storage-class specifier or with the storage-class specifier "static", - // constitutes a tentative definition. Note: A tentative definition with - // external linkage is valid (C99 6.2.2p5). - if (!Init && SC == VarDecl::Static) { - // C99 6.9.2p3: If the declaration of an identifier for an object is - // a tentative definition and has internal linkage (C99 6.2.2p3), the - // declared type shall not be an incomplete type. - if (R->isIncompleteType()) { - Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, - R.getAsString()); - return 0; - } - } - // FIXME: Find C99 spec reference - if (SC == VarDecl::Auto || SC == VarDecl::Register) { - Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope, - R.getAsString()); - return 0; - } - // C99 6.7.5.2p2: If an identifier is declared to be an object with - // static storage duration, it shall not have a variable length array. - if (ArrayType *ary = dyn_cast(R)) { - if (!isConstantArrayType(ary, D.getIdentifierLoc())) - return 0; - } - NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC); - } else { - // Block scope. C99 6.7p7: If an identifier for an object is declared with - // no linkage (C99 6.2.2p6), the type for the object shall be complete... - if (SC != VarDecl::Extern) { - if (R->isIncompleteType()) { - Diag(D.getIdentifierLoc(), diag::err_typecheck_decl_incomplete_type, - R.getAsString()); - return 0; - } - } - if (SC == VarDecl::Static) { - // C99 6.7.5.2p2: If an identifier is declared to be an object with - // static storage duration, it shall not have a variable length array. - if (ArrayType *ary = dyn_cast(R)) { - if (!isConstantArrayType(ary, D.getIdentifierLoc())) - return 0; - } - } - NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC); - } - // Merge the decl with the existing one if appropriate. - if (PrevDecl) { - NewVD = MergeVarDecl(NewVD, PrevDecl); - if (NewVD == 0) return 0; - } - New = NewVD; - } - - - // If this has an identifier, add it to the scope stack. - if (II) { - New->setNext(II->getFETokenInfo()); - II->setFETokenInfo(New); - S->AddDecl(New); - } - - if (S->getParent() == 0) - AddTopLevelDecl(New, (Decl *)LastInGroup); - - return New; -} - -VarDecl * -Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo, - Scope *FnScope) { - const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo]; - - IdentifierInfo *II = PI.Ident; - // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope. - // Can this happen for params? We already checked that they don't conflict - // among each other. Here they can only shadow globals, which is ok. - if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary, - PI.IdentLoc, FnScope)) { - - } - - // FIXME: Handle storage class (auto, register). No declarator? - VarDecl *New = new ParmVarDecl(PI.IdentLoc, II, - QualType::getFromOpaquePtr(PI.TypeInfo), - VarDecl::None); - - // If this has an identifier, add it to the scope stack. - if (II) { - New->setNext(II->getFETokenInfo()); - II->setFETokenInfo(New); - FnScope->AddDecl(New); - } - - return New; -} - - -Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { - assert(CurFunctionDecl == 0 && "Function parsing confused"); - assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; - - // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' - // for a K&R function. - if (!FTI.hasPrototype) { - for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { - if (FTI.ArgInfo[i].TypeInfo == 0) { - Diag(FTI.ArgInfo[i].IdentLoc, diag::err_param_not_declared, - FTI.ArgInfo[i].Ident->getName()); - // Implicitly declare the argument as type 'int' for lack of a better - // type. - FTI.ArgInfo[i].TypeInfo = Context.IntTy.getAsOpaquePtr(); - } - } - - // Since this is a function definition, act as though we have information - // about the arguments. - FTI.hasPrototype = true; - } else { - // FIXME: Diagnose arguments without names in C. - - } - - Scope *GlobalScope = FnBodyScope->getParent(); - - FunctionDecl *FD = - static_cast(ParseDeclarator(GlobalScope, D, 0, 0)); - CurFunctionDecl = FD; - - // Create Decl objects for each parameter, adding them to the FunctionDecl. - SmallVector Params; - - // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes - // no arguments, not a function that takes a single void argument. - if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && - FTI.ArgInfo[0].TypeInfo == Context.VoidTy.getAsOpaquePtr()) { - // empty arg list, don't push any params. - } else { - for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) - Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i,FnBodyScope)); - } - - FD->setParams(&Params[0], Params.size()); - - return FD; -} - -Sema::DeclTy *Sema::ParseFunctionDefBody(DeclTy *D, StmtTy *Body) { - FunctionDecl *FD = static_cast(D); - FD->setBody((Stmt*)Body); - - assert(FD == CurFunctionDecl && "Function parsing confused"); - CurFunctionDecl = 0; - return FD; -} - - -/// ImplicitlyDefineFunction - An undeclared identifier was used in a function -/// call, forming a call to an implicitly defined function (per C99 6.5.1p2). -Decl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, - Scope *S) { - if (getLangOptions().C99) // Extension in C99. - Diag(Loc, diag::ext_implicit_function_decl, II.getName()); - else // Legal in C90, but warn about it. - Diag(Loc, diag::warn_implicit_function_decl, II.getName()); - - // FIXME: handle stuff like: - // void foo() { extern float X(); } - // void bar() { X(); } <-- implicit decl for X in another scope. - - // Set a Declarator for the implicit definition: int foo(); - const char *Dummy; - DeclSpec DS; - bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy); - Error = Error; // Silence warning. - assert(!Error && "Error setting up implicit decl!"); - Declarator D(DS, Declarator::BlockContext); - D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, Loc)); - D.SetIdentifier(&II, Loc); - - // Find translation-unit scope to insert this function into. - while (S->getParent()) - S = S->getParent(); - - return static_cast(ParseDeclarator(S, D, 0, 0)); -} - - -TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D) { - assert(D.getIdentifier() && "Wrong callback for declspec withotu declarator"); - - QualType T = GetTypeForDeclarator(D, S); - if (T.isNull()) return 0; - - // Scope manipulation handled by caller. - return new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), T); -} - - -/// ParseTag - This is invoked when we see 'struct foo' or 'struct {'. In the -/// former case, Name will be non-null. In the later case, Name will be null. -/// TagType indicates what kind of tag this is. TK indicates whether this is a -/// reference/declaration/definition of a tag. -Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK, - SourceLocation KWLoc, IdentifierInfo *Name, - SourceLocation NameLoc) { - // If this is a use of an existing tag, it must have a name. - assert((Name != 0 || TK == TK_Definition) && - "Nameless record must be a definition!"); - - Decl::Kind Kind; - switch (TagType) { - default: assert(0 && "Unknown tag type!"); - case DeclSpec::TST_struct: Kind = Decl::Struct; break; - case DeclSpec::TST_union: Kind = Decl::Union; break; -//case DeclSpec::TST_class: Kind = Decl::Class; break; - case DeclSpec::TST_enum: Kind = Decl::Enum; break; - } - - // If this is a named struct, check to see if there was a previous forward - // declaration or definition. - if (TagDecl *PrevDecl = - dyn_cast_or_null(LookupScopedDecl(Name, Decl::IDNS_Tag, - NameLoc, S))) { - - // 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 - // rementions the tag), reuse the decl. - if (TK == TK_Reference || S->isDeclScope(PrevDecl)) { - // Make sure that this wasn't declared as an enum and now used as a struct - // or something similar. - if (PrevDecl->getKind() != Kind) { - Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName()); - Diag(PrevDecl->getLocation(), diag::err_previous_use); - } - - // If this is a use or a forward declaration, we're good. - if (TK != TK_Definition) - return PrevDecl; - - // Diagnose attempts to redefine a tag. - if (PrevDecl->isDefinition()) { - Diag(NameLoc, diag::err_redefinition, Name->getName()); - Diag(PrevDecl->getLocation(), diag::err_previous_definition); - // If this is a redefinition, recover by making this struct be - // anonymous, which will make any later references get the previous - // definition. - Name = 0; - } else { - // Okay, this is definition of a previously declared or referenced tag. - // Move the location of the decl to be the definition site. - PrevDecl->setLocation(NameLoc); - return PrevDecl; - } - } - // If we get here, this is a definition of a new struct type in a nested - // scope, e.g. "struct foo; void bar() { struct foo; }", just create a new - // type. - } - - // 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. - SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; - - // Otherwise, if this is the first time we've seen this tag, create the decl. - TagDecl *New; - switch (Kind) { - default: assert(0 && "Unknown tag kind!"); - case Decl::Enum: - New = new EnumDecl(Loc, Name); - // If this is an undefined enum, warn. - if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum); - break; - case Decl::Union: - case Decl::Struct: - case Decl::Class: - New = new RecordDecl(Kind, Loc, Name); - break; - } - - // If this has an identifier, add it to the scope stack. - if (Name) { - New->setNext(Name->getFETokenInfo()); - Name->setFETokenInfo(New); - S->AddDecl(New); - } - - return New; -} - -/// ParseField - Each field of a struct/union/class is passed into this in order -/// to create a FieldDecl object for it. -Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl, - SourceLocation DeclStart, - Declarator &D, ExprTy *BitfieldWidth) { - IdentifierInfo *II = D.getIdentifier(); - Expr *BitWidth = (Expr*)BitfieldWidth; - - SourceLocation Loc = DeclStart; - if (II) Loc = D.getIdentifierLoc(); - - // FIXME: Unnamed fields can be handled in various different ways, for - // example, unnamed unions inject all members into the struct namespace! - - - if (BitWidth) { - // TODO: Validate. - printf("WARNING: BITFIELDS IGNORED!\n"); - - // 6.7.2.1p3 - // 6.7.2.1p4 - - } else { - // Not a bitfield. - - // validate II. - - } - - QualType T = GetTypeForDeclarator(D, S); - if (T.isNull()) return 0; - - // C99 6.7.2.1p8: A member of a structure or union may have any type other - // than a variably modified type. - if (ArrayType *ary = dyn_cast(T)) { - if (!isConstantArrayType(ary, Loc)) - return 0; - } - return new FieldDecl(Loc, II, T); -} - -void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl, - DeclTy **Fields, unsigned NumFields) { - RecordDecl *Record = cast(static_cast(RecDecl)); - if (Record->isDefinition()) { - // Diagnose code like: - // struct S { struct S {} X; }; - // We discover this when we complete the outer S. Reject and ignore the - // outer S. - Diag(Record->getLocation(), diag::err_nested_redefinition, - Record->getKindName()); - Diag(RecLoc, diag::err_previous_definition); - return; - } - - // Verify that all the fields are okay. - unsigned NumNamedMembers = 0; - SmallVector RecFields; - SmallSet FieldIDs; - - for (unsigned i = 0; i != NumFields; ++i) { - FieldDecl *FD = cast_or_null(static_cast(Fields[i])); - if (!FD) continue; // Already issued a diagnostic. - - // Get the type for the field. - Type *FDTy = FD->getType().getCanonicalType().getTypePtr(); - - // C99 6.7.2.1p2 - A field may not be a function type. - if (isa(FDTy)) { - Diag(FD->getLocation(), diag::err_field_declared_as_function, - FD->getName()); - delete FD; - continue; - } - - // C99 6.7.2.1p2 - A field may not be an incomplete type except... - if (FDTy->isIncompleteType()) { - if (i != NumFields-1 || // ... that the last member ... - Record->getKind() != Decl::Struct || // ... of a structure ... - !isa(FDTy)) { //... may have incomplete array type. - Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName()); - delete FD; - continue; - } - if (NumNamedMembers < 1) { //... must have more than named member ... - Diag(FD->getLocation(), diag::err_flexible_array_empty_struct, - FD->getName()); - delete FD; - continue; - } - - // Okay, we have a legal flexible array member at the end of the struct. - Record->setHasFlexibleArrayMember(true); - } - - - /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the - /// field of another structure or the element of an array. - if (RecordType *FDTTy = dyn_cast(FDTy)) { - if (FDTTy->getDecl()->hasFlexibleArrayMember()) { - // If this is a member of a union, then entire union becomes "flexible". - if (Record->getKind() == Decl::Union) { - Record->setHasFlexibleArrayMember(true); - } else { - // If this is a struct/class and this is not the last element, reject - // it. Note that GCC supports variable sized arrays in the middle of - // structures. - if (i != NumFields-1) { - Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct, - FD->getName()); - delete FD; - continue; - } - - // We support flexible arrays at the end of structs in other structs - // as an extension. - Diag(FD->getLocation(), diag::ext_flexible_array_in_struct, - FD->getName()); - Record->setHasFlexibleArrayMember(true); - } - } - } - - // Keep track of the number of named members. - if (IdentifierInfo *II = FD->getIdentifier()) { - // Detect duplicate member names. - if (!FieldIDs.insert(II)) { - Diag(FD->getLocation(), diag::err_duplicate_member, II->getName()); - // Find the previous decl. - SourceLocation PrevLoc; - for (unsigned i = 0, e = RecFields.size(); ; ++i) { - assert(i != e && "Didn't find previous def!"); - if (RecFields[i]->getIdentifier() == II) { - PrevLoc = RecFields[i]->getLocation(); - break; - } - } - Diag(PrevLoc, diag::err_previous_definition); - delete FD; - continue; - } - ++NumNamedMembers; - } - - // Remember good fields. - RecFields.push_back(FD); - } - - - // Okay, we successfully defined 'Record'. - Record->defineBody(&RecFields[0], RecFields.size()); -} - -Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX, - SourceLocation IdLoc, IdentifierInfo *Id, - SourceLocation EqualLoc, ExprTy *Val) { - EnumDecl *TheEnumDecl = cast(static_cast(EnumDeclX)); - - // Verify that there isn't already something declared with this name in this - // scope. - if (Decl *PrevDecl = LookupScopedDecl(Id, Decl::IDNS_Ordinary, IdLoc, S)) { - if (S->isDeclScope(PrevDecl)) { - if (isa(PrevDecl)) - Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName()); - else - Diag(IdLoc, diag::err_redefinition, Id->getName()); - Diag(PrevDecl->getLocation(), diag::err_previous_definition); - return 0; - } - } - SourceLocation expLoc; - // C99 6.7.2.2p2: Make sure we have an integer constant expression. - if (Val && !((Expr *)Val)->isIntegerConstantExpr(expLoc)) { - Diag(expLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName()); - return 0; - } - QualType Ty = Context.getTagDeclType(TheEnumDecl); - EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty, (Expr *)Val); - - // Register this decl in the current scope stack. - New->setNext(Id->getFETokenInfo()); - Id->setFETokenInfo(New); - S->AddDecl(New); - return New; -} - -void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, - DeclTy **Elements, unsigned NumElements) { - EnumDecl *Enum = cast(static_cast(EnumDeclX)); - assert(!Enum->isDefinition() && "Enum redefinitions can't reach here"); - - // Verify that all the values are okay. - SmallVector Values; - for (unsigned i = 0; i != NumElements; ++i) { - EnumConstantDecl *ECD = - cast_or_null(static_cast(Elements[i])); - if (!ECD) continue; // Already issued a diagnostic. - - Values.push_back(ECD); - } - - Enum->defineElements(&Values[0], Values.size()); -} - -void Sema::AddTopLevelDecl(Decl *current, Decl *last) { - if (!current) return; - - // If this is a top-level decl that is chained to some other (e.g. int A,B,C;) - // remember this in the LastInGroupList list. - if (last) { - LastInGroupList.push_back((Decl*)last); - } -} diff --git a/clang/AST/SemaExpr.cpp b/clang/AST/SemaExpr.cpp deleted file mode 100644 index fc05189d23d6..000000000000 --- a/clang/AST/SemaExpr.cpp +++ /dev/null @@ -1,1196 +0,0 @@ -//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements semantic analysis for expressions. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/LiteralSupport.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -using namespace llvm; -using namespace clang; - -/// ParseStringLiteral - The specified tokens were lexed as pasted string -/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string -/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from -/// multiple tokens. However, the common case is that StringToks points to one -/// string. -/// -Action::ExprResult -Sema::ParseStringLiteral(const LexerToken *StringToks, unsigned NumStringToks) { - assert(NumStringToks && "Must have at least one string!"); - - StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target); - if (Literal.hadError) - return ExprResult(true); - - SmallVector StringTokLocs; - for (unsigned i = 0; i != NumStringToks; ++i) - StringTokLocs.push_back(StringToks[i].getLocation()); - - // FIXME: handle wchar_t - QualType t = Context.getPointerType(Context.CharTy); - - // FIXME: use factory. - // Pass &StringTokLocs[0], StringTokLocs.size() to factory! - return new StringLiteral(Literal.GetString(), Literal.GetStringLength(), - Literal.AnyWide, t, StringToks[0].getLocation(), - StringToks[NumStringToks-1].getLocation()); -} - - -/// ParseIdentifierExpr - The parser read an identifier in expression context, -/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this -/// identifier is used in an function call context. -Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc, - IdentifierInfo &II, - bool HasTrailingLParen) { - // Could be enum-constant or decl. - Decl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S); - if (D == 0) { - // Otherwise, this could be an implicitly declared function reference (legal - // in C90, extension in C99). - if (HasTrailingLParen && - // Not in C++. - !getLangOptions().CPlusPlus) - D = ImplicitlyDefineFunction(Loc, II, S); - else { - // If this name wasn't predeclared and if this is not a function call, - // diagnose the problem. - return Diag(Loc, diag::err_undeclared_var_use, II.getName()); - } - } - - if (ValueDecl *VD = dyn_cast(D)) - return new DeclRefExpr(VD, VD->getType(), Loc); - if (isa(D)) - return Diag(Loc, diag::err_unexpected_typedef, II.getName()); - - assert(0 && "Invalid decl"); -} - -Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc, - tok::TokenKind Kind) { - switch (Kind) { - default: - assert(0 && "Unknown simple primary expr!"); - // TODO: MOVE this to be some other callback. - case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2] - case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU] - case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] - return 0; - } -} - -Sema::ExprResult Sema::ParseCharacterConstant(const LexerToken &Tok) { - SmallString<16> CharBuffer; - CharBuffer.resize(Tok.getLength()); - const char *ThisTokBegin = &CharBuffer[0]; - unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin); - - CharLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, - Tok.getLocation(), PP); - if (Literal.hadError()) - return ExprResult(true); - return new CharacterLiteral(Literal.getValue(), Context.IntTy, - Tok.getLocation()); -} - -Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) { - // fast path for a single digit (which is quite common). A single digit - // cannot have a trigraph, escaped newline, radix prefix, or type suffix. - if (Tok.getLength() == 1) { - const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation()); - - unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation()); - return ExprResult(new IntegerLiteral(APInt(IntSize, *t-'0'), Context.IntTy, - Tok.getLocation())); - } - SmallString<512> IntegerBuffer; - IntegerBuffer.resize(Tok.getLength()); - const char *ThisTokBegin = &IntegerBuffer[0]; - - // Get the spelling of the token, which eliminates trigraphs, etc. - unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin); - NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, - Tok.getLocation(), PP); - if (Literal.hadError) - return ExprResult(true); - - if (Literal.isIntegerLiteral()) { - QualType t; - - // Get the value in the widest-possible width. - APInt ResultVal(Context.Target.getIntMaxTWidth(Tok.getLocation()), 0); - - if (Literal.GetIntegerValue(ResultVal)) { - // If this value didn't fit into uintmax_t, warn and force to ull. - Diag(Tok.getLocation(), diag::warn_integer_too_large); - t = Context.UnsignedLongLongTy; - assert(Context.getIntegerBitwidth(t, Tok.getLocation()) == - ResultVal.getBitWidth() && "long long is not intmax_t?"); - } else { - // If this value fits into a ULL, try to figure out what else it fits into - // according to the rules of C99 6.4.4.1p5. - - // Octal, Hexadecimal, and integers with a U suffix are allowed to - // be an unsigned int. - bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10; - - // Check from smallest to largest, picking the smallest type we can. - if (!Literal.isLong) { // Are int/unsigned possibilities? - unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation()); - // Does it fit in a unsigned int? - if (ResultVal.isIntN(IntSize)) { - // Does it fit in a signed int? - if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0) - t = Context.IntTy; - else if (AllowUnsigned) - t = Context.UnsignedIntTy; - } - - if (!t.isNull()) - ResultVal.trunc(IntSize); - } - - // Are long/unsigned long possibilities? - if (t.isNull() && !Literal.isLongLong) { - unsigned LongSize = Context.Target.getLongWidth(Tok.getLocation()); - - // Does it fit in a unsigned long? - if (ResultVal.isIntN(LongSize)) { - // Does it fit in a signed long? - if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0) - t = Context.LongTy; - else if (AllowUnsigned) - t = Context.UnsignedLongTy; - } - if (!t.isNull()) - ResultVal.trunc(LongSize); - } - - // Finally, check long long if needed. - if (t.isNull()) { - unsigned LongLongSize = - Context.Target.getLongLongWidth(Tok.getLocation()); - - // Does it fit in a unsigned long long? - if (ResultVal.isIntN(LongLongSize)) { - // Does it fit in a signed long long? - if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0) - t = Context.LongLongTy; - else if (AllowUnsigned) - t = Context.UnsignedLongLongTy; - } - } - - // If we still couldn't decide a type, we probably have something that - // does not fit in a signed long long, but has no U suffix. - if (t.isNull()) { - Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed); - t = Context.UnsignedLongLongTy; - } - } - - return new IntegerLiteral(ResultVal, t, Tok.getLocation()); - } else if (Literal.isFloatingLiteral()) { - // FIXME: fill in the value and compute the real type... - return new FloatingLiteral(7.7, Context.FloatTy, Tok.getLocation()); - } - return ExprResult(true); -} - -Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R, - ExprTy *Val) { - Expr *e = (Expr *)Val; - assert((e != 0) && "ParseParenExpr() missing expr"); - return new ParenExpr(L, R, e); -} - -/// The UsualUnaryConversion() function is *not* called by this routine. -/// See C99 6.3.2.1p[2-4] for more details. -QualType Sema::CheckSizeOfAlignOfOperand(QualType exprType, - SourceLocation OpLoc, bool isSizeof) { - // C99 6.5.3.4p1: - if (isa(exprType) && isSizeof) - // alignof(function) is allowed. - Diag(OpLoc, diag::ext_sizeof_function_type); - else if (exprType->isVoidType()) - Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof"); - else if (exprType->isIncompleteType()) { - Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type : - diag::err_alignof_incomplete_type, - exprType.getAsString()); - return QualType(); // error - } - // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. - return Context.getSizeType(); -} - -Action::ExprResult Sema:: -ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof, - SourceLocation LPLoc, TypeTy *Ty, - SourceLocation RPLoc) { - // If error parsing type, ignore. - if (Ty == 0) return true; - - // Verify that this is a valid expression. - QualType ArgTy = QualType::getFromOpaquePtr(Ty); - - QualType resultType = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, isSizeof); - - if (resultType.isNull()) - return true; - return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, resultType, OpLoc, RPLoc); -} - - -Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc, - tok::TokenKind Kind, - ExprTy *Input) { - UnaryOperator::Opcode Opc; - switch (Kind) { - default: assert(0 && "Unknown unary op!"); - case tok::plusplus: Opc = UnaryOperator::PostInc; break; - case tok::minusminus: Opc = UnaryOperator::PostDec; break; - } - QualType result = CheckIncrementDecrementOperand((Expr *)Input, OpLoc); - if (result.isNull()) - return true; - return new UnaryOperator((Expr *)Input, Opc, result, OpLoc); -} - -Action::ExprResult Sema:: -ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc, - ExprTy *Idx, SourceLocation RLoc) { - QualType t1 = ((Expr *)Base)->getType(); - QualType t2 = ((Expr *)Idx)->getType(); - - assert(!t1.isNull() && "no type for array base expression"); - assert(!t2.isNull() && "no type for array index expression"); - - QualType canonT1 = t1.getCanonicalType(); - QualType canonT2 = t2.getCanonicalType(); - - // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent - // to the expression *((e1)+(e2)). This means the array "Base" may actually be - // in the subscript position. As a result, we need to derive the array base - // and index from the expression types. - - QualType baseType, indexType; - if (isa(canonT1) || isa(canonT1)) { - baseType = canonT1; - indexType = canonT2; - } else if (isa(canonT2) || isa(canonT2)) { // uncommon - baseType = canonT2; - indexType = canonT1; - } else - return Diag(LLoc, diag::err_typecheck_subscript_value); - - // C99 6.5.2.1p1 - if (!indexType->isIntegerType()) - return Diag(LLoc, diag::err_typecheck_subscript); - - // FIXME: need to deal with const... - QualType resultType; - if (ArrayType *ary = dyn_cast(baseType)) { - resultType = ary->getElementType(); - } else if (PointerType *ary = dyn_cast(baseType)) { - resultType = ary->getPointeeType(); - // in practice, the following check catches trying to index a pointer - // to a function (e.g. void (*)(int)). Functions are not objects in c99. - if (!resultType->isObjectType()) - return Diag(LLoc, diag::err_typecheck_subscript_not_object, - baseType.getAsString()); - } - return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, resultType, RLoc); -} - -Action::ExprResult Sema:: -ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, - tok::TokenKind OpKind, SourceLocation MemberLoc, - IdentifierInfo &Member) { - QualType qualifiedType = ((Expr *)Base)->getType(); - - assert(!qualifiedType.isNull() && "no type for member expression"); - - QualType canonType = qualifiedType.getCanonicalType(); - - if (OpKind == tok::arrow) { - if (PointerType *PT = dyn_cast(canonType)) { - qualifiedType = PT->getPointeeType(); - canonType = qualifiedType.getCanonicalType(); - } else - return Diag(OpLoc, diag::err_typecheck_member_reference_arrow); - } - if (!isa(canonType)) - return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion); - - // get the struct/union definition from the type. - RecordDecl *RD = cast(canonType)->getDecl(); - - if (canonType->isIncompleteType()) - return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName()); - - FieldDecl *MemberDecl = RD->getMember(&Member); - if (!MemberDecl) - return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName()); - - return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl); -} - -/// ParseCallExpr - Handle a call to Fn with the specified array of arguments. -/// This provides the location of the left/right parens and a list of comma -/// locations. -Action::ExprResult Sema:: -ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc, - ExprTy **Args, unsigned NumArgsInCall, - SourceLocation *CommaLocs, SourceLocation RParenLoc) { - QualType qType = ((Expr *)Fn)->getType(); - - assert(!qType.isNull() && "no type for function call expression"); - - const FunctionType *funcT = dyn_cast(qType.getCanonicalType()); - - assert(funcT && "ParseCallExpr(): not a function type"); - - // If a prototype isn't declared, the parser implicitly defines a func decl - QualType resultType = funcT->getResultType(); - - if (const FunctionTypeProto *proto = dyn_cast(funcT)) { - // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by - // assignment, to the types of the corresponding parameter, ... - - unsigned NumArgsInProto = proto->getNumArgs(); - unsigned NumArgsToCheck = NumArgsInCall; - - if (NumArgsInCall < NumArgsInProto) - Diag(LParenLoc, diag::err_typecheck_call_too_few_args); - else if (NumArgsInCall > NumArgsInProto) { - if (!proto->isVariadic()) - Diag(LParenLoc, diag::err_typecheck_call_too_many_args); - NumArgsToCheck = NumArgsInProto; - } - // Continue to check argument types (even if we have too few/many args). - for (unsigned i = 0; i < NumArgsToCheck; i++) { - QualType lhsType = proto->getArgType(i); - QualType rhsType = ((Expr **)Args)[i]->getType(); - - if (lhsType == rhsType) // common case, fast path... - continue; - AssignmentConversionResult result; - UsualAssignmentConversions(lhsType, rhsType, result); - - SourceLocation l = (i == 0) ? LParenLoc : CommaLocs[i-1]; - - // decode the result (notice that AST's are still created for extensions). - // FIXME: consider fancier error diagnostics (since this is quite common). - // #1: emit the actual prototype arg...requires adding source loc info. - // #2: pass Diag the offending argument type...requires hacking Diag. - switch (result) { - case Compatible: - break; - case PointerFromInt: - // check for null pointer constant (C99 6.3.2.3p3) - if (!((Expr **)Args)[i]->isNullPointerConstant()) - Diag(l, diag::ext_typecheck_passing_pointer_from_int, utostr(i+1)); - break; - case IntFromPointer: - Diag(l, diag::ext_typecheck_passing_int_from_pointer, utostr(i+1)); - break; - case IncompatiblePointer: - Diag(l, diag::ext_typecheck_passing_incompatible_pointer, utostr(i+1)); - break; - case CompatiblePointerDiscardsQualifiers: - Diag(l, diag::ext_typecheck_passing_discards_qualifiers, utostr(i+1)); - break; - case Incompatible: - return Diag(l, diag::err_typecheck_passing_incompatible, utostr(i+1)); - } - } - // Even if the types checked, bail if we had the wrong number of arguments. - if ((NumArgsInCall != NumArgsInProto) && !proto->isVariadic()) - return true; - } - return new CallExpr((Expr*)Fn, (Expr**)Args, NumArgsInCall, resultType, - RParenLoc); -} - -Action::ExprResult Sema:: -ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc, ExprTy *Op) { - // If error parsing type, ignore. - assert((Ty != 0) && "ParseCastExpr(): missing type"); - return new CastExpr(QualType::getFromOpaquePtr(Ty), (Expr*)Op, LParenLoc); -} - -inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 - Expr *Cond, Expr *LHS, Expr *RHS, SourceLocation questionLoc) { - QualType cond = Cond->getType(); - QualType lhs = LHS->getType(); - QualType rhs = RHS->getType(); - - assert(!cond.isNull() && "ParseConditionalOp(): no conditional type"); - assert(!lhs.isNull() && "ParseConditionalOp(): no lhs type"); - assert(!rhs.isNull() && "ParseConditionalOp(): no rhs type"); - - cond = UsualUnaryConversion(cond); - lhs = UsualUnaryConversion(lhs); - rhs = UsualUnaryConversion(rhs); - - // first, check the condition. - if (!cond->isScalarType()) { // C99 6.5.15p2 - Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar, - cond.getAsString()); - return QualType(); - } - // now check the two expressions. - if (lhs->isArithmeticType() && rhs->isArithmeticType()) // C99 6.5.15p3,5 - return UsualArithmeticConversions(lhs, rhs); - - if ((lhs->isStructureType() && rhs->isStructureType()) || // C99 6.5.15p3 - (lhs->isUnionType() && rhs->isUnionType())) { - TagType *lTag = cast(lhs.getCanonicalType()); - TagType *rTag = cast(rhs.getCanonicalType()); - - if (lTag->getDecl()->getIdentifier() == rTag->getDecl()->getIdentifier()) - return lhs; - else { - Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands, - lhs.getAsString(), rhs.getAsString()); - return QualType(); - } - } - if (lhs->isPointerType() && RHS->isNullPointerConstant()) // C99 6.5.15p3 - return lhs; - if (rhs->isPointerType() && LHS->isNullPointerConstant()) - return rhs; - - if (lhs->isPointerType() && rhs->isPointerType()) { // C99 6.5.15p3,6 - QualType lhptee, rhptee; - - // get the "pointed to" type - lhptee = cast(lhs.getCanonicalType())->getPointeeType(); - rhptee = cast(rhs.getCanonicalType())->getPointeeType(); - - // ignore qualifiers on void (C99 6.5.15p3, clause 6) - if (lhptee.getUnqualifiedType()->isVoidType() && - (rhptee->isObjectType() || rhptee->isIncompleteType())) - return lhs; - if (rhptee.getUnqualifiedType()->isVoidType() && - (lhptee->isObjectType() || lhptee->isIncompleteType())) - return rhs; - - // FIXME: C99 6.5.15p6: If both operands are pointers to compatible types - // *or* to differently qualified versions of compatible types, the result - // type is a pointer to an appropriately qualified version of the - // *composite* type. - if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) { - Diag(questionLoc, diag::ext_typecheck_cond_incompatible_pointers, - lhs.getAsString(), rhs.getAsString()); - return lhs; // FIXME: this is an _ext - is this return o.k? - } - } - if (lhs->isVoidType() && rhs->isVoidType()) // C99 6.5.15p3 - return lhs; - - Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands, - lhs.getAsString(), rhs.getAsString()); - return QualType(); -} - -/// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null -/// in the case of a the GNU conditional expr extension. -Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc, - SourceLocation ColonLoc, - ExprTy *Cond, ExprTy *LHS, - ExprTy *RHS) { - QualType result = CheckConditionalOperands((Expr *)Cond, (Expr *)LHS, - (Expr *)RHS, QuestionLoc); - if (result.isNull()) - return true; - return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS, result); -} - -/// UsualUnaryConversion - Performs various conversions that are common to most -/// operators (C99 6.3). The conversions of array and function types are -/// sometimes surpressed. For example, the array->pointer conversion doesn't -/// apply if the array is an argument to the sizeof or address (&) operators. -/// In these instances, this routine should *not* be called. -QualType Sema::UsualUnaryConversion(QualType t) { - assert(!t.isNull() && "UsualUnaryConversion - missing type"); - - if (t->isPromotableIntegerType()) // C99 6.3.1.1p2 - return Context.IntTy; - if (t->isFunctionType()) // C99 6.3.2.1p4 - return Context.getPointerType(t.getCanonicalType()); - if (const ArrayType *ary = dyn_cast(t.getCanonicalType())) - return Context.getPointerType(ary->getElementType()); // C99 6.3.2.1p3 - return t; -} - -/// UsualArithmeticConversions - Performs various conversions that are common to -/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this -/// routine returns the first non-arithmetic type found. The client is -/// responsible for emitting appropriate error diagnostics. -QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) { - QualType lhs = UsualUnaryConversion(t1); - QualType rhs = UsualUnaryConversion(t2); - - // if either operand is not of arithmetic type, no conversion is possible. - if (!lhs->isArithmeticType()) - return lhs; - if (!rhs->isArithmeticType()) - return rhs; - - // if both arithmetic types are identical, no conversion is needed. - if (lhs == rhs) - return lhs; - - // at this point, we have two different arithmetic types. - - // Handle complex types first (C99 6.3.1.8p1). - if (lhs->isComplexType() || rhs->isComplexType()) { - // if we have an integer operand, the result is the complex type. - if (rhs->isIntegerType()) - return lhs; - if (lhs->isIntegerType()) - return rhs; - - return Context.maxComplexType(lhs, rhs); - } - // Now handle "real" floating types (i.e. float, double, long double). - if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) { - // if we have an integer operand, the result is the real floating type. - if (rhs->isIntegerType()) - return lhs; - if (lhs->isIntegerType()) - return rhs; - - // we have two real floating types, float/complex combos were handled above. - return Context.maxFloatingType(lhs, rhs); - } - return Context.maxIntegerType(lhs, rhs); -} - -// CheckPointerTypesForAssignment - This is a very tricky routine (despite -// being closely modeled after the C99 spec:-). The odd characteristic of this -// routine is it effectively iqnores the qualifiers on the top level pointee. -// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3]. -// FIXME: add a couple examples in this comment. -QualType Sema::CheckPointerTypesForAssignment(QualType lhsType, - QualType rhsType, - AssignmentConversionResult &r) { - QualType lhptee, rhptee; - - // get the "pointed to" type (ignoring qualifiers at the top level) - lhptee = cast(lhsType.getCanonicalType())->getPointeeType(); - rhptee = cast(rhsType.getCanonicalType())->getPointeeType(); - - // make sure we operate on the canonical type - lhptee = lhptee.getCanonicalType(); - rhptee = rhptee.getCanonicalType(); - - // C99 6.5.16.1p1: This following citation is common to constraints - // 3 & 4 (below). ...and the type *pointed to* by the left has all the - // qualifiers of the type *pointed to* by the right; - if ((lhptee.getQualifiers() & rhptee.getQualifiers()) != - rhptee.getQualifiers()) - r = CompatiblePointerDiscardsQualifiers; - - // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or - // incomplete type and the other is a pointer to a qualified or unqualified - // version of void... - if (lhptee.getUnqualifiedType()->isVoidType() && - (rhptee->isObjectType() || rhptee->isIncompleteType())) - ; - else if (rhptee.getUnqualifiedType()->isVoidType() && - (lhptee->isObjectType() || lhptee->isIncompleteType())) - ; - // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or - // unqualified versions of compatible types, ... - else if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) - r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers - return rhsType; -} - -/// UsualAssignmentConversions (C99 6.5.16) - This routine currently -/// has code to accommodate several GCC extensions when type checking -/// pointers. Here are some objectionable examples that GCC considers warnings: -/// -/// int a, *pint; -/// short *pshort; -/// struct foo *pfoo; -/// -/// pint = pshort; // warning: assignment from incompatible pointer type -/// a = pint; // warning: assignment makes integer from pointer without a cast -/// pint = a; // warning: assignment makes pointer from integer without a cast -/// pint = pfoo; // warning: assignment from incompatible pointer type -/// -/// As a result, the code for dealing with pointers is more complex than the -/// C99 spec dictates. -/// Note: the warning above turn into errors when -pedantic-errors is enabled. -/// -QualType Sema::UsualAssignmentConversions(QualType lhsType, QualType rhsType, - AssignmentConversionResult &r) { - // this check seems unnatural, however it necessary to insure the proper - // conversion of functions/arrays. If the conversion where done for all - // DeclExpr's (created by ParseIdentifierExpr), it would mess up the - // unary expressions that surpress this implicit conversion (&, sizeof). - if (rhsType->isFunctionType() || rhsType->isArrayType()) - rhsType = UsualUnaryConversion(rhsType); - - r = Compatible; - if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) - return lhsType; - else if (lhsType->isPointerType()) { - if (rhsType->isIntegerType()) { - r = PointerFromInt; - return rhsType; - } - if (rhsType->isPointerType()) - return CheckPointerTypesForAssignment(lhsType, rhsType, r); - } else if (rhsType->isPointerType()) { - if (lhsType->isIntegerType()) { - // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer. - if (lhsType != Context.BoolTy) - r = IntFromPointer; - return rhsType; - } - if (lhsType->isPointerType()) - return CheckPointerTypesForAssignment(lhsType, rhsType, r); - } else if (isa(lhsType) && isa(rhsType)) { - if (Type::tagTypesAreCompatible(lhsType, rhsType)) - return rhsType; - } - r = Incompatible; - return QualType(); -} - -inline QualType Sema::CheckMultiplyDivideOperands( - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType()); - - if (resType->isArithmeticType()) - return resType; - Diag(loc, diag::err_typecheck_invalid_operands, - lex->getType().getAsString(), rex->getType().getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckRemainderOperands( - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType()); - - if (resType->isIntegerType()) - return resType; - Diag(loc, diag::err_typecheck_invalid_operands, - lex->getType().getAsString(), rex->getType().getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType lhsType = lex->getType(), rhsType = rex->getType(); - QualType resType = UsualArithmeticConversions(lhsType, rhsType); - - // handle the common case first (both operands are arithmetic). - if (resType->isArithmeticType()) - return resType; - - if ((lhsType->isPointerType() && rhsType->isIntegerType()) || - (lhsType->isIntegerType() && rhsType->isPointerType())) - return resType; - Diag(loc, diag::err_typecheck_invalid_operands, - lhsType.getAsString(), rhsType.getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6 - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType lhsType = lex->getType(), rhsType = rex->getType(); - QualType resType = UsualArithmeticConversions(lhsType, rhsType); - - // handle the common case first (both operands are arithmetic). - if (resType->isArithmeticType()) - return resType; - if ((lhsType->isPointerType() && rhsType->isIntegerType()) || - (lhsType->isPointerType() && rhsType->isPointerType())) - return resType; - Diag(loc, diag::err_typecheck_invalid_operands, - lhsType.getAsString(), rhsType.getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckShiftOperands( // C99 6.5.7 - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType()); - - if (resType->isIntegerType()) - return resType; - Diag(loc, diag::err_typecheck_invalid_operands, - lex->getType().getAsString(), rex->getType().getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckRelationalOperands( // C99 6.5.8 - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType lType = lex->getType(), rType = rex->getType(); - - if (lType->isRealType() && rType->isRealType()) - return Context.IntTy; - - if (lType->isPointerType() && rType->isPointerType()) - return Context.IntTy; - - if (lType->isIntegerType() || rType->isIntegerType()) { // GCC extension. - Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer); - return Context.IntTy; - } - Diag(loc, diag::err_typecheck_invalid_operands, - lType.getAsString(), rType.getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckEqualityOperands( // C99 6.5.9 - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType lType = lex->getType(), rType = rex->getType(); - - if (lType->isArithmeticType() && rType->isArithmeticType()) - return Context.IntTy; - if (lType->isPointerType() && rType->isPointerType()) - return Context.IntTy; - - if (lType->isIntegerType() || rType->isIntegerType()) { // GCC extension. - Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer); - return Context.IntTy; - } - Diag(loc, diag::err_typecheck_invalid_operands, - lType.getAsString(), rType.getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckBitwiseOperands( - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType resType = UsualArithmeticConversions(lex->getType(), rex->getType()); - - if (resType->isIntegerType()) - return resType; - Diag(loc, diag::err_typecheck_invalid_operands, - lex->getType().getAsString(), rex->getType().getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] - Expr *lex, Expr *rex, SourceLocation loc) -{ - QualType lhsType = UsualUnaryConversion(lex->getType()); - QualType rhsType = UsualUnaryConversion(rex->getType()); - - if (lhsType->isScalarType() || rhsType->isScalarType()) - return Context.IntTy; - Diag(loc, diag::err_typecheck_invalid_operands, - lex->getType().getAsString(), rex->getType().getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - return QualType(); -} - -inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1 - Expr *lex, Expr *rex, SourceLocation loc, QualType compoundType) -{ - QualType lhsType = lex->getType(); - QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType; - bool hadError = false; - - // this check is done first to give a more precise diagnostic. - // isModifiableLvalue() will also check for "const". - if (lhsType.isConstQualified()) { - Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange()); - hadError = true; - } else if (!lex->isModifiableLvalue()) { // C99 6.5.16p2 - Diag(loc, diag::err_typecheck_assign_non_lvalue, lex->getSourceRange()); - return QualType(); // no need to continue checking... - } - if (lhsType == rhsType) // common case, fast path... - return lhsType; - - AssignmentConversionResult result; - QualType resType = UsualAssignmentConversions(lhsType, rhsType, result); - - // decode the result (notice that extensions still return a type). - switch (result) { - case Compatible: - break; - case Incompatible: - Diag(loc, diag::err_typecheck_assign_incompatible, - lhsType.getAsString(), rhsType.getAsString(), - lex->getSourceRange(), rex->getSourceRange()); - hadError = true; - break; - case PointerFromInt: - // check for null pointer constant (C99 6.3.2.3p3) - if (compoundType.isNull() && !rex->isNullPointerConstant()) - Diag(loc, diag::ext_typecheck_assign_pointer_from_int); - break; - case IntFromPointer: - Diag(loc, diag::ext_typecheck_assign_int_from_pointer); - break; - case IncompatiblePointer: - Diag(loc, diag::ext_typecheck_assign_incompatible_pointer); - break; - case CompatiblePointerDiscardsQualifiers: - Diag(loc, diag::ext_typecheck_assign_discards_qualifiers); - break; - } - return hadError ? QualType() : resType; -} - -inline QualType Sema::CheckCommaOperands( // C99 6.5.17 - Expr *lex, Expr *rex, SourceLocation loc) { - return UsualUnaryConversion(rex->getType()); -} - -QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) { - QualType resType = UsualArithmeticConversions(op->getType(), Context.IntTy); - assert(!resType.isNull() && "no type for increment/decrement expression"); - - // C99 6.5.2.4p1 - if (const PointerType *pt = dyn_cast(resType)) { - if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2 - Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type, - resType.getAsString(), op->getSourceRange()); - return QualType(); - } - } else if (!resType->isRealType()) { - // FIXME: Allow Complex as a GCC extension. - Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement, - resType.getAsString(), op->getSourceRange()); - return QualType(); - } - // At this point, we know we have a real or pointer type. Now make sure - // the operand is a modifiable lvalue. - if (!op->isModifiableLvalue()) { - Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr, - op->getSourceRange()); - return QualType(); - } - return resType; -} - -/// getPrimaryDeclaration - Helper function for CheckAddressOfOperand(). -/// This routine allows us to typecheck complex/recursive expressions -/// where the declaration is needed for type checking. Here are some -/// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2]. -static Decl *getPrimaryDeclaration(Expr *e) { - switch (e->getStmtClass()) { - case Stmt::DeclRefExprClass: - return cast(e)->getDecl(); - case Stmt::MemberExprClass: - return getPrimaryDeclaration(cast(e)->getBase()); - case Stmt::ArraySubscriptExprClass: - return getPrimaryDeclaration(cast(e)->getBase()); - case Stmt::CallExprClass: - return getPrimaryDeclaration(cast(e)->getCallee()); - case Stmt::UnaryOperatorClass: - return getPrimaryDeclaration(cast(e)->getSubExpr()); - case Stmt::ParenExprClass: - return getPrimaryDeclaration(cast(e)->getSubExpr()); - default: - return 0; - } -} - -/// CheckAddressOfOperand - The operand of & must be either a function -/// designator or an lvalue designating an object. If it is an lvalue, the -/// object cannot be declared with storage class register or be a bit field. -/// Note: The usual conversions are *not* applied to the operand of the & -/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. -QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { - Decl *dcl = getPrimaryDeclaration(op); - - if (!op->isLvalue()) { // C99 6.5.3.2p1 - if (dcl && isa(dcl)) // allow function designators - ; - else { - Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof, - op->getSourceRange()); - return QualType(); - } - } else if (dcl) { - // We have an lvalue with a decl. Make sure the decl is not declared - // with the register storage-class specifier. - if (const VarDecl *vd = dyn_cast(dcl)) { - if (vd->getStorageClass() == VarDecl::Register) { - Diag(OpLoc, diag::err_typecheck_address_of_register, - op->getSourceRange()); - return QualType(); - } - } else - assert(0 && "Unknown/unexpected decl type"); - - // FIXME: add check for bitfields! - } - // If the operand has type "type", the result has type "pointer to type". - return Context.getPointerType(op->getType()); -} - -QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) { - QualType qType = UsualUnaryConversion(op->getType()); - - assert(!qType.isNull() && "no type for * expression"); - - if (PointerType *PT = dyn_cast(qType)) - return PT->getPointeeType(); - Diag(OpLoc, diag::err_typecheck_unary_expr, qType.getAsString(), - op->getSourceRange()); - return QualType(); -} - -static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode( - tok::TokenKind Kind) { - BinaryOperator::Opcode Opc; - switch (Kind) { - default: assert(0 && "Unknown binop!"); - case tok::star: Opc = BinaryOperator::Mul; break; - case tok::slash: Opc = BinaryOperator::Div; break; - case tok::percent: Opc = BinaryOperator::Rem; break; - case tok::plus: Opc = BinaryOperator::Add; break; - case tok::minus: Opc = BinaryOperator::Sub; break; - case tok::lessless: Opc = BinaryOperator::Shl; break; - case tok::greatergreater: Opc = BinaryOperator::Shr; break; - case tok::lessequal: Opc = BinaryOperator::LE; break; - case tok::less: Opc = BinaryOperator::LT; break; - case tok::greaterequal: Opc = BinaryOperator::GE; break; - case tok::greater: Opc = BinaryOperator::GT; break; - case tok::exclaimequal: Opc = BinaryOperator::NE; break; - case tok::equalequal: Opc = BinaryOperator::EQ; break; - case tok::amp: Opc = BinaryOperator::And; break; - case tok::caret: Opc = BinaryOperator::Xor; break; - case tok::pipe: Opc = BinaryOperator::Or; break; - case tok::ampamp: Opc = BinaryOperator::LAnd; break; - case tok::pipepipe: Opc = BinaryOperator::LOr; break; - case tok::equal: Opc = BinaryOperator::Assign; break; - case tok::starequal: Opc = BinaryOperator::MulAssign; break; - case tok::slashequal: Opc = BinaryOperator::DivAssign; break; - case tok::percentequal: Opc = BinaryOperator::RemAssign; break; - case tok::plusequal: Opc = BinaryOperator::AddAssign; break; - case tok::minusequal: Opc = BinaryOperator::SubAssign; break; - case tok::lesslessequal: Opc = BinaryOperator::ShlAssign; break; - case tok::greatergreaterequal: Opc = BinaryOperator::ShrAssign; break; - case tok::ampequal: Opc = BinaryOperator::AndAssign; break; - case tok::caretequal: Opc = BinaryOperator::XorAssign; break; - case tok::pipeequal: Opc = BinaryOperator::OrAssign; break; - case tok::comma: Opc = BinaryOperator::Comma; break; - } - return Opc; -} - -static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode( - tok::TokenKind Kind) { - UnaryOperator::Opcode Opc; - switch (Kind) { - default: assert(0 && "Unknown unary op!"); - case tok::plusplus: Opc = UnaryOperator::PreInc; break; - case tok::minusminus: Opc = UnaryOperator::PreDec; break; - case tok::amp: Opc = UnaryOperator::AddrOf; break; - case tok::star: Opc = UnaryOperator::Deref; break; - case tok::plus: Opc = UnaryOperator::Plus; break; - case tok::minus: Opc = UnaryOperator::Minus; break; - case tok::tilde: Opc = UnaryOperator::Not; break; - case tok::exclaim: Opc = UnaryOperator::LNot; break; - case tok::kw_sizeof: Opc = UnaryOperator::SizeOf; break; - case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break; - case tok::kw___real: Opc = UnaryOperator::Real; break; - case tok::kw___imag: Opc = UnaryOperator::Imag; break; - case tok::ampamp: Opc = UnaryOperator::AddrLabel; break; - // FIXME: case tok::kw___extension__: - } - return Opc; -} - -// Binary Operators. 'Tok' is the token for the operator. -Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind, - ExprTy *LHS, ExprTy *RHS) { - BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind); - Expr *lhs = (Expr *)LHS, *rhs = (Expr*)RHS; - - assert((lhs != 0) && "ParseBinOp(): missing left expression"); - assert((rhs != 0) && "ParseBinOp(): missing right expression"); - - QualType result; - - switch (Opc) { - default: - assert(0 && "Unknown binary expr!"); - case BinaryOperator::Assign: - result = CheckAssignmentOperands(lhs, rhs, TokLoc, QualType()); - break; - case BinaryOperator::Mul: - case BinaryOperator::Div: - result = CheckMultiplyDivideOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::Rem: - result = CheckRemainderOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::Add: - result = CheckAdditionOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::Sub: - result = CheckSubtractionOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::Shl: - case BinaryOperator::Shr: - result = CheckShiftOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::LE: - case BinaryOperator::LT: - case BinaryOperator::GE: - case BinaryOperator::GT: - result = CheckRelationalOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::EQ: - case BinaryOperator::NE: - result = CheckEqualityOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::And: - case BinaryOperator::Xor: - case BinaryOperator::Or: - result = CheckBitwiseOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::LAnd: - case BinaryOperator::LOr: - result = CheckLogicalOperands(lhs, rhs, TokLoc); - break; - case BinaryOperator::MulAssign: - case BinaryOperator::DivAssign: - result = CheckMultiplyDivideOperands(lhs, rhs, TokLoc); - if (result.isNull()) - return true; - result = CheckAssignmentOperands(lhs, rhs, TokLoc, result); - break; - case BinaryOperator::RemAssign: - result = CheckRemainderOperands(lhs, rhs, TokLoc); - if (result.isNull()) - return true; - result = CheckAssignmentOperands(lhs, rhs, TokLoc, result); - break; - case BinaryOperator::AddAssign: - result = CheckAdditionOperands(lhs, rhs, TokLoc); - if (result.isNull()) - return true; - result = CheckAssignmentOperands(lhs, rhs, TokLoc, result); - break; - case BinaryOperator::SubAssign: - result = CheckSubtractionOperands(lhs, rhs, TokLoc); - if (result.isNull()) - return true; - result = CheckAssignmentOperands(lhs, rhs, TokLoc, result); - break; - case BinaryOperator::ShlAssign: - case BinaryOperator::ShrAssign: - result = CheckShiftOperands(lhs, rhs, TokLoc); - if (result.isNull()) - return true; - result = CheckAssignmentOperands(lhs, rhs, TokLoc, result); - break; - case BinaryOperator::AndAssign: - case BinaryOperator::XorAssign: - case BinaryOperator::OrAssign: - result = CheckBitwiseOperands(lhs, rhs, TokLoc); - if (result.isNull()) - return true; - result = CheckAssignmentOperands(lhs, rhs, TokLoc, result); - break; - case BinaryOperator::Comma: - result = CheckCommaOperands(lhs, rhs, TokLoc); - break; - } - if (result.isNull()) - return true; - return new BinaryOperator(lhs, rhs, Opc, result); -} - -// Unary Operators. 'Tok' is the token for the operator. -Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op, - ExprTy *Input) { - UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op); - QualType resultType; - switch (Opc) { - default: - assert(0 && "Unimplemented unary expr!"); - case UnaryOperator::PreInc: - case UnaryOperator::PreDec: - resultType = CheckIncrementDecrementOperand((Expr *)Input, OpLoc); - break; - case UnaryOperator::AddrOf: - resultType = CheckAddressOfOperand((Expr *)Input, OpLoc); - break; - case UnaryOperator::Deref: - resultType = CheckIndirectionOperand((Expr *)Input, OpLoc); - break; - case UnaryOperator::Plus: - case UnaryOperator::Minus: - resultType = UsualUnaryConversion(((Expr *)Input)->getType()); - if (!resultType->isArithmeticType()) // C99 6.5.3.3p1 - return Diag(OpLoc, diag::err_typecheck_unary_expr, - resultType.getAsString()); - break; - case UnaryOperator::Not: // bitwise complement - resultType = UsualUnaryConversion(((Expr *)Input)->getType()); - if (!resultType->isIntegerType()) // C99 6.5.3.3p1 - return Diag(OpLoc, diag::err_typecheck_unary_expr, - resultType.getAsString()); - break; - case UnaryOperator::LNot: // logical negation - resultType = UsualUnaryConversion(((Expr *)Input)->getType()); - if (!resultType->isScalarType()) // C99 6.5.3.3p1 - return Diag(OpLoc, diag::err_typecheck_unary_expr, - resultType.getAsString()); - break; - case UnaryOperator::SizeOf: - resultType = CheckSizeOfAlignOfOperand(((Expr *)Input)->getType(), OpLoc, - true); - break; - case UnaryOperator::AlignOf: - resultType = CheckSizeOfAlignOfOperand(((Expr *)Input)->getType(), OpLoc, - false); - break; - } - if (resultType.isNull()) - return true; - return new UnaryOperator((Expr *)Input, Opc, resultType, OpLoc); -} diff --git a/clang/AST/SemaExprCXX.cpp b/clang/AST/SemaExprCXX.cpp deleted file mode 100644 index 5b0c17086d5a..000000000000 --- a/clang/AST/SemaExprCXX.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Bill Wendling and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements semantic analysis for C++ expressions. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "clang/AST/ExprCXX.h" -using namespace llvm; -using namespace clang; - -/// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's. -Action::ExprResult -Sema::ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, TypeTy *Ty, - SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, ExprTy *E, - SourceLocation RParenLoc) { - CXXCastExpr::Opcode Op; - - switch (Kind) { - default: assert(0 && "Unknown C++ cast!"); - case tok::kw_const_cast: Op = CXXCastExpr::ConstCast; break; - case tok::kw_dynamic_cast: Op = CXXCastExpr::DynamicCast; break; - case tok::kw_reinterpret_cast: Op = CXXCastExpr::ReinterpretCast; break; - case tok::kw_static_cast: Op = CXXCastExpr::StaticCast; break; - } - - return new CXXCastExpr(Op, QualType::getFromOpaquePtr(Ty), (Expr*)E); -} - -/// ParseCXXBoolLiteral - Parse {true,false} literals. -Action::ExprResult -Sema::ParseCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { - assert((Kind != tok::kw_true || Kind != tok::kw_false) && - "Unknown C++ Boolean value!"); - return new CXXBoolLiteralExpr(Kind == tok::kw_true, OpLoc); -} diff --git a/clang/AST/SemaStmt.cpp b/clang/AST/SemaStmt.cpp deleted file mode 100644 index 99aa1a9e00ee..000000000000 --- a/clang/AST/SemaStmt.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements semantic analysis for statements. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "clang/AST/Stmt.h" -#include "clang/AST/Expr.h" -#include "clang/Parse/Scope.h" -#include "clang/Basic/Diagnostic.h" -using namespace llvm; -using namespace clang; - - -Action::StmtResult -Sema::ParseCompoundStmt(SourceLocation L, SourceLocation R, - StmtTy **Elts, unsigned NumElts) { - return new CompoundStmt((Stmt**)Elts, NumElts); -} - -Action::StmtResult -Sema::ParseCaseStmt(SourceLocation CaseLoc, ExprTy *LHSVal, - SourceLocation DotDotDotLoc, ExprTy *RHSVal, - SourceLocation ColonLoc, StmtTy *SubStmt) { - assert((LHSVal != 0) && "missing expression in case statement"); - - SourceLocation expLoc; - // C99 6.8.4.2p3: The expression shall be an integer constant. - if (!((Expr *)LHSVal)->isIntegerConstantExpr(expLoc)) - return Diag(CaseLoc, diag::err_case_label_not_integer_constant_expr); - - return new CaseStmt((Expr*)LHSVal, (Expr*)RHSVal, (Stmt*)SubStmt); -} - -Action::StmtResult -Sema::ParseDefaultStmt(SourceLocation DefaultLoc, - SourceLocation ColonLoc, StmtTy *SubStmt) { - return new DefaultStmt((Stmt*)SubStmt); -} - -Action::StmtResult -Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, - SourceLocation ColonLoc, StmtTy *SubStmt) { - return new LabelStmt(II, (Stmt*)SubStmt); -} - -Action::StmtResult -Sema::ParseIfStmt(SourceLocation IfLoc, ExprTy *CondVal, - StmtTy *ThenVal, SourceLocation ElseLoc, - StmtTy *ElseVal) { - return new IfStmt((Expr*)CondVal, (Stmt*)ThenVal, (Stmt*)ElseVal); -} -Action::StmtResult -Sema::ParseSwitchStmt(SourceLocation SwitchLoc, ExprTy *Cond, StmtTy *Body) { - return new SwitchStmt((Expr*)Cond, (Stmt*)Body); -} - -Action::StmtResult -Sema::ParseWhileStmt(SourceLocation WhileLoc, ExprTy *Cond, StmtTy *Body){ - return new WhileStmt((Expr*)Cond, (Stmt*)Body); -} - -Action::StmtResult -Sema::ParseDoStmt(SourceLocation DoLoc, StmtTy *Body, - SourceLocation WhileLoc, ExprTy *Cond) { - return new DoStmt((Stmt*)Body, (Expr*)Cond); -} - -Action::StmtResult -Sema::ParseForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtTy *First, ExprTy *Second, ExprTy *Third, - SourceLocation RParenLoc, StmtTy *Body) { - return new ForStmt((Stmt*)First, (Expr*)Second, (Expr*)Third, (Stmt*)Body); -} - - -Action::StmtResult -Sema::ParseGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, - IdentifierInfo *LabelII) { - return new GotoStmt(LabelII); -} -Action::StmtResult -Sema::ParseIndirectGotoStmt(SourceLocation GotoLoc,SourceLocation StarLoc, - ExprTy *DestExp) { - return new IndirectGotoStmt((Expr*)DestExp); -} - -Action::StmtResult -Sema::ParseContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { - Scope *S = CurScope->getContinueParent(); - if (!S) { - // C99 6.8.6.2p1: A break shall appear only in or as a loop body. - Diag(ContinueLoc, diag::err_continue_not_in_loop); - return true; - } - - // FIXME: Remember that this continue goes with this loop. - return new ContinueStmt(); -} - -Action::StmtResult -Sema::ParseBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { - Scope *S = CurScope->getBreakParent(); - if (!S) { - // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body. - Diag(BreakLoc, diag::err_break_not_in_loop_or_switch); - return true; - } - - // FIXME: Remember that this break goes with this loop/switch. - return new BreakStmt(); -} - - -Action::StmtResult -Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) { - return new ReturnStmt((Expr*)RetValExp); -} - diff --git a/clang/AST/SemaType.cpp b/clang/AST/SemaType.cpp deleted file mode 100644 index e353b6d93dab..000000000000 --- a/clang/AST/SemaType.cpp +++ /dev/null @@ -1,242 +0,0 @@ -//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements type-related semantic analysis. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Lex/IdentifierTable.h" -using namespace llvm; -using namespace clang; - -/// ConvertDeclSpecToType - Convert the specified declspec to the appropriate -/// type object. This returns null on error. -static QualType ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) { - // FIXME: Should move the logic from DeclSpec::Finish to here for validity - // checking. - - switch (DS.getTypeSpecType()) { - default: return QualType(); // FIXME: Handle unimp cases! - case DeclSpec::TST_void: return Ctx.VoidTy; - case DeclSpec::TST_char: - if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) - return Ctx.CharTy; - else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) - return Ctx.SignedCharTy; - else { - assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && - "Unknown TSS value"); - return Ctx.UnsignedCharTy; - } - case DeclSpec::TST_int: - if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { - switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_unspecified: return Ctx.IntTy; - case DeclSpec::TSW_short: return Ctx.ShortTy; - case DeclSpec::TSW_long: return Ctx.LongTy; - case DeclSpec::TSW_longlong: return Ctx.LongLongTy; - } - } else { - switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_unspecified: return Ctx.UnsignedIntTy; - case DeclSpec::TSW_short: return Ctx.UnsignedShortTy; - case DeclSpec::TSW_long: return Ctx.UnsignedLongTy; - case DeclSpec::TSW_longlong: return Ctx.UnsignedLongLongTy; - } - } - case DeclSpec::TST_float: - if (DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified) - return Ctx.FloatTy; - assert(DS.getTypeSpecComplex() == DeclSpec::TSC_complex && - "FIXME: imaginary types not supported yet!"); - return Ctx.FloatComplexTy; - - case DeclSpec::TST_double: { - bool isLong = DS.getTypeSpecWidth() == DeclSpec::TSW_long; - if (DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified) - return isLong ? Ctx.LongDoubleTy : Ctx.DoubleTy; - assert(DS.getTypeSpecComplex() == DeclSpec::TSC_complex && - "FIXME: imaginary types not supported yet!"); - return isLong ? Ctx.LongDoubleComplexTy : Ctx.DoubleComplexTy; - } - case DeclSpec::TST_bool: // _Bool or bool - return Ctx.BoolTy; - case DeclSpec::TST_decimal32: // _Decimal32 - case DeclSpec::TST_decimal64: // _Decimal64 - case DeclSpec::TST_decimal128: // _Decimal128 - assert(0 && "FIXME: GNU decimal extensions not supported yet!"); - case DeclSpec::TST_enum: - case DeclSpec::TST_union: - case DeclSpec::TST_struct: { - Decl *D = static_cast(DS.getTypeRep()); - assert(D && "Didn't get a decl for a enum/union/struct?"); - assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && - DS.getTypeSpecSign() == 0 && - "Can't handle qualifiers on typedef names yet!"); - // TypeQuals handled by caller. - return Ctx.getTagDeclType(cast(D)); - } - case DeclSpec::TST_typedef: { - Decl *D = static_cast(DS.getTypeRep()); - assert(D && "Didn't get a decl for a typedef?"); - assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && - DS.getTypeSpecSign() == 0 && - "Can't handle qualifiers on typedef names yet!"); - // TypeQuals handled by caller. - return Ctx.getTypedefType(cast(D)); - } - } -} - -/// GetTypeForDeclarator - Convert the type for the specified declarator to Type -/// instances. -QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { - QualType T = ConvertDeclSpecToType(D.getDeclSpec(), Context); - - // If there was an error parsing declspecs, return a null type pointer. - if (T.isNull()) return T; - - // Apply const/volatile/restrict qualifiers to T. - T = T.getQualifiedType(D.getDeclSpec().getTypeQualifiers()); - - // Walk the DeclTypeInfo, building the recursive type as we go. DeclTypeInfos - // are ordered from the identifier out, which is opposite of what we want :). - for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { - const DeclaratorChunk &DeclType = D.getTypeObject(e-i-1); - switch (DeclType.Kind) { - default: assert(0 && "Unknown decltype!"); - case DeclaratorChunk::Pointer: - T = Context.getPointerType(T); - - // Apply the pointer typequals to the pointer object. - T = T.getQualifiedType(DeclType.Ptr.TypeQuals); - break; - case DeclaratorChunk::Array: { - const DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr; - ArrayType::ArraySizeModifier ASM; - if (ATI.isStar) - ASM = ArrayType::Star; - else if (ATI.hasStatic) - ASM = ArrayType::Static; - else - ASM = ArrayType::Normal; - - Type *CanonicalT = T.getCanonicalType().getTypePtr(); - - // C99 6.7.5.2p1: If the element type is an incomplete or function type, - // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) - if (T->isIncompleteType()) { - Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type, - T.getAsString()); - return QualType(); - } else if (isa(CanonicalT)) { - Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions, - D.getIdentifier()->getName()); - return QualType(); - } else if (RecordType *EltTy = dyn_cast(CanonicalT)) { - // If the element type is a struct or union that contains a variadic - // array, reject it: C99 6.7.2.1p2. - if (EltTy->getDecl()->hasFlexibleArrayMember()) { - Diag(DeclType.Loc, diag::err_flexible_array_in_array, - T.getAsString()); - return QualType(); - } - } - T = Context.getArrayType(T, ASM, ATI.TypeQuals, - static_cast(ATI.NumElts)); - break; - } - case DeclaratorChunk::Function: - // If the function declarator has a prototype (i.e. it is not () and - // does not have a K&R-style identifier list), then the arguments are part - // of the type, otherwise the argument list is (). - const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - if (!FTI.hasPrototype) { - // Simple void foo(), where the incoming T is the result type. - T = Context.getFunctionTypeNoProto(T); - - // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition. - if (FTI.NumArgs != 0) - Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); - - } else { - // Otherwise, we have a function with an argument list that is - // potentially variadic. - SmallVector ArgTys; - - for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { - QualType ArgTy = QualType::getFromOpaquePtr(FTI.ArgInfo[i].TypeInfo); - if (ArgTy.isNull()) - return QualType(); // Error occurred parsing argument type. - - // Look for 'void'. void is allowed only as a single argument to a - // function with no other parameters (C99 6.7.5.3p10). We record - // int(void) as a FunctionTypeProto with an empty argument list. - if (ArgTy->isVoidType()) { - // If this is something like 'float(int, void)', reject it. 'void' - // is an incomplete type (C99 6.2.5p19) and function decls cannot - // have arguments of incomplete type. - if (FTI.NumArgs != 1 || FTI.isVariadic) { - Diag(DeclType.Loc, diag::err_void_only_param); - return QualType(); - } - // Reject, but continue to parse 'int(void abc)'. - if (FTI.ArgInfo[i].Ident) - Diag(FTI.ArgInfo[i].IdentLoc, - diag::err_void_param_with_identifier); - - // Reject, but continue to parse 'float(const void)'. - if (ArgTy.getQualifiers()) - Diag(DeclType.Loc, diag::err_void_param_qualified); - - // Do not add 'void' to the ArgTys list. - break; - } - - ArgTys.push_back(ArgTy); - } - T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(), - FTI.isVariadic); - } - break; - } - } - - return T; -} - -Sema::TypeResult Sema::ParseTypeName(Scope *S, Declarator &D) { - // C99 6.7.6: Type names have no identifier. This is already validated by - // the parser. - assert(D.getIdentifier() == 0 && "Type name should have no identifier!"); - - QualType T = GetTypeForDeclarator(D, S); - - // If the type of the declarator was invalid, this is an invalid typename. - if (T.isNull()) - return true; - - return T.getAsOpaquePtr(); -} - -Sema::TypeResult Sema::ParseParamDeclaratorType(Scope *S, Declarator &D) { - // Note: parameters have identifiers, but we don't care about them here, we - // just want the type converted. - QualType T = GetTypeForDeclarator(D, S); - - // If the type of the declarator was invalid, this is an invalid typename. - if (T.isNull()) - return true; - - return T.getAsOpaquePtr(); -} diff --git a/clang/Driver/Makefile b/clang/Driver/Makefile index 4a01f0ea12eb..f64200ac0e24 100644 --- a/clang/Driver/Makefile +++ b/clang/Driver/Makefile @@ -3,6 +3,6 @@ CPPFLAGS += -I$(PROJ_SRC_DIR)/../include CXXFLAGS = -fno-rtti TOOLNAME = clang -USEDLIBS = clangAST.a clangParse.a clangLex.a clangBasic.a LLVMSupport.a LLVMSystem.a +USEDLIBS = clangSEMA.a clangAST.a clangParse.a clangLex.a clangBasic.a LLVMSupport.a LLVMSystem.a include $(LEVEL)/Makefile.common diff --git a/clang/Makefile b/clang/Makefile index 593e8e681e5a..8b8510d12d9f 100644 --- a/clang/Makefile +++ b/clang/Makefile @@ -1,5 +1,5 @@ LEVEL = ../.. -DIRS := Basic Lex Parse AST Driver +DIRS := Basic Lex Parse AST Sema Driver include $(LEVEL)/Makefile.common diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 12a91340e076..f35a0bd6c688 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -20,9 +20,7 @@ DE1733000B068B700080B521 /* ASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1732FF0B068B700080B521 /* ASTContext.cpp */; }; DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE17336D0B068DC20080B521 /* DeclSpec.cpp */; }; DE1733700B068DC60080B521 /* DeclSpec.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE17336F0B068DC60080B521 /* DeclSpec.h */; }; - DE1737A90B0847BC0080B521 /* SemaType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1737A80B0847BC0080B521 /* SemaType.cpp */; }; DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; }; - DE2E60610B04461800F3FAFE /* SemaExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE2E60600B04461800F3FAFE /* SemaExpr.cpp */; }; DE344AB80AE5DF6D00DBC861 /* HeaderSearch.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE344AB70AE5DF6D00DBC861 /* HeaderSearch.h */; }; DE344B540AE5E46C00DBC861 /* HeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */; }; DE3450D70AEB543100DBC861 /* DirectoryLookup.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3450D60AEB543100DBC861 /* DirectoryLookup.h */; }; @@ -39,23 +37,26 @@ DE3460130AFDCCDA00DBC861 /* ParseExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */; }; DE3461270AFE68BE00DBC861 /* MinimalAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */; }; DE34621D0AFEB19B00DBC861 /* StmtPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */; }; - DE3463400B02F0F800DBC861 /* SemaDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34633F0B02F0F800DBC861 /* SemaDecl.cpp */; }; DE3464220B03040900DBC861 /* Type.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3464210B03040900DBC861 /* Type.h */; }; - DE34644C0B043E0000DBC861 /* Sema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34644B0B043E0000DBC861 /* Sema.cpp */; }; - DE34646E0B043E5B00DBC861 /* Sema.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE34646D0B043E5B00DBC861 /* Sema.h */; }; DE46BF280AE0A82D00CC047C /* TargetInfo.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE46BF270AE0A82D00CC047C /* TargetInfo.h */; }; DE5932D10AD60FF400BC794C /* clang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5932CD0AD60FF400BC794C /* clang.cpp */; }; DE5932D20AD60FF400BC794C /* clang.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE5932CE0AD60FF400BC794C /* clang.h */; }; DE5932D30AD60FF400BC794C /* PrintParserCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5932CF0AD60FF400BC794C /* PrintParserCallbacks.cpp */; }; DE5932D40AD60FF400BC794C /* PrintPreprocessedOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE5932D00AD60FF400BC794C /* PrintPreprocessedOutput.cpp */; }; - DE75ED190B0446470020CF81 /* SemaStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE75ED180B0446470020CF81 /* SemaStmt.cpp */; }; + DE67E70B0C020EC500F66BC5 /* SemaType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E70A0C020EC500F66BC5 /* SemaType.cpp */; }; + DE67E70D0C020ECA00F66BC5 /* SemaStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */; }; + DE67E70F0C020ECF00F66BC5 /* SemaExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */; }; + DE67E7110C020ED400F66BC5 /* SemaExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */; }; + DE67E7130C020ED900F66BC5 /* SemaDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */; }; + DE67E7150C020EDF00F66BC5 /* Sema.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE67E7140C020EDF00F66BC5 /* Sema.h */; }; + DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7160C020EE400F66BC5 /* Sema.cpp */; }; + DE67E71A0C020F4F00F66BC5 /* ASTStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */; }; DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE75ED280B044DC90020CF81 /* ASTContext.h */; }; DE75EDF10B06880E0020CF81 /* Type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE75EDF00B06880E0020CF81 /* Type.cpp */; }; DEAEE98B0A5A2B970045101B /* MultipleIncludeOpt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */; }; DEAEED4B0A5AF89A0045101B /* NOTES.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEED4A0A5AF89A0045101B /* NOTES.txt */; }; DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9900A9433CD00353FCA /* Decl.h */; }; DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9A30A94346E00353FCA /* AST.h */; }; - DEC8DAAD0A94400300353FCA /* ASTStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEC8DAAC0A94400300353FCA /* ASTStreamer.cpp */; }; DEC8DAC00A94402500353FCA /* ASTStreamer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8DABF0A94402500353FCA /* ASTStreamer.h */; }; DED626C90AE0C065001E80A4 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED626C80AE0C065001E80A4 /* TargetInfo.cpp */; }; DED627030AE0C51D001E80A4 /* Targets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED627020AE0C51D001E80A4 /* Targets.cpp */; }; @@ -135,7 +136,6 @@ DE345C1A0AFC658B00DBC861 /* StmtVisitor.h in CopyFiles */, DE345F220AFD347900DBC861 /* StmtNodes.def in CopyFiles */, DE3464220B03040900DBC861 /* Type.h in CopyFiles */, - DE34646E0B043E5B00DBC861 /* Sema.h in CopyFiles */, DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */, DE1733700B068DC60080B521 /* DeclSpec.h in CopyFiles */, DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */, @@ -145,6 +145,7 @@ DED67AF00B6DB92F00AAD4A3 /* PPCBuiltins.def in CopyFiles */, 1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */, 1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */, + DE67E7150C020EDF00F66BC5 /* Sema.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -165,9 +166,7 @@ DE1732FF0B068B700080B521 /* ASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTContext.cpp; path = AST/ASTContext.cpp; sourceTree = ""; }; DE17336D0B068DC20080B521 /* DeclSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DeclSpec.cpp; path = Parse/DeclSpec.cpp; sourceTree = ""; }; DE17336F0B068DC60080B521 /* DeclSpec.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DeclSpec.h; path = clang/Parse/DeclSpec.h; sourceTree = ""; }; - DE1737A80B0847BC0080B521 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = AST/SemaType.cpp; sourceTree = ""; }; DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = ""; }; - DE2E60600B04461800F3FAFE /* SemaExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExpr.cpp; path = AST/SemaExpr.cpp; sourceTree = ""; }; DE344AB70AE5DF6D00DBC861 /* HeaderSearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HeaderSearch.h; sourceTree = ""; }; DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HeaderSearch.cpp; sourceTree = ""; }; DE3450D60AEB543100DBC861 /* DirectoryLookup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DirectoryLookup.h; sourceTree = ""; }; @@ -184,23 +183,26 @@ DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExpr.cpp; path = Parse/ParseExpr.cpp; sourceTree = ""; }; DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = MinimalAction.cpp; path = Parse/MinimalAction.cpp; sourceTree = ""; }; DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = StmtPrinter.cpp; path = AST/StmtPrinter.cpp; sourceTree = ""; }; - DE34633F0B02F0F800DBC861 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = AST/SemaDecl.cpp; sourceTree = ""; }; DE3464210B03040900DBC861 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Type.h; path = clang/AST/Type.h; sourceTree = ""; }; - DE34644B0B043E0000DBC861 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = AST/Sema.cpp; sourceTree = ""; }; - DE34646D0B043E5B00DBC861 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = AST/Sema.h; sourceTree = ""; }; DE46BF270AE0A82D00CC047C /* TargetInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetInfo.h; sourceTree = ""; }; DE5932CD0AD60FF400BC794C /* clang.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = clang.cpp; path = Driver/clang.cpp; sourceTree = ""; }; DE5932CE0AD60FF400BC794C /* clang.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = clang.h; path = Driver/clang.h; sourceTree = ""; }; DE5932CF0AD60FF400BC794C /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = Driver/PrintParserCallbacks.cpp; sourceTree = ""; }; DE5932D00AD60FF400BC794C /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = Driver/PrintPreprocessedOutput.cpp; sourceTree = ""; }; - DE75ED180B0446470020CF81 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = AST/SemaStmt.cpp; sourceTree = ""; }; + DE67E70A0C020EC500F66BC5 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = Sema/SemaType.cpp; sourceTree = ""; }; + DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = Sema/SemaStmt.cpp; sourceTree = ""; }; + DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprCXX.cpp; path = Sema/SemaExprCXX.cpp; sourceTree = ""; }; + DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExpr.cpp; path = Sema/SemaExpr.cpp; sourceTree = ""; }; + DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = Sema/SemaDecl.cpp; sourceTree = ""; }; + DE67E7140C020EDF00F66BC5 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = Sema/Sema.h; sourceTree = ""; }; + DE67E7160C020EE400F66BC5 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = Sema/Sema.cpp; sourceTree = ""; }; + DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = Sema/ASTStreamer.cpp; sourceTree = ""; }; DE75ED280B044DC90020CF81 /* ASTContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTContext.h; path = clang/AST/ASTContext.h; sourceTree = ""; }; DE75EDF00B06880E0020CF81 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = AST/Type.cpp; sourceTree = ""; }; DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = ""; }; DEAEED4A0A5AF89A0045101B /* NOTES.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = NOTES.txt; sourceTree = ""; }; DEC8D9900A9433CD00353FCA /* Decl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Decl.h; path = clang/AST/Decl.h; sourceTree = ""; }; DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = ""; }; - DEC8DAAC0A94400300353FCA /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = AST/ASTStreamer.cpp; sourceTree = ""; }; DEC8DABF0A94402500353FCA /* ASTStreamer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTStreamer.h; path = clang/AST/ASTStreamer.h; sourceTree = ""; }; DED626C80AE0C065001E80A4 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInfo.cpp; sourceTree = ""; }; DED627020AE0C51D001E80A4 /* Targets.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Targets.cpp; path = Driver/Targets.cpp; sourceTree = ""; }; @@ -269,6 +271,7 @@ DED7D78C0A5242E6003AD0FB /* Lex */, DE1F22600A7D8C9B00FBF588 /* Parse */, DEC8D9920A9433F400353FCA /* AST */, + DE67E7070C020EAB00F66BC5 /* Sema */, ); name = Source; sourceTree = ""; @@ -316,6 +319,21 @@ name = Parse; sourceTree = ""; }; + DE67E7070C020EAB00F66BC5 /* Sema */ = { + isa = PBXGroup; + children = ( + DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */, + DE67E7140C020EDF00F66BC5 /* Sema.h */, + DE67E7160C020EE400F66BC5 /* Sema.cpp */, + DE67E70A0C020EC500F66BC5 /* SemaType.cpp */, + DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */, + DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */, + DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */, + DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */, + ); + name = Sema; + sourceTree = ""; + }; DEAEECAE0A5AF0FA0045101B /* Driver */ = { isa = PBXGroup; children = ( @@ -353,18 +371,11 @@ isa = PBXGroup; children = ( DE1732FF0B068B700080B521 /* ASTContext.cpp */, - DEC8DAAC0A94400300353FCA /* ASTStreamer.cpp */, DED677C80B6C854100AAD4A3 /* Builtins.cpp */, DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */, DE0FCB330A9C21F100248FD5 /* Expr.cpp */, DE3452400AEF1A2D00DBC861 /* Stmt.cpp */, DE75EDF00B06880E0020CF81 /* Type.cpp */, - DE34646D0B043E5B00DBC861 /* Sema.h */, - DE34644B0B043E0000DBC861 /* Sema.cpp */, - DE34633F0B02F0F800DBC861 /* SemaDecl.cpp */, - DE2E60600B04461800F3FAFE /* SemaExpr.cpp */, - DE75ED180B0446470020CF81 /* SemaStmt.cpp */, - DE1737A80B0847BC0080B521 /* SemaType.cpp */, DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */, DE345C560AFC69E800DBC861 /* StmtVisitor.cpp */, ); @@ -502,7 +513,6 @@ DED7D7C90A5242E6003AD0FB /* Preprocessor.cpp in Sources */, DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */, DE06D4310A8BB52D0050E87E /* Parser.cpp in Sources */, - DEC8DAAD0A94400300353FCA /* ASTStreamer.cpp in Sources */, DE0FCB340A9C21F100248FD5 /* Expr.cpp in Sources */, DE5932D10AD60FF400BC794C /* clang.cpp in Sources */, DE5932D30AD60FF400BC794C /* PrintParserCallbacks.cpp in Sources */, @@ -521,16 +531,18 @@ DE3460130AFDCCDA00DBC861 /* ParseExpr.cpp in Sources */, DE3461270AFE68BE00DBC861 /* MinimalAction.cpp in Sources */, DE34621D0AFEB19B00DBC861 /* StmtPrinter.cpp in Sources */, - DE3463400B02F0F800DBC861 /* SemaDecl.cpp in Sources */, - DE34644C0B043E0000DBC861 /* Sema.cpp in Sources */, - DE2E60610B04461800F3FAFE /* SemaExpr.cpp in Sources */, - DE75ED190B0446470020CF81 /* SemaStmt.cpp in Sources */, DE75EDF10B06880E0020CF81 /* Type.cpp in Sources */, DE1733000B068B700080B521 /* ASTContext.cpp in Sources */, DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */, - DE1737A90B0847BC0080B521 /* SemaType.cpp in Sources */, DED677C90B6C854100AAD4A3 /* Builtins.cpp in Sources */, 1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */, + DE67E70B0C020EC500F66BC5 /* SemaType.cpp in Sources */, + DE67E70D0C020ECA00F66BC5 /* SemaStmt.cpp in Sources */, + DE67E70F0C020ECF00F66BC5 /* SemaExprCXX.cpp in Sources */, + DE67E7110C020ED400F66BC5 /* SemaExpr.cpp in Sources */, + DE67E7130C020ED900F66BC5 /* SemaDecl.cpp in Sources */, + DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */, + DE67E71A0C020F4F00F66BC5 /* ASTStreamer.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };