Split the AST library into two libraries: libast and libsema.
llvm-svn: 39477
This commit is contained in:
		
							parent
							
								
									e6b0f626bb
								
							
						
					
					
						commit
						d1654ef0ed
					
				| 
						 | 
				
			
			@ -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<Decl*> 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<Decl*>(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<Decl*>(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<ASTStreamer*>(Streamer)->ReadTopLevelDecl();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// ASTStreamer_PrintStats - Emit statistic information to stderr.
 | 
			
		||||
///
 | 
			
		||||
void llvm::clang::ASTStreamer_PrintStats(ASTStreamerTy *Streamer) {
 | 
			
		||||
  return static_cast<ASTStreamer*>(Streamer)->PrintStats();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// ASTStreamer_Terminate - Gracefully shut down the streamer.
 | 
			
		||||
///
 | 
			
		||||
void llvm::clang::ASTStreamer_Terminate(ASTStreamerTy *Streamer) {
 | 
			
		||||
  delete static_cast<ASTStreamer*>(Streamer);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<Decl*> &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();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										311
									
								
								clang/AST/Sema.h
								
								
								
								
							
							
						
						
									
										311
									
								
								clang/AST/Sema.h
								
								
								
								
							| 
						 | 
				
			
			@ -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 <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
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<Decl*> &LastInGroupList;
 | 
			
		||||
public:
 | 
			
		||||
  Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &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
 | 
			
		||||
| 
						 | 
				
			
			@ -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<TypedefDecl>(II.getFETokenInfo<Decl>());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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<Decl*>(*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<Decl>() == 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<Decl>();
 | 
			
		||||
      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<Decl>(); 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<Decl>()) {
 | 
			
		||||
    // 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<TypedefDecl>(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<FunctionDecl>(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<VarDecl>(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<ArrayType>(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<ArrayType>(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<ArrayType>(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<Decl>());
 | 
			
		||||
    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<Decl>());
 | 
			
		||||
    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<FunctionDecl*>(ParseDeclarator(GlobalScope, D, 0, 0));
 | 
			
		||||
  CurFunctionDecl = FD;
 | 
			
		||||
  
 | 
			
		||||
  // Create Decl objects for each parameter, adding them to the FunctionDecl.
 | 
			
		||||
  SmallVector<VarDecl*, 16> 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<FunctionDecl*>(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<Decl*>(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<TagDecl>(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<Decl>());
 | 
			
		||||
    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<ArrayType>(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<RecordDecl>(static_cast<Decl*>(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<FieldDecl*, 32> RecFields;
 | 
			
		||||
  SmallSet<const IdentifierInfo*, 32> FieldIDs;
 | 
			
		||||
  
 | 
			
		||||
  for (unsigned i = 0; i != NumFields; ++i) {
 | 
			
		||||
    FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(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<FunctionType>(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<ArrayType>(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<RecordType>(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<EnumDecl>(static_cast<Decl*>(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<EnumConstantDecl>(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<Decl>());
 | 
			
		||||
  Id->setFETokenInfo(New);
 | 
			
		||||
  S->AddDecl(New);
 | 
			
		||||
  return New;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
 | 
			
		||||
                         DeclTy **Elements, unsigned NumElements) {
 | 
			
		||||
  EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
 | 
			
		||||
  assert(!Enum->isDefinition() && "Enum redefinitions can't reach here");
 | 
			
		||||
  
 | 
			
		||||
  // Verify that all the values are okay.
 | 
			
		||||
  SmallVector<EnumConstantDecl*, 32> Values;
 | 
			
		||||
  for (unsigned i = 0; i != NumElements; ++i) {
 | 
			
		||||
    EnumConstantDecl *ECD =
 | 
			
		||||
      cast_or_null<EnumConstantDecl>(static_cast<Decl*>(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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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<Decl *>(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<TagDecl>(D));
 | 
			
		||||
  }    
 | 
			
		||||
  case DeclSpec::TST_typedef: {
 | 
			
		||||
    Decl *D = static_cast<Decl *>(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<TypedefDecl>(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<FunctionType>(CanonicalT)) {
 | 
			
		||||
        Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_of_functions,
 | 
			
		||||
             D.getIdentifier()->getName());
 | 
			
		||||
        return QualType();
 | 
			
		||||
      } else if (RecordType *EltTy = dyn_cast<RecordType>(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<Expr *>(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<QualType, 16> 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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
LEVEL = ../..
 | 
			
		||||
DIRS := Basic Lex Parse AST Driver
 | 
			
		||||
DIRS := Basic Lex Parse AST Sema Driver
 | 
			
		||||
 | 
			
		||||
include $(LEVEL)/Makefile.common
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = "<group>"; };
 | 
			
		||||
		DE17336D0B068DC20080B521 /* DeclSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DeclSpec.cpp; path = Parse/DeclSpec.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE17336F0B068DC60080B521 /* DeclSpec.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DeclSpec.h; path = clang/Parse/DeclSpec.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE1737A80B0847BC0080B521 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = AST/SemaType.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE2E60600B04461800F3FAFE /* SemaExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExpr.cpp; path = AST/SemaExpr.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE344AB70AE5DF6D00DBC861 /* HeaderSearch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HeaderSearch.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HeaderSearch.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE3450D60AEB543100DBC861 /* DirectoryLookup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DirectoryLookup.h; sourceTree = "<group>"; };
 | 
			
		||||
| 
						 | 
				
			
			@ -184,23 +183,26 @@
 | 
			
		|||
		DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExpr.cpp; path = Parse/ParseExpr.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = MinimalAction.cpp; path = Parse/MinimalAction.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = StmtPrinter.cpp; path = AST/StmtPrinter.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE34633F0B02F0F800DBC861 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = AST/SemaDecl.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE3464210B03040900DBC861 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Type.h; path = clang/AST/Type.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE34644B0B043E0000DBC861 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = AST/Sema.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE34646D0B043E5B00DBC861 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = AST/Sema.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE46BF270AE0A82D00CC047C /* TargetInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetInfo.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE5932CD0AD60FF400BC794C /* clang.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = clang.cpp; path = Driver/clang.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE5932CE0AD60FF400BC794C /* clang.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = clang.h; path = Driver/clang.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE5932CF0AD60FF400BC794C /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = Driver/PrintParserCallbacks.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE5932D00AD60FF400BC794C /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = Driver/PrintPreprocessedOutput.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE75ED180B0446470020CF81 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = AST/SemaStmt.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E70A0C020EC500F66BC5 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = Sema/SemaType.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = Sema/SemaStmt.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprCXX.cpp; path = Sema/SemaExprCXX.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExpr.cpp; path = Sema/SemaExpr.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = Sema/SemaDecl.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E7140C020EDF00F66BC5 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = Sema/Sema.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E7160C020EE400F66BC5 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = Sema/Sema.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = Sema/ASTStreamer.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DE75ED280B044DC90020CF81 /* ASTContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTContext.h; path = clang/AST/ASTContext.h; sourceTree = "<group>"; };
 | 
			
		||||
		DE75EDF00B06880E0020CF81 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = AST/Type.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = "<group>"; };
 | 
			
		||||
		DEAEED4A0A5AF89A0045101B /* NOTES.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = NOTES.txt; sourceTree = "<group>"; };
 | 
			
		||||
		DEC8D9900A9433CD00353FCA /* Decl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Decl.h; path = clang/AST/Decl.h; sourceTree = "<group>"; };
 | 
			
		||||
		DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = "<group>"; };
 | 
			
		||||
		DEC8DAAC0A94400300353FCA /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = AST/ASTStreamer.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DEC8DABF0A94402500353FCA /* ASTStreamer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTStreamer.h; path = clang/AST/ASTStreamer.h; sourceTree = "<group>"; };
 | 
			
		||||
		DED626C80AE0C065001E80A4 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInfo.cpp; sourceTree = "<group>"; };
 | 
			
		||||
		DED627020AE0C51D001E80A4 /* Targets.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Targets.cpp; path = Driver/Targets.cpp; sourceTree = "<group>"; };
 | 
			
		||||
| 
						 | 
				
			
			@ -269,6 +271,7 @@
 | 
			
		|||
				DED7D78C0A5242E6003AD0FB /* Lex */,
 | 
			
		||||
				DE1F22600A7D8C9B00FBF588 /* Parse */,
 | 
			
		||||
				DEC8D9920A9433F400353FCA /* AST */,
 | 
			
		||||
				DE67E7070C020EAB00F66BC5 /* Sema */,
 | 
			
		||||
			);
 | 
			
		||||
			name = Source;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
| 
						 | 
				
			
			@ -316,6 +319,21 @@
 | 
			
		|||
			name = Parse;
 | 
			
		||||
			sourceTree = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
		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 = "<group>";
 | 
			
		||||
		};
 | 
			
		||||
		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;
 | 
			
		||||
		};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue