├── .gitignore ├── LICENSE.TXT ├── Makefile ├── README.txt ├── include ├── Makefile └── flang │ ├── AST │ ├── ASTContext.h │ ├── Decl.h │ ├── DeclContextInternals.h │ ├── DeclGroup.h │ ├── DeclarationName.h │ ├── Expr.h │ ├── FormatSpec.h │ ├── Makefile │ ├── Rename.h │ ├── Stmt.h │ ├── StmtDumper.h │ └── Type.h │ ├── Basic │ ├── DeclNodes.td │ ├── Diagnostic.h │ ├── Diagnostic.td │ ├── DiagnosticCommonKinds.td │ ├── DiagnosticLexKinds.td │ ├── DiagnosticParseKinds.td │ ├── IdentifierTable.h │ ├── LLVM.h │ ├── LangOptions.h │ ├── Makefile │ ├── SourceLocation.h │ ├── Specifiers.h │ ├── Token.h │ ├── TokenKinds.def │ └── TokenKinds.h │ ├── Frontend │ └── TextDiagnosticPrinter.h │ ├── Makefile │ ├── Parse │ ├── Lexer.h │ └── Parser.h │ └── Sema │ ├── DeclSpec.h │ ├── Ownership.h │ ├── Scope.h │ └── Sema.h ├── lib ├── AST │ ├── ASTContext.cpp │ ├── Decl.cpp │ ├── DeclGroup.cpp │ ├── DeclarationName.cpp │ ├── Expr.cpp │ ├── FormatSpec.cpp │ ├── Makefile │ ├── Stmt.cpp │ ├── StmtDumper.cpp │ └── Type.cpp ├── Basic │ ├── Diagnostic.cpp │ ├── IdentifierTable.cpp │ ├── Makefile │ ├── Token.cpp │ └── TokenKinds.cpp ├── Frontend │ ├── Makefile │ └── TextDiagnosticPrinter.cpp ├── Makefile ├── Parse │ ├── Lexer.cpp │ ├── Makefile │ ├── ParseDecl.cpp │ ├── ParseExec.cpp │ ├── ParseExpr.cpp │ └── Parser.cpp └── Sema │ ├── DeclSpec.cpp │ ├── Makefile │ ├── Scope.cpp │ └── Sema.cpp ├── test ├── Lexer │ └── torture.f95 ├── Makefile ├── Parser │ ├── empty.f95 │ ├── hello_world.f95 │ └── minimal.f95 ├── TestRunner.sh ├── lit.cfg └── lit.site.cfg.in └── tools ├── Makefile └── driver ├── Info.plist.in ├── Main.cpp └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | #==============================================================================# 2 | # This file specifies intentionally untracked files that git should ignore. 3 | # See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html 4 | # 5 | # This file is intentionally different from the output of `git svn show-ignore`, 6 | # as most of those are useless. 7 | #==============================================================================# 8 | 9 | #==============================================================================# 10 | # File extensions to be ignored anywhere in the tree. 11 | #==============================================================================# 12 | # Temp files created by most text editors. 13 | *~ 14 | # Merge files created by git. 15 | *.orig 16 | # Byte compiled python modules. 17 | *.pyc 18 | # vim swap files 19 | .*.swp 20 | 21 | #==============================================================================# 22 | # Explicit files to ignore (only matches one). 23 | #==============================================================================# 24 | cscope.files 25 | cscope.out 26 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | LLVM Release License 3 | ============================================================================== 4 | University of Illinois/NCSA 5 | Open Source License 6 | 7 | Copyright (c) 2011 University of Illinois at Urbana-Champaign. 8 | All rights reserved. 9 | 10 | Developed by: 11 | 12 | LLVM Team 13 | 14 | University of Illinois at Urbana-Champaign 15 | 16 | http://llvm.org 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy of 19 | this software and associated documentation files (the "Software"), to deal with 20 | the Software without restriction, including without limitation the rights to 21 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 22 | of the Software, and to permit persons to whom the Software is furnished to do 23 | so, subject to the following conditions: 24 | 25 | * Redistributions of source code must retain the above copyright notice, 26 | this list of conditions and the following disclaimers. 27 | 28 | * Redistributions in binary form must reproduce the above copyright notice, 29 | this list of conditions and the following disclaimers in the 30 | documentation and/or other materials provided with the distribution. 31 | 32 | * Neither the names of the LLVM Team, University of Illinois at 33 | Urbana-Champaign, nor the names of its contributors may be used to 34 | endorse or promote products derived from this Software without specific 35 | prior written permission. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 39 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 43 | SOFTWARE. 44 | 45 | ============================================================================== 46 | The LLVM software contains code written by third parties. Such software will 47 | have its own individual LICENSE.TXT file in the directory in which it appears. 48 | This file will describe the copyrights, license, and restrictions which apply 49 | to that code. 50 | 51 | The disclaimer of warranty in the University of Illinois Open Source License 52 | applies to all code in the LLVM Distribution, and nothing in any of the 53 | other licenses gives permission to use the names of the LLVM Team or the 54 | University of Illinois to endorse or promote products derived from this 55 | Software. 56 | 57 | The following pieces of software have additional or alternate copyrights, 58 | licenses, and/or restrictions: 59 | 60 | Program Directory 61 | ------- --------- 62 | 63 | 64 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ##===- Makefile --------------------------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | # If FLANG_LEVEL is not set, then we are the top-level Makefile. Otherwise, we 11 | # are being included from a subdirectory makefile. 12 | 13 | ifndef FLANG_LEVEL 14 | 15 | IS_TOP_LEVEL := 1 16 | FLANG_LEVEL := . 17 | DIRS := include lib tools 18 | 19 | PARALLEL_DIRS := 20 | 21 | endif 22 | 23 | ifeq ($(MAKECMDGOALS),libs-only) 24 | DIRS := $(filter-out tools docs, $(DIRS)) 25 | OPTIONAL_DIRS := 26 | endif 27 | 28 | ### 29 | # Common Makefile code, shared by all Flang Makefiles. 30 | 31 | # Set LLVM source root level. 32 | LEVEL := $(FLANG_LEVEL)/../.. 33 | 34 | # Include LLVM common makefile. 35 | include $(LEVEL)/Makefile.common 36 | 37 | ifneq ($(ENABLE_DOCS),1) 38 | DIRS := $(filter-out docs, $(DIRS)) 39 | endif 40 | 41 | # Set common Flang build flags. 42 | CPP.Flags += -I$(PROJ_SRC_DIR)/$(FLANG_LEVEL)/include -I$(PROJ_OBJ_DIR)/$(FLANG_LEVEL)/include 43 | ifdef FLANG_VENDOR 44 | CPP.Flags += -DFLANG_VENDOR='"$(FLANG_VENDOR) "' 45 | endif 46 | 47 | # Disable -fstrict-aliasing. Darwin disables it by default (and LLVM doesn't 48 | # work with it enabled with GCC), Flang/llvm-gc don't support it yet, and newer 49 | # GCC's have false positive warnings with it on Linux (which prove a pain to 50 | # fix). For example: 51 | # 52 | # http://gcc.gnu.org/PR41874 53 | # http://gcc.gnu.org/PR41838 54 | # 55 | # We can revisit this when LLVM/Flang support it. 56 | CXX.Flags += -fno-strict-aliasing 57 | 58 | # Set up Clang's tblgen. 59 | ifndef CLANG_TBLGEN 60 | ifeq ($(LLVM_CROSS_COMPILING),1) 61 | CLANG_TBLGEN := $(BuildLLVMToolDir)/clang-tblgen$(BUILD_EXEEXT) 62 | else 63 | CLANG_TBLGEN := $(LLVMToolDir)/clang-tblgen$(EXEEXT) 64 | endif 65 | endif 66 | ClangTableGen = $(CLANG_TBLGEN) $(TableGen.Flags) 67 | 68 | ### 69 | # Flang Top Level specific stuff. 70 | 71 | ifeq ($(IS_TOP_LEVEL),1) 72 | 73 | ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) 74 | $(RecursiveTargets):: 75 | $(Verb) if [ ! -f test/Makefile ]; then \ 76 | $(MKDIR) test; \ 77 | $(CP) $(PROJ_SRC_DIR)/test/Makefile test/Makefile; \ 78 | fi 79 | endif 80 | 81 | test:: 82 | @ $(MAKE) -C test 83 | 84 | report:: 85 | @ $(MAKE) -C test report 86 | 87 | clean:: 88 | @ $(MAKE) -C test clean 89 | 90 | libs-only: all 91 | 92 | tags:: 93 | $(Verb) etags `find . -type f -name '*.h' -or -name '*.cpp' | \ 94 | grep -v /lib/Headers | grep -v /test/` 95 | 96 | cscope.files: 97 | find lib include -name '*.cpp' \ 98 | -or -name '*.def' \ 99 | -or -name '*.td' \ 100 | -or -name '*.h' > cscope.files 101 | 102 | .PHONY: test report clean cscope.files 103 | 104 | endif 105 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Fortran Language Family Front-end 3 | //===----------------------------------------------------------------------===// 4 | 5 | flang: 6 | n. 1. A miner's two-pointed pick. 7 | 8 | Flang is a Fortran front-end. 9 | 10 | //===----------------------------------------------------------------------===// 11 | // To Do List 12 | //===----------------------------------------------------------------------===// 13 | 14 | Short term: 15 | 16 | * Fix lexing bugs 17 | - Continuations in BOZ and character literals 18 | - Others 19 | * Support 'INCLUDE' statement 20 | * Full parsing of statements 21 | * Clang-style diagnostics 22 | - Warnings and notes 23 | - Ranges for errors (i.e. ^~~~~~ ) 24 | * Testing infrastructure 25 | 26 | Long term: 27 | 28 | * Flang driver (?) 29 | * Parsing GNU modules 30 | * Sema 31 | * Code generation 32 | * Builtin functions 33 | 34 | Longer term: 35 | 36 | * Fortran77 support 37 | -------------------------------------------------------------------------------- /include/Makefile: -------------------------------------------------------------------------------- 1 | FLANG_LEVEL := .. 2 | DIRS := flang 3 | 4 | include $(FLANG_LEVEL)/Makefile 5 | -------------------------------------------------------------------------------- /include/flang/AST/ASTContext.h: -------------------------------------------------------------------------------- 1 | //===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the ASTContext interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_AST_ASTCONTEXT_H__ 15 | #define FLANG_AST_ASTCONTEXT_H__ 16 | 17 | #include "flang/AST/Decl.h" 18 | #include "flang/AST/Type.h" 19 | #include "llvm/ADT/FoldingSet.h" 20 | #include "llvm/Support/Allocator.h" 21 | #include "llvm/Support/SourceMgr.h" 22 | #include 23 | #include 24 | #include 25 | 26 | namespace llvm { 27 | template class ArrayRef; 28 | } // end llvm namespace 29 | 30 | namespace flang { 31 | 32 | class StoredDeclsMap; 33 | 34 | // Decls 35 | class DeclContext; 36 | class Decl; 37 | class RecordDecl; 38 | class TypeDecl; 39 | 40 | class ASTContext { 41 | ASTContext &this_() { return *this; } 42 | 43 | mutable std::vector Types; 44 | mutable llvm::FoldingSet ExtQualNodes; 45 | mutable llvm::FoldingSet PointerTypes; 46 | mutable llvm::FoldingSet ArrayTypes; 47 | mutable llvm::FoldingSet RecordTypes; 48 | 49 | /// \brief The allocator used to create AST objects. 50 | /// 51 | /// AST objects are never destructed; rather, all memory associated with the 52 | /// AST objects will be released when the ASTContext itself is destroyed. 53 | mutable llvm::BumpPtrAllocator BumpAlloc; 54 | 55 | TranslationUnitDecl *TUDecl; 56 | 57 | /// SrcMgr - The associated SourceMgr object. 58 | llvm::SourceMgr &SrcMgr; 59 | 60 | //===--------------------------------------------------------------------===// 61 | // Type Constructors 62 | //===--------------------------------------------------------------------===// 63 | 64 | public: 65 | /// getExtQualType - Return a type with extended qualifiers. 66 | QualType getExtQualType(const Type *Base, Qualifiers Quals, 67 | Expr *KindSel, Expr *LenSel) const; 68 | private: 69 | QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const; 70 | 71 | void InitBuiltinTypes(); 72 | void InitBuiltinType(QualType &R, BuiltinType::TypeSpec K); 73 | 74 | public: 75 | ASTContext(llvm::SourceMgr &SM); 76 | ~ASTContext(); 77 | 78 | TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } 79 | 80 | llvm::SourceMgr &getSourceManager() { return SrcMgr; } 81 | const llvm::SourceMgr &getSourceManager() const { return SrcMgr; } 82 | 83 | void *Allocate(unsigned Size, unsigned Align = 8) const { 84 | return BumpAlloc.Allocate(Size, Align); 85 | } 86 | void Deallocate(void *Ptr) const { 87 | BumpAlloc.Deallocate(Ptr); 88 | } 89 | 90 | // Builtin Types: [R404] 91 | QualType IntegerTy; 92 | QualType RealTy; 93 | QualType DoublePrecisionTy; 94 | QualType CharacterTy; 95 | QualType LogicalTy; 96 | QualType ComplexTy; 97 | 98 | /// getBuiltinQualType - Return the QualType for the specified builtin type. 99 | QualType getBuiltinQualType(BuiltinType::TypeSpec TS) const; 100 | 101 | /// getPointerType - Return the uniqued reference to the type for a pointer to 102 | /// the specified type. 103 | PointerType *getPointerType(const Type *Ty, unsigned NumDims); 104 | 105 | /// getArrayType - Return the unique reference to the type for an array of the 106 | /// specified element type. 107 | QualType getArrayType(QualType EltTy, ArrayRef Dims) const; 108 | 109 | /// getRecordType - Return the uniqued reference to the type for a structure 110 | /// of the specified type. 111 | QualType getRecordType(const RecordDecl *Decl) const; 112 | 113 | /// getTypeDeclType - Return the unique reference to the type for 114 | /// the specified type declaration. 115 | QualType getTypeDeclType(const TypeDecl *Decl, 116 | const TypeDecl *PrevDecl = 0) const { 117 | assert(Decl && "Passed null for Decl param"); 118 | if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); 119 | 120 | if (PrevDecl) { 121 | assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); 122 | Decl->TypeForDecl = PrevDecl->TypeForDecl; 123 | return QualType(PrevDecl->TypeForDecl, 0); 124 | } 125 | 126 | return getTypeDeclTypeSlow(Decl); 127 | } 128 | 129 | const std::vector &getTypes() const { return Types; } 130 | 131 | /// getQualifiedType - Returns a type with additional qualifiers. 132 | QualType getQualifiedType(QualType T, Qualifiers Qs) const { 133 | QualifierCollector Qc(Qs); 134 | const Type *Ptr = Qc.strip(T); 135 | return getExtQualType(Ptr, Qc, 0, 0); 136 | } 137 | 138 | /// getQualifiedType - Returns a type with additional qualifiers. 139 | QualType getQualifiedType(const Type *T, Qualifiers Qs) const { 140 | return getExtQualType(T, Qs, 0, 0); 141 | } 142 | 143 | //===--------------------------------------------------------------------===// 144 | // Type Operators 145 | //===--------------------------------------------------------------------===// 146 | 147 | /// getCanonicalType - Return the canonical (structural) type corresponding to 148 | /// the specified potentially non-canonical type. 149 | QualType getCanonicalType(QualType T) const { 150 | return T.getCanonicalType(); 151 | } 152 | 153 | const Type *getCanonicalType(const Type *T) const { 154 | return T->getCanonicalTypeInternal().getTypePtr(); 155 | } 156 | 157 | private: 158 | // FIXME: This currently contains the set of StoredDeclMaps used 159 | // by DeclContext objects. This probably should not be in ASTContext, 160 | // but we include it here so that ASTContext can quickly deallocate them. 161 | StoredDeclsMap *LastSDM; 162 | 163 | void ReleaseDeclContextMaps(); 164 | friend class DeclContext; 165 | }; 166 | 167 | } // end flang namespace 168 | 169 | // operator new and delete aren't allowed inside namespaces. The throw 170 | // specifications are mandated by the standard. 171 | 172 | /// @brief Placement new for using the ASTContext's allocator. 173 | /// 174 | /// This placement form of operator new uses the ASTContext's allocator for 175 | /// obtaining memory. It is a non-throwing new, which means that it returns null 176 | /// on error. (If that is what the allocator does. The current does, so if this 177 | /// ever changes, this operator will have to be changed, too.) 178 | /// 179 | /// Usage looks like this (assuming there's an ASTContext 'Context' in scope): 180 | /// 181 | /// @code 182 | /// // Default alignment (8) 183 | /// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); 184 | /// // Specific alignment 185 | /// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); 186 | /// @endcode 187 | /// 188 | /// Please note that you cannot use delete on the pointer; it must be 189 | /// deallocated using an explicit destructor call followed by 190 | /// @c Context.Deallocate(Ptr). 191 | /// 192 | /// @param Bytes The number of bytes to allocate. Calculated by the compiler. 193 | /// @param C The ASTContext that provides the allocator. 194 | /// @param Alignment The alignment of the allocated memory (if the underlying 195 | /// allocator supports it). 196 | /// @return The allocated memory. Could be NULL. 197 | inline void *operator new(size_t Bytes, const flang::ASTContext &C, 198 | size_t Alignment = 8) throw () { 199 | return C.Allocate(Bytes, Alignment); 200 | } 201 | 202 | /// @brief Placement delete companion to the new above. 203 | /// 204 | /// This operator is just a companion to the new above. There is no way of 205 | /// invoking it directly; see the new operator for more details. This operator 206 | /// is called implicitly by the compiler if a placement new expression using the 207 | /// ASTContext throws in the object constructor. 208 | inline void operator delete(void *Ptr, const flang::ASTContext &C, size_t) 209 | throw () { 210 | C.Deallocate(Ptr); 211 | } 212 | 213 | /// This placement form of operator new[] uses the ASTContext's allocator for 214 | /// obtaining memory. It is a non-throwing new[], which means that it returns 215 | /// null on error. 216 | /// 217 | /// Usage looks like this (assuming there's an ASTContext 'Context' in scope): 218 | /// 219 | /// @code 220 | /// // Default alignment (8) 221 | /// char *data = new (Context) char[10]; 222 | /// // Specific alignment 223 | /// char *data = new (Context, 4) char[10]; 224 | /// @endcode 225 | /// 226 | /// Please note that you cannot use delete on the pointer; it must be 227 | /// deallocated using an explicit destructor call followed by 228 | /// @c Context.Deallocate(Ptr). 229 | /// 230 | /// @param Bytes The number of bytes to allocate. Calculated by the compiler. 231 | /// @param C The ASTContext that provides the allocator. 232 | /// @param Alignment The alignment of the allocated memory (if the underlying 233 | /// allocator supports it). 234 | /// @return The allocated memory. Could be NULL. 235 | inline void *operator new[](size_t Bytes, const flang::ASTContext& C, 236 | size_t Alignment = 8) throw () { 237 | return C.Allocate(Bytes, Alignment); 238 | } 239 | 240 | /// @brief Placement delete[] companion to the new[] above. 241 | /// 242 | /// This operator is just a companion to the new[] above. There is no way of 243 | /// invoking it directly; see the new[] operator for more details. This operator 244 | /// is called implicitly by the compiler if a placement new[] expression using 245 | /// the ASTContext throws in the object constructor. 246 | inline void operator delete[](void *Ptr, const flang::ASTContext &C, size_t) 247 | throw () { 248 | C.Deallocate(Ptr); 249 | } 250 | 251 | #endif 252 | -------------------------------------------------------------------------------- /include/flang/AST/DeclContextInternals.h: -------------------------------------------------------------------------------- 1 | //===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the data structures used in the implementation 11 | // of DeclContext. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef FLANG_AST_DECLCONTEXTINTERNALS_H__ 16 | #define FLANG_AST_DECLCONTEXTINTERNALS_H__ 17 | 18 | #include "flang/AST/Decl.h" 19 | #include "flang/AST/DeclarationName.h" 20 | #include "llvm/ADT/DenseMap.h" 21 | #include "llvm/ADT/PointerUnion.h" 22 | #include "llvm/ADT/SmallVector.h" 23 | #include 24 | 25 | namespace flang { 26 | 27 | class DependentDiagnostic; 28 | 29 | /// StoredDeclsList - This is an array of decls optimized for the common case of 30 | /// only containing one entry. 31 | struct StoredDeclsList { 32 | /// DeclsTy - When in vector form, this is what the Data pointer points to. 33 | typedef SmallVector DeclsTy; 34 | 35 | /// \brief The stored data, which will be either a pointer to a NamedDecl, or 36 | /// a pointer to a vector. 37 | llvm::PointerUnion Data; 38 | public: 39 | StoredDeclsList() {} 40 | StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { 41 | if (DeclsTy *RHSVec = RHS.getAsVector()) 42 | Data = new DeclsTy(*RHSVec); 43 | } 44 | ~StoredDeclsList() { 45 | // If this is a vector-form, free the vector. 46 | if (DeclsTy *Vector = getAsVector()) 47 | delete Vector; 48 | } 49 | 50 | StoredDeclsList &operator=(const StoredDeclsList &RHS) { 51 | if (DeclsTy *Vector = getAsVector()) 52 | delete Vector; 53 | Data = RHS.Data; 54 | if (DeclsTy *RHSVec = RHS.getAsVector()) 55 | Data = new DeclsTy(*RHSVec); 56 | return *this; 57 | } 58 | 59 | bool isNull() const { return Data.isNull(); } 60 | 61 | NamedDecl *getAsDecl() const { 62 | return Data.dyn_cast(); 63 | } 64 | DeclsTy *getAsVector() const { 65 | return Data.dyn_cast(); 66 | } 67 | 68 | void setOnlyValue(NamedDecl *ND) { 69 | assert(!getAsVector() && "Not inline"); 70 | Data = ND; 71 | // Make sure that Data is a plain NamedDecl* so we can use its address at 72 | // getLookupResult. 73 | assert(*(NamedDecl **)&Data == ND && 74 | "PointerUnion mangles the NamedDecl pointer!"); 75 | } 76 | 77 | void remove(NamedDecl *D) { 78 | assert(!isNull() && "removing from empty list"); 79 | if (NamedDecl *Singleton = getAsDecl()) { 80 | assert(Singleton == D && "list is different singleton"); 81 | (void)Singleton; 82 | Data = (NamedDecl *)0; 83 | return; 84 | } 85 | 86 | DeclsTy &Vec = *getAsVector(); 87 | DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); 88 | assert(I != Vec.end() && "list does not contain decl"); 89 | Vec.erase(I); 90 | 91 | assert(std::find(Vec.begin(), Vec.end(), D) 92 | == Vec.end() && "list still contains decl"); 93 | } 94 | 95 | /// getLookupResult - Return an array of all the decls that this list 96 | /// represents. 97 | DeclContext::lookup_result getLookupResult() { 98 | if (isNull()) 99 | return DeclContext::lookup_result(DeclContext::lookup_iterator(0), 100 | DeclContext::lookup_iterator(0)); 101 | 102 | // If we have a single NamedDecl, return it. 103 | if (getAsDecl()) { 104 | assert(!isNull() && "Empty list isn't allowed"); 105 | 106 | // Data is a raw pointer to a NamedDecl*, return it. 107 | void *Ptr = &Data; 108 | return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); 109 | } 110 | 111 | assert(getAsVector() && "Must have a vector at this point"); 112 | DeclsTy &Vector = *getAsVector(); 113 | 114 | // Otherwise, we have a range result. 115 | return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size()); 116 | } 117 | 118 | /// AddSubsequentDecl - This is called on the second and later decl when it is 119 | /// not a redeclaration to merge it into the appropriate place in our list. 120 | void AddSubsequentDecl(NamedDecl *D) { 121 | // If this is the second decl added to the list, convert this to vector 122 | // form. 123 | if (NamedDecl *OldD = getAsDecl()) { 124 | DeclsTy *VT = new DeclsTy(); 125 | VT->push_back(OldD); 126 | Data = VT; 127 | } 128 | 129 | getAsVector()->push_back(D); 130 | } 131 | }; 132 | 133 | class StoredDeclsMap : public llvm::DenseMap { 134 | friend class ASTContext; // Walks the chain deleting these. 135 | friend class DeclContext; 136 | StoredDeclsMap *Previous; 137 | public: 138 | static void DestroyAll(StoredDeclsMap *Map); 139 | }; 140 | 141 | } // end namespace flang 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /include/flang/AST/DeclGroup.h: -------------------------------------------------------------------------------- 1 | //===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_AST_DECLGROUP_H__ 15 | #define FLANG_AST_DECLGROUP_H__ 16 | 17 | #include "llvm/Support/DataTypes.h" 18 | #include 19 | 20 | namespace flang { 21 | 22 | class ASTContext; 23 | class Decl; 24 | class DeclGroup; 25 | class DeclGroupIterator; 26 | 27 | class DeclGroup { 28 | // FIXME: Include a TypeSpecifier object. 29 | unsigned NumDecls; 30 | 31 | private: 32 | DeclGroup() : NumDecls(0) {} 33 | DeclGroup(unsigned numdecls, Decl** decls); 34 | 35 | public: 36 | static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); 37 | 38 | unsigned size() const { return NumDecls; } 39 | 40 | Decl *&operator[](unsigned i) { 41 | assert (i < NumDecls && "Out-of-bounds access."); 42 | return ((Decl**) (this+1))[i]; 43 | } 44 | 45 | Decl * const &operator[](unsigned i) const { 46 | assert (i < NumDecls && "Out-of-bounds access."); 47 | return ((Decl* const*) (this + 1))[i]; 48 | } 49 | }; 50 | 51 | class DeclGroupRef { 52 | // Note this is not a PointerIntPair because we need the address of the 53 | // non-group case to be valid as a Decl** for iteration. 54 | enum Kind { SingleDeclKind = 0x0, DeclGroupKind = 0x1, Mask = 0x1 }; 55 | Decl* D; 56 | 57 | Kind getKind() const { 58 | return (Kind) (reinterpret_cast(D) & Mask); 59 | } 60 | 61 | public: 62 | DeclGroupRef() : D(0) {} 63 | 64 | explicit DeclGroupRef(Decl* d) : D(d) {} 65 | explicit DeclGroupRef(DeclGroup* dg) 66 | : D((Decl*) (reinterpret_cast(dg) | DeclGroupKind)) {} 67 | 68 | static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { 69 | if (NumDecls == 0) 70 | return DeclGroupRef(); 71 | if (NumDecls == 1) 72 | return DeclGroupRef(Decls[0]); 73 | return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); 74 | } 75 | 76 | typedef Decl** iterator; 77 | typedef Decl* const * const_iterator; 78 | 79 | bool isNull() const { return D == 0; } 80 | bool isSingleDecl() const { return getKind() == SingleDeclKind; } 81 | bool isDeclGroup() const { return getKind() == DeclGroupKind; } 82 | 83 | Decl *getSingleDecl() { 84 | assert(isSingleDecl() && "Isn't a declgroup"); 85 | return D; 86 | } 87 | const Decl *getSingleDecl() const { 88 | return const_cast(this)->getSingleDecl(); 89 | } 90 | 91 | DeclGroup &getDeclGroup() { 92 | assert(isDeclGroup() && "Isn't a declgroup"); 93 | return *((DeclGroup*)(reinterpret_cast(D) & ~Mask)); 94 | } 95 | const DeclGroup &getDeclGroup() const { 96 | return const_cast(this)->getDeclGroup(); 97 | } 98 | 99 | iterator begin() { 100 | if (isSingleDecl()) 101 | return D ? &D : 0; 102 | return &getDeclGroup()[0]; 103 | } 104 | 105 | iterator end() { 106 | if (isSingleDecl()) 107 | return D ? &D+1 : 0; 108 | DeclGroup &G = getDeclGroup(); 109 | return &G[0] + G.size(); 110 | } 111 | 112 | const_iterator begin() const { 113 | if (isSingleDecl()) 114 | return D ? &D : 0; 115 | return &getDeclGroup()[0]; 116 | } 117 | 118 | const_iterator end() const { 119 | if (isSingleDecl()) 120 | return D ? &D+1 : 0; 121 | const DeclGroup &G = getDeclGroup(); 122 | return &G[0] + G.size(); 123 | } 124 | 125 | void *getAsOpaquePtr() const { return D; } 126 | static DeclGroupRef getFromOpaquePtr(void *Ptr) { 127 | DeclGroupRef X; 128 | X.D = static_cast(Ptr); 129 | return X; 130 | } 131 | }; 132 | 133 | } // end flang namespace 134 | 135 | namespace llvm { 136 | // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. 137 | template 138 | class PointerLikeTypeTraits; 139 | template <> 140 | class PointerLikeTypeTraits { 141 | public: 142 | static inline void *getAsVoidPointer(flang::DeclGroupRef P) { 143 | return P.getAsOpaquePtr(); 144 | } 145 | static inline flang::DeclGroupRef getFromVoidPointer(void *P) { 146 | return flang::DeclGroupRef::getFromOpaquePtr(P); 147 | } 148 | enum { NumLowBitsAvailable = 0 }; 149 | }; 150 | } // end llvm namespace 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /include/flang/AST/DeclarationName.h: -------------------------------------------------------------------------------- 1 | //===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares the DeclarationName and DeclarationNameTable classes. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_AST_DECLARATIONNAME_H__ 15 | #define FLANG_AST_DECLARATIONNAME_H__ 16 | 17 | #include "flang/Basic/IdentifierTable.h" 18 | #include "flang/Basic/SourceLocation.h" 19 | #include "flang/AST/Type.h" 20 | 21 | namespace llvm { 22 | template struct DenseMapInfo; 23 | } 24 | 25 | namespace flang { 26 | 27 | class DeclarationNameTable; 28 | class IdentifierInfo; 29 | class MultiKeywordSelector; 30 | class NamedDecl; 31 | class TypeSourceInfo; 32 | 33 | /// DeclarationName - The name of a declaration. In the common case, this just 34 | /// stores an IdentifierInfo pointer to a normal name 35 | class DeclarationName { 36 | public: 37 | /// NameKind - The kind of name this object contains. 38 | enum NameKind { 39 | Identifier 40 | }; 41 | 42 | private: 43 | /// StoredNameKind - The kind of name that is actually stored in the upper 44 | /// bits of the Ptr field. This is only used internally. 45 | enum StoredNameKind { 46 | StoredIdentifier = 0, 47 | PtrMask = 0x03 48 | }; 49 | 50 | /// Ptr - The lowest two bits are used to express what kind of name we're 51 | /// actually storing, using the values of NameKind. Depending on the kind of 52 | /// name this is, the upper bits of Ptr may have one of several different 53 | /// meanings: 54 | /// 55 | /// StoredIdentifier - The name is a normal identifier, and Ptr is a normal 56 | /// IdentifierInfo pointer. 57 | /// 58 | uintptr_t Ptr; 59 | 60 | /// getStoredNameKind - Return the kind of object that is stored in Ptr. 61 | StoredNameKind getStoredNameKind() const { 62 | return static_cast(Ptr & PtrMask); 63 | } 64 | 65 | /// Construct a declaration name from a raw pointer. 66 | DeclarationName(uintptr_t Ptr) : Ptr(Ptr) {} 67 | 68 | friend class DeclarationNameTable; 69 | friend class NamedDecl; 70 | 71 | /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer 72 | /// for this name as a void pointer. 73 | void *getFETokenInfoAsVoid() const; 74 | 75 | public: 76 | /// DeclarationName - Used to create an empty selector. 77 | DeclarationName() : Ptr(0) {} 78 | 79 | // Construct a declaration name from an IdentifierInfo*. 80 | DeclarationName(const IdentifierInfo *II) 81 | : Ptr(reinterpret_cast(II)) { 82 | assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo"); 83 | } 84 | 85 | // operator bool() - Evaluates true when this declaration name is non-empty. 86 | operator bool() const { 87 | return ((Ptr & PtrMask) != 0) || 88 | (reinterpret_cast(Ptr & ~PtrMask)); 89 | } 90 | 91 | /// Predicate functions for querying what type of name this is. 92 | bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; } 93 | 94 | /// getNameKind - Determine what kind of name this is. 95 | NameKind getNameKind() const; 96 | 97 | /// getAsString - Retrieve the human-readable string for this name. 98 | std::string getAsString() const; 99 | 100 | /// printName - Print the human-readable name to a stream. 101 | void printName(llvm::raw_ostream &OS) const; 102 | 103 | /// getAsIdentifierInfo - Retrieve the IdentifierInfo* stored in this 104 | /// declaration name, or NULL if this declaration name isn't a simple 105 | /// identifier. 106 | IdentifierInfo *getAsIdentifierInfo() const { 107 | if (isIdentifier()) 108 | return reinterpret_cast(Ptr); 109 | return 0; 110 | } 111 | 112 | /// getAsOpaqueInteger - Get the representation of this declaration name as an 113 | /// opaque integer. 114 | uintptr_t getAsOpaqueInteger() const { return Ptr; } 115 | 116 | /// getAsOpaquePtr - Get the representation of this declaration name as an 117 | /// opaque pointer. 118 | void *getAsOpaquePtr() const { return reinterpret_cast(Ptr); } 119 | 120 | static DeclarationName getFromOpaquePtr(void *P) { 121 | DeclarationName N; 122 | N.Ptr = reinterpret_cast (P); 123 | return N; 124 | } 125 | static DeclarationName getFromOpaqueInteger(uintptr_t P) { 126 | DeclarationName N; 127 | N.Ptr = P; 128 | return N; 129 | } 130 | 131 | /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to 132 | /// associate arbitrary metadata with some kinds of declaration names, 133 | /// including normal identifiers and conversion functions. 134 | template 135 | T *getFETokenInfo() const { return static_cast(getFETokenInfoAsVoid()); } 136 | 137 | void setFETokenInfo(void *T); 138 | 139 | /// operator== - Determine whether the specified names are identical. 140 | friend bool operator==(DeclarationName LHS, DeclarationName RHS) { 141 | return LHS.Ptr == RHS.Ptr; 142 | } 143 | 144 | /// operator!= - Determine whether the specified names are different. 145 | friend bool operator!=(DeclarationName LHS, DeclarationName RHS) { 146 | return LHS.Ptr != RHS.Ptr; 147 | } 148 | 149 | static DeclarationName getEmptyMarker() { 150 | return DeclarationName(uintptr_t(-1)); 151 | } 152 | 153 | static DeclarationName getTombstoneMarker() { 154 | return DeclarationName(uintptr_t(-2)); 155 | } 156 | 157 | static int compare(DeclarationName LHS, DeclarationName RHS); 158 | 159 | void dump() const; 160 | }; 161 | 162 | /// Ordering on two declaration names. If both names are identifiers, this 163 | /// provides a lexicographical ordering. 164 | inline bool operator<(DeclarationName LHS, DeclarationName RHS) { 165 | return DeclarationName::compare(LHS, RHS) < 0; 166 | } 167 | 168 | /// Ordering on two declaration names. If both names are identifiers, this 169 | /// provides a lexicographical ordering. 170 | inline bool operator>(DeclarationName LHS, DeclarationName RHS) { 171 | return DeclarationName::compare(LHS, RHS) > 0; 172 | } 173 | 174 | /// Ordering on two declaration names. If both names are identifiers, this 175 | /// provides a lexicographical ordering. 176 | inline bool operator<=(DeclarationName LHS, DeclarationName RHS) { 177 | return DeclarationName::compare(LHS, RHS) <= 0; 178 | } 179 | 180 | /// Ordering on two declaration names. If both names are identifiers, this 181 | /// provides a lexicographical ordering. 182 | inline bool operator>=(DeclarationName LHS, DeclarationName RHS) { 183 | return DeclarationName::compare(LHS, RHS) >= 0; 184 | } 185 | 186 | /// DeclarationNameTable - Used to store and retrieve DeclarationName instances 187 | /// for the various kinds of declaration names, e.g., normal identifiers, etc. 188 | class DeclarationNameTable { 189 | const ASTContext &Ctx; 190 | 191 | DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE 192 | DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE 193 | 194 | public: 195 | DeclarationNameTable(const ASTContext &C) : Ctx(C) {} 196 | ~DeclarationNameTable(); 197 | 198 | /// getIdentifier - Create a declaration name that is a simple 199 | /// identifier. 200 | DeclarationName getIdentifier(const IdentifierInfo *ID) { 201 | return DeclarationName(ID); 202 | } 203 | }; 204 | 205 | /// DeclarationNameInfo - A collector data type for bundling together a 206 | /// DeclarationName and the correspnding source/type location info. 207 | class DeclarationNameInfo { 208 | /// Name - The declaration name, also encoding name kind. 209 | DeclarationName Name; 210 | /// Loc - The main source location for the declaration name. 211 | llvm::SMLoc NameLoc; 212 | 213 | public: 214 | DeclarationNameInfo(DeclarationName Name, llvm::SMLoc NameLoc) 215 | : Name(Name), NameLoc(NameLoc) {} 216 | 217 | /// getName - Returns the embedded declaration name. 218 | DeclarationName getName() const { return Name; } 219 | /// setName - Sets the embedded declaration name. 220 | void setName(DeclarationName N) { Name = N; } 221 | 222 | /// getLoc - Returns the main location of the declaration name. 223 | llvm::SMLoc getLoc() const { return NameLoc; } 224 | /// setLoc - Sets the main location of the declaration name. 225 | void setLoc(llvm::SMLoc L) { NameLoc = L; } 226 | 227 | /// getAsString - Retrieve the human-readable string for this name. 228 | std::string getAsString() const; 229 | 230 | /// printName - Print the human-readable name to a stream. 231 | void printName(llvm::raw_ostream &OS) const; 232 | 233 | /// getBeginLoc - Retrieve the location of the first token. 234 | llvm::SMLoc getBeginLoc() const { return NameLoc; } 235 | /// getEndLoc - Retrieve the location of the last token. 236 | llvm::SMLoc getEndLoc() const; 237 | /// getSourceRange - The range of the declaration name. 238 | SourceRange getSourceRange() const { 239 | return SourceRange(getBeginLoc(), getEndLoc()); 240 | } 241 | }; 242 | 243 | inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 244 | DeclarationNameInfo DNInfo) { 245 | DNInfo.printName(OS); 246 | return OS; 247 | } 248 | 249 | } // end namespace flang 250 | 251 | namespace llvm { 252 | 253 | /// Define DenseMapInfo so that DeclarationNames can be used as keys in DenseMap 254 | /// and DenseSets. 255 | template<> 256 | struct DenseMapInfo { 257 | static inline flang::DeclarationName getEmptyKey() { 258 | return flang::DeclarationName::getEmptyMarker(); 259 | } 260 | 261 | static inline flang::DeclarationName getTombstoneKey() { 262 | return flang::DeclarationName::getTombstoneMarker(); 263 | } 264 | 265 | static unsigned getHashValue(flang::DeclarationName); 266 | 267 | static inline bool 268 | isEqual(flang::DeclarationName LHS, flang::DeclarationName RHS) { 269 | return LHS == RHS; 270 | } 271 | }; 272 | 273 | template <> 274 | struct isPodLike { static const bool value = true; }; 275 | 276 | } // end namespace llvm 277 | 278 | #endif 279 | -------------------------------------------------------------------------------- /include/flang/AST/FormatSpec.h: -------------------------------------------------------------------------------- 1 | //===--- FormatSpec.h - Fortran Format Specifier ----------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the format specifier class, used by the PRINT statement, 11 | // et al. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef FLANG_AST_FORMATSPEC_H__ 16 | #define FLANG_AST_FORMATSPEC_H__ 17 | 18 | #include "flang/Sema/Ownership.h" 19 | #include "llvm/Support/SMLoc.h" 20 | #include "flang/Basic/LLVM.h" 21 | 22 | namespace flang { 23 | 24 | class ASTContext; 25 | 26 | class FormatSpec { 27 | protected: 28 | enum FormatType { FS_DefaultCharExpr, FS_Label, FS_Star }; 29 | private: 30 | FormatType ID; 31 | SMLoc Loc; 32 | protected: 33 | FormatSpec(FormatType id, SMLoc L) 34 | : ID(id), Loc(L) {} 35 | friend class ASTContext; 36 | public: 37 | SMLoc getLocation() const { return Loc; } 38 | 39 | FormatType getFormatSpecID() const { return ID; } 40 | static bool classof(const FormatSpec *) { return true; } 41 | }; 42 | 43 | class StarFormatSpec : public FormatSpec { 44 | StarFormatSpec(SMLoc L); 45 | public: 46 | static StarFormatSpec *Create(ASTContext &C, SMLoc Loc); 47 | 48 | static bool classof(const StarFormatSpec *) { return true; } 49 | static bool classof(const FormatSpec *F) { 50 | return F->getFormatSpecID() == FS_Star; 51 | } 52 | }; 53 | 54 | class DefaultCharFormatSpec : public FormatSpec { 55 | ExprResult Fmt; 56 | DefaultCharFormatSpec(SMLoc L, ExprResult Fmt); 57 | public: 58 | static DefaultCharFormatSpec *Create(ASTContext &C, SMLoc Loc, 59 | ExprResult Fmt); 60 | 61 | ExprResult getFormat() const { return Fmt; } 62 | 63 | static bool classof(const DefaultCharFormatSpec *) { return true; } 64 | static bool classof(const FormatSpec *F) { 65 | return F->getFormatSpecID() == FS_DefaultCharExpr; 66 | } 67 | }; 68 | 69 | class LabelFormatSpec : public FormatSpec { 70 | ExprResult Label; 71 | LabelFormatSpec(SMLoc L, ExprResult Lbl); 72 | public: 73 | static LabelFormatSpec *Create(ASTContext &C, SMLoc Loc, 74 | ExprResult Lbl); 75 | 76 | ExprResult getLabel() const { return Label; } 77 | 78 | static bool classof(const LabelFormatSpec *) { return true; } 79 | static bool classof(const FormatSpec *F) { 80 | return F->getFormatSpecID() == FS_Label; 81 | } 82 | }; 83 | 84 | } // end namespace flang 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /include/flang/AST/Makefile: -------------------------------------------------------------------------------- 1 | FLANG_LEVEL := ../../.. 2 | TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic 3 | BUILT_SOURCES = DeclNodes.inc 4 | 5 | TABLEGEN_INC_FILES_COMMON = 1 6 | 7 | include $(FLANG_LEVEL)/Makefile 8 | 9 | $(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(TBLGEN) \ 10 | $(ObjDir)/.dir 11 | $(Echo) "Building Flang declaration node tables with tblgen" 12 | $(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $< 13 | -------------------------------------------------------------------------------- /include/flang/AST/Rename.h: -------------------------------------------------------------------------------- 1 | //===-- Rename.h - Renamed Objects ------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #ifndef FLANG_AST_RENAME_H__ 14 | #define FLANG_AST_RENAME_H__ 15 | 16 | #include "llvm/ADT/StringRef.h" 17 | #include "llvm/Support/raw_stream.h" 18 | 19 | namespace flang { 20 | 21 | //===----------------------------------------------------------------------===// 22 | /// Rename - Used in a 'USE' statement to rename a module name to a local name. 23 | /// 24 | class Rename { 25 | llvm::StringRef LocalName; 26 | llvm::StringRef UseName; 27 | public: 28 | Rename(llvm::StringRef LN, llvm::StringRef UN) 29 | : LocalName(LN), UseName(UN) {} 30 | 31 | friend llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const Rename &RN) { 32 | return O << RN.LocalName << " => " << RN.UseName; 33 | } 34 | }; 35 | 36 | } // end flang namespace 37 | 38 | #endif // FLANG_AST_RENAME_H__ 39 | -------------------------------------------------------------------------------- /include/flang/AST/StmtDumper.h: -------------------------------------------------------------------------------- 1 | //===--- StmtDumper.h - Dump Fortran Statements -----------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares the functions that dump statements. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_AST_STMTDUMPER_H__ 15 | #define FLANG_AST_STMTDUMPER_H__ 16 | 17 | #include "flang/Sema/Ownership.h" 18 | #include "llvm/ADT/ArrayRef.h" 19 | 20 | namespace flang { 21 | 22 | /// dump - Dump a statement. 23 | void dump(StmtResult S); 24 | 25 | /// dump - Dump an array of statements. 26 | void dump(llvm::ArrayRef S); 27 | 28 | } // end flang namespace 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/flang/Basic/DeclNodes.td: -------------------------------------------------------------------------------- 1 | //===-- DeclNodes.td - Declaration Nodes -------------------*- tablegen -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Fortran declaration nodes. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | class AttrSubject; 15 | 16 | class Decl : AttrSubject { 17 | bit Abstract = abstract; 18 | } 19 | 20 | class DDecl : Decl { 21 | Decl Base = base; 22 | } 23 | 24 | class DeclContext { } 25 | 26 | def TranslationUnit : Decl, DeclContext; 27 | def Named : Decl<1>; 28 | def Type : DDecl; 29 | def Record : DDecl, DeclContext; 30 | def Value : DDecl; 31 | def EnumConstant : DDecl; 32 | def Declarator : DDecl; 33 | def MainProgram : Decl, DeclContext; 34 | def Function : DDecl, DeclContext; 35 | def Subroutine : DDecl, DeclContext; 36 | def Module : DDecl, DeclContext; 37 | def Submodule : DDecl, DeclContext; 38 | def Field : DDecl; 39 | def Var : DDecl; 40 | def FileScopeAsm : Decl; 41 | -------------------------------------------------------------------------------- /include/flang/Basic/Diagnostic.h: -------------------------------------------------------------------------------- 1 | //===--- Diagnostic.h - Fortran Language Diagnostic Handling ----*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the Diagnostic-related interfaces. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_DIAGNOSTIC_H__ 15 | #define FLANG_DIAGNOSTIC_H__ 16 | 17 | #include "llvm/Support/SMLoc.h" 18 | #include "llvm/ADT/IntrusiveRefCntPtr.h" 19 | 20 | namespace llvm { 21 | class SourceMgr; 22 | class Twine; 23 | } // end namespace llvm 24 | 25 | namespace flang { 26 | 27 | class DiagnosticClient; 28 | class DiagnosticErrorTrap; 29 | class LangOptions; 30 | 31 | /// Diagnostic - This concrete class is used by the front-end to report problems 32 | /// and issues. It manages the diagnostics and passes them off to the 33 | /// DiagnosticClient for reporting to the user. 34 | class Diagnostic : public llvm::RefCountedBase { 35 | public: 36 | /// Level - The level of the diagnostic, after it has been through mapping. 37 | enum Level { 38 | Ignored = 0, 39 | Note = 1, 40 | Warning = 2, 41 | Error = 3, 42 | Fatal = 4 43 | }; 44 | private: 45 | DiagnosticClient *Client; 46 | bool OwnsDiagClient; 47 | llvm::SourceMgr *SrcMgr; 48 | 49 | /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred 50 | /// during a parsing section, e.g. during parsing a function. 51 | unsigned TrapNumErrorsOccurred; 52 | unsigned TrapNumUnrecoverableErrorsOccurred; 53 | public: 54 | Diagnostic(llvm::SourceMgr *SM, DiagnosticClient *DC, 55 | bool ShouldOwnClient = true) 56 | : Client(DC), OwnsDiagClient(ShouldOwnClient), SrcMgr(SM) {} 57 | 58 | DiagnosticClient *getClient() { return Client; } 59 | const DiagnosticClient *getClient() const { return Client; } 60 | 61 | bool hadErrors(); 62 | bool hadWarnings(); 63 | 64 | /// \brief Return the current diagnostic client along with ownership of that 65 | /// client. 66 | DiagnosticClient *takeClient() { 67 | OwnsDiagClient = false; 68 | return Client; 69 | } 70 | 71 | bool hasSourceManager() const { return SrcMgr != 0; } 72 | llvm::SourceMgr &getSourceManager() const { 73 | assert(SrcMgr && "SourceManager not set!"); 74 | return *SrcMgr; 75 | } 76 | void setSourceManager(llvm::SourceMgr *SM) { SrcMgr = SM; } 77 | 78 | /// \brief Set the diagnostic client associated with this diagnostic object. 79 | /// 80 | /// \param ShouldOwnClient true if the diagnostic object should take 81 | /// ownership of \c client. 82 | void setClient(DiagnosticClient *client, bool ShouldOwnClient = true) { 83 | Client = client; 84 | OwnsDiagClient = ShouldOwnClient; 85 | } 86 | 87 | /// ReportError - Emit an error at the location \arg L, with the message \arg 88 | /// Msg. 89 | /// 90 | /// \return The return value is always true, as an idiomatic convenience to 91 | /// clients. 92 | bool ReportError(llvm::SMLoc L, const llvm::Twine &Msg); 93 | 94 | /// ReportWarning - Emit a warning at the location \arg L, with the message 95 | /// \arg Msg. 96 | /// 97 | /// \return The return value is always true, as an idiomatic convenience to 98 | /// clients. 99 | bool ReportWarning(llvm::SMLoc L, const llvm::Twine &Msg); 100 | 101 | private: 102 | // This is private state used by DiagnosticBuilder. We put it here instead of 103 | // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight 104 | // object. This implementation choice means that we can only have one 105 | // diagnostic "in flight" at a time, but this seems to be a reasonable 106 | // tradeoff to keep these objects small. Assertions verify that only one 107 | // diagnostic is in flight at a time. 108 | friend class DiagnosticErrorTrap; 109 | }; 110 | 111 | /// \brief RAII class that determines when any errors have occurred between the 112 | /// time the instance was created and the time it was queried. 113 | class DiagnosticErrorTrap { 114 | Diagnostic &Diag; 115 | unsigned NumErrors; 116 | unsigned NumUnrecoverableErrors; 117 | public: 118 | explicit DiagnosticErrorTrap(Diagnostic &Diag) 119 | : Diag(Diag) { reset(); } 120 | 121 | /// \brief Determine whether any errors have occurred since this 122 | /// object instance was created. 123 | bool hasErrorOccurred() const { 124 | return Diag.TrapNumErrorsOccurred > NumErrors; 125 | } 126 | 127 | /// \brief Determine whether any unrecoverable errors have occurred since this 128 | /// object instance was created. 129 | bool hasUnrecoverableErrorOccurred() const { 130 | return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; 131 | } 132 | 133 | // Set to initial state of "no errors occurred". 134 | void reset() { 135 | NumErrors = Diag.TrapNumErrorsOccurred; 136 | NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; 137 | } 138 | }; 139 | 140 | /// DiagnosticClient - This is an abstract interface implemented by clients of 141 | /// the front-end, which formats and prints fully processed diagnostics. 142 | class DiagnosticClient { 143 | protected: 144 | unsigned NumWarnings; // Number of warnings reported 145 | unsigned NumErrors; // Number of errors reported 146 | public: 147 | DiagnosticClient() : NumWarnings(0), NumErrors(0) { } 148 | 149 | unsigned getNumErrors() const { return NumErrors; } 150 | unsigned getNumWarnings() const { return NumWarnings; } 151 | 152 | virtual ~DiagnosticClient(); 153 | 154 | /// BeginSourceFile - Callback to inform the diagnostic client that processing 155 | /// of a source file is beginning. 156 | /// 157 | /// Note that diagnostics may be emitted outside the processing of a source 158 | /// file, for example during the parsing of command line options. However, 159 | /// diagnostics with source range information are required to be emitted only 160 | /// in between BeginSourceFile() and EndSourceFile(). 161 | /// 162 | /// \arg LO - The language options for the source file being processed. 163 | virtual void BeginSourceFile(const LangOptions &) {} 164 | 165 | /// EndSourceFile - Callback to inform the diagnostic client that processing 166 | /// of a source file has ended. The diagnostic client should assume that any 167 | /// objects made available via \see BeginSourceFile() are inaccessible. 168 | virtual void EndSourceFile() {} 169 | 170 | /// IncludeInDiagnosticCounts - This method (whose default implementation 171 | /// returns true) indicates whether the diagnostics handled by this 172 | /// DiagnosticClient should be included in the number of diagnostics reported 173 | /// by Diagnostic. 174 | virtual bool IncludeInDiagnosticCounts() const { return true; } 175 | 176 | /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or 177 | /// capturing it to a log as needed. 178 | /// 179 | /// Default implementation just keeps track of the total number of warnings 180 | /// and errors. 181 | virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, llvm::SMLoc L, 182 | const llvm::Twine &Msg); 183 | }; 184 | 185 | } // end namespace flang 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /include/flang/Basic/Diagnostic.td: -------------------------------------------------------------------------------- 1 | //===--- Diagnostic.td - Fortran Language Family Diagnostic Handling ------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the TableGen core definitions for the diagnostics and 11 | // diagnostic control. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | // Define the diagnostic mappings. 16 | class DiagMapping; 17 | def MAP_IGNORE : DiagMapping; 18 | def MAP_WARNING : DiagMapping; 19 | def MAP_ERROR : DiagMapping; 20 | def MAP_FATAL : DiagMapping; 21 | def MAP_WARNING_NO_WERROR : DiagMapping; 22 | def MAP_WARNING_SHOW_IN_SYSTEM_HEADER : DiagMapping; 23 | 24 | // Define the diagnostic classes. 25 | class DiagClass; 26 | def CLASS_NOTE : DiagClass; 27 | def CLASS_WARNING : DiagClass; 28 | def CLASS_EXTENSION : DiagClass; 29 | def CLASS_ERROR : DiagClass; 30 | 31 | // Diagnostic Categories. These can be applied to groups or individual 32 | // diagnostics to specify a category. 33 | class DiagCategory { 34 | string CategoryName = Name; 35 | } 36 | 37 | // Diagnostic Groups. 38 | class DiagGroup subgroups = []> { 39 | string GroupName = Name; 40 | list SubGroups = subgroups; 41 | string CategoryName = ""; 42 | } 43 | class InGroup { DiagGroup Group = G; } 44 | 45 | // All diagnostics emitted by the compiler are an indirect subclass of this. 46 | class Diagnostic { 47 | /// Component is specified by the file with a big let directive. 48 | string Component = ?; 49 | string Text = text; 50 | DiagClass Class = DC; 51 | bit SFINAE = 1; 52 | bit AccessControl = 0; 53 | DiagMapping DefaultMapping = defaultmapping; 54 | DiagGroup Group; 55 | string CategoryName = ""; 56 | string Brief = ""; 57 | string Explanation = ""; 58 | } 59 | 60 | class Error : Diagnostic; 61 | class Warning : Diagnostic; 62 | class Extension : Diagnostic; 63 | class ExtWarn : Diagnostic; 64 | class Note : Diagnostic; 65 | 66 | class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; } 67 | class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; } 68 | class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; } 69 | class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; } 70 | class DefaultWarnNoWerror { DiagMapping DefaultMapping= MAP_WARNING_NO_WERROR; } 71 | class DefaultWarnShowInSystemHeader { 72 | DiagMapping DefaultMapping = MAP_WARNING_SHOW_IN_SYSTEM_HEADER; 73 | } 74 | 75 | class NoSFINAE { bit SFINAE = 0; } 76 | class AccessControl { bit AccessControl = 1; } 77 | 78 | class Brief { string Brief = str; } 79 | class FullExplanation { 80 | string Brief = brief; 81 | string Explanation = full; 82 | } 83 | 84 | // Definitions for Diagnostics. 85 | include "DiagnosticCommonKinds.td" 86 | include "DiagnosticLexKinds.td" 87 | include "DiagnosticParseKinds.td" 88 | -------------------------------------------------------------------------------- /include/flang/Basic/DiagnosticCommonKinds.td: -------------------------------------------------------------------------------- 1 | //==--- DiagnosticCommonKinds.td - common diagnostics ---------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | //===----------------------------------------------------------------------===// 11 | // Common Helpers 12 | //===----------------------------------------------------------------------===// 13 | 14 | let Component = "Common" in { 15 | 16 | // Basic. 17 | 18 | def fatal_too_many_errors 19 | : Error<"too many errors emitted, stopping now">, DefaultFatal; 20 | 21 | def note_previous_definition : Note<"previous definition is here">; 22 | def note_previous_declaration : Note<"previous declaration is here">; 23 | 24 | // Source manager 25 | def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; 26 | def err_file_modified : Error< 27 | "file '%0' modified since it was first processed">, DefaultFatal; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /include/flang/Basic/DiagnosticLexKinds.td: -------------------------------------------------------------------------------- 1 | //==--- DiagnosticLexKinds.td - Lexer Diagnostics -------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | //===----------------------------------------------------------------------===// 11 | // Lexer Diagnostics 12 | //===----------------------------------------------------------------------===// 13 | 14 | let Component = "Lex", CategoryName = "Lexical Issue" in { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /include/flang/Basic/DiagnosticParseKinds.td: -------------------------------------------------------------------------------- 1 | //==--- DiagnosticParseKinds.td - libparse diagnostics --------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | //===----------------------------------------------------------------------===// 11 | // Parser Diagnostics 12 | //===----------------------------------------------------------------------===// 13 | 14 | let Component = "Parse" in { 15 | 16 | let CategoryName = "Parse Issue" in { 17 | 18 | // Generic errors 19 | def err_parse_error : Error<"parse error">; 20 | def err_duplicate_declspec : Error<"duplicate '%0' declaration specifier">; 21 | 22 | // Declarations 23 | def err_invalid_decl_spec_combination : Error< 24 | "cannot combine with previous '%0' declaration specifier">; 25 | 26 | } // end of Parse Issue category. 27 | } // end of Parser diagnostics 28 | -------------------------------------------------------------------------------- /include/flang/Basic/LLVM.h: -------------------------------------------------------------------------------- 1 | //===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file forward declares and imports various common LLVM datatypes that 11 | // clang wants to use unqualified. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef FLANG_BASIC_LLVM_H__ 16 | #define FLANG_BASIC_LLVM_H__ 17 | 18 | // This should be the only #include, force #includes of all the others on 19 | // clients. 20 | #include "llvm/Support/Casting.h" 21 | 22 | namespace llvm { 23 | // ADT's. 24 | class APInt; 25 | class APFloat; 26 | class SMLoc; 27 | class StringRef; 28 | class Twine; 29 | template class ArrayRef; 30 | template class SmallVector; 31 | template class SmallVectorImpl; 32 | 33 | class raw_ostream; 34 | // TODO: DenseMap, ... 35 | } 36 | 37 | 38 | namespace flang { 39 | // Casting operators. 40 | using llvm::isa; 41 | using llvm::cast; 42 | using llvm::dyn_cast; 43 | using llvm::dyn_cast_or_null; 44 | using llvm::cast_or_null; 45 | 46 | // ADT's. 47 | using llvm::APInt; 48 | using llvm::APFloat; 49 | using llvm::SMLoc; 50 | using llvm::StringRef; 51 | using llvm::Twine; 52 | using llvm::ArrayRef; 53 | using llvm::SmallVector; 54 | using llvm::SmallVectorImpl; 55 | 56 | using llvm::raw_ostream; 57 | } // end namespace flang. 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/flang/Basic/LangOptions.h: -------------------------------------------------------------------------------- 1 | //===--- LangOptions.h - Fortran Language Family Language Opts --*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the LangOptions interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_LANGOPTIONS_H__ 15 | #define FLANG_LANGOPTIONS_H__ 16 | 17 | #include 18 | 19 | namespace flang { 20 | 21 | /// LangOptions - This class keeps track of the various options that can be 22 | /// enabled, which controls the dialect of Fortran that is accepted. 23 | class LangOptions { 24 | public: 25 | unsigned Fortran77 : 1; // Fortran 77 26 | unsigned Fortran90 : 1; // Fortran 90 27 | unsigned Fortran95 : 1; // Fortran 95 28 | unsigned Fortran2000 : 1; // Fortran 2000 29 | unsigned Fortran2003 : 1; // Fortran 2003 30 | unsigned Fortran2008 : 1; // Fortran 2008 31 | 32 | unsigned FixedForm : 1; // Fixed-form style 33 | unsigned FreeForm : 1; // Free-form style 34 | 35 | unsigned ReturnComments : 1; // Return comments as lexical tokens 36 | 37 | unsigned SpellChecking : 1; // Whether to perform spell-checking for error 38 | // recovery. 39 | LangOptions() { 40 | Fortran77 = 0; 41 | Fortran90 = Fortran95 = Fortran2000 = Fortran2003 = 1; 42 | FixedForm = 0; 43 | FreeForm = 1; 44 | ReturnComments = 0; 45 | SpellChecking = 1; 46 | } 47 | }; 48 | 49 | } // end namespace flang 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /include/flang/Basic/Makefile: -------------------------------------------------------------------------------- 1 | FLANG_LEVEL := ../../.. 2 | BUILT_SOURCES = \ 3 | DiagnosticCommonKinds.inc DiagnosticLexKinds.inc DiagnosticParseKinds.inc 4 | 5 | TABLEGEN_INC_FILES_COMMON = 1 6 | 7 | include $(FLANG_LEVEL)/Makefile 8 | 9 | INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td) 10 | 11 | $(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN) $(ObjDir)/.dir 12 | $(Echo) "Building Flang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen" 13 | $(Verb) $(ClangTableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $< 14 | -------------------------------------------------------------------------------- /include/flang/Basic/SourceLocation.h: -------------------------------------------------------------------------------- 1 | //===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the SourceLocation class. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLVM_FLANG_SOURCELOCATION_H 15 | #define LLVM_FLANG_SOURCELOCATION_H 16 | 17 | #include "llvm/Support/SMLoc.h" 18 | 19 | namespace flang { 20 | 21 | /// SourceRange - a trival tuple used to represent a source range. 22 | class SourceRange { 23 | llvm::SMLoc B; 24 | llvm::SMLoc E; 25 | public: 26 | SourceRange(): B(llvm::SMLoc()), E(llvm::SMLoc()) {} 27 | SourceRange(llvm::SMLoc loc) : B(loc), E(loc) {} 28 | SourceRange(llvm::SMLoc begin, llvm::SMLoc end) : B(begin), E(end) {} 29 | 30 | llvm::SMLoc getBegin() const { return B; } 31 | llvm::SMLoc getEnd() const { return E; } 32 | 33 | void setBegin(llvm::SMLoc b) { B = b; } 34 | void setEnd(llvm::SMLoc e) { E = e; } 35 | 36 | bool isValid() const { return B.isValid() && E.isValid(); } 37 | bool isInvalid() const { return !isValid(); } 38 | 39 | bool operator==(const SourceRange &that) const { 40 | return B == that.B && E == that.E; 41 | } 42 | 43 | bool operator!=(const SourceRange &that) const { 44 | return !(*this == that); 45 | } 46 | }; 47 | 48 | } // end flang namespace 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/flang/Basic/Specifiers.h: -------------------------------------------------------------------------------- 1 | //===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines various enumerations that describe declaration and 11 | // type specifiers. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef FLANG_BASIC_SPECIFIERS_H 16 | #define FLANG_BASIC_SPECIFIERS_H 17 | 18 | namespace flang { 19 | /// \brief [R404] Specifies the intrinsic type specifier. 20 | enum TypeSpecifierType { 21 | TST_unspecified, 22 | TST_integer, 23 | TST_real, 24 | TST_doubleprecision, 25 | TST_complex, 26 | TST_character, 27 | TST_logical, 28 | TST_struct 29 | }; 30 | 31 | /// \brief [R502] Specifies the attribute specifiers for types. 32 | enum AttributeSpecifier { 33 | AS_unspecified = 0, 34 | AS_allocatable = 1 << 0, 35 | AS_asynchronous = 1 << 1, 36 | AS_codimension = 1 << 2, 37 | AS_contiguous = 1 << 3, 38 | AS_dimension = 1 << 4, 39 | AS_external = 1 << 5, 40 | AS_intrinsic = 1 << 6, 41 | AS_optional = 1 << 7, 42 | AS_parameter = 1 << 8, 43 | AS_pointer = 1 << 9, 44 | AS_protected = 1 << 10, 45 | AS_save = 1 << 11, 46 | AS_target = 1 << 12, 47 | AS_value = 1 << 13, 48 | AS_volatile = 1 << 14 49 | }; 50 | 51 | /// \brief [R523] Specifies the intent specifier. 52 | enum IntentSpecifier { 53 | IS_unspecified, 54 | IS_in, 55 | IS_out, 56 | IS_inout 57 | }; 58 | 59 | /// \brief [R507] Access specifier (public, private). 60 | enum AccessSpecifier { 61 | AC_unspecified, 62 | AC_public, 63 | AC_private 64 | }; 65 | 66 | } // end namespace flang 67 | 68 | #endif // FLANG_BASIC_SPECIFIERS_H 69 | -------------------------------------------------------------------------------- /include/flang/Basic/Token.h: -------------------------------------------------------------------------------- 1 | //===--- Token.h - Token interface ------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the Token interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLVM_FLANG_TOKEN_H__ 15 | #define LLVM_FLANG_TOKEN_H__ 16 | 17 | #include "flang/Basic/TokenKinds.h" 18 | #include "llvm/Support/SMLoc.h" 19 | #include "flang/Basic/LLVM.h" 20 | #include 21 | #include 22 | #include 23 | 24 | namespace llvm { 25 | class Twine; 26 | } // end llvm namespace 27 | 28 | namespace flang { 29 | 30 | class IdentifierInfo; 31 | 32 | /// Token - This structure provides full information about a lexed token. It is 33 | /// not intended to be space efficient, it is intended to return as much 34 | /// information as possible about each returned token. This is expected to be 35 | /// compressed into a smaller form if memory footprint is important. 36 | class Token { 37 | /// The location of the token. 38 | llvm::SMLoc Loc; 39 | 40 | // Conceptually these next two fields could be in a union. However, this 41 | // causes gcc 4.2 to pessimize LexTokenInternal, a very performance critical 42 | // routine. Keeping as separate members with casts until a more beautiful fix 43 | // presents itself. 44 | 45 | /// UintData - This holds either the length of the token text, when 46 | /// a normal token, or the end of the SourceRange when an annotation 47 | /// token. 48 | unsigned UintData; 49 | 50 | /// PtrData - This is a union of three different pointer types, which depends 51 | /// on what type of token this is: 52 | /// Identifiers, keywords, etc: 53 | /// This is an IdentifierInfo*, which contains the uniqued identifier 54 | /// spelling. 55 | /// Literals: isLiteral() returns true. 56 | /// This is a pointer to the start of the token in a text buffer, which 57 | /// may be dirty (span more than one line). 58 | /// Other: 59 | /// This is null. 60 | void *PtrData; 61 | 62 | /// Kind - The actual flavor of token this is. 63 | unsigned Kind : 8; // DON'T make Kind a 'tok::TokenKind'; 64 | // MSVC will treat it as a signed char and 65 | // TokenKinds > 127 won't be handled correctly. 66 | 67 | /// Flags - Bits we track about this token, members of the TokenFlags enum. 68 | unsigned Flags : 8; 69 | public: 70 | 71 | // Various flags set per token: 72 | enum TokenFlags { 73 | StartOfStatement = 0x01, // At start of statement or only after whitespace 74 | NeedsCleaning = 0x02 // Contained a continuation 75 | }; 76 | 77 | tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } 78 | void setKind(tok::TokenKind K) { Kind = K; } 79 | 80 | /// is/isNot - Predicates to check if this token is a specific kind, as in 81 | /// "if (Tok.is(tok::l_brace)) {...}". 82 | bool is(tok::TokenKind K) const { return Kind == (unsigned) K; } 83 | bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; } 84 | 85 | /// isLiteral - Return true if this is a "literal", like a numeric constant, 86 | /// string, etc. 87 | bool isLiteral() const { 88 | return is(tok::int_literal_constant)|| is(tok::real_literal_constant) 89 | || is(tok::statement_label) || is(tok::char_literal_constant) 90 | || is(tok::binary_boz_constant) || is(tok::octal_boz_constant) 91 | || is(tok::hex_boz_constant) || is(tok::defined_operator) 92 | || is(tok::comment); 93 | } 94 | 95 | /// getLocation - Return a source location identifier for the specified offset 96 | /// in the current file. 97 | llvm::SMLoc getLocation() const { return Loc; } 98 | unsigned getLength() const { return UintData; } 99 | 100 | void setLocation(llvm::SMLoc L) { Loc = L; } 101 | void setLength(unsigned Len) { UintData = Len; } 102 | 103 | const char *getName() const { 104 | return tok::getTokenName((tok::TokenKind)Kind); 105 | } 106 | 107 | /// startToken - Reset all flags to cleared. 108 | void startToken() { 109 | Kind = tok::unknown; 110 | Flags = 0; 111 | PtrData = 0; 112 | Loc = llvm::SMLoc(); 113 | } 114 | 115 | IdentifierInfo *getIdentifierInfo() const { 116 | if (isLiteral()) return 0; 117 | return (IdentifierInfo*)PtrData; 118 | } 119 | void setIdentifierInfo(IdentifierInfo *II) { 120 | PtrData = (void*)II; 121 | } 122 | 123 | /// getLiteralData - For a literal token (numeric constant, string, etc), this 124 | /// returns a pointer to the start of it in the text buffer if known, null 125 | /// otherwise. 126 | const char *getLiteralData() const { 127 | assert(isLiteral() && "Cannot get literal data of non-literal"); 128 | return reinterpret_cast(PtrData); 129 | } 130 | void setLiteralData(const char *Ptr) { 131 | assert(isLiteral() && "Cannot set literal data of non-literal"); 132 | PtrData = (void*)Ptr; 133 | } 134 | 135 | /// setFlag - Set the specified flag. 136 | void setFlag(TokenFlags Flag) { 137 | Flags |= Flag; 138 | } 139 | 140 | /// clearFlag - Unset the specified flag. 141 | void clearFlag(TokenFlags Flag) { 142 | Flags &= ~Flag; 143 | } 144 | 145 | /// getFlags - Return the internal represtation of the flags. Only intended 146 | /// for low-level operations such as writing tokens to disk. 147 | unsigned getFlags() const { return Flags; } 148 | 149 | /// setFlagValue - Set a flag to either true or false. 150 | void setFlagValue(TokenFlags Flag, bool Val) { 151 | if (Val) 152 | setFlag(Flag); 153 | else 154 | clearFlag(Flag); 155 | } 156 | 157 | /// CleanLiteral - Return the literal cleaned up of any line continuations. 158 | std::string CleanLiteral(SmallVectorImpl &Spelling) const; 159 | 160 | /// CleanCharContext - Return the string from a character context that was 161 | /// continued over many lines. 162 | llvm::Twine CleanCharContext(); 163 | 164 | /// isAtStartOfStatement - Return true if this token is at the start of a 165 | /// statement. 166 | bool isAtStartOfStatement() const { 167 | return (Flags & StartOfStatement) ? true : false; 168 | } 169 | 170 | /// needsCleaning - Return true if this token has a continuation. 171 | bool needsCleaning() const { 172 | return (Flags & NeedsCleaning) ? true : false; 173 | } 174 | }; 175 | 176 | } // end namespace flang 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /include/flang/Basic/TokenKinds.h: -------------------------------------------------------------------------------- 1 | //===--- TokenKinds.h - Enum values for Fortran Token Kinds -----*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the TokenKind enum and support functions. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLVM_FLANG_TOKENKINDS_H__ 15 | #define LLVM_FLANG_TOKENKINDS_H__ 16 | 17 | namespace flang { 18 | namespace tok { 19 | 20 | /// TokenKind - This provides a simple uniform namespace for tokens from all 21 | /// Fortran languages. 22 | enum TokenKind { 23 | #define TOK(X) X, 24 | #include "flang/Basic/TokenKinds.def" 25 | NUM_TOKENS 26 | }; 27 | 28 | /// \brief Determines the name of a token as used within the front end. 29 | /// 30 | /// The name of a token will be an internal name (such as "l_paren") and should 31 | /// not be used as part of diagnostic messages. 32 | const char *getTokenName(enum TokenKind Kind); 33 | 34 | /// \brief Determines the spelling of simple punctuation tokens like '**' or 35 | /// '(', and returns NULL for literal and annotation tokens. 36 | /// 37 | /// This routine only retrieves the "simple" spelling of the token, and will not 38 | /// produce any alternative spellings. 39 | const char *getTokenSimpleSpelling(enum TokenKind Kind); 40 | 41 | } // end namespace tok 42 | } // end namespace flang 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/flang/Frontend/TextDiagnosticPrinter.h: -------------------------------------------------------------------------------- 1 | //===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This is a concrete diagnostic client, which prints the diagnostics to 11 | // standard error. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef FLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ 16 | #define FLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ 17 | 18 | #include "flang/Basic/Diagnostic.h" 19 | 20 | namespace llvm { 21 | class raw_ostream; 22 | class SMLoc; 23 | class SourceMgr; 24 | } // end namespace llvm 25 | 26 | namespace flang { 27 | 28 | class LangOptions; 29 | 30 | class TextDiagnosticPrinter : public DiagnosticClient { 31 | llvm::SourceMgr &SrcMgr; 32 | public: 33 | TextDiagnosticPrinter(llvm::SourceMgr &SM) : SrcMgr(SM) {} 34 | virtual ~TextDiagnosticPrinter(); 35 | 36 | // TODO: Emit caret diagnostics and Highlight range. 37 | virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, llvm::SMLoc L, 38 | const llvm::Twine &Msg); 39 | }; 40 | 41 | } // end namespace flang 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/flang/Makefile: -------------------------------------------------------------------------------- 1 | FLANG_LEVEL := ../.. 2 | DIRS := Basic AST 3 | 4 | include $(FLANG_LEVEL)/Makefile 5 | -------------------------------------------------------------------------------- /include/flang/Parse/Lexer.h: -------------------------------------------------------------------------------- 1 | //===-- Lexer.h - Fortran Lexer Interface -----------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // The Fortran lexer interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_PARSER_LEXER_H__ 15 | #define FLANG_PARSER_LEXER_H__ 16 | 17 | #include "flang/Basic/LangOptions.h" 18 | #include "flang/Basic/Token.h" 19 | #include "llvm/ADT/SmallVector.h" 20 | #include "llvm/ADT/StringRef.h" 21 | #include 22 | 23 | namespace llvm { 24 | 25 | class MemoryBuffer; 26 | class SMLoc; 27 | class SourceMgr; 28 | 29 | } // end namespace llvm 30 | 31 | namespace flang { 32 | 33 | class Diagnostic; 34 | 35 | class Lexer { 36 | /// LineOfText - This represents a line of text in the program where 37 | /// continuation contexts are concatenated. 38 | class LineOfText { 39 | Diagnostic &Diags; 40 | 41 | /// Atoms - A vector of atoms which make up one continuation context free 42 | /// line in the program. E.g. 43 | /// 44 | /// 'hello & 45 | /// ! comment 46 | /// &world' 47 | /// 48 | /// becomes two 'atoms' which can be treated as one contiguous line. I.e. 49 | /// 50 | /// 'hello world' 51 | SmallVector Atoms; 52 | 53 | /// BufPtr - This is the next line to be lexed. 54 | const char *BufPtr; 55 | 56 | /// CurAtom - The current atom. 57 | unsigned CurAtom; 58 | 59 | /// CurPtr - Current index into the buffer. This is the next character to be 60 | /// lexed. 61 | uint64_t CurPtr; 62 | 63 | /// SkipBlankLinesAndComments - Helper function that skips blank lines and 64 | /// lines with only comments. 65 | bool SkipBlankLinesAndComments(unsigned &I, const char *&LineBegin); 66 | 67 | /// GetCharacterLiteral - A character literal has to be treated specially 68 | /// because an ampersand may exist within it. 69 | void GetCharacterLiteral(unsigned &I, const char *&LineBegin); 70 | 71 | /// Padding - This is an extra space that we insert between two 72 | /// continuations which were merged. E.g.: 73 | /// 74 | /// FOO& 75 | /// BAR 76 | /// 77 | /// is interpreted as "FOO BAR" instead of "FOOBAR". 78 | static const char *Padding; 79 | 80 | friend class Lexer; 81 | public: 82 | explicit LineOfText(Diagnostic &D) 83 | : Diags(D), BufPtr(0), CurAtom(0), CurPtr(0) {} 84 | 85 | void SetBuffer(const llvm::MemoryBuffer *Buf, const char *Ptr); 86 | 87 | bool empty() const { return Atoms.empty(); } 88 | 89 | /// IsInCurrentAtom - Return true if the pointer is within the current atom 90 | /// and before the current pointer. 91 | bool IsInCurrentAtom(const char *Ptr) const { 92 | const char *Data = Atoms[CurAtom].data(); 93 | return Ptr >= Data && Ptr < &Data[CurPtr]; 94 | } 95 | 96 | /// GetNextLine - Get the next line of the program to lex. 97 | void GetNextLine(); 98 | 99 | /// Reset the internal state to make ready for a new line of text. 100 | void Reset() { 101 | CurPtr = CurAtom = 0; 102 | Atoms.clear(); 103 | } 104 | 105 | bool AtEndOfLine() const { 106 | return CurAtom == Atoms.size() - 1 && CurPtr >= Atoms[CurAtom].size(); 107 | } 108 | 109 | char GetNextChar(); 110 | char PeekNextChar() const; 111 | char PeekPrevChar() const; 112 | char GetCurrentChar() const; 113 | 114 | const char *GetLineBegin() const { 115 | assert(!Atoms.empty() && "Trying to get the start of an empty string!"); 116 | return Atoms[0].data(); 117 | } 118 | const char *GetCurrentPtr() const { 119 | assert(!Atoms.empty() && "Trying to get data from an empty string!"); 120 | if (Atoms[CurAtom].data() == Padding) 121 | return Atoms[CurAtom + 1].data(); 122 | return &Atoms[CurAtom].data()[CurPtr]; 123 | } 124 | 125 | void dump() const; 126 | void dump(raw_ostream &OS) const; 127 | }; 128 | 129 | /// Text - The text of the program. 130 | LineOfText Text; 131 | 132 | /// getNextChar - Get the next character from the buffer. 133 | char getNextChar() { return Text.GetNextChar(); } 134 | 135 | /// peekNextChar - Peek at the next character, but don't advance the buffer. 136 | char peekNextChar() const { return Text.PeekNextChar(); } 137 | 138 | /// peekPrevChar - Peek at the previous character. 139 | char peekPrevChar() const { return Text.PeekPrevChar(); } 140 | 141 | /// getCurrentChar - Get the current character the buffer's looking at. 142 | char getCurrentChar() { return Text.GetCurrentChar(); } 143 | 144 | /// getLineBegin - Get the start of the current line of text. 145 | const char *getLineBegin() const { return Text.GetLineBegin(); } 146 | 147 | /// getCurrentPtr - Get a pointer to the current character. 148 | const char *getCurrentPtr() const { return Text.GetCurrentPtr(); } 149 | 150 | Diagnostic &Diags; 151 | llvm::SourceMgr &SrcMgr; 152 | LangOptions Features; 153 | 154 | //===--------------------------------------------------------------------===// 155 | // Constant configuration values for this lexer. 156 | const llvm::MemoryBuffer *CurBuf; // Start of the buffer. 157 | 158 | //===--------------------------------------------------------------------===// 159 | // Context that changes as the file is lexed. 160 | 161 | /// TokStart - Start of the current token. 162 | const char *TokStart; 163 | 164 | /// CurKind - The current "kind" of token. 165 | tok::TokenKind CurKind; 166 | 167 | /// LastTokenWasSemicolon - True if the last token we returned was a 168 | /// semicolon. 169 | bool LastTokenWasSemicolon; 170 | 171 | /// SkipWhitespace - Efficiently skip over a series of whitespace characters. 172 | /// Update CurPtr to point to the next non-whitespace character and return. 173 | bool SkipWhitespace(Token &Result, const char *CurPtr); 174 | 175 | /// LexBlankLinesAndComments - Lex blank lines and lines with only 176 | /// comments. Used after we've parsed an ampersand. 177 | void LexBlankLinesAndComments(); 178 | 179 | /// LexComment - Lex a comment. We sometimes want to return the comment. 180 | void LexComment(Token &Result); 181 | 182 | /// LexIdentifier - Lex an identifier token. 183 | void LexIdentifier(Token &Result); 184 | 185 | /// LexStatementLabel - Lex the remainder of a statement label -- a 5-digit 186 | /// number. 187 | void LexStatementLabel(Token &Result); 188 | 189 | /// LexIntegerLiteralConstant - Lex an integer literal constant. 190 | bool LexIntegerLiteralConstant(); 191 | 192 | /// LexNumericConstant - Lex an integer or floating point constant. 193 | void LexNumericConstant(Token &Result); 194 | 195 | /// LexCharacterLiteralConstant - Lex the remainder of a character literal 196 | /// constant (string). 197 | void LexCharacterLiteralConstant(Token &Result, bool DoubleQuotes); 198 | 199 | /// LexBOZConstant - Lex the remainder of a BOZ constant. From[-1] is the 200 | /// first character lexed. Return the end of the constant. 201 | template 202 | void LexBOZConstant(Token &Result, const char *CurPtr, tok::TokenKind Kind); 203 | 204 | /// GetNextCharacter - Get the next character from the buffer ignoring 205 | /// continuation contexts. 206 | char GetNextCharacter(bool IncPtr = true); 207 | 208 | /// LexTokenInternal - This implements a simple Fortran family lexer. It is an 209 | /// extremely performance critical piece of code. This assumes that the buffer 210 | /// has a null character at the end of the file. It assumes that the Flags of 211 | /// result have been cleared before calling this. 212 | void LexTokenInternal(Token &Result); 213 | 214 | /// FormTokenWithChars - When we lex a token, we have identified a span 215 | /// starting at CurPtr, going to TokEnd that forms the token. This method 216 | /// takes that range and assigns it to the token as its location and size. In 217 | /// addition, since tokens cannot overlap, this also updates CurPtr to be 218 | /// TokEnd. 219 | void FormTokenWithChars(Token &Result, tok::TokenKind Kind); 220 | 221 | /// FormDefinedOperatorTokenWithChars - A special form of 222 | /// FormTokenWithChars. It will see if the defined operator is an intrinsic 223 | /// operator. If so, it will set the token's kind to that value. 224 | void FormDefinedOperatorTokenWithChars(Token &Result); 225 | 226 | /// ReturnError - Set the error to the specified string at the specified 227 | /// location. This is defined to always return tok::error. 228 | tok::TokenKind ReturnError(const char *Loc, const std::string &Msg); 229 | 230 | Lexer(const Lexer&); // DO NOT IMPLEMENT 231 | void operator=(const Lexer&); // DO NOT IMPLEMENT 232 | public: 233 | /// Lexer constructor - Create a new lexer object. This lexer assumes that the 234 | /// text range will outlive it, so it doesn't take ownership of it. 235 | Lexer(llvm::SourceMgr &SM, const LangOptions &Features, Diagnostic &D); 236 | 237 | Diagnostic &getDiagnostics() const { return Diags; } 238 | 239 | const llvm::SourceMgr &getSourceManager() const { return SrcMgr; } 240 | 241 | llvm::SMLoc getLoc() const; 242 | 243 | void setBuffer(const llvm::MemoryBuffer *buf, const char *ptr = 0); 244 | 245 | // FIXME: CurKind isn't set. 246 | bool isa(tok::TokenKind Kind) const { return CurKind == Kind; } 247 | 248 | /// Lex - Return the next token in the file. If this is the end of file, it 249 | /// return the tok::eof token. Return true if an error occurred and 250 | /// compilation should terminate, false if normal. 251 | void Lex(Token &Result) { 252 | // Start a new token. 253 | Result.startToken(); 254 | 255 | // Get a token. Note that this may delete the current lexer if the end of 256 | // file is reached. 257 | LexTokenInternal(Result); 258 | } 259 | 260 | #if 0 261 | //[TODO]: 262 | /// Diag - Forwarding function for diagnostics. This emits a diagnostic at the 263 | /// specified Token's location, translating the token's start position in the 264 | /// current buffer into a SourcePosition object for rendering. 265 | clang::DiagnosticBuilder Diag(clang::SourceLocation Loc, unsigned DiagID) { 266 | return Diags->Report(FullSourceLoc(Loc, getSourceManager()), DiagID); 267 | } 268 | clang::DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) { 269 | return Diags->Report(FullSourceLoc(Tok.getLocation(), getSourceManager()), 270 | DiagID); 271 | } 272 | #endif 273 | 274 | /// getSpelling - Return the 'spelling' of the Tok token. The spelling of a 275 | /// token is the characters used to represent the token in the source file. 276 | void getSpelling(const Token &Tok, 277 | llvm::SmallVectorImpl &Spelling) const; 278 | 279 | /// PrintError - Error printing methods. 280 | void PrintError(const char *Loc, const std::string &Msg) const; 281 | }; 282 | 283 | } // end namespace flang 284 | 285 | #endif 286 | -------------------------------------------------------------------------------- /include/flang/Parse/Parser.h: -------------------------------------------------------------------------------- 1 | //===-- Parser.h - Fortran Parser Interface ---------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // The Fortran parser interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_PARSER_PARSER_H__ 15 | #define FLANG_PARSER_PARSER_H__ 16 | 17 | #include "flang/AST/ASTContext.h" // FIXME: Move to AST construction. 18 | #include "flang/Basic/Diagnostic.h" 19 | #include "flang/Basic/IdentifierTable.h" 20 | #include "flang/Basic/LangOptions.h" 21 | #include "flang/Basic/TokenKinds.h" 22 | #include "flang/Parse/Lexer.h" 23 | #include "flang/Sema/DeclSpec.h" 24 | #include "flang/Sema/Ownership.h" 25 | #include "llvm/Support/PrettyStackTrace.h" 26 | #include "llvm/ADT/SmallSet.h" 27 | #include "llvm/ADT/Twine.h" 28 | #include 29 | 30 | namespace llvm { 31 | class SourceMgr; 32 | } // end namespace llvm 33 | 34 | namespace flang { 35 | 36 | class Action; 37 | class ConstantExpr; 38 | class DeclGroupRef; 39 | class Expr; 40 | class Parser; 41 | class Selector; 42 | class Sema; 43 | 44 | /// PrettyStackTraceParserEntry - If a crash happens while the parser is active, 45 | /// an entry is printed for it. 46 | class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { 47 | const Parser &FP; 48 | public: 49 | PrettyStackTraceParserEntry(const Parser &fp) : FP(fp) {} 50 | virtual void print(llvm::raw_ostream &OS) const; 51 | }; 52 | 53 | /// Parser - This implements a parser for the Fortran family of languages. After 54 | /// parsing units of the grammar, productions are invoked to handle whatever has 55 | /// been read. 56 | class Parser { 57 | public: 58 | enum RetTy { 59 | Success, //< The construct was parsed successfully 60 | WrongConstruct, //< The construct we wanted to parse wasn't present 61 | Error //< There was an error parsing 62 | }; 63 | private: 64 | Lexer TheLexer; 65 | LangOptions Features; 66 | PrettyStackTraceParserEntry CrashInfo; 67 | llvm::SourceMgr &SrcMgr; 68 | 69 | /// This is the current buffer index we're lexing from as managed by the 70 | /// SourceMgr object. 71 | int CurBuffer; 72 | 73 | ASTContext &Context; 74 | 75 | /// Diag - Diagnostics for parsing errors. 76 | Diagnostic &Diag; 77 | 78 | /// Actions - These are the callbacks we invoke as we parse various constructs 79 | /// in the file. 80 | Sema &Actions; 81 | #if 0 82 | /// Actions - These are the callbacks we invoke as we parse various constructs 83 | /// in the file. 84 | Action &Actions; 85 | #endif 86 | 87 | /// Tok - The current token we are parsing. All parsing methods assume that 88 | /// this is valid. 89 | Token Tok; 90 | 91 | /// NextTok - The next token so that we can do one level of lookahead. 92 | Token NextTok; 93 | 94 | /// StmtLabel - If set, this is the statement label for the statement. 95 | Expr *StmtLabel; 96 | 97 | // PrevTokLocation - The location of the token we previously consumed. This 98 | // token is used for diagnostics where we expected to see a token following 99 | // another token. 100 | llvm::SMLoc PrevTokLocation; 101 | 102 | /// Identifiers - This is mapping/lookup information for all identifiers in 103 | /// the program, including program keywords. 104 | mutable IdentifierTable Identifiers; 105 | 106 | /// getIdentifierInfo - Return information about the specified identifier 107 | /// token. 108 | IdentifierInfo *getIdentifierInfo(std::string &Name) const { 109 | return &Identifiers.get(Name); 110 | } 111 | 112 | /// ConsumeToken - Consume the current 'peek token' and lex the next one. This 113 | /// returns the location of the consumed token. 114 | llvm::SMLoc ConsumeToken() { 115 | PrevTokLocation = Tok.getLocation(); 116 | TheLexer.Lex(Tok); 117 | return PrevTokLocation; 118 | } 119 | 120 | /// CleanLiteral - Cleans up a literal if it needs cleaning. It removes the 121 | /// continuation contexts and comments. Cleaning a dirty literal is SLOW! 122 | void CleanLiteral(Token T, std::string &NameStr); 123 | 124 | bool EnterIncludeFile(const std::string &Filename); 125 | 126 | const Token &PeekAhead() const { 127 | return NextTok; 128 | } 129 | 130 | void Lex(); 131 | void ClassifyToken(Token &T); 132 | public: 133 | typedef OpaquePtr DeclGroupPtrTy; 134 | 135 | typedef flang::ExprResult ExprResult; 136 | typedef flang::StmtResult StmtResult; 137 | 138 | bool isaIdentifier(const llvm::StringRef &ID) const { 139 | return Identifiers.isaIdentifier(ID); 140 | } 141 | bool isaKeyword(const llvm::StringRef &KW) const { 142 | return Identifiers.isaKeyword(KW); 143 | } 144 | bool isaBuiltin(const llvm::StringRef &BI) const { 145 | return Identifiers.isaBuiltin(BI); 146 | } 147 | 148 | Parser(llvm::SourceMgr &SrcMgr, const LangOptions &Opts, 149 | Diagnostic &D, Sema &actions); 150 | 151 | llvm::SourceMgr &getSourceManager() { return SrcMgr; } 152 | 153 | const Token &getCurToken() const { return Tok; } 154 | const Lexer &getLexer() const { return TheLexer; } 155 | Lexer &getLexer() { return TheLexer; } 156 | 157 | bool ParseProgramUnits(); 158 | 159 | private: 160 | // High-level parsing methods. 161 | bool ParseProgramUnit(); 162 | bool ParseMainProgram(std::vector &Body); 163 | bool ParseExternalSubprogram(); 164 | bool ParseFunctionSubprogram(); 165 | bool ParseSubroutineSubprogram(); 166 | bool ParseModule(); 167 | bool ParseBlockData(); 168 | 169 | bool ParseSpecificationPart(std::vector &Body); 170 | bool ParseImplicitPartList(std::vector &Body); 171 | StmtResult ParseImplicitPart(); 172 | bool ParseExecutionPart(std::vector &Body); 173 | 174 | bool ParseDeclarationConstructList(); 175 | bool ParseDeclarationConstruct(); 176 | bool ParseForAllConstruct(); 177 | StmtResult ParseExecutableConstruct(); 178 | 179 | bool ParseTypeDeclarationStmt(SmallVectorImpl &Decls); 180 | bool ParseProcedureDeclStmt(); 181 | bool ParseSpecificationStmt(); 182 | StmtResult ParseActionStmt(); 183 | 184 | // Designator parsing methods. 185 | ExprResult ParseDesignator(); 186 | ExprResult ParseArrayElement(); 187 | ExprResult ParseArraySection(); 188 | ExprResult ParseCoindexedNamedObject(); 189 | ExprResult ParseComplexPartDesignator(); 190 | ExprResult ParseStructureComponent(); 191 | ExprResult ParseSubstring(); 192 | ExprResult ParseDataReference(); 193 | ExprResult ParsePartReference(); 194 | 195 | // Stmt-level parsing methods. 196 | StmtResult ParsePROGRAMStmt(); 197 | StmtResult ParseUSEStmt(); 198 | StmtResult ParseIMPORTStmt(); 199 | StmtResult ParseIMPLICITStmt(); 200 | StmtResult ParsePARAMETERStmt(); 201 | StmtResult ParseFORMATStmt(); 202 | StmtResult ParseENTRYStmt(); 203 | StmtResult ParseEND_PROGRAMStmt(); 204 | 205 | // Specification statement's contents. 206 | StmtResult ParseACCESSStmt(); 207 | StmtResult ParseALLOCATABLEStmt(); 208 | StmtResult ParseASYNCHRONOUSStmt(); 209 | StmtResult ParseBINDStmt(); 210 | StmtResult ParseCOMMONStmt(); 211 | StmtResult ParseDATAStmt(); 212 | StmtResult ParseDIMENSIONStmt(); 213 | StmtResult ParseEQUIVALENCEStmt(); 214 | StmtResult ParseEXTERNALStmt(); 215 | StmtResult ParseINTENTStmt(); 216 | StmtResult ParseINTRINSICStmt(); 217 | StmtResult ParseNAMELISTStmt(); 218 | StmtResult ParseOPTIONALStmt(); 219 | StmtResult ParsePOINTERStmt(); 220 | StmtResult ParsePROTECTEDStmt(); 221 | StmtResult ParseSAVEStmt(); 222 | StmtResult ParseTARGETStmt(); 223 | StmtResult ParseVALUEStmt(); 224 | StmtResult ParseVOLATILEStmt(); 225 | 226 | // Dynamic association. 227 | StmtResult ParseALLOCATEStmt(); 228 | StmtResult ParseNULLIFYStmt(); 229 | StmtResult ParseDEALLOCATEStmt(); 230 | 231 | StmtResult ParseWHEREStmt(); 232 | StmtResult ParseFORALLStmt(); 233 | StmtResult ParseEND_FORALLStmt(); 234 | 235 | // 236 | StmtResult ParseAssignmentStmt(); 237 | StmtResult ParsePrintStmt(); 238 | 239 | // Helper functions. 240 | ExprResult ParseLevel5Expr(); 241 | ExprResult ParseEquivOperand(); 242 | ExprResult ParseOrOperand(); 243 | ExprResult ParseAndOperand(); 244 | ExprResult ParseLevel4Expr(); 245 | ExprResult ParseLevel3Expr(); 246 | ExprResult ParseLevel2Expr(); 247 | ExprResult ParseAddOperand(); 248 | ExprResult ParseMultOperand(); 249 | ExprResult ParseLevel1Expr(); 250 | ExprResult ParsePrimaryExpr(); 251 | ExprResult ParseExpression(); 252 | 253 | void ParseStatementLabel(); 254 | 255 | // Declaration construct functions 256 | bool ParseDeclarationTypeSpec(DeclSpec &DS); 257 | bool ParseTypeOrClassDeclTypeSpec(DeclSpec &DS); 258 | ExprResult ParseSelector(bool IsKindSel); 259 | bool ParseDerivedTypeSpec(DeclSpec &DS); 260 | bool ParseArraySpec(llvm::SmallVectorImpl &Dims); 261 | bool ParseTypeDeclarationList(DeclSpec &DS, 262 | SmallVectorImpl &Decls); 263 | 264 | bool AssignAttrSpec(DeclSpec &DS, DeclSpec::AS Val); 265 | bool AssignAccessSpec(DeclSpec &DS, DeclSpec::AC Val); 266 | bool AssignIntentSpec(DeclSpec &DS, DeclSpec::IS Val); 267 | 268 | void SetKindSelector(ConstantExpr *E, StringRef Kind); 269 | 270 | void LexToEndOfStatement(); 271 | bool EatIfPresent(tok::TokenKind); 272 | }; 273 | 274 | } // end flang namespace 275 | 276 | #endif 277 | -------------------------------------------------------------------------------- /include/flang/Sema/DeclSpec.h: -------------------------------------------------------------------------------- 1 | //===-- DeclSpec.h - Declaration Type Specifiers ----------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Declaration type specifiers. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_SEMA_DECLSPEC_H__ 15 | #define FLANG_SEMA_DECLSPEC_H__ 16 | 17 | #include "flang/AST/Type.h" 18 | #include "flang/Basic/Specifiers.h" 19 | #include "flang/Sema/Ownership.h" 20 | #include "llvm/Support/SMLoc.h" 21 | #include "llvm/ADT/ArrayRef.h" 22 | #include "llvm/ADT/SmallVector.h" 23 | 24 | namespace llvm { 25 | class raw_ostream; 26 | } // end llvm namespace 27 | 28 | namespace flang { 29 | 30 | class Expr; 31 | 32 | //===----------------------------------------------------------------------===// 33 | /// DeclSpec - A declaration type specifier is the type -- intrinsic, TYPE, or 34 | /// CLASS -- plus any kind selectors for that type. 35 | class DeclSpec { 36 | public: 37 | // Import intrinsic type specifiers. 38 | typedef TypeSpecifierType TST; 39 | static const TST TST_unspecified = flang::TST_unspecified; 40 | static const TST TST_integer = flang::TST_integer; 41 | static const TST TST_real = flang::TST_real; 42 | static const TST TST_doubleprecision = flang::TST_doubleprecision; 43 | static const TST TST_complex = flang::TST_complex; 44 | static const TST TST_character = flang::TST_character; 45 | static const TST TST_logical = flang::TST_logical; 46 | static const TST TST_struct = flang::TST_struct; 47 | 48 | // Import attribute specifiers. 49 | typedef AttributeSpecifier AS; 50 | static const AS AS_unspecified = flang::AS_unspecified; 51 | static const AS AS_allocatable = flang::AS_allocatable; 52 | static const AS AS_asynchronous = flang::AS_asynchronous; 53 | static const AS AS_codimension = flang::AS_codimension; 54 | static const AS AS_contiguous = flang::AS_contiguous; 55 | static const AS AS_dimension = flang::AS_dimension; 56 | static const AS AS_external = flang::AS_external; 57 | static const AS AS_intrinsic = flang::AS_intrinsic; 58 | static const AS AS_optional = flang::AS_optional; 59 | static const AS AS_parameter = flang::AS_parameter; 60 | static const AS AS_pointer = flang::AS_pointer; 61 | static const AS AS_protected = flang::AS_protected; 62 | static const AS AS_save = flang::AS_save; 63 | static const AS AS_target = flang::AS_target; 64 | static const AS AS_value = flang::AS_value; 65 | static const AS AS_volatile = flang::AS_volatile; 66 | 67 | /// Import intent specifiers. 68 | typedef IntentSpecifier IS; 69 | static const IS IS_unspecified = flang::IS_unspecified; 70 | static const IS IS_in = flang::IS_in; 71 | static const IS IS_out = flang::IS_out; 72 | static const IS IS_inout = flang::IS_inout; 73 | 74 | /// Import access specifiers. 75 | typedef AccessSpecifier AC; 76 | static const AC AC_unspecified = flang::AC_unspecified; 77 | static const AC AC_public = flang::AC_public; 78 | static const AC AC_private = flang::AC_private; 79 | 80 | private: 81 | /*TST*/unsigned TypeSpecType : 3; 82 | /*AS*/ unsigned AttributeSpecs : 15; 83 | /*IS*/ unsigned IntentSpec : 3; 84 | /*AC*/ unsigned AccessSpec : 3; 85 | 86 | /// \brief The kind and length selectors. 87 | Expr *Kind; 88 | Expr *Len; 89 | SmallVector Dimensions; 90 | 91 | public: 92 | explicit DeclSpec() 93 | : TypeSpecType(TST_unspecified), 94 | AttributeSpecs(AS_unspecified), 95 | IntentSpec(IS_unspecified), 96 | AccessSpec(AC_unspecified), 97 | Kind(0), Len(0) {} 98 | virtual ~DeclSpec(); 99 | 100 | bool hasKindSelector() const { return Kind != 0; } 101 | Expr *getKindSelector() const { return Kind; } 102 | void setKindSelector(Expr *K) { Kind = K; } 103 | 104 | bool hasLengthSelector() const { return Len != 0; } 105 | Expr *getLengthSelector() const { return Len; } 106 | void setLengthSelector(Expr *L) { Len = L; } 107 | 108 | bool hasDimensions() const { return !Dimensions.empty(); } 109 | void setDimensions(ArrayRef Dims); 110 | ArrayRef getDimensions() const { return Dimensions; } 111 | 112 | typedef SmallVectorImpl::iterator dim_iterator; 113 | typedef SmallVectorImpl::const_iterator const_dim_iterator; 114 | dim_iterator begin() { return Dimensions.begin(); } 115 | dim_iterator end() { return Dimensions.end(); } 116 | const_dim_iterator begin() const { return Dimensions.begin(); } 117 | const_dim_iterator end() const { return Dimensions.end(); } 118 | 119 | /// getSpecifierName - Turn a type-specifier-type into a string like "REAL" 120 | /// or "ALLOCATABLE". 121 | static const char *getSpecifierName(DeclSpec::TST I); 122 | static const char *getSpecifierName(DeclSpec::AS A); 123 | static const char *getSpecifierName(DeclSpec::IS I); 124 | 125 | bool hasAttributeSpec(DeclSpec::AS A) const { 126 | return AttributeSpecs & A; 127 | } 128 | unsigned getAttributeSpecs() const { return AttributeSpecs; } 129 | void setAttributeSpec(DeclSpec::AS A) { 130 | AttributeSpecs |= A; 131 | } 132 | 133 | bool hasIntentSpec(DeclSpec::IS I) const { 134 | return IntentSpec & I; 135 | } 136 | IS getIntentSpec() const { return IS(IntentSpec); } 137 | void setIntentSpec(DeclSpec::IS I) { 138 | IntentSpec |= I; 139 | } 140 | 141 | bool hasAccessSpec(DeclSpec::AC A) const { 142 | return AccessSpec & A; 143 | } 144 | AC getAccessSpec() const { return AC(AccessSpec); } 145 | void setAccessSpec(DeclSpec::AC A) { 146 | AccessSpec |= A; 147 | } 148 | 149 | TST getTypeSpecType() const { return TST(TypeSpecType); } 150 | bool SetTypeSpecType(TST T) { 151 | if (TST(TypeSpecType) != TST_unspecified) 152 | return true; 153 | TypeSpecType = T; 154 | return false; 155 | } 156 | 157 | bool hasAttributes() const { 158 | return hasKindSelector() || hasLengthSelector() || 159 | AttributeSpecs != 0 || IntentSpec != 0 || AccessSpec != 0; 160 | } 161 | 162 | virtual void print(llvm::raw_ostream &) {} 163 | 164 | static bool classof(DeclSpec*) { return true; } 165 | }; 166 | 167 | } // end flang namespace 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /include/flang/Sema/Ownership.h: -------------------------------------------------------------------------------- 1 | //===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains classes for managing ownership of Stmt and Expr nodes. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_SEMA_OWNERSHIP_H__ 15 | #define FLANG_SEMA_OWNERSHIP_H__ 16 | 17 | #include "llvm/ADT/PointerIntPair.h" 18 | #include "llvm/ADT/SmallVector.h" 19 | 20 | namespace flang { 21 | 22 | class Decl; 23 | class Expr; 24 | class QualType; 25 | class Stmt; 26 | 27 | /// OpaquePtr - This is a very simple POD type that wraps a pointer that the 28 | /// Parser doesn't know about but that Sema or another client does. The UID 29 | /// template argument is used to make sure that "Decl" pointers are not 30 | /// compatible with "Type" pointers for example. 31 | template 32 | class OpaquePtr { 33 | void *Ptr; 34 | explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {} 35 | typedef llvm::PointerLikeTypeTraits Traits; 36 | public: 37 | OpaquePtr() : Ptr(0) {} 38 | 39 | static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; } 40 | 41 | template T* getAs() const { 42 | return get(); 43 | } 44 | 45 | template T getAsVal() const { 46 | return get(); 47 | } 48 | 49 | PtrTy get() const { 50 | return Traits::getFromVoidPointer(Ptr); 51 | } 52 | 53 | void set(PtrTy P) { 54 | Ptr = Traits::getAsVoidPointer(P); 55 | } 56 | 57 | operator bool() const { return Ptr != 0; } 58 | 59 | void *getAsOpaquePtr() const { return Ptr; } 60 | static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); } 61 | }; 62 | 63 | } // end flang namespace 64 | 65 | namespace llvm { 66 | template 67 | class PointerLikeTypeTraits > { 68 | public: 69 | static inline void *getAsVoidPointer(flang::OpaquePtr P) { 70 | // FIXME: Doesn't work? return P.getAs< void >(); 71 | return P.getAsOpaquePtr(); 72 | } 73 | static inline flang::OpaquePtr getFromVoidPointer(void *P) { 74 | return flang::OpaquePtr::getFromOpaquePtr(P); 75 | } 76 | enum { NumLowBitsAvailable = 0 }; 77 | }; 78 | 79 | template 80 | struct isPodLike > { static const bool value = true; }; 81 | } 82 | 83 | namespace flang { 84 | 85 | /// ActionResult - This structure is used while parsing and acting on 86 | /// expressions, stmts, etc. 87 | template 88 | class ActionResult { 89 | PtrTy Val; 90 | bool Invalid; 91 | public: 92 | ActionResult(bool invalid = false) : Val(PtrTy()), Invalid(invalid) {} 93 | ActionResult(PtrTy val) : Val(val), Invalid(false) {} 94 | 95 | // These two overloads prevent void* -> bool conversions. 96 | ActionResult(const void *); 97 | ActionResult(volatile void *); 98 | 99 | bool isInvalid() const { return Invalid; } 100 | bool isUsable() const { return !Invalid && Val; } 101 | 102 | PtrTy get() const { return Val; } 103 | PtrTy release() const { return Val; } 104 | PtrTy take() const { return Val; } 105 | template T *takeAs() { return static_cast(get()); } 106 | 107 | void set(PtrTy V) { Val = V; } 108 | 109 | const ActionResult &operator=(PtrTy RHS) { 110 | Val = RHS; 111 | Invalid = false; 112 | return *this; 113 | } 114 | }; 115 | 116 | /// An opaque type for threading parsed type information through the parser. 117 | typedef OpaquePtr ParsedType; 118 | typedef ActionResult TypeResult; 119 | 120 | typedef ActionResult DeclResult; 121 | typedef ActionResult ExprResult; 122 | typedef ActionResult StmtResult; 123 | 124 | } // end flang namespace 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /include/flang/Sema/Scope.h: -------------------------------------------------------------------------------- 1 | //===--- Scope.h - Scope interface ------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the Scope interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef FLANG_SEMA_SCOPE_H__ 15 | #define FLANG_SEMA_SCOPE_H__ 16 | 17 | #include "flang/Basic/Diagnostic.h" 18 | #include "llvm/ADT/SmallPtrSet.h" 19 | #include "llvm/ADT/SmallVector.h" 20 | 21 | namespace flang { 22 | 23 | class Decl; 24 | class UsingDirectiveDecl; 25 | 26 | /// Scope - A scope is a transient data structure that is used while parsing the 27 | /// program. It assists with resolving identifiers to the appropriate 28 | /// declaration. 29 | /// 30 | class Scope { 31 | public: 32 | /// ScopeFlags - These are bitfields that are or'd together when creating a 33 | /// scope, which defines the sorts of things the scope contains. 34 | enum ScopeFlags { 35 | /// FnScope - This indicates that the scope corresponds to a function, which 36 | /// means that labels are set here. 37 | FnScope = 0x01, 38 | 39 | /// DeclScope - This is a scope that can contain a declaration. Some scopes 40 | /// just contain loop constructs but don't contain decls. 41 | DeclScope = 0x02, 42 | 43 | /// RecordScope - The scope of a record definition. 44 | RecordScope = 0x04 45 | }; 46 | private: 47 | /// The parent scope for this scope. This is null for the translation-unit 48 | /// scope. 49 | Scope *AnyParent; 50 | 51 | /// Depth - This is the depth of this scope. The translation-unit scope has 52 | /// depth 0. 53 | unsigned short Depth; 54 | 55 | /// Flags - This contains a set of ScopeFlags, which indicates how the scope 56 | /// interrelates with other control flow statements. 57 | unsigned short Flags; 58 | 59 | /// PrototypeDepth - This is the number of function prototype scopes 60 | /// enclosing this scope, including this scope. 61 | unsigned short PrototypeDepth; 62 | 63 | /// PrototypeIndex - This is the number of parameters currently 64 | /// declared in this scope. 65 | unsigned short PrototypeIndex; 66 | 67 | /// FnParent - If this scope has a parent scope that is a function body, this 68 | /// pointer is non-null and points to it. This is used for label processing. 69 | Scope *FnParent; 70 | 71 | /// DeclsInScope - This keeps track of all declarations in this scope. When 72 | /// the declaration is added to the scope, it is set as the current 73 | /// declaration for the identifier in the IdentifierTable. When the scope is 74 | /// popped, these declarations are removed from the IdentifierTable's notion 75 | /// of current declaration. It is up to the current Action implementation to 76 | /// implement these semantics. 77 | typedef llvm::SmallPtrSet DeclSetTy; 78 | DeclSetTy DeclsInScope; 79 | 80 | /// Entity - The entity with which this scope is associated. For example, the 81 | /// entity of a record scope is the record itself, the entity of a function 82 | /// scope is a function, etc. This field is maintained by the Action 83 | /// implementation. 84 | void *Entity; 85 | 86 | /// \brief Used to determine if errors occurred in this scope. 87 | DiagnosticErrorTrap ErrorTrap; 88 | 89 | public: 90 | Scope(Scope *Parent, unsigned ScopeFlags, Diagnostic &Diag) 91 | : ErrorTrap(Diag) { 92 | Init(Parent, ScopeFlags); 93 | } 94 | 95 | /// getFlags - Return the flags for this scope. 96 | /// 97 | unsigned getFlags() const { return Flags; } 98 | void setFlags(unsigned F) { Flags = F; } 99 | 100 | /// getParent - Return the scope that this is nested in. 101 | /// 102 | const Scope *getParent() const { return AnyParent; } 103 | Scope *getParent() { return AnyParent; } 104 | 105 | /// getFnParent - Return the closest scope that is a function body. 106 | /// 107 | const Scope *getFnParent() const { return FnParent; } 108 | Scope *getFnParent() { return FnParent; } 109 | 110 | /// Returns the number of function prototype scopes in this scope 111 | /// chain. 112 | unsigned getFunctionPrototypeDepth() const { 113 | return PrototypeDepth; 114 | } 115 | 116 | typedef DeclSetTy::iterator decl_iterator; 117 | decl_iterator decl_begin() const { return DeclsInScope.begin(); } 118 | decl_iterator decl_end() const { return DeclsInScope.end(); } 119 | bool decl_empty() const { return DeclsInScope.empty(); } 120 | 121 | void AddDecl(Decl *D) { 122 | DeclsInScope.insert(D); 123 | } 124 | 125 | void RemoveDecl(Decl *D) { 126 | DeclsInScope.erase(D); 127 | } 128 | 129 | /// isDeclScope - Return true if this is the scope that the specified decl is 130 | /// declared in. 131 | bool isDeclScope(Decl *D) { 132 | return DeclsInScope.count(D) != 0; 133 | } 134 | 135 | void* getEntity() const { return Entity; } 136 | void setEntity(void *E) { Entity = E; } 137 | 138 | bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); } 139 | 140 | /// isRecordScope - Return true if this scope is a structure scope. 141 | bool isRecordScope() const { 142 | return (getFlags() & Scope::RecordScope); 143 | } 144 | 145 | /// Init - This is used by the parser to implement scope caching. 146 | /// 147 | void Init(Scope *parent, unsigned flags); 148 | }; 149 | 150 | } // end namespace flang 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /include/flang/Sema/Sema.h: -------------------------------------------------------------------------------- 1 | //===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the Sema class, which performs semantic analysis and builds 11 | // ASTs. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef FLANG_SEMA_SEMA_H__ 16 | #define FLANG_SEMA_SEMA_H__ 17 | 18 | #include "flang/Basic/Token.h" 19 | #include "flang/AST/FormatSpec.h" 20 | #include "flang/AST/Stmt.h" 21 | #include "flang/AST/Type.h" 22 | #include "flang/Sema/Ownership.h" 23 | #include "llvm/ADT/StringRef.h" 24 | #include "llvm/Support/SourceMgr.h" 25 | #include "llvm/Support/SMLoc.h" 26 | #include "flang/Basic/LLVM.h" 27 | 28 | namespace flang { 29 | 30 | class ASTContext; 31 | class DeclContext; 32 | class DeclSpec; 33 | class DeclarationNameInfo; 34 | class Diagnostic; 35 | class Expr; 36 | class FormatSpec; 37 | class IdentifierInfo; 38 | class Token; 39 | class VarDecl; 40 | 41 | /// Sema - This implements semantic analysis and AST buiding for Fortran. 42 | class Sema { 43 | Sema(const Sema&); // DO NOT IMPLEMENT 44 | void operator=(const Sema&); // DO NOT IMPLEMENT 45 | public: 46 | typedef Expr ExprTy; 47 | 48 | ASTContext &Context; 49 | Diagnostic &Diags; 50 | 51 | /// CurContext - This is the current declaration context of parsing. 52 | DeclContext *CurContext; 53 | 54 | Sema(ASTContext &ctxt, Diagnostic &Diags); 55 | ~Sema(); 56 | 57 | DeclContext *getContainingDC(DeclContext *DC); 58 | 59 | /// Set the current declaration context until it gets popped. 60 | void PushDeclContext(DeclContext *DC); 61 | void PopDeclContext(); 62 | 63 | void ActOnTranslationUnit(); 64 | void ActOnEndProgramUnit(); 65 | 66 | void ActOnMainProgram(const IdentifierInfo *IDInfo, SMLoc NameLoc); 67 | void ActOnEndMainProgram(const IdentifierInfo *IDInfo, SMLoc NameLoc); 68 | 69 | QualType ActOnTypeName(ASTContext &C, DeclSpec &DS); 70 | VarDecl *ActOnKindSelector(ASTContext &C, SMLoc IDLoc, 71 | const IdentifierInfo *IDInfo); 72 | Decl *ActOnEntityDecl(ASTContext &C, DeclSpec &DS, SMLoc IDLoc, 73 | const IdentifierInfo *IDInfo); 74 | 75 | Decl *ActOnImplicitEntityDecl(ASTContext &C, SMLoc IDLoc, 76 | const IdentifierInfo *IDInfo); 77 | 78 | // PROGRAM statement: 79 | StmtResult ActOnPROGRAM(ASTContext &C, const IdentifierInfo *ProgName, 80 | SMLoc Loc, SMLoc NameLoc, Expr *StmtLabel); 81 | 82 | // USE statement: 83 | StmtResult ActOnUSE(ASTContext &C, UseStmt::ModuleNature MN, 84 | const IdentifierInfo *ModName, ExprResult StmtLabel); 85 | StmtResult ActOnUSE(ASTContext &C, UseStmt::ModuleNature MN, 86 | const IdentifierInfo *ModName, bool OnlyList, 87 | ArrayRef RenameNames, 88 | ExprResult StmtLabel); 89 | 90 | // IMPORT statement: 91 | StmtResult ActOnIMPORT(ASTContext &C, SMLoc Loc, 92 | ArrayRef ImportNamesList, 93 | ExprResult StmtLabel); 94 | 95 | // IMPLICIT statement: 96 | StmtResult ActOnIMPLICIT(ASTContext &C, SMLoc Loc, DeclSpec &DS, 97 | ArrayRef LetterSpecs, 98 | Expr *StmtLabel); 99 | StmtResult ActOnIMPLICIT(ASTContext &C, SMLoc Loc, Expr *StmtLabel); 100 | 101 | // PARAMETER statement: 102 | ParameterStmt::ParamPair ActOnPARAMETERPair(ASTContext &C, SMLoc Loc, 103 | const IdentifierInfo *IDInfo, 104 | ExprResult CE); 105 | StmtResult ActOnPARAMETER(ASTContext &C, SMLoc Loc, 106 | ArrayRef ParamList, 107 | Expr *StmtLabel); 108 | 109 | // ASYNCHRONOUS statement: 110 | StmtResult ActOnASYNCHRONOUS(ASTContext &C, SMLoc Loc, 111 | ArrayRef ObjNames, 112 | Expr *StmtLabel); 113 | 114 | // END PROGRAM statement: 115 | StmtResult ActOnENDPROGRAM(ASTContext &C, 116 | const IdentifierInfo *ProgName, 117 | SMLoc Loc, SMLoc NameLoc, 118 | Expr *StmtLabel); 119 | 120 | // EXTERNAL statement: 121 | StmtResult ActOnEXTERNAL(ASTContext &C, SMLoc Loc, 122 | ArrayRef ExternalNames, 123 | Expr *StmtLabel); 124 | 125 | StmtResult ActOnAssignmentStmt(ASTContext &C, ExprResult LHS, 126 | ExprResult RHS, Expr *StmtLabel); 127 | 128 | QualType ActOnArraySpec(ASTContext &C, QualType ElemTy, 129 | ArrayRef Dims); 130 | 131 | StarFormatSpec *ActOnStarFormatSpec(ASTContext &C, SMLoc Loc); 132 | DefaultCharFormatSpec *ActOnDefaultCharFormatSpec(ASTContext &C, 133 | SMLoc Loc, 134 | ExprResult Fmt); 135 | LabelFormatSpec *ActOnLabelFormatSpec(ASTContext &C, SMLoc Loc, 136 | ExprResult Label); 137 | 138 | StmtResult ActOnPrintStmt(ASTContext &C, SMLoc Loc, FormatSpec *FS, 139 | ArrayRef OutputItemList, 140 | Expr *StmtLabel); 141 | 142 | // FIXME: TODO: 143 | 144 | QualType ActOnBuiltinType(ASTContext *Ctx, 145 | BuiltinType::TypeSpec TS, 146 | Expr *Kind) { return QualType(); } 147 | QualType ActOnCharacterBuiltinType(ASTContext *Ctx, 148 | Expr *Len, 149 | Expr *Kind) { return QualType(); } 150 | DeclSpec *ActOnTypeDeclSpec(ASTContext *Ctx) { return 0; } 151 | 152 | ExprResult ActOnDataReference(llvm::ArrayRef Exprs) { 153 | return ExprResult(); 154 | } 155 | }; 156 | 157 | } // end flang namespace 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /lib/AST/ASTContext.cpp: -------------------------------------------------------------------------------- 1 | //===--- ASTContext.cpp - Context to hold long-lived AST nodes ------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the ASTContext interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/AST/ASTContext.h" 15 | #include "llvm/ADT/ArrayRef.h" 16 | #include "llvm/Support/ErrorHandling.h" 17 | using namespace flang; 18 | 19 | ASTContext::ASTContext(llvm::SourceMgr &SM) 20 | : SrcMgr(SM), LastSDM(0) { 21 | TUDecl = TranslationUnitDecl::Create(*this); 22 | InitBuiltinTypes(); 23 | } 24 | 25 | ASTContext::~ASTContext() { 26 | // Release the DenseMaps associated with DeclContext objects. 27 | // FIXME: Is this the ideal solution? 28 | ReleaseDeclContextMaps(); 29 | } 30 | 31 | void ASTContext::InitBuiltinType(QualType &R, BuiltinType::TypeSpec K) { 32 | BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); 33 | R = QualType(Ty, 0); 34 | Types.push_back(Ty); 35 | } 36 | 37 | void ASTContext::InitBuiltinTypes() { 38 | // [R404] 39 | InitBuiltinType(IntegerTy, BuiltinType::Integer); 40 | InitBuiltinType(RealTy, BuiltinType::Real); 41 | InitBuiltinType(DoublePrecisionTy, BuiltinType::DoublePrecision); 42 | InitBuiltinType(ComplexTy, BuiltinType::Complex); 43 | InitBuiltinType(CharacterTy, BuiltinType::Character); 44 | InitBuiltinType(LogicalTy, BuiltinType::Logical); 45 | } 46 | 47 | QualType ASTContext::getBuiltinQualType(BuiltinType::TypeSpec TS) const { 48 | switch (TS) { 49 | case BuiltinType::Invalid: assert(false && "Invalid type spec!"); break; 50 | case BuiltinType::Integer: return IntegerTy; 51 | case BuiltinType::Real: return RealTy; 52 | case BuiltinType::DoublePrecision: return DoublePrecisionTy; 53 | case BuiltinType::Character: return CharacterTy; 54 | case BuiltinType::Logical: return LogicalTy; 55 | case BuiltinType::Complex: return ComplexTy; 56 | } 57 | return QualType(); 58 | } 59 | 60 | //===----------------------------------------------------------------------===// 61 | // Type creation/memoization methods 62 | //===----------------------------------------------------------------------===// 63 | 64 | QualType ASTContext::getExtQualType(const Type *BaseType, Qualifiers Quals, 65 | Expr *KindSel, Expr *LenSel) const { 66 | // Check if we've already instantiated this type. 67 | llvm::FoldingSetNodeID ID; 68 | ExtQuals::Profile(ID, BaseType, Quals, KindSel, LenSel); 69 | void *InsertPos = 0; 70 | if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) { 71 | assert(EQ->getQualifiers() == Quals); 72 | return QualType(EQ, 0); 73 | } 74 | 75 | // If the base type is not canonical, make the appropriate canonical type. 76 | QualType Canon; 77 | if (!BaseType->isCanonicalUnqualified()) { 78 | SplitQualType CanonSplit = BaseType->getCanonicalTypeInternal().split(); 79 | CanonSplit.second.addConsistentQualifiers(Quals); 80 | Canon = getExtQualType(CanonSplit.first, CanonSplit.second, KindSel, 81 | LenSel); 82 | 83 | // Re-find the insert position. 84 | (void) ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos); 85 | } 86 | 87 | ExtQuals *EQ = new (*this, TypeAlignment) ExtQuals(BaseType, Canon, Quals, 88 | KindSel, LenSel); 89 | ExtQualNodes.InsertNode(EQ, InsertPos); 90 | return QualType(EQ, 0); 91 | } 92 | 93 | /// getPointerType - Return the uniqued reference to the type for a pointer to 94 | /// the specified type. 95 | PointerType *ASTContext::getPointerType(const Type *Ty, unsigned NumDims) { 96 | // Unique pointers, to guarantee there is only one pointer of a particular 97 | // structure. 98 | llvm::FoldingSetNodeID ID; 99 | PointerType::Profile(ID, Ty, NumDims); 100 | 101 | void *InsertPos = 0; 102 | if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos)) 103 | return PT; 104 | 105 | PointerType *New = new (*this) PointerType(Ty, NumDims); 106 | Types.push_back(New); 107 | PointerTypes.InsertNode(New, InsertPos); 108 | return New; 109 | } 110 | 111 | /// getArrayType - Return the unique reference to the type for an array of the 112 | /// specified element type. 113 | QualType ASTContext::getArrayType(QualType EltTy, 114 | ArrayRef Dims) const { 115 | llvm::FoldingSetNodeID ID; 116 | ArrayType::Profile(ID, EltTy, Dims); 117 | 118 | void *InsertPos = 0; 119 | if (ArrayType *ATP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos)) 120 | return QualType(ATP, 0); 121 | 122 | ArrayType *New = new (*this,TypeAlignment) ArrayType(Type::Array, EltTy, 123 | QualType(), Dims); 124 | ArrayTypes.InsertNode(New, InsertPos); 125 | Types.push_back(New); 126 | return QualType(New, 0); 127 | } 128 | 129 | /// getTypeDeclTypeSlow - Return the unique reference to the type for the 130 | /// specified type declaration. 131 | QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { 132 | assert(Decl && "Passed null for Decl param"); 133 | assert(!Decl->TypeForDecl && "TypeForDecl present in slow case"); 134 | 135 | const RecordDecl *Record = dyn_cast(Decl); 136 | if (!Record) { 137 | llvm_unreachable("TypeDecl without a type?"); 138 | return QualType(Decl->TypeForDecl, 0); 139 | } 140 | 141 | return getRecordType(Record); 142 | } 143 | 144 | QualType ASTContext::getRecordType(const RecordDecl *Decl) const { 145 | return QualType(); 146 | #if 0 147 | if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); 148 | 149 | RecordType *newType = new (*this, TypeAlignment) RecordType(Decl); 150 | Decl->TypeForDecl = newType; 151 | Types.push_back(newType); 152 | return QualType(newType, 0); 153 | #endif 154 | } 155 | -------------------------------------------------------------------------------- /lib/AST/DeclGroup.cpp: -------------------------------------------------------------------------------- 1 | //===--- DeclGroup.cpp - Classes for representing groups of Decls ----------==// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the DeclGroup and DeclGroupRef classes. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/AST/DeclGroup.h" 15 | #include "flang/AST/Decl.h" 16 | #include "flang/AST/ASTContext.h" 17 | #include "llvm/Support/Allocator.h" 18 | using namespace flang; 19 | 20 | DeclGroup *DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { 21 | assert(NumDecls > 1 && "Invalid DeclGroup"); 22 | unsigned Size = sizeof(DeclGroup) + sizeof(Decl*) * NumDecls; 23 | void* Mem = C.Allocate(Size, llvm::AlignOf::Alignment); 24 | new (Mem) DeclGroup(NumDecls, Decls); 25 | return static_cast(Mem); 26 | } 27 | 28 | DeclGroup::DeclGroup(unsigned numdecls, Decl **decls) : NumDecls(numdecls) { 29 | assert(numdecls > 0); 30 | assert(decls); 31 | memcpy(this + 1, decls, numdecls * sizeof(*decls)); 32 | } 33 | -------------------------------------------------------------------------------- /lib/AST/DeclarationName.cpp: -------------------------------------------------------------------------------- 1 | //===-- DeclarationName.cpp - Declaration names implementation ------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the DeclarationName and DeclarationNameTable classes. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/AST/ASTContext.h" 15 | #include "flang/AST/Decl.h" 16 | #include "flang/AST/DeclarationName.h" 17 | #include "flang/Basic/IdentifierTable.h" 18 | #include "llvm/ADT/DenseMap.h" 19 | #include "llvm/ADT/FoldingSet.h" 20 | #include "llvm/Support/ErrorHandling.h" 21 | #include "llvm/Support/raw_ostream.h" 22 | using namespace flang; 23 | 24 | //===----------------------------------------------------------------------===// 25 | // DeclarationName Implementation 26 | //===----------------------------------------------------------------------===// 27 | 28 | DeclarationName::NameKind DeclarationName::getNameKind() const { 29 | switch (getStoredNameKind()) { 30 | default: break; 31 | case StoredIdentifier: 32 | return Identifier; 33 | } 34 | 35 | // Can't actually get here. 36 | assert(false && "This should be unreachable!"); 37 | return Identifier; 38 | } 39 | 40 | std::string DeclarationName::getAsString() const { 41 | std::string Result; 42 | llvm::raw_string_ostream OS(Result); 43 | printName(OS); 44 | return OS.str(); 45 | } 46 | 47 | void DeclarationName::printName(llvm::raw_ostream &OS) const { 48 | if (getNameKind() == Identifier) { 49 | if (const IdentifierInfo *II = getAsIdentifierInfo()) 50 | OS << II->getName(); 51 | return; 52 | } 53 | 54 | assert(false && "Unexpected declaration name kind"); 55 | } 56 | 57 | void *DeclarationName::getFETokenInfoAsVoid() const { 58 | switch (getNameKind()) { 59 | case Identifier: 60 | return getAsIdentifierInfo()->getFETokenInfo(); 61 | } 62 | 63 | assert(false && "Declaration name has no FETokenInfo"); 64 | return 0; 65 | } 66 | 67 | void DeclarationName::setFETokenInfo(void *T) { 68 | if (getNameKind() == Identifier) { 69 | getAsIdentifierInfo()->setFETokenInfo(T); 70 | return; 71 | } 72 | 73 | assert(false && "Declaration name has no FETokenInfo"); 74 | } 75 | 76 | int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { 77 | if (LHS.getNameKind() != RHS.getNameKind()) 78 | return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1); 79 | 80 | switch (LHS.getNameKind()) { 81 | case DeclarationName::Identifier: { 82 | IdentifierInfo *LII = LHS.getAsIdentifierInfo(); 83 | IdentifierInfo *RII = RHS.getAsIdentifierInfo(); 84 | if (!LII) return RII ? -1 : 0; 85 | if (!RII) return 1; 86 | 87 | return LII->getName().compare(RII->getName()); 88 | } 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | void DeclarationName::dump() const { 95 | printName(llvm::errs()); 96 | llvm::errs() << '\n'; 97 | } 98 | 99 | //===----------------------------------------------------------------------===// 100 | // DeclarationNameTable Implementation 101 | //===----------------------------------------------------------------------===// 102 | 103 | DeclarationNameTable::~DeclarationNameTable() {} 104 | 105 | //===----------------------------------------------------------------------===// 106 | // DeclarationNameInfo Implementation 107 | //===----------------------------------------------------------------------===// 108 | 109 | std::string DeclarationNameInfo::getAsString() const { 110 | std::string Result; 111 | llvm::raw_string_ostream OS(Result); 112 | printName(OS); 113 | return OS.str(); 114 | } 115 | 116 | void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const { 117 | switch (Name.getNameKind()) { 118 | case DeclarationName::Identifier: 119 | Name.printName(OS); 120 | return; 121 | } 122 | 123 | assert(false && "Unexpected declaration name kind"); 124 | } 125 | 126 | llvm::SMLoc DeclarationNameInfo::getEndLoc() const { 127 | switch (Name.getNameKind()) { 128 | case DeclarationName::Identifier: 129 | return NameLoc; 130 | } 131 | 132 | assert(false && "Unexpected declaration name kind"); 133 | return llvm::SMLoc(); 134 | } 135 | 136 | //===----------------------------------------------------------------------===// 137 | // DenseMapInfo Implementation 138 | //===----------------------------------------------------------------------===// 139 | 140 | unsigned 141 | llvm::DenseMapInfo:: 142 | getHashValue(flang::DeclarationName N) { 143 | return DenseMapInfo::getHashValue(N.getAsOpaquePtr()); 144 | } 145 | -------------------------------------------------------------------------------- /lib/AST/Expr.cpp: -------------------------------------------------------------------------------- 1 | //===--- Expr.cpp - Fortran Expressions -----------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include "flang/AST/Expr.h" 11 | #include "flang/AST/ASTContext.h" 12 | #include "flang/AST/Decl.h" 13 | #include "llvm/ADT/APSInt.h" 14 | #include "llvm/ADT/StringRef.h" 15 | using namespace flang; 16 | 17 | void APNumericStorage::setIntValue(ASTContext &C, const APInt &Val) { 18 | if (hasAllocation()) 19 | C.Deallocate(pVal); 20 | 21 | BitWidth = Val.getBitWidth(); 22 | unsigned NumWords = Val.getNumWords(); 23 | const uint64_t* Words = Val.getRawData(); 24 | if (NumWords > 1) { 25 | pVal = new (C) uint64_t[NumWords]; 26 | std::copy(Words, Words + NumWords, pVal); 27 | } else if (NumWords == 1) 28 | VAL = Words[0]; 29 | else 30 | VAL = 0; 31 | } 32 | 33 | IntegerConstantExpr::IntegerConstantExpr(ASTContext &C, SMLoc Loc, 34 | StringRef Data) 35 | : ConstantExpr(IntegerConstant, C.IntegerTy, Loc) { 36 | llvm::APSInt Val(64); 37 | Data.getAsInteger(10, Val); 38 | Num.setValue(C, Val); 39 | } 40 | 41 | IntegerConstantExpr *IntegerConstantExpr::Create(ASTContext &C, SMLoc Loc, 42 | StringRef Data) { 43 | return new (C) IntegerConstantExpr(C, Loc, Data); 44 | } 45 | 46 | RealConstantExpr::RealConstantExpr(ASTContext &C, SMLoc Loc, StringRef Data) 47 | : ConstantExpr(RealConstant, C.RealTy /*FIXME: Double?*/, Loc) { 48 | // FIXME: IEEEdouble? 49 | APFloat Val(APFloat::IEEEsingle, Data); 50 | Num.setValue(C, Val); 51 | } 52 | 53 | RealConstantExpr *RealConstantExpr::Create(ASTContext &C, SMLoc Loc, 54 | StringRef Data) { 55 | return new (C) RealConstantExpr(C, Loc, Data); 56 | } 57 | 58 | CharacterConstantExpr::CharacterConstantExpr(ASTContext &C, SMLoc Loc, 59 | StringRef data) 60 | : ConstantExpr(CharacterConstant, C.CharacterTy, Loc) { 61 | // TODO: A 'kind' on a character literal constant. 62 | Data = new (C) char[data.size() + 1]; 63 | std::strncpy(Data, data.data(), data.size()); 64 | Data[data.size()] = '\0'; 65 | } 66 | 67 | CharacterConstantExpr *CharacterConstantExpr::Create(ASTContext &C, SMLoc Loc, 68 | StringRef Data) { 69 | return new (C) CharacterConstantExpr(C, Loc, Data); 70 | } 71 | 72 | BOZConstantExpr::BOZConstantExpr(ASTContext &C, SMLoc Loc, StringRef Data) 73 | : ConstantExpr(BOZConstant, C.IntegerTy, Loc) { 74 | unsigned Radix = 0; 75 | switch (Data[0]) { 76 | case 'B': 77 | Kind = Binary; 78 | Radix = 2; 79 | break; 80 | case 'O': 81 | Kind = Octal; 82 | Radix = 8; 83 | break; 84 | case 'Z': case 'X': 85 | Kind = Hexadecimal; 86 | Radix = 16; 87 | break; 88 | } 89 | 90 | size_t LastQuote = Data.rfind(Data[1]); 91 | assert(LastQuote == StringRef::npos && "Invalid BOZ constant!"); 92 | llvm::StringRef NumStr = Data.slice(2, LastQuote); 93 | APInt Val; 94 | NumStr.getAsInteger(Radix, Val); 95 | Num.setValue(C, Val); 96 | } 97 | 98 | BOZConstantExpr *BOZConstantExpr::Create(ASTContext &C, SMLoc Loc, 99 | StringRef Data) { 100 | return new (C) BOZConstantExpr(C, Loc, Data); 101 | } 102 | 103 | LogicalConstantExpr::LogicalConstantExpr(ASTContext &C, SMLoc Loc, 104 | StringRef Data) 105 | : ConstantExpr(LogicalConstant, C.LogicalTy, Loc) { 106 | Val = (Data.compare_upper(".TRUE.") == 0); 107 | } 108 | 109 | LogicalConstantExpr *LogicalConstantExpr::Create(ASTContext &C, SMLoc Loc, 110 | StringRef Data) { 111 | return new (C) LogicalConstantExpr(C, Loc, Data); 112 | } 113 | 114 | VarExpr::VarExpr(llvm::SMLoc Loc, const VarDecl *Var) 115 | : DesignatorExpr(Loc, Var->getType(), DesignatorExpr::ObjectName), 116 | Variable(Var) {} 117 | 118 | VarExpr *VarExpr::Create(ASTContext &C, SMLoc Loc, const VarDecl *VD) { 119 | return new (C) VarExpr(Loc, VD); 120 | } 121 | 122 | UnaryExpr *UnaryExpr::Create(ASTContext &C, SMLoc loc, Operator op, 123 | ExprResult e) { 124 | return new (C) UnaryExpr(Expr::Unary, 125 | (op != Not) ? e.get()->getType() : C.LogicalTy, 126 | loc, op, e); 127 | } 128 | 129 | DefinedOperatorUnaryExpr::DefinedOperatorUnaryExpr(SMLoc loc, ExprResult e, 130 | IdentifierInfo *ii) 131 | : UnaryExpr(Expr::DefinedUnaryOperator, e.get()->getType(), loc, Defined, e), 132 | II(ii) {} 133 | 134 | DefinedOperatorUnaryExpr *DefinedOperatorUnaryExpr::Create(ASTContext &C, 135 | SMLoc loc, 136 | ExprResult e, 137 | IdentifierInfo *ii) { 138 | return new (C) DefinedOperatorUnaryExpr(loc, e, ii); 139 | } 140 | 141 | BinaryExpr *BinaryExpr::Create(ASTContext &C, SMLoc loc, Operator op, 142 | ExprResult lhs, ExprResult rhs) { 143 | QualType Ty; 144 | 145 | switch (op) { 146 | default: { 147 | // FIXME: Combine two types. 148 | Ty = lhs.get()->getType(); 149 | break; 150 | } 151 | case Eqv: case Neqv: case Or: case And: 152 | case Equal: case NotEqual: case LessThan: case LessThanEqual: 153 | case GreaterThan: case GreaterThanEqual: 154 | Ty = C.LogicalTy; 155 | break; 156 | case Concat: 157 | Ty = C.CharacterTy; 158 | break; 159 | } 160 | 161 | return new (C) BinaryExpr(Expr::Binary, Ty, loc, op, lhs, rhs); 162 | } 163 | 164 | DefinedOperatorBinaryExpr * 165 | DefinedOperatorBinaryExpr::Create(ASTContext &C, SMLoc loc, ExprResult lhs, 166 | ExprResult rhs, IdentifierInfo *ii) { 167 | return new (C) DefinedOperatorBinaryExpr(loc, lhs, rhs, ii); 168 | } 169 | 170 | //===----------------------------------------------------------------------===// 171 | // Expression Print Statements 172 | //===----------------------------------------------------------------------===// 173 | 174 | void Expr::dump() { 175 | this->print(llvm::outs()); 176 | } 177 | 178 | void Expr::print(llvm::raw_ostream &O) { 179 | } 180 | 181 | void DesignatorExpr::print(llvm::raw_ostream &O) { 182 | } 183 | 184 | void UnaryExpr::print(llvm::raw_ostream &O) { 185 | O << '('; 186 | const char *op = 0; 187 | switch (Op) { 188 | default: break; 189 | case Not: op = ".NOT."; break; 190 | case Plus: op = "+"; break; 191 | case Minus: op = "-"; break; 192 | } 193 | O << op; 194 | E.get()->print(O); 195 | O << ')'; 196 | } 197 | 198 | void DefinedOperatorUnaryExpr::print(llvm::raw_ostream &O) { 199 | O << '(' << II->getName(); 200 | E.get()->print(O); 201 | O << ')'; 202 | } 203 | 204 | void ConstantExpr::print(llvm::raw_ostream &O) { 205 | if (Kind) 206 | O << '_' << Kind; 207 | } 208 | 209 | void IntegerConstantExpr::print(llvm::raw_ostream &O) { 210 | O << Num.getValue(); 211 | } 212 | 213 | void VarExpr::print(llvm::raw_ostream &O) { 214 | O << *Variable; 215 | } 216 | 217 | void BinaryExpr::print(llvm::raw_ostream &O) { 218 | O << '('; 219 | LHS.get()->print(O); 220 | const char *op = 0; 221 | switch (Op) { 222 | default: break; 223 | case Eqv: op = ".EQV."; break; 224 | case Neqv: op = ".NEQV."; break; 225 | case Or: op = ".OR."; break; 226 | case And: op = ".AND."; break; 227 | case Equal: op = "=="; break; 228 | case NotEqual: op = "/="; break; 229 | case LessThan: op = "<"; break; 230 | case LessThanEqual: op = "<="; break; 231 | case GreaterThan: op = ">"; break; 232 | case GreaterThanEqual: op = ">="; break; 233 | case Concat: op = "//"; break; 234 | case Plus: op = "+"; break; 235 | case Minus: op = "-"; break; 236 | case Multiply: op = "*"; break; 237 | case Divide: op = "/"; break; 238 | case Power: op = "**"; break; 239 | } 240 | O << op; 241 | RHS.get()->print(O); 242 | O << ')'; 243 | } 244 | 245 | void DefinedOperatorBinaryExpr::print(llvm::raw_ostream &O) { 246 | O << '('; 247 | LHS.get()->print(O); 248 | II->getName(); 249 | RHS.get()->print(O); 250 | O << ')'; 251 | } 252 | 253 | //===----------------------------------------------------------------------===// 254 | // Array Specification 255 | //===----------------------------------------------------------------------===// 256 | 257 | ArraySpec::ArraySpec(ArraySpecKind K) 258 | : Kind(K) {} 259 | 260 | ExplicitShapeSpec::ExplicitShapeSpec(ExprResult UB) 261 | : ArraySpec(k_ExplicitShape), LowerBound(), UpperBound(UB) {} 262 | ExplicitShapeSpec::ExplicitShapeSpec(ExprResult LB, ExprResult UB) 263 | : ArraySpec(k_ExplicitShape), LowerBound(LB), UpperBound(UB) {} 264 | 265 | ExplicitShapeSpec *ExplicitShapeSpec::Create(ASTContext &C, ExprResult UB) { 266 | return new (C) ExplicitShapeSpec(UB); 267 | } 268 | 269 | ExplicitShapeSpec *ExplicitShapeSpec::Create(ASTContext &C, 270 | ExprResult LB, ExprResult UB) { 271 | return new (C) ExplicitShapeSpec(LB, UB); 272 | } 273 | 274 | AssumedShapeSpec::AssumedShapeSpec() 275 | : ArraySpec(k_AssumedShape), LowerBound() {} 276 | AssumedShapeSpec::AssumedShapeSpec(ExprResult LB) 277 | : ArraySpec(k_AssumedShape), LowerBound(LB) {} 278 | 279 | AssumedShapeSpec *AssumedShapeSpec::Create(ASTContext &C) { 280 | return new (C) AssumedShapeSpec(); 281 | } 282 | 283 | AssumedShapeSpec *AssumedShapeSpec::Create(ASTContext &C, ExprResult LB) { 284 | return new (C) AssumedShapeSpec(LB); 285 | } 286 | 287 | DeferredShapeSpec::DeferredShapeSpec() 288 | : ArraySpec(k_DeferredShape) {} 289 | 290 | DeferredShapeSpec *DeferredShapeSpec::Create(ASTContext &C) { 291 | return new (C) DeferredShapeSpec(); 292 | } 293 | 294 | ImpliedShapeSpec::ImpliedShapeSpec() 295 | : ArraySpec(k_ImpliedShape), LowerBound() {} 296 | ImpliedShapeSpec::ImpliedShapeSpec(ExprResult LB) 297 | : ArraySpec(k_ImpliedShape), LowerBound(LB) {} 298 | 299 | ImpliedShapeSpec *ImpliedShapeSpec::Create(ASTContext &C) { 300 | return new (C) ImpliedShapeSpec(); 301 | } 302 | 303 | ImpliedShapeSpec *ImpliedShapeSpec::Create(ASTContext &C, ExprResult LB) { 304 | return new (C) ImpliedShapeSpec(LB); 305 | } 306 | -------------------------------------------------------------------------------- /lib/AST/FormatSpec.cpp: -------------------------------------------------------------------------------- 1 | //===--- FormatSpec.cpp - Fortran FormatSpecifier -------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | 10 | #include "flang/AST/FormatSpec.h" 11 | #include "flang/AST/ASTContext.h" 12 | using namespace flang; 13 | 14 | StarFormatSpec::StarFormatSpec(SMLoc Loc) 15 | : FormatSpec(FormatSpec::FS_Star, Loc) {} 16 | 17 | StarFormatSpec *StarFormatSpec::Create(ASTContext &C, SMLoc Loc) { 18 | return new (C) StarFormatSpec(Loc); 19 | } 20 | 21 | DefaultCharFormatSpec::DefaultCharFormatSpec(SMLoc L, ExprResult F) 22 | : FormatSpec(FormatSpec::FS_DefaultCharExpr, L), Fmt(F) {} 23 | 24 | DefaultCharFormatSpec *DefaultCharFormatSpec::Create(ASTContext &C, SMLoc Loc, 25 | ExprResult Fmt) { 26 | return new (C) DefaultCharFormatSpec(Loc, Fmt); 27 | } 28 | 29 | LabelFormatSpec::LabelFormatSpec(SMLoc L, ExprResult Lbl) 30 | : FormatSpec(FormatSpec::FS_Label, L), Label(Lbl) {} 31 | 32 | LabelFormatSpec *LabelFormatSpec::Create(ASTContext &C, SMLoc Loc, 33 | ExprResult Label) { 34 | return new (C) LabelFormatSpec(Loc, Label); 35 | } 36 | -------------------------------------------------------------------------------- /lib/AST/Makefile: -------------------------------------------------------------------------------- 1 | ##===- flang/lib/AST/Makefile ------------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | # 10 | # This implements the AST library for the Fortran front-end. 11 | # 12 | ##===----------------------------------------------------------------------===## 13 | 14 | FLANG_LEVEL := ../.. 15 | LIBRARYNAME := flangAST 16 | 17 | include $(FLANG_LEVEL)/Makefile 18 | -------------------------------------------------------------------------------- /lib/AST/Stmt.cpp: -------------------------------------------------------------------------------- 1 | //===--- Stmt.cpp - Fortran Statements ------------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the statement objects. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/AST/Stmt.h" 15 | #include "flang/AST/ASTContext.h" 16 | #include "flang/Basic/IdentifierTable.h" 17 | #include "llvm/ADT/StringRef.h" 18 | using namespace flang; 19 | 20 | //===----------------------------------------------------------------------===// 21 | // Statement Base Class 22 | //===----------------------------------------------------------------------===// 23 | 24 | Stmt::~Stmt() {} 25 | 26 | //===----------------------------------------------------------------------===// 27 | // Program Statement 28 | //===----------------------------------------------------------------------===// 29 | 30 | ProgramStmt *ProgramStmt::Create(ASTContext &C, const IdentifierInfo *ProgName, 31 | llvm::SMLoc Loc, llvm::SMLoc NameLoc, 32 | ExprResult StmtLabel) { 33 | return new (C) ProgramStmt(ProgName, Loc, NameLoc, StmtLabel); 34 | } 35 | 36 | //===----------------------------------------------------------------------===// 37 | // EndProgram Statement 38 | //===----------------------------------------------------------------------===// 39 | 40 | EndProgramStmt *EndProgramStmt::Create(ASTContext &C, 41 | const IdentifierInfo *ProgName, 42 | llvm::SMLoc Loc, llvm::SMLoc NameLoc, 43 | ExprResult StmtLabel) { 44 | return new (C) EndProgramStmt(ProgName, Loc, NameLoc, StmtLabel); 45 | } 46 | 47 | //===----------------------------------------------------------------------===// 48 | // Use Statement 49 | //===----------------------------------------------------------------------===// 50 | 51 | UseStmt::UseStmt(ASTContext &C, ModuleNature MN, const IdentifierInfo *modName, 52 | ArrayRef RenameList, ExprResult StmtLabel) 53 | : ListStmt(C, Use, SMLoc(), RenameList, StmtLabel), 54 | ModNature(MN), ModName(modName), Only(false) {} 55 | 56 | UseStmt *UseStmt::Create(ASTContext &C, ModuleNature MN, 57 | const IdentifierInfo *modName, 58 | ExprResult StmtLabel) { 59 | return new (C) UseStmt(C, MN, modName, ArrayRef(), StmtLabel); 60 | } 61 | 62 | UseStmt *UseStmt::Create(ASTContext &C, ModuleNature MN, 63 | const IdentifierInfo *modName, bool Only, 64 | ArrayRef RenameList, 65 | ExprResult StmtLabel) { 66 | UseStmt *US = new (C) UseStmt(C, MN, modName, RenameList, StmtLabel); 67 | US->Only = Only; 68 | return US; 69 | } 70 | 71 | llvm::StringRef UseStmt::getModuleName() const { 72 | return ModName->getName(); 73 | } 74 | 75 | //===----------------------------------------------------------------------===// 76 | // Import Statement 77 | //===----------------------------------------------------------------------===// 78 | 79 | ImportStmt::ImportStmt(ASTContext &C, SMLoc Loc, 80 | ArrayRef Names, 81 | ExprResult StmtLabel) 82 | : ListStmt(C, Import, Loc, Names, StmtLabel) {} 83 | 84 | ImportStmt *ImportStmt::Create(ASTContext &C, SMLoc Loc, 85 | ArrayRef Names, 86 | ExprResult StmtLabel) { 87 | return new (C) ImportStmt(C, Loc, Names, StmtLabel); 88 | } 89 | 90 | //===----------------------------------------------------------------------===// 91 | // Implicit Statement 92 | //===----------------------------------------------------------------------===// 93 | 94 | ImplicitStmt::ImplicitStmt(ASTContext &C, SMLoc L, ExprResult StmtLabel) 95 | : ListStmt(C, Implicit, L, ArrayRef(), StmtLabel), None(true) {} 96 | 97 | ImplicitStmt::ImplicitStmt(ASTContext &C, SMLoc L, QualType T, 98 | ArrayRef SpecList, 99 | ExprResult StmtLabel) 100 | : ListStmt(C, Implicit, L, SpecList, StmtLabel), Ty(T), None(false) {} 101 | 102 | ImplicitStmt *ImplicitStmt::Create(ASTContext &C, SMLoc L, 103 | ExprResult StmtLabel) { 104 | return new (C) ImplicitStmt(C, L, StmtLabel); 105 | } 106 | 107 | ImplicitStmt *ImplicitStmt::Create(ASTContext &C, SMLoc L, QualType T, 108 | ArrayRef SpecList, 109 | ExprResult StmtLabel) { 110 | return new (C) ImplicitStmt(C, L, T, SpecList, StmtLabel); 111 | } 112 | 113 | //===----------------------------------------------------------------------===// 114 | // Parameter Statement 115 | //===----------------------------------------------------------------------===// 116 | 117 | ParameterStmt::ParameterStmt(ASTContext &C, SMLoc Loc, 118 | ArrayRef PList, ExprResult StmtLabel) 119 | : ListStmt(C, Parameter, Loc, PList, StmtLabel) {} 120 | 121 | ParameterStmt *ParameterStmt::Create(ASTContext &C, SMLoc Loc, 122 | ArrayRefParamList, 123 | ExprResult StmtLabel) { 124 | return new (C) ParameterStmt(C, Loc, ParamList, StmtLabel); 125 | } 126 | 127 | //===----------------------------------------------------------------------===// 128 | // Format Statement 129 | //===----------------------------------------------------------------------===// 130 | 131 | FormatStmt::FormatStmt(SMLoc Loc, FormatSpec *fs, ExprResult StmtLabel) 132 | : Stmt(Format, Loc, StmtLabel), FS(fs) {} 133 | 134 | FormatStmt *FormatStmt::Create(ASTContext &C, SMLoc Loc, FormatSpec *fs, 135 | ExprResult StmtLabel) { 136 | return new (C) FormatStmt(Loc, fs, StmtLabel); 137 | } 138 | 139 | //===----------------------------------------------------------------------===// 140 | // Entry Statement 141 | //===----------------------------------------------------------------------===// 142 | 143 | EntryStmt::EntryStmt(SMLoc Loc, ExprResult StmtLabel) 144 | : Stmt(Entry, Loc, StmtLabel) {} 145 | 146 | EntryStmt *EntryStmt::Create(ASTContext &C, SMLoc Loc, ExprResult StmtLabel) { 147 | return new (C) EntryStmt(Loc, StmtLabel); 148 | } 149 | 150 | //===----------------------------------------------------------------------===// 151 | // Asynchronous Statement 152 | //===----------------------------------------------------------------------===// 153 | 154 | AsynchronousStmt:: 155 | AsynchronousStmt(ASTContext &C, SMLoc Loc, 156 | ArrayRef objNames, 157 | ExprResult StmtLabel) 158 | : ListStmt(C, Asynchronous, Loc, objNames, StmtLabel) {} 159 | 160 | AsynchronousStmt *AsynchronousStmt:: 161 | Create(ASTContext &C, SMLoc Loc, ArrayRef objNames, 162 | ExprResult StmtLabel) { 163 | return new (C) AsynchronousStmt(C, Loc, objNames, StmtLabel); 164 | } 165 | 166 | //===----------------------------------------------------------------------===// 167 | // External Statement 168 | //===----------------------------------------------------------------------===// 169 | 170 | ExternalStmt::ExternalStmt(ASTContext &C, SMLoc Loc, 171 | ArrayRef ExternalNames, 172 | ExprResult StmtLabel) 173 | : ListStmt(C, External, Loc, ExternalNames, StmtLabel) {} 174 | 175 | ExternalStmt *ExternalStmt::Create(ASTContext &C, SMLoc Loc, 176 | ArrayRefExternalNames, 177 | ExprResult StmtLabel) { 178 | return new (C) ExternalStmt(C, Loc, ExternalNames, StmtLabel); 179 | } 180 | 181 | //===----------------------------------------------------------------------===// 182 | // Assignment Statement 183 | //===----------------------------------------------------------------------===// 184 | 185 | AssignmentStmt::AssignmentStmt(ExprResult lhs, ExprResult rhs, 186 | ExprResult StmtLabel) 187 | : Stmt(Assignment, llvm::SMLoc(), StmtLabel), LHS(lhs), RHS(rhs) 188 | {} 189 | 190 | AssignmentStmt *AssignmentStmt::Create(ASTContext &C, ExprResult lhs, 191 | ExprResult rhs, ExprResult StmtLabel) { 192 | return new (C) AssignmentStmt(lhs, rhs, StmtLabel); 193 | } 194 | 195 | //===----------------------------------------------------------------------===// 196 | // Print Statement 197 | //===----------------------------------------------------------------------===// 198 | 199 | PrintStmt::PrintStmt(ASTContext &C, SMLoc L, FormatSpec *fs, 200 | ArrayRef OutList, ExprResult StmtLabel) 201 | : ListStmt(C, Print, L, OutList, StmtLabel), FS(fs) {} 202 | 203 | PrintStmt *PrintStmt::Create(ASTContext &C, SMLoc L, FormatSpec *fs, 204 | ArrayRef OutList, 205 | ExprResult StmtLabel) { 206 | return new (C) PrintStmt(C, L, fs, OutList, StmtLabel); 207 | } 208 | -------------------------------------------------------------------------------- /lib/AST/StmtDumper.cpp: -------------------------------------------------------------------------------- 1 | //===--- StmtDumper.cpp - Dump Fortran Statements -------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file dumps statements. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/AST/StmtDumper.h" 15 | #include "flang/AST/Expr.h" 16 | #include "flang/AST/Stmt.h" 17 | #include "flang/AST/Type.h" 18 | #include "flang/Basic/LLVM.h" 19 | #include "llvm/Support/raw_ostream.h" 20 | using namespace flang; 21 | 22 | namespace { 23 | 24 | class StmtVisitor { 25 | raw_ostream &OS; 26 | public: 27 | StmtVisitor(raw_ostream &os) : OS(os) {} 28 | 29 | void visit(StmtResult); 30 | 31 | private: 32 | #define VISIT(STMT) void visit(const STMT *S) 33 | VISIT(ProgramStmt); 34 | VISIT(EndProgramStmt); 35 | VISIT(UseStmt); 36 | VISIT(ImportStmt); 37 | VISIT(ImplicitStmt); 38 | VISIT(AsynchronousStmt); 39 | VISIT(AssignmentStmt); 40 | VISIT(PrintStmt); 41 | #undef VISIT 42 | }; 43 | 44 | } // end anonymous namespace 45 | 46 | void StmtVisitor::visit(StmtResult S) { 47 | #define HANDLE(STMT) \ 48 | if (const STMT *stmt = dyn_cast(S.get())) { \ 49 | visit(stmt); \ 50 | return; \ 51 | } 52 | HANDLE(ProgramStmt); 53 | HANDLE(EndProgramStmt); 54 | HANDLE(UseStmt); 55 | HANDLE(ImportStmt); 56 | HANDLE(ImplicitStmt); 57 | HANDLE(AsynchronousStmt); 58 | HANDLE(AssignmentStmt); 59 | HANDLE(PrintStmt); 60 | #undef HANDLE 61 | } 62 | 63 | void StmtVisitor::visit(const ProgramStmt *S) { 64 | const IdentifierInfo *Name = S->getProgramName(); 65 | OS << "(program"; 66 | if (Name) OS << ": '" << Name->getName() << "'"; 67 | OS << ")\n"; 68 | } 69 | void StmtVisitor::visit(const EndProgramStmt *S) { 70 | const IdentifierInfo *Name = S->getProgramName(); 71 | OS << "(end program"; 72 | if (Name) OS << ": '" << Name->getName() << "'"; 73 | OS << ")\n"; 74 | } 75 | void StmtVisitor::visit(const UseStmt *S) { 76 | } 77 | void StmtVisitor::visit(const ImportStmt *S) { 78 | ArrayRef NameList = S->getIDList(); 79 | OS << "(import"; 80 | if (NameList.size() != 0) { 81 | OS << ":"; 82 | for (unsigned I = 0, E = NameList.size(); I != E; ++I) 83 | OS << "\n ('" << NameList[I]->getName() << "')"; 84 | } 85 | OS << ")\n"; 86 | } 87 | void StmtVisitor::visit(const ImplicitStmt *S) { 88 | ArrayRef LS = S->getIDList(); 89 | OS << "(implicit"; 90 | if (S->isNone()) { 91 | OS << " none)\n"; 92 | return; 93 | } 94 | OS << ":\n ("; 95 | S->getType().print(OS); 96 | OS << " ::\n"; 97 | for (unsigned I = 0, E = LS.size(); I != E; ++I) { 98 | ImplicitStmt::LetterSpec Spec = LS[I]; 99 | OS << " (" << Spec.first->getName(); 100 | if (Spec.second) 101 | OS << "-" << Spec.second->getName(); 102 | OS << ")\n"; 103 | } 104 | 105 | OS << " )\n)\n"; 106 | } 107 | void StmtVisitor::visit(const AsynchronousStmt *S) { 108 | } 109 | void StmtVisitor::visit(const AssignmentStmt *S) { 110 | OS << "(assignment:\n ("; 111 | S->getLHS()->getType().print(OS); 112 | OS << ")\n ("; 113 | S->getRHS()->getType().print(OS); 114 | OS << "))\n"; 115 | } 116 | void StmtVisitor::visit(const PrintStmt *S) { 117 | OS << "(print)\n"; 118 | } 119 | 120 | void flang::dump(StmtResult S) { 121 | StmtVisitor SV(llvm::errs()); 122 | SV.visit(S); 123 | } 124 | 125 | void flang::dump(ArrayRef S) { 126 | StmtVisitor SV(llvm::errs()); 127 | 128 | for (ArrayRef::iterator I = S.begin(), E = S.end(); I != E; ++I) 129 | if (!isa(I->get())) 130 | SV.visit(*I); 131 | } 132 | -------------------------------------------------------------------------------- /lib/AST/Type.cpp: -------------------------------------------------------------------------------- 1 | //===-- Type.cpp - Fortran Type Interface ---------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // The Fortran type interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/AST/Type.h" 15 | #include "flang/AST/ASTContext.h" 16 | #include "flang/AST/Expr.h" 17 | #include "llvm/Support/Casting.h" 18 | #include "llvm/Support/raw_ostream.h" 19 | using namespace flang; 20 | 21 | QualType 22 | QualifierCollector::apply(const ASTContext &Context, QualType QT) const { 23 | return Context.getQualifiedType(QT, *this); 24 | } 25 | 26 | QualType 27 | QualifierCollector::apply(const ASTContext &Context, const Type *T) const { 28 | return Context.getQualifiedType(T, *this); 29 | } 30 | 31 | //===----------------------------------------------------------------------===// 32 | // Subtype Methods 33 | //===----------------------------------------------------------------------===// 34 | 35 | ArrayType *ArrayType::Create(ASTContext &C, QualType ElemTy, 36 | ArrayRef Dims) { 37 | return new (C) ArrayType(Array, ElemTy, QualType(), Dims); 38 | } 39 | 40 | void BuiltinType::print(llvm::raw_ostream &O) const { 41 | switch (getTypeSpec()) { 42 | default: assert(false && "Invalid built-in type!"); 43 | case BuiltinType::Integer: 44 | O << "INTEGER"; 45 | break; 46 | case BuiltinType::Real: 47 | O << "REAL"; 48 | break; 49 | case BuiltinType::DoublePrecision: 50 | O << "DOUBLE PRECISION"; 51 | break; 52 | case BuiltinType::Character: 53 | O << "CHARACTER"; 54 | break; 55 | case BuiltinType::Complex: 56 | O << "COMPLEX"; 57 | break; 58 | case BuiltinType::Logical: 59 | O << "LOGICAL"; 60 | break; 61 | } 62 | } 63 | 64 | void QualType::dump() const { 65 | print(llvm::errs()); 66 | } 67 | 68 | void QualType::print(raw_ostream &OS) const { 69 | if (const Type *Ty = Value.getPointer().dyn_cast()) { 70 | if (const BuiltinType *BTy = dyn_cast(Ty)) 71 | BTy->print(OS); 72 | else if (const ArrayType *ATy = dyn_cast(Ty)) 73 | ATy->print(OS); 74 | return; 75 | } 76 | 77 | const ExtQuals *EQ = Value.getPointer().get(); 78 | if (const BuiltinType *BTy = dyn_cast(EQ->BaseType)) 79 | BTy->print(OS); 80 | 81 | bool Comma = false; 82 | if (EQ->hasKindSelector()) { 83 | OS << " (KIND="; 84 | EQ->getKindSelector()->print(OS); 85 | if (EQ->hasLengthSelector()) { 86 | OS << ", LEN="; 87 | EQ->getLengthSelector()->print(OS); 88 | } 89 | OS << ")"; 90 | Comma = true; 91 | } else if (EQ->hasLengthSelector()) { 92 | OS << " (LEN="; 93 | EQ->getLengthSelector()->print(OS); 94 | OS << ")"; 95 | Comma = true; 96 | } 97 | 98 | #define PRINT_QUAL(Q, QNAME) \ 99 | do { \ 100 | if (Quals.hasAttributeSpec(Qualifiers::Q)) { \ 101 | if (Comma) OS << ", "; Comma = true; \ 102 | OS << QNAME; \ 103 | } \ 104 | } while (0) 105 | 106 | Qualifiers Quals = EQ->getQualifiers(); 107 | PRINT_QUAL(AS_allocatable, "ALLOCATABLE"); 108 | PRINT_QUAL(AS_asynchronous, "ASYNCHRONOUS"); 109 | PRINT_QUAL(AS_codimension, "CODIMENSION"); 110 | PRINT_QUAL(AS_contiguous, "CONTIGUOUS"); 111 | PRINT_QUAL(AS_external, "EXTERNAL"); 112 | PRINT_QUAL(AS_intrinsic, "INTRINSIC"); 113 | PRINT_QUAL(AS_optional, "OPTIONAL"); 114 | PRINT_QUAL(AS_parameter, "PARAMETER"); 115 | PRINT_QUAL(AS_pointer, "POINTER"); 116 | PRINT_QUAL(AS_protected, "PROTECTED"); 117 | PRINT_QUAL(AS_save, "SAVE"); 118 | PRINT_QUAL(AS_target, "TARGET"); 119 | PRINT_QUAL(AS_value, "VALUE"); 120 | PRINT_QUAL(AS_volatile, "VOLATILE"); 121 | 122 | if (Quals.hasIntentAttr()) { 123 | if (Comma) OS << ", "; Comma = true; 124 | OS << "INTENT("; 125 | switch (Quals.getIntentAttr()) { 126 | default: assert(false && "Invalid intent attribute"); break; 127 | case Qualifiers::IS_in: OS << "IN"; break; 128 | case Qualifiers::IS_out: OS << "OUT"; break; 129 | case Qualifiers::IS_inout: OS << "INOUT"; break; 130 | } 131 | OS << ")"; 132 | } 133 | 134 | if (Quals.hasAccessAttr()) { 135 | if (Comma) OS << ", "; Comma = true; 136 | switch (Quals.getAccessAttr()) { 137 | default: assert(false && "Invalid access attribute"); break; 138 | case Qualifiers::AC_public: OS << "PUBLIC"; break; 139 | case Qualifiers::AC_private: OS << "PRIVATE"; break; 140 | } 141 | OS << ")"; 142 | } 143 | } 144 | 145 | void ArrayType::print(raw_ostream &OS) const { 146 | ElementType.print(OS); 147 | OS << ", DIMENSION("; 148 | 149 | for (SmallVectorImpl::const_iterator 150 | I = Dims.begin(), E = Dims.end(); I != E; ++I) { 151 | if (I != Dims.begin()) OS << ", "; 152 | I->get()->print(OS); 153 | } 154 | 155 | OS << ")"; 156 | } 157 | -------------------------------------------------------------------------------- /lib/Basic/Diagnostic.cpp: -------------------------------------------------------------------------------- 1 | //===--- Diagnostic.cpp - Fortran Language Diagnostic Handling ------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the Diagnostic-related interfaces. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Basic/Diagnostic.h" 15 | #include "llvm/Support/SourceMgr.h" 16 | #include "llvm/ADT/Twine.h" 17 | using namespace flang; 18 | 19 | bool Diagnostic::hadErrors() { 20 | return Client->getNumErrors() != 0; 21 | } 22 | 23 | bool Diagnostic::hadWarnings() { 24 | return Client->getNumWarnings() != 0; 25 | } 26 | 27 | /// ReportError - Emit an error at the location \arg L, with the message \arg 28 | /// Msg. 29 | /// 30 | /// \return The return value is always true, as an idiomatic convenience to 31 | /// clients. 32 | bool Diagnostic::ReportError(llvm::SMLoc L, const llvm::Twine &Msg) { 33 | Client->HandleDiagnostic(Error, L, Msg); 34 | return true; 35 | } 36 | 37 | /// ReportWarning - Emit a warning at the location \arg L, with the message \arg 38 | /// Msg. 39 | /// 40 | /// \return The return value is always true, as an idiomatic convenience to 41 | /// clients. 42 | bool Diagnostic::ReportWarning(llvm::SMLoc L, const llvm::Twine &Msg) { 43 | Client->HandleDiagnostic(Warning, L, Msg); 44 | return true; 45 | } 46 | 47 | DiagnosticClient::~DiagnosticClient() {} 48 | 49 | void DiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel, 50 | llvm::SMLoc, 51 | const llvm::Twine &) { 52 | if (!IncludeInDiagnosticCounts()) 53 | return; 54 | 55 | if (DiagLevel == Diagnostic::Warning) 56 | ++NumWarnings; 57 | else if (DiagLevel >= Diagnostic::Error) 58 | ++NumErrors; 59 | } 60 | -------------------------------------------------------------------------------- /lib/Basic/IdentifierTable.cpp: -------------------------------------------------------------------------------- 1 | //===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the IdentifierInfo, IdentifierVisitor, and 11 | // IdentifierTable interfaces. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "flang/Basic/IdentifierTable.h" 16 | #include "flang/Basic/LangOptions.h" 17 | #include "llvm/ADT/FoldingSet.h" 18 | #include "llvm/ADT/StringRef.h" 19 | #include 20 | using namespace flang; 21 | 22 | //===----------------------------------------------------------------------===// 23 | // IdentifierInfo Implementation 24 | //===----------------------------------------------------------------------===// 25 | 26 | IdentifierInfo::IdentifierInfo() 27 | : TokenID(tok::identifier), FETokenInfo(0), Entry(0) {} 28 | 29 | //===----------------------------------------------------------------------===// 30 | // IdentifierTable Implementation 31 | //===----------------------------------------------------------------------===// 32 | 33 | IdentifierInfoLookup::~IdentifierInfoLookup() {} 34 | 35 | IdentifierTable::IdentifierTable(const LangOptions &LangOpts, 36 | IdentifierInfoLookup* externalLookup) 37 | : IdentifierHashTable(8192), // Start with space for 8K identifiers. 38 | KeywordHashTable(64), // Start with space for 64 keywords. 39 | BuiltinHashTable(256), // Start with space for 256 builtins. 40 | ExternalLookup(externalLookup) { 41 | 42 | // Populate the identifier table with info about keywords for the current 43 | // language. 44 | AddPredefineds(LangOpts); 45 | } 46 | 47 | //===----------------------------------------------------------------------===// 48 | // Language Keyword Implementation 49 | //===----------------------------------------------------------------------===// 50 | 51 | // Constants for TokenKinds.def 52 | namespace { 53 | enum { 54 | KEYALL = 0x01, 55 | KEYF77 = 0x02, 56 | KEYF90 = 0x04, 57 | KEYF95 = 0x08, 58 | KEYF2003 = 0x10, 59 | KEYF2008 = 0x20, 60 | KEYNOTF77 = 0x40 61 | }; 62 | } 63 | 64 | /// AddPredefined - This method is used to associate a token ID with specific 65 | /// identifiers because they are language keywords or built-ins. This causes the 66 | /// lexer to automatically map matching identifiers to specialized token codes. 67 | static void AddPredefined(llvm::StringRef ID, tok::TokenKind TokenCode, 68 | unsigned Flags, const LangOptions &LangOpts, 69 | IdentifierTable &Table, bool isBuiltin) { 70 | if ((Flags & KEYALL) || 71 | (!LangOpts.Fortran77 && (Flags & KEYNOTF77)) || 72 | (LangOpts.Fortran77 && (Flags & KEYF77)) || 73 | (LangOpts.Fortran90 && (Flags & KEYF90)) || 74 | (LangOpts.Fortran95 && (Flags & KEYF95)) || 75 | (LangOpts.Fortran2003 && (Flags & KEYF2003)) || 76 | (LangOpts.Fortran2008 && (Flags & KEYF2008))) { 77 | if (!isBuiltin) 78 | Table.getKeyword(ID, TokenCode); 79 | else 80 | Table.getBuiltin(ID, TokenCode); 81 | } 82 | } 83 | 84 | /// AddPredefineds - Add all predefined identifiers to the symbol tables. 85 | void IdentifierTable::AddPredefineds(const LangOptions &LangOpts) { 86 | // Add keywords and tokens for the current language. 87 | #define KEYWORD(NAME, FLAGS) \ 88 | AddPredefined(llvm::StringRef(#NAME), tok::kw_ ## NAME, \ 89 | FLAGS, LangOpts, *this, false); 90 | #define BUILTIN(NAME, FLAGS) \ 91 | AddPredefined(llvm::StringRef(#NAME), tok::bi_ ## NAME, \ 92 | FLAGS, LangOpts, *this, true); 93 | #include "flang/Basic/TokenKinds.def" 94 | } 95 | 96 | //===----------------------------------------------------------------------===// 97 | // Stats Implementation 98 | //===----------------------------------------------------------------------===// 99 | 100 | /// PrintStats - Print statistics about how well the identifier table is doing 101 | /// at hashing identifiers. 102 | void IdentifierTable::PrintStats() const { 103 | unsigned NumBuckets = 104 | IdentifierHashTable.getNumBuckets() + KeywordHashTable.getNumBuckets() + 105 | BuiltinHashTable.getNumBuckets(); 106 | unsigned NumIdentifiers = 107 | IdentifierHashTable.getNumItems() + KeywordHashTable.getNumItems() + 108 | BuiltinHashTable.getNumItems(); 109 | unsigned NumEmptyBuckets = NumBuckets - NumIdentifiers; 110 | unsigned AverageIdentifierSize = 0; 111 | unsigned MaxIdentifierLength = 0; 112 | 113 | // TODO: Figure out maximum times an identifier had to probe for -stats. 114 | for (llvm::StringMap::const_iterator 115 | I = IdentifierHashTable.begin(), E = IdentifierHashTable.end(); 116 | I != E; ++I) { 117 | unsigned IdLen = I->getKeyLength(); 118 | AverageIdentifierSize += IdLen; 119 | if (MaxIdentifierLength < IdLen) 120 | MaxIdentifierLength = IdLen; 121 | } 122 | 123 | for (llvm::StringMap::const_iterator 124 | I = KeywordHashTable.begin(), E = KeywordHashTable.end(); 125 | I != E; ++I) { 126 | unsigned IdLen = I->getKeyLength(); 127 | AverageIdentifierSize += IdLen; 128 | if (MaxIdentifierLength < IdLen) 129 | MaxIdentifierLength = IdLen; 130 | } 131 | 132 | for (llvm::StringMap::const_iterator 133 | I = BuiltinHashTable.begin(), E = BuiltinHashTable.end(); 134 | I != E; ++I) { 135 | unsigned IdLen = I->getKeyLength(); 136 | AverageIdentifierSize += IdLen; 137 | if (MaxIdentifierLength < IdLen) 138 | MaxIdentifierLength = IdLen; 139 | } 140 | 141 | fprintf(stderr, "\n*** Identifier Tables Stats:\n"); 142 | fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers); 143 | fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets); 144 | fprintf(stderr, "Hash density (#identifiers per bucket): %f\n", 145 | NumIdentifiers / (double)NumBuckets); 146 | fprintf(stderr, "Ave identifier length: %f\n", 147 | (AverageIdentifierSize / (double)NumIdentifiers)); 148 | fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength); 149 | 150 | // Compute statistics about the memory allocated for identifiers. 151 | IdentifierHashTable.getAllocator().PrintStats(); 152 | KeywordHashTable.getAllocator().PrintStats(); 153 | BuiltinHashTable.getAllocator().PrintStats(); 154 | } 155 | -------------------------------------------------------------------------------- /lib/Basic/Makefile: -------------------------------------------------------------------------------- 1 | ##===- flang/lib/Basic/Makefile ----------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | # 10 | # This implements the Basic library for the Fortran front-end. 11 | # 12 | ##===----------------------------------------------------------------------===## 13 | 14 | FLANG_LEVEL := ../.. 15 | LIBRARYNAME := flangBasic 16 | 17 | include $(FLANG_LEVEL)/Makefile 18 | 19 | SVN_REVISION := $(strip \ 20 | $(shell $(LLVM_SRC_ROOT)/utils/GetSourceVersion $(PROJ_SRC_DIR)/../..)) 21 | 22 | SVN_REPOSITORY := $(strip \ 23 | $(shell $(LLVM_SRC_ROOT)/utils/GetRepositoryPath $(PROJ_SRC_DIR)/../..)) 24 | 25 | CPP.Defines += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include \ 26 | -DSVN_REVISION='"$(SVN_REVISION)"' -DSVN_REPOSITORY='"$(SVN_REPOSITORY)"' 27 | 28 | $(ObjDir)/.ver-svn .ver: $(ObjDir)/.dir 29 | @if [ '$(SVN_REVISION)' != '$(shell cat $(ObjDir)/.ver-svn 2>/dev/null)' ]; then\ 30 | echo '$(SVN_REVISION)' > $(ObjDir)/.ver-svn; \ 31 | fi 32 | $(ObjDir)/.ver-svn: .ver 33 | $(ObjDir)/Version.o: $(ObjDir)/.ver-svn 34 | -------------------------------------------------------------------------------- /lib/Basic/Token.cpp: -------------------------------------------------------------------------------- 1 | //===--- Token.cpp - Token implementation ---------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the Token interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Basic/Token.h" 15 | #include "llvm/Support/raw_ostream.h" 16 | #include "llvm/ADT/StringRef.h" 17 | #include "llvm/ADT/SmallString.h" 18 | #include "llvm/ADT/Twine.h" 19 | #include "flang/Basic/LLVM.h" 20 | using namespace flang; 21 | 22 | static inline bool isHorizontalWhitespace(char C) { 23 | return C == ' ' || C == '\t' || C == '\f' || C == '\v'; 24 | } 25 | 26 | /// CleanLiteral - Return the literal cleaned up of any line continuations. 27 | std::string Token::CleanLiteral(SmallVectorImpl &Spelling) const { 28 | if (!needsCleaning()) 29 | return Spelling[0].str(); 30 | 31 | std::string Name; 32 | Name.reserve(256); 33 | for (llvm::SmallVectorImpl::const_iterator 34 | I = Spelling.begin(), E = Spelling.end(); I != E; ++I) 35 | Name += *I; 36 | 37 | return Name; 38 | } 39 | 40 | /// CleanCharContext - Clean up a character context which is "dirty" (has 41 | /// continuations in it). 42 | llvm::Twine Token::CleanCharContext() { 43 | assert(is(tok::char_literal_constant) && needsCleaning() && 44 | "Trying to clean a pristene character context!"); 45 | llvm::Twine CharContext; 46 | const char *CurPtr = getLiteralData(); 47 | const char *Start = Start; 48 | 49 | while (true) { 50 | while (*CurPtr != '&') { 51 | if (*CurPtr != '\'') 52 | ++CurPtr; 53 | else if (CurPtr[1] == '\'') 54 | CurPtr += 2; 55 | else 56 | break; 57 | } 58 | 59 | if (*CurPtr == '\'') break; 60 | 61 | const char *Amp = CurPtr++; 62 | while (isHorizontalWhitespace(*CurPtr)) 63 | ++CurPtr; 64 | 65 | if (*CurPtr != '\n' && *CurPtr != '\r') 66 | continue; 67 | 68 | CharContext = CharContext + 69 | llvm::Twine(llvm::StringRef(Start, Amp - Start)); 70 | 71 | while (true) { 72 | while (isHorizontalWhitespace(*CurPtr) || 73 | *CurPtr == '\n' || *CurPtr == '\r') 74 | ++CurPtr; 75 | 76 | if (*CurPtr == '!') { 77 | while (*CurPtr != '\n' && *CurPtr != '\r') 78 | ++CurPtr; 79 | } else { 80 | break; 81 | } 82 | } 83 | 84 | Start = ++CurPtr; 85 | } 86 | 87 | return CharContext + 88 | llvm::Twine(llvm::StringRef(CurPtr, Start - CurPtr)); 89 | } 90 | -------------------------------------------------------------------------------- /lib/Basic/TokenKinds.cpp: -------------------------------------------------------------------------------- 1 | //===--- TokenKinds.cpp - Token Kinds Support -----------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the TokenKind enum and support functions. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Basic/TokenKinds.h" 15 | #include 16 | 17 | using namespace flang; 18 | 19 | static char const * const TokNames[] = { 20 | #define TOK(X) #X, 21 | #define KEYWORD(X,Y) #X, 22 | #define BUILTIN(X,Y) #X, 23 | #include "flang/Basic/TokenKinds.def" 24 | 0 25 | }; 26 | 27 | const char *tok::getTokenName(enum TokenKind Kind) { 28 | assert(Kind < tok::NUM_TOKENS && "Invalid token kind!"); 29 | return TokNames[Kind]; 30 | } 31 | 32 | const char *tok::getTokenSimpleSpelling(enum TokenKind Kind) { 33 | switch (Kind) { 34 | case tok::equal: return "="; 35 | case tok::equalequal: return "=="; 36 | case tok::plus: return "+"; 37 | case tok::minus: return "-"; 38 | case tok::star: return "*"; 39 | case tok::starstar: return "**"; 40 | case tok::slash: return "/"; 41 | case tok::slashequal: return "/="; 42 | case tok::backslash: return "\\"; 43 | case tok::l_paren: return "("; 44 | case tok::r_paren: return ")"; 45 | case tok::l_square: return "["; 46 | case tok::r_square: return "]"; 47 | case tok::l_brace: return "{"; 48 | case tok::r_brace: return "}"; 49 | case tok::comma: return ","; 50 | case tok::period: return "."; 51 | case tok::colon: return ":"; 52 | case tok::coloncolon: return "::"; 53 | case tok::semicolon: return ";"; 54 | case tok::exclaim: return "!"; 55 | case tok::percent: return "%"; 56 | case tok::ampersand: return "&"; 57 | case tok::tilde: return "~"; 58 | case tok::less: return "<"; 59 | case tok::lessequal: return "<="; 60 | case tok::greater: return ">"; 61 | case tok::greaterequal: return ">="; 62 | case tok::question: return "?"; 63 | case tok::backtick: return "`"; 64 | case tok::caret: return "^"; 65 | case tok::pipe: return "|"; 66 | case tok::dollar: return "$"; 67 | case tok::hash: return "#"; 68 | case tok::at: return "@"; 69 | default: break; 70 | } 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /lib/Frontend/Makefile: -------------------------------------------------------------------------------- 1 | ##===- flang/lib/Parse/Makefile ----------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | # 10 | # This implements the Parser library for the Fortran front-end. 11 | # 12 | ##===----------------------------------------------------------------------===## 13 | 14 | FLANG_LEVEL := ../.. 15 | LIBRARYNAME := flangFrontend 16 | 17 | include $(FLANG_LEVEL)/Makefile 18 | -------------------------------------------------------------------------------- /lib/Frontend/TextDiagnosticPrinter.cpp: -------------------------------------------------------------------------------- 1 | //===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This diagnostic client prints out their diagnostic messages. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Frontend/TextDiagnosticPrinter.h" 15 | #include "llvm/Support/MemoryBuffer.h" 16 | #include "llvm/Support/SourceMgr.h" 17 | #include "llvm/Support/raw_ostream.h" 18 | #include "llvm/ADT/SmallString.h" 19 | #include "llvm/ADT/StringExtras.h" 20 | #include 21 | using namespace flang; 22 | 23 | static const enum llvm::raw_ostream::Colors noteColor = 24 | llvm::raw_ostream::BLACK; 25 | static const enum llvm::raw_ostream::Colors fixitColor = 26 | llvm::raw_ostream::GREEN; 27 | static const enum llvm::raw_ostream::Colors caretColor = 28 | llvm::raw_ostream::GREEN; 29 | static const enum llvm::raw_ostream::Colors warningColor = 30 | llvm::raw_ostream::MAGENTA; 31 | static const enum llvm::raw_ostream::Colors errorColor = llvm::raw_ostream::RED; 32 | static const enum llvm::raw_ostream::Colors fatalColor = llvm::raw_ostream::RED; 33 | // Used for changing only the bold attribute. 34 | static const enum llvm::raw_ostream::Colors savedColor = 35 | llvm::raw_ostream::SAVEDCOLOR; 36 | 37 | /// \brief Number of spaces to indent when word-wrapping. 38 | const unsigned WordWrapIndentation = 6; 39 | 40 | TextDiagnosticPrinter::~TextDiagnosticPrinter() {} 41 | 42 | void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, 43 | llvm::SMLoc L, 44 | const llvm::Twine &Msg) { 45 | // Default implementation (Warnings/errors count). 46 | DiagnosticClient::HandleDiagnostic(Level, L, Msg); 47 | llvm::SourceMgr::DiagKind MsgTy; 48 | switch (Level) { 49 | case Diagnostic::Ignored: return; 50 | case Diagnostic::Note: MsgTy = llvm::SourceMgr::DK_Note; break; 51 | case Diagnostic::Warning: MsgTy = llvm::SourceMgr::DK_Warning; break; 52 | case Diagnostic::Error: MsgTy = llvm::SourceMgr::DK_Error; break; 53 | case Diagnostic::Fatal: MsgTy = llvm::SourceMgr::DK_Error; break; 54 | } 55 | 56 | SrcMgr.PrintMessage(L, MsgTy, Msg); 57 | } 58 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | ##===- lib/Makefile ----------------------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | FLANG_LEVEL := .. 11 | 12 | PARALLEL_DIRS = Basic Parse AST Frontend Sema 13 | 14 | include $(FLANG_LEVEL)/Makefile 15 | -------------------------------------------------------------------------------- /lib/Parse/Makefile: -------------------------------------------------------------------------------- 1 | ##===- flang/lib/Parse/Makefile ----------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | # 10 | # This implements the Parser library for the Fortran front-end. 11 | # 12 | ##===----------------------------------------------------------------------===## 13 | 14 | FLANG_LEVEL := ../.. 15 | LIBRARYNAME := flangParse 16 | 17 | include $(FLANG_LEVEL)/Makefile 18 | -------------------------------------------------------------------------------- /lib/Parse/ParseExec.cpp: -------------------------------------------------------------------------------- 1 | //===-- ParseExec.cpp - Parse Executable Construct ------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Functions to parse the executable construct (R213). 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Parse/Parser.h" 15 | #include "flang/AST/Decl.h" 16 | #include "flang/AST/Expr.h" 17 | #include "flang/AST/Stmt.h" 18 | #include "flang/Basic/TokenKinds.h" 19 | #include "flang/Sema/DeclSpec.h" 20 | #include "flang/Sema/Sema.h" 21 | #include "llvm/Support/SourceMgr.h" 22 | #include "llvm/Support/raw_ostream.h" 23 | using namespace flang; 24 | 25 | /// ParseExecutableConstruct - Parse the executable construct. 26 | /// 27 | /// [R213]: 28 | /// executable-construct := 29 | /// action-stmt 30 | /// or associate-construct 31 | /// or block-construct 32 | /// or case-construct 33 | /// or critical-construct 34 | /// or do-construct 35 | /// or forall-construct 36 | /// or if-construct 37 | /// or select-type-construct 38 | /// or where-construct 39 | StmtResult Parser::ParseExecutableConstruct() { 40 | StmtResult SR = ParseActionStmt(); 41 | if (!SR.isUsable()) return StmtResult(); 42 | 43 | return SR; 44 | } 45 | 46 | /// ParseActionStmt - Parse an action statement. 47 | /// 48 | /// [R214]: 49 | /// action-stmt := 50 | /// allocate-stmt 51 | /// or assignment-stmt 52 | /// or backspace-stmt 53 | /// or call-stmt 54 | /// or close-stmt 55 | /// or continue-stmt 56 | /// or cycle-stmt 57 | /// or deallocate-stmt 58 | /// or end-function-stmt 59 | /// or end-mp-subprogram-stmt 60 | /// or end-program-stmt 61 | /// or end-subroutine-stmt 62 | /// or endfile-stmt 63 | /// or error-stop-stmt 64 | /// or exit-stmt 65 | /// or flush-stmt 66 | /// or forall-stmt 67 | /// or goto-stmt 68 | /// or if-stmt 69 | /// or inquire-stmt 70 | /// or lock-stmt 71 | /// or nullify-stmt 72 | /// or open-stmt 73 | /// or pointer-assignment-stmt 74 | /// or print-stmt 75 | /// or read-stmt 76 | /// or return-stmt 77 | /// or rewind-stmt 78 | /// or stop-stmt 79 | /// or sync-all-stmt 80 | /// or sync-images-stmt 81 | /// or sync-memory-stmt 82 | /// or unlock-stmt 83 | /// or wait-stmt 84 | /// or where-stmt 85 | /// or write-stmt 86 | ///[obs] or arithmetic-if-stmt 87 | ///[obs] or computed-goto-stmt 88 | Parser::StmtResult Parser::ParseActionStmt() { 89 | ParseStatementLabel(); 90 | 91 | // This is an assignment. 92 | if (Tok.getIdentifierInfo() && !NextTok.isAtStartOfStatement() && 93 | NextTok.is(tok::equal)) 94 | return ParseAssignmentStmt(); 95 | 96 | StmtResult SR; 97 | switch (Tok.getKind()) { 98 | default: assert(false && "Unknown statement type!"); break; 99 | case tok::kw_PRINT: 100 | return ParsePrintStmt(); 101 | 102 | case tok::kw_END: 103 | // TODO: All of the end-* stmts. 104 | break; 105 | case tok::kw_ENDFUNCTION: 106 | case tok::kw_ENDPROGRAM: 107 | case tok::kw_ENDSUBPROGRAM: 108 | case tok::kw_ENDSUBROUTINE: 109 | // Handle in parent. 110 | return StmtResult(); 111 | } 112 | 113 | return SR; 114 | } 115 | 116 | /// ParseAssignmentStmt 117 | /// [R732]: 118 | /// assignment-stmt := 119 | /// variable = expr 120 | Parser::StmtResult Parser::ParseAssignmentStmt() { 121 | ExprResult LHS = ParseExpression(); 122 | 123 | assert(Tok.is(tok::equal) && "Not a valid assignment statement!"); 124 | EatIfPresent(tok::equal); 125 | 126 | ExprResult RHS = ParseExpression(); 127 | return Actions.ActOnAssignmentStmt(Context, LHS, RHS, StmtLabel); 128 | } 129 | 130 | /// ParsePrintStatement 131 | /// [R912]: 132 | /// print-stmt := 133 | /// PRINT format [, output-item-list] 134 | /// [R915]: 135 | /// format := 136 | /// default-char-expr 137 | /// or label 138 | /// or * 139 | Parser::StmtResult Parser::ParsePrintStmt() { 140 | SMLoc Loc = Tok.getLocation(); 141 | Lex(); 142 | 143 | SMLoc FormatLoc = Tok.getLocation(); 144 | FormatSpec *FS = 0; 145 | if (EatIfPresent(tok::star)) { 146 | FS = Actions.ActOnStarFormatSpec(Context, FormatLoc); 147 | } 148 | 149 | // TODO: Parse the FORMAT default-char-expr & label. 150 | 151 | if (!EatIfPresent(tok::comma)) { 152 | Diag.ReportError(Tok.getLocation(), 153 | "expected ',' after format specifier in PRINT statement"); 154 | return StmtResult(true); 155 | } 156 | 157 | SmallVector OutputItemList; 158 | while (!Tok.isAtStartOfStatement()) { 159 | OutputItemList.push_back(ParseExpression()); 160 | if (!EatIfPresent(tok::comma)) 161 | break; 162 | } 163 | 164 | return Actions.ActOnPrintStmt(Context, Loc, FS, OutputItemList, StmtLabel); 165 | } 166 | 167 | /// ParseEND_PROGRAMStmt - Parse the END PROGRAM statement. 168 | /// 169 | /// [R1103]: 170 | /// end-program-stmt := 171 | /// END [ PROGRAM [ program-name ] ] 172 | Parser::StmtResult Parser::ParseEND_PROGRAMStmt() { 173 | llvm::SMLoc Loc = Tok.getLocation(); 174 | if (Tok.isNot(tok::kw_END) && Tok.isNot(tok::kw_ENDPROGRAM)) { 175 | Diag.ReportError(Tok.getLocation(), 176 | "expected 'END PROGRAM' statement"); 177 | return StmtResult(); 178 | } 179 | Lex(); 180 | 181 | const IdentifierInfo *IDInfo = 0; 182 | llvm::SMLoc NameLoc; 183 | if (Tok.is(tok::identifier) && !Tok.isAtStartOfStatement()) { 184 | IDInfo = Tok.getIdentifierInfo(); 185 | NameLoc = Tok.getLocation(); 186 | Lex(); // Eat the ending token. 187 | } 188 | 189 | return Actions.ActOnENDPROGRAM(Context, IDInfo, Loc, NameLoc, StmtLabel); 190 | } 191 | -------------------------------------------------------------------------------- /lib/Sema/DeclSpec.cpp: -------------------------------------------------------------------------------- 1 | //===-- DeclSpec.cpp - Fortran Declaration Type Specifier Interface ---===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // The Fortran declaration type specifier interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Sema/DeclSpec.h" 15 | #include "flang/AST/Expr.h" 16 | #include "flang/AST/Type.h" 17 | #include "llvm/Support/raw_ostream.h" 18 | #include "llvm/ADT/ArrayRef.h" 19 | #include "llvm/Support/ErrorHandling.h" 20 | using namespace flang; 21 | 22 | namespace flang { 23 | namespace diag { 24 | enum { 25 | #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ 26 | SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, 27 | #include "flang/Basic/DiagnosticParseKinds.inc" 28 | #undef DIAG 29 | NUM_BUILTIN_PARSE_DIAGNOSTICS 30 | }; 31 | } // end namespace diag 32 | } // end namespace flang 33 | 34 | DeclSpec::~DeclSpec() {} 35 | 36 | template 37 | static bool BadSpecifier(T TNew, T TPrev, const char *&PrevSpec, 38 | unsigned &DiagID) { 39 | PrevSpec = DeclSpec::getSpecifierName(TPrev); 40 | DiagID = (TNew == TPrev ? diag::err_duplicate_declspec 41 | : diag::err_invalid_decl_spec_combination); 42 | return true; 43 | } 44 | 45 | const char *DeclSpec::getSpecifierName(DeclSpec::TST I) { 46 | switch (I) { 47 | case TST_unspecified: return "unspecified"; 48 | case TST_integer: return "INTEGER"; 49 | case TST_real: return "REAL"; 50 | case TST_doubleprecision: return "DOUBLEPRECISION"; 51 | case TST_complex: return "COMPLEX"; 52 | case TST_character: return "CHARACTER"; 53 | case TST_logical: return "LOGICAL"; 54 | case TST_struct: return "TYPE"; 55 | } 56 | llvm_unreachable("Unknown typespec!"); 57 | } 58 | 59 | const char *DeclSpec::getSpecifierName(DeclSpec::AS A) { 60 | switch (A) { 61 | case AS_unspecified: return "unspecified"; 62 | case AS_allocatable: return "ALLOCATABLE"; 63 | case AS_asynchronous: return "ASYNCHRONOUS"; 64 | case AS_codimension: return "CODIMENSION"; 65 | case AS_contiguous: return "CONTIGUOUS"; 66 | case AS_dimension: return "DIMENSION"; 67 | case AS_external: return "EXTERNAL"; 68 | case AS_intrinsic: return "INTRINSIC"; 69 | case AS_optional: return "OPTIONAL"; 70 | case AS_parameter: return "PARAMETER"; 71 | case AS_pointer: return "POINTER"; 72 | case AS_protected: return "PROTECTED"; 73 | case AS_save: return "SAVE"; 74 | case AS_target: return "TARGET"; 75 | case AS_value: return "VALUE"; 76 | case AS_volatile: return "VOLATILE"; 77 | } 78 | llvm_unreachable("Unknown typespec!"); 79 | } 80 | 81 | const char *DeclSpec::getSpecifierName(DeclSpec::IS I) { 82 | switch (I) { 83 | case IS_unspecified: return "unspecified"; 84 | case IS_in: return "IN"; 85 | case IS_out: return "OUT"; 86 | case IS_inout: return "INOUT"; 87 | } 88 | llvm_unreachable("Unknown typespec!"); 89 | } 90 | 91 | void DeclSpec::setDimensions(ArrayRef Dims) { 92 | assert(hasAttributeSpec(AS_dimension) && 93 | "Adding dimensions to a non-array declspec!"); 94 | Dimensions.reserve(Dims.size()); 95 | for (ArrayRef::iterator 96 | I = Dims.begin(), E = Dims.end(); I != E; ++I) 97 | Dimensions.push_back(*I); 98 | } 99 | -------------------------------------------------------------------------------- /lib/Sema/Makefile: -------------------------------------------------------------------------------- 1 | ##===- flang/lib/Sema/Makefile -----------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | # 10 | # This implements the Sema library for the Fortran front-end. 11 | # 12 | ##===----------------------------------------------------------------------===## 13 | 14 | FLANG_LEVEL := ../.. 15 | LIBRARYNAME := flangSema 16 | 17 | include $(FLANG_LEVEL)/Makefile 18 | -------------------------------------------------------------------------------- /lib/Sema/Scope.cpp: -------------------------------------------------------------------------------- 1 | //===- Scope.cpp - Lexical scope information ------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the Scope class, which is used for recording information 11 | // about a lexical scope. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "flang/Sema/Scope.h" 16 | using namespace flang; 17 | 18 | void Scope::Init(Scope *parent, unsigned flags) { 19 | AnyParent = parent; 20 | Flags = flags; 21 | 22 | if (parent) { 23 | Depth = parent->Depth + 1; 24 | PrototypeDepth = parent->PrototypeDepth; 25 | PrototypeIndex = 0; 26 | FnParent = parent->FnParent; 27 | } else { 28 | Depth = 0; 29 | PrototypeDepth = 0; 30 | PrototypeIndex = 0; 31 | FnParent = 0; 32 | } 33 | 34 | // If this scope is a function or contains breaks/continues, remember it. 35 | if (flags & FnScope) FnParent = this; 36 | 37 | DeclsInScope.clear(); 38 | Entity = 0; 39 | ErrorTrap.reset(); 40 | } 41 | -------------------------------------------------------------------------------- /lib/Sema/Sema.cpp: -------------------------------------------------------------------------------- 1 | //===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file implements the actions class which performs semantic analysis and 11 | // builds an AST out of a parse stream. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "flang/Sema/Sema.h" 16 | #include "flang/Sema/DeclSpec.h" 17 | #include "flang/AST/ASTContext.h" 18 | #include "flang/AST/Decl.h" 19 | #include "flang/AST/Expr.h" 20 | #include "flang/AST/Stmt.h" 21 | #include "flang/Basic/Diagnostic.h" 22 | #include "llvm/Support/raw_ostream.h" 23 | using namespace flang; 24 | 25 | Sema::Sema(ASTContext &ctxt, Diagnostic &D) 26 | : Context(ctxt), Diags(D), CurContext(0) {} 27 | 28 | Sema::~Sema() {} 29 | 30 | // getContainingDC - Determines the context to return to after temporarily 31 | // entering a context. This depends in an unnecessarily complicated way on the 32 | // exact ordering of callbacks from the parser. 33 | DeclContext *Sema::getContainingDC(DeclContext *DC) { 34 | return DC->getParent(); 35 | } 36 | 37 | void Sema::PushDeclContext(DeclContext *DC) { 38 | assert(getContainingDC(DC) == CurContext && 39 | "The next DeclContext should be lexically contained in the current one."); 40 | CurContext = DC; 41 | } 42 | 43 | void Sema::PopDeclContext() { 44 | assert(CurContext && "DeclContext imbalance!"); 45 | CurContext = getContainingDC(CurContext); 46 | assert(CurContext && "Popped translation unit!"); 47 | } 48 | 49 | void Sema::ActOnTranslationUnit() { 50 | PushDeclContext(Context.getTranslationUnitDecl()); 51 | } 52 | 53 | void Sema::ActOnEndProgramUnit() { 54 | PopDeclContext(); 55 | } 56 | 57 | void Sema::ActOnMainProgram(const IdentifierInfo *IDInfo, SMLoc NameLoc) { 58 | DeclarationName DN(IDInfo); 59 | DeclarationNameInfo NameInfo(DN, NameLoc); 60 | PushDeclContext(MainProgramDecl::Create(Context, 61 | Context.getTranslationUnitDecl(), 62 | NameInfo)); 63 | } 64 | 65 | void Sema::ActOnEndMainProgram(const IdentifierInfo *IDInfo, SMLoc NameLoc) { 66 | assert(CurContext && "DeclContext imbalance!"); 67 | 68 | DeclarationName DN(IDInfo); 69 | DeclarationNameInfo EndNameInfo(DN, NameLoc); 70 | 71 | StringRef ProgName = cast(CurContext)->getName(); 72 | if (ProgName.empty()) { 73 | PopDeclContext(); 74 | return; 75 | } 76 | 77 | const IdentifierInfo *ID = EndNameInfo.getName().getAsIdentifierInfo(); 78 | if (!ID) goto exit; 79 | 80 | if (ProgName != ID->getName()) 81 | Diags.ReportError(EndNameInfo.getLoc(), 82 | llvm::Twine("expected label '") + 83 | ProgName + "' for END PROGRAM statement"); 84 | exit: 85 | PopDeclContext(); 86 | } 87 | 88 | /// \brief Convert the specified DeclSpec to the appropriate type object. 89 | QualType Sema::ActOnTypeName(ASTContext &C, DeclSpec &DS) { 90 | QualType Result; 91 | switch (DS.getTypeSpecType()) { 92 | case DeclSpec::TST_integer: 93 | Result = C.IntegerTy; 94 | break; 95 | case DeclSpec::TST_unspecified: // FIXME: Correct? 96 | case DeclSpec::TST_real: 97 | Result = C.RealTy; 98 | break; 99 | case DeclSpec::TST_doubleprecision: 100 | Result = C.DoublePrecisionTy; 101 | break; 102 | case DeclSpec::TST_character: 103 | Result = C.CharacterTy; 104 | break; 105 | case DeclSpec::TST_logical: 106 | Result = C.LogicalTy; 107 | break; 108 | case DeclSpec::TST_complex: 109 | Result = C.ComplexTy; 110 | break; 111 | case DeclSpec::TST_struct: 112 | // FIXME: Finish this. 113 | break; 114 | } 115 | 116 | if (!DS.hasAttributes()) 117 | return Result; 118 | 119 | const Type *TypeNode = Result.getTypePtr(); 120 | Qualifiers Quals = Qualifiers::fromOpaqueValue(DS.getAttributeSpecs()); 121 | Quals.setIntentAttr(DS.getIntentSpec()); 122 | Quals.setAccessAttr(DS.getAccessSpec()); 123 | QualType EQs = C.getExtQualType(TypeNode, Quals, DS.getKindSelector(), 124 | DS.getLengthSelector()); 125 | if (!Quals.hasAttributeSpec(Qualifiers::AS_dimension)) 126 | return EQs; 127 | 128 | return ActOnArraySpec(C, EQs, DS.getDimensions()); 129 | } 130 | 131 | VarDecl *Sema::ActOnKindSelector(ASTContext &C, SMLoc IDLoc, 132 | const IdentifierInfo *IDInfo) { 133 | VarDecl *VD = VarDecl::Create(C, CurContext, IDLoc, IDInfo, QualType()); 134 | CurContext->addDecl(VD); 135 | 136 | // Store the Decl in the IdentifierInfo for easy access. 137 | const_cast(IDInfo)->setFETokenInfo(VD); 138 | return VD; 139 | } 140 | 141 | Decl *Sema::ActOnEntityDecl(ASTContext &C, DeclSpec &DS, llvm::SMLoc IDLoc, 142 | const IdentifierInfo *IDInfo) { 143 | if (const VarDecl *Prev = IDInfo->getFETokenInfo()) { 144 | if (Prev->getDeclContext() == CurContext) { 145 | Diags.ReportError(IDLoc, 146 | llvm::Twine("variable '") + IDInfo->getName() + 147 | "' already declared"); 148 | Diags.getClient()->HandleDiagnostic(Diagnostic::Note, Prev->getLocation(), 149 | "previous declaration"); 150 | return 0; 151 | } 152 | } 153 | 154 | QualType T = ActOnTypeName(C, DS); 155 | VarDecl *VD = VarDecl::Create(C, CurContext, IDLoc, IDInfo, T); 156 | CurContext->addDecl(VD); 157 | 158 | // Store the Decl in the IdentifierInfo for easy access. 159 | const_cast(IDInfo)->setFETokenInfo(VD); 160 | 161 | // FIXME: For debugging: 162 | llvm::outs() << "(declaration\n '"; 163 | VD->print(llvm::outs()); 164 | llvm::outs() << "')\n"; 165 | 166 | return VD; 167 | } 168 | 169 | Decl *Sema::ActOnImplicitEntityDecl(ASTContext &C, SMLoc IDLoc, 170 | const IdentifierInfo *IDInfo) { 171 | // FIXME: This needs to look at the IMPLICIT statements, if any. 172 | DeclSpec DS; 173 | DS.SetTypeSpecType(DeclSpec::TST_real); 174 | 175 | return ActOnEntityDecl(C, DS, IDLoc, IDInfo); 176 | } 177 | 178 | StmtResult Sema::ActOnPROGRAM(ASTContext &C, const IdentifierInfo *ProgName, 179 | SMLoc Loc, SMLoc NameLoc, Expr *StmtLabel) { 180 | return ProgramStmt::Create(C, ProgName, Loc, NameLoc, StmtLabel); 181 | } 182 | 183 | StmtResult Sema::ActOnUSE(ASTContext &C, UseStmt::ModuleNature MN, 184 | const IdentifierInfo *ModName, ExprResult StmtLabel) { 185 | return UseStmt::Create(C, MN, ModName, StmtLabel); 186 | } 187 | 188 | StmtResult Sema::ActOnUSE(ASTContext &C, UseStmt::ModuleNature MN, 189 | const IdentifierInfo *ModName, bool OnlyList, 190 | ArrayRef RenameNames, 191 | ExprResult StmtLabel) { 192 | return UseStmt::Create(C, MN, ModName, OnlyList, RenameNames, StmtLabel); 193 | } 194 | 195 | StmtResult Sema::ActOnIMPORT(ASTContext &C, SMLoc Loc, 196 | ArrayRef ImportNamesList, 197 | ExprResult StmtLabel) { 198 | return ImportStmt::Create(C, Loc, ImportNamesList, StmtLabel); 199 | } 200 | 201 | StmtResult Sema::ActOnIMPLICIT(ASTContext &C, SMLoc Loc, DeclSpec &DS, 202 | ArrayRef LetterSpecs, 203 | Expr *StmtLabel) { 204 | QualType Ty = ActOnTypeName(C, DS); 205 | return ImplicitStmt::Create(C, Loc, Ty, LetterSpecs, StmtLabel); 206 | } 207 | 208 | StmtResult Sema::ActOnIMPLICIT(ASTContext &C, SMLoc Loc, Expr *StmtLabel) { 209 | // IMPLICIT NONE 210 | return ImplicitStmt::Create(C, Loc, StmtLabel); 211 | } 212 | 213 | ParameterStmt::ParamPair 214 | Sema::ActOnPARAMETERPair(ASTContext &C, SMLoc Loc, const IdentifierInfo *IDInfo, 215 | ExprResult CE) { 216 | if (const VarDecl *Prev = IDInfo->getFETokenInfo()) { 217 | Diags.ReportError(Loc, 218 | llvm::Twine("variable '") + IDInfo->getName() + 219 | "' already defined"); 220 | Diags.getClient()->HandleDiagnostic(Diagnostic::Note, Prev->getLocation(), 221 | "previous definition"); 222 | return ParameterStmt::ParamPair(0, ExprResult()); 223 | } 224 | 225 | QualType T = CE.get()->getType(); 226 | VarDecl *VD = VarDecl::Create(C, CurContext, Loc, IDInfo, T); 227 | CurContext->addDecl(VD); 228 | 229 | // Store the Decl in the IdentifierInfo for easy access. 230 | const_cast(IDInfo)->setFETokenInfo(VD); 231 | return ParameterStmt::ParamPair(IDInfo, CE); 232 | } 233 | 234 | StmtResult Sema::ActOnPARAMETER(ASTContext &C, SMLoc Loc, 235 | ArrayRef ParamList, 236 | Expr *StmtLabel) { 237 | return ParameterStmt::Create(C, Loc, ParamList, StmtLabel); 238 | } 239 | 240 | StmtResult Sema::ActOnASYNCHRONOUS(ASTContext &C, SMLoc Loc, 241 | ArrayRefObjNames, 242 | Expr *StmtLabel) { 243 | return AsynchronousStmt::Create(C, Loc, ObjNames, StmtLabel); 244 | } 245 | 246 | StmtResult Sema::ActOnENDPROGRAM(ASTContext &C, 247 | const IdentifierInfo *ProgName, 248 | llvm::SMLoc Loc, llvm::SMLoc NameLoc, 249 | Expr *StmtLabel) { 250 | return EndProgramStmt::Create(C, ProgName, Loc, NameLoc, StmtLabel); 251 | } 252 | 253 | StmtResult Sema::ActOnEXTERNAL(ASTContext &C, SMLoc Loc, 254 | ArrayRef ExternalNames, 255 | Expr *StmtLabel) { 256 | return ExternalStmt::Create(C, Loc, ExternalNames, StmtLabel); 257 | } 258 | 259 | StmtResult Sema::ActOnAssignmentStmt(ASTContext &C, ExprResult LHS, 260 | ExprResult RHS, Expr *StmtLabel) { 261 | return AssignmentStmt::Create(C, LHS, RHS, StmtLabel); 262 | } 263 | 264 | QualType Sema::ActOnArraySpec(ASTContext &C, QualType ElemTy, 265 | ArrayRef Dims) { 266 | return QualType(ArrayType::Create(C, ElemTy, Dims), 0); 267 | } 268 | 269 | StarFormatSpec *Sema::ActOnStarFormatSpec(ASTContext &C, SMLoc Loc) { 270 | return StarFormatSpec::Create(C, Loc); 271 | } 272 | 273 | DefaultCharFormatSpec *Sema::ActOnDefaultCharFormatSpec(ASTContext &C, 274 | SMLoc Loc, 275 | ExprResult Fmt) { 276 | return DefaultCharFormatSpec::Create(C, Loc, Fmt); 277 | } 278 | 279 | LabelFormatSpec *ActOnLabelFormatSpec(ASTContext &C, SMLoc Loc, 280 | ExprResult Label) { 281 | return LabelFormatSpec::Create(C, Loc, Label); 282 | } 283 | 284 | StmtResult Sema::ActOnPrintStmt(ASTContext &C, SMLoc Loc, FormatSpec *FS, 285 | ArrayRef OutputItemList, 286 | Expr *StmtLabel) { 287 | return PrintStmt::Create(C, Loc, FS, OutputItemList, StmtLabel); 288 | } 289 | -------------------------------------------------------------------------------- /test/Lexer/torture.f95: -------------------------------------------------------------------------------- 1 | ! RUN: %flang < %s 2 | P& 3 | &R& 4 | &O& 5 | &G& 6 | &R& 7 | &A& 8 | &M& 9 | & TORTURE 10 | ! Torture the lexer and parser. 11 | CHARACTER (LEN=256) :: A, B, C, D, E, F 12 | 13 | A = '& 14 | &' 15 | B = '"& 16 | &"' 17 | C = 'Hello & ! world & 18 | & ooh! here'& 19 | &'s a & 20 | ! Yo! comment here! 21 | &fugly contiua& 22 | &tion''' 23 | ! An '&' is not allowed on a line by itself or with only a comment. 24 | D = '''& 25 | &"' 26 | END PROGRAM TORTURE 27 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | ##===- Makefile --------------------------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | FLANG_LEVEL := .. 11 | include $(FLANG_LEVEL)/Makefile 12 | 13 | # Test in all immediate subdirectories if unset. 14 | ifdef TESTSUITE 15 | TESTDIRS := $(TESTSUITE:%=$(PROJ_SRC_DIR)/%) 16 | else 17 | TESTDIRS ?= $(PROJ_SRC_DIR) 18 | endif 19 | 20 | # 'lit' wants objdir paths, so it will pick up the lit.site.cfg. 21 | TESTDIRS := $(TESTDIRS:$(PROJ_SRC_DIR)%=$(PROJ_OBJ_DIR)%) 22 | 23 | # Allow EXTRA_TESTDIRS to provide additional test directories. 24 | TESTDIRS += $(EXTRA_TESTDIRS) 25 | 26 | ifndef TESTARGS 27 | ifdef VERBOSE 28 | TESTARGS = -v 29 | else 30 | TESTARGS = -s -v 31 | endif 32 | endif 33 | 34 | # Make sure any extra test suites can find the main site config. 35 | LIT_ARGS := --param flang_site_config=$(PROJ_OBJ_DIR)/lit.site.cfg 36 | 37 | ifdef VG 38 | LIT_ARGS += "--vg" 39 | endif 40 | 41 | all:: lit.site.cfg 42 | @ echo '--- Running flang tests for $(TARGET_TRIPLE) ---' 43 | @ $(PYTHON) $(LLVM_SRC_ROOT)/utils/lit/lit.py \ 44 | $(LIT_ARGS) $(TESTARGS) $(TESTDIRS) 45 | 46 | FORCE: 47 | 48 | lit.site.cfg: FORCE 49 | @echo "Making Flang 'lit.site.cfg' file..." 50 | @sed -e "s#@LLVM_SOURCE_DIR@#$(LLVM_SRC_ROOT)#g" \ 51 | -e "s#@LLVM_BINARY_DIR@#$(LLVM_OBJ_ROOT)#g" \ 52 | -e "s#@LLVM_TOOLS_DIR@#$(ToolDir)#g" \ 53 | -e "s#@LLVM_LIBS_DIR@#$(LibDir)#g" \ 54 | -e "s#@FLANG_SOURCE_DIR@#$(PROJ_SRC_DIR)/..#g" \ 55 | -e "s#@FLANG_BINARY_DIR@#$(PROJ_OBJ_DIR)/..#g" \ 56 | -e "s#@TARGET_TRIPLE@#$(TARGET_TRIPLE)#g" \ 57 | $(PROJ_SRC_DIR)/lit.site.cfg.in > $@ 58 | 59 | clean:: 60 | @ find . -name Output | xargs rm -fr 61 | 62 | .PHONY: all report clean 63 | -------------------------------------------------------------------------------- /test/Parser/empty.f95: -------------------------------------------------------------------------------- 1 | ! RUN: %flang < %s 2 | PROGRAM test 3 | END PROGRAM test 4 | -------------------------------------------------------------------------------- /test/Parser/hello_world.f95: -------------------------------------------------------------------------------- 1 | ! RUN: %flang < %s 2 | PROGRAM HELLO_WORLD 3 | CHARACTER (LEN=11) :: C 4 | C = 'hello world' 5 | PRINT *, C 6 | PRINT *, 'hello world' 7 | END PROGRAM HELLO_WORLD 8 | -------------------------------------------------------------------------------- /test/Parser/minimal.f95: -------------------------------------------------------------------------------- 1 | ! RUN: %flang < %s 2 | END 3 | -------------------------------------------------------------------------------- /test/TestRunner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # TestRunner.sh - Backward compatible utility for testing an individual file. 4 | 5 | # Find where this script is. 6 | Dir=$(dirname $(which $0)) 7 | AbsDir=$(cd $Dir; pwd) 8 | 9 | # Find 'lit', assuming standard layout. 10 | lit=$AbsDir/../../../utils/lit/lit.py 11 | 12 | # Dispatch to lit. 13 | $lit "$@" 14 | -------------------------------------------------------------------------------- /test/lit.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- 2 | 3 | import os 4 | import platform 5 | 6 | # Configuration file for the 'lit' test runner. 7 | 8 | # name: The name of this test suite. 9 | config.name = 'Flang' 10 | 11 | # testFormat: The test format to use to interpret tests. 12 | # 13 | # For now we require '&&' between commands, until they get globally killed and 14 | # the test runner updated. 15 | execute_external = platform.system() != 'Windows' 16 | config.test_format = lit.formats.ShTest(execute_external) 17 | 18 | # suffixes: A list of file extensions to treat as test files. 19 | config.suffixes = ['.f95', '.ll'] 20 | 21 | # test_source_root: The root path where tests are located. 22 | config.test_source_root = os.path.dirname(__file__) 23 | 24 | # test_exec_root: The root path where tests should be run. 25 | flang_obj_root = getattr(config, 'flang_obj_root', None) 26 | if flang_obj_root is not None: 27 | config.test_exec_root = os.path.join(flang_obj_root, 'test') 28 | 29 | # Set llvm_{src,obj}_root for use by others. 30 | config.llvm_src_root = getattr(config, 'llvm_src_root', None) 31 | config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) 32 | 33 | # Tweak the PATH to include the tools dir and the scripts dir. 34 | if flang_obj_root is not None: 35 | llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) 36 | if not llvm_tools_dir: 37 | lit.fatal('No LLVM tools dir set!') 38 | path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH'])) 39 | config.environment['PATH'] = path 40 | 41 | llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) 42 | if not llvm_libs_dir: 43 | lit.fatal('No LLVM libs dir set!') 44 | path = os.path.pathsep.join((llvm_libs_dir, 45 | config.environment.get('LD_LIBRARY_PATH',''))) 46 | config.environment['LD_LIBRARY_PATH'] = path 47 | 48 | ### 49 | 50 | # Check that the object root is known. 51 | if config.test_exec_root is None: 52 | # Otherwise, we haven't loaded the site specific configuration (the user is 53 | # probably trying to run on a test file directly, and either the site 54 | # configuration hasn't been created by the build system, or we are in an 55 | # out-of-tree build situation). 56 | 57 | # Check for 'flang_site_config' user parameter, and use that if available. 58 | site_cfg = lit.params.get('flang_site_config', None) 59 | if site_cfg and os.path.exists(site_cfg): 60 | lit.load_config(config, site_cfg) 61 | raise SystemExit 62 | 63 | # Try to detect the situation where we are using an out-of-tree build by 64 | # looking for 'llvm-config'. 65 | # 66 | # FIXME: I debated (i.e., wrote and threw away) adding logic to 67 | # automagically generate the lit.site.cfg if we are in some kind of fresh 68 | # build situation. This means knowing how to invoke the build system though, 69 | # and I decided it was too much magic. We should solve this by just having 70 | # the .cfg files generated during the configuration step. 71 | 72 | llvm_config = lit.util.which('llvm-config', config.environment['PATH']) 73 | if not llvm_config: 74 | lit.fatal('No site specific configuration available!') 75 | 76 | # Get the source and object roots. 77 | llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() 78 | llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() 79 | flang_src_root = os.path.join(llvm_src_root, "tools", "flang") 80 | flang_obj_root = os.path.join(llvm_obj_root, "tools", "flang") 81 | 82 | # Validate that we got a tree which points to here, using the standard 83 | # tools/flang layout. 84 | this_src_root = os.path.dirname(config.test_source_root) 85 | if os.path.realpath(flang_src_root) != os.path.realpath(this_src_root): 86 | lit.fatal('No site specific configuration available!') 87 | 88 | # Check that the site specific configuration exists. 89 | site_cfg = os.path.join(flang_obj_root, 'test', 'lit.site.cfg') 90 | if not os.path.exists(site_cfg): 91 | lit.fatal('No site specific configuration available! You may need to ' 92 | 'run "make test" in your Flang build directory.') 93 | 94 | # Okay, that worked. Notify the user of the automagic, and reconfigure. 95 | lit.note('using out-of-tree build at %r' % flang_obj_root) 96 | lit.load_config(config, site_cfg) 97 | raise SystemExit 98 | 99 | ### 100 | 101 | # Discover the 'flang' to use. 102 | 103 | import os 104 | 105 | def inferFlang(PATH): 106 | # Determine which flang to use. 107 | flang = os.getenv('FLANG') 108 | 109 | # If the user set flang in the environment, definitely use that and don't 110 | # try to validate. 111 | if flang: 112 | return flang 113 | 114 | # Otherwise look in the path. 115 | flang = lit.util.which('flang', PATH) 116 | 117 | if not flang: 118 | lit.fatal("couldn't find 'flang' program, try setting " 119 | "FLANG in your environment") 120 | 121 | return flang 122 | 123 | # When running under valgrind, we mangle '-vg' onto the end of the triple so we 124 | # can check it with XFAIL and XTARGET. 125 | if lit.useValgrind: 126 | config.target_triple += '-vg' 127 | 128 | config.flang = inferFlang(config.environment['PATH']) 129 | if not lit.quiet: 130 | lit.note('using flang: %r' % config.flang) 131 | config.substitutions.append( ('%flang', ' ' + config.flang + ' ') ) 132 | config.substitutions.append( ('%test_debuginfo', ' ' + config.llvm_src_root + '/utils/test_debuginfo.pl ') ) 133 | 134 | # FIXME: Find nicer way to prohibit this. 135 | config.substitutions.append( 136 | (' flang ', """*** Do not use 'flang' in tests, use '%flang'. ***""") ) 137 | 138 | ### 139 | 140 | # Set available features we allow tests to conditionalize on. 141 | if platform.system() != 'Windows': 142 | config.available_features.add('crash-recovery') 143 | -------------------------------------------------------------------------------- /test/lit.site.cfg.in: -------------------------------------------------------------------------------- 1 | ## Autogenerated by LLVM/Flang configuration. 2 | # Do not edit! 3 | config.llvm_src_root = "@LLVM_SOURCE_DIR@" 4 | config.llvm_obj_root = "@LLVM_BINARY_DIR@" 5 | config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" 6 | config.llvm_libs_dir = "@LLVM_LIBS_DIR@" 7 | config.flang_obj_root = "@FLANG_BINARY_DIR@" 8 | config.target_triple = "@TARGET_TRIPLE@" 9 | 10 | # Support substitution of the tools and libs dirs with user parameters. This is 11 | # used when we can't determine the tool dir at configuration time. 12 | try: 13 | config.llvm_tools_dir = config.llvm_tools_dir % lit.params 14 | config.llvm_libs_dir = config.llvm_libs_dir % lit.params 15 | except KeyError,e: 16 | key, = e.args 17 | lit.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) 18 | 19 | # Let the main config do the real work. 20 | lit.load_config(config, "@FLANG_SOURCE_DIR@/test/lit.cfg") 21 | -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | ##===- tools/Makefile --------------------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | FLANG_LEVEL := .. 11 | DIRS := driver 12 | 13 | include $(FLANG_LEVEL)/../../Makefile.config 14 | 15 | include $(FLANG_LEVEL)/Makefile 16 | -------------------------------------------------------------------------------- /tools/driver/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | @TOOL_INFO_UTI@ 7 | CFBundleInfoDictionaryVersion 8 | 6.0 9 | CFBundleName 10 | @TOOL_INFO_NAME 11 | CFBundleShortVersionString 12 | @TOOL_INFO_VERSION@ 13 | CFBundleVersion 14 | @TOOL_INFO_BUILD_VERSION@ 15 | CFBundleSignature 16 | ???? 17 | 18 | 19 | -------------------------------------------------------------------------------- /tools/driver/Main.cpp: -------------------------------------------------------------------------------- 1 | //===-- Main.cpp - LLVM-based Fortran Compiler ----------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // The Fortran Compiler. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "flang/Frontend/TextDiagnosticPrinter.h" 15 | #include "flang/Parse/Parser.h" 16 | #include "flang/Sema/Sema.h" 17 | #include "llvm/Support/CommandLine.h" 18 | #include "llvm/Support/ManagedStatic.h" 19 | #include "llvm/Support/MemoryBuffer.h" 20 | #include "llvm/Support/Path.h" 21 | #include "llvm/Support/PrettyStackTrace.h" 22 | #include "llvm/Support/raw_ostream.h" 23 | #include "llvm/Support/Signals.h" 24 | #include "llvm/Support/SourceMgr.h" 25 | #include "llvm/Support/Timer.h" 26 | #include "llvm/Support/system_error.h" 27 | #include "llvm/ADT/OwningPtr.h" 28 | using namespace llvm; 29 | using namespace flang; 30 | 31 | llvm::sys::Path GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { 32 | if (!CanonicalPrefixes) 33 | return llvm::sys::Path(Argv0); 34 | 35 | // This just needs to be some symbol in the binary; C++ doesn't 36 | // allow taking the address of ::main however. 37 | void *P = (void*) (intptr_t) GetExecutablePath; 38 | return llvm::sys::Path::GetMainExecutable(Argv0, P); 39 | } 40 | 41 | //===----------------------------------------------------------------------===// 42 | // Command line options. 43 | //===----------------------------------------------------------------------===// 44 | 45 | namespace { 46 | 47 | cl::opt 48 | InputFilename(cl::Positional, cl::desc(""), cl::init("-")); 49 | 50 | cl::list 51 | IncludeDirs("I", cl::desc("Directory of include files"), 52 | cl::value_desc("directory"), cl::Prefix); 53 | 54 | cl::opt 55 | ReturnComments("C", cl::desc("Do not discard comments"), cl::init(false)); 56 | 57 | } // end anonymous namespace 58 | 59 | static bool ParseFile(const std::string &Filename, 60 | const std::vector &IncludeDirs) { 61 | llvm::OwningPtr MB; 62 | if (llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(Filename.c_str(), 63 | MB)) { 64 | llvm::errs() << "Could not open input file '" << Filename << "': " 65 | << ec.message() <<"\n"; 66 | return true; 67 | } 68 | 69 | // Record the location of the include directory so that the lexer can find it 70 | // later. 71 | SourceMgr SrcMgr; 72 | SrcMgr.setIncludeDirs(IncludeDirs); 73 | 74 | // Tell SrcMgr about this buffer, which is what Parser will pick up. 75 | SrcMgr.AddNewSourceBuffer(MB.take(), SMLoc()); 76 | 77 | LangOptions Opts; 78 | Opts.ReturnComments = ReturnComments; 79 | TextDiagnosticPrinter TDP(SrcMgr); 80 | Diagnostic Diag(&SrcMgr, &TDP, false); 81 | #if 0 82 | PrintAction PA(Diag); 83 | #endif 84 | ASTContext Context(SrcMgr); 85 | Sema SA(Context, Diag); 86 | Parser P(SrcMgr, Opts, Diag, SA); 87 | return P.ParseProgramUnits(); 88 | } 89 | 90 | int main(int argc, char **argv) { 91 | sys::PrintStackTraceOnErrorSignal(); 92 | PrettyStackTraceProgram X(argc, argv); 93 | cl::ParseCommandLineOptions(argc, argv, "LLVM Fortran compiler"); 94 | 95 | bool CanonicalPrefixes = true; 96 | for (int i = 1; i < argc; ++i) 97 | if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") { 98 | CanonicalPrefixes = false; 99 | break; 100 | } 101 | 102 | llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes); 103 | 104 | // Parse the input file. 105 | int Res = ParseFile(InputFilename, IncludeDirs); 106 | 107 | // If any timers were active but haven't been destroyed yet, print their 108 | // results now. This happens in -disable-free mode. 109 | llvm::TimerGroup::printAll(llvm::errs()); 110 | 111 | llvm::llvm_shutdown(); 112 | return Res; 113 | } 114 | -------------------------------------------------------------------------------- /tools/driver/Makefile: -------------------------------------------------------------------------------- 1 | ##===- tools/driver/Makefile -------------------------------*- Makefile -*-===## 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | ##===----------------------------------------------------------------------===## 9 | 10 | FLANG_LEVEL := ../.. 11 | 12 | TOOLNAME = flang 13 | 14 | # We don't currently expect production Flang builds to be interested in 15 | # plugins. This is important for startup performance. 16 | ifdef FLANG_IS_PRODUCTION 17 | TOOL_NO_EXPORTS := 1 18 | endif 19 | 20 | ifdef FLANG_ORDER_FILE 21 | TOOL_ORDER_FILE := $(FLANG_ORDER_FILE) 22 | endif 23 | 24 | # Include tool version information on OS X. 25 | TOOL_INFO_PLIST := Info.plist 26 | 27 | # Include this here so we can get the configuration of the targets that have 28 | # been configured for construction. We have to do this early so we can set up 29 | # LINK_COMPONENTS before including Makefile.rules 30 | include $(FLANG_LEVEL)/../../Makefile.config 31 | 32 | LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \ 33 | ipo selectiondag 34 | USEDLIBS = flangAST.a flangFrontend.a flangParse.a flangSema.a flangBasic.a 35 | 36 | include $(FLANG_LEVEL)/Makefile 37 | 38 | # Set the tool version information values. 39 | ifeq ($(HOST_OS),Darwin) 40 | ifdef FLANG_VENDOR 41 | TOOL_INFO_NAME := $(FLANG_VENDOR) flang 42 | else 43 | TOOL_INFO_NAME := flang 44 | endif 45 | 46 | ifdef FLANG_VENDOR_UTI 47 | TOOL_INFO_UTI := $(FLANG_VENDOR_UTI) 48 | else 49 | TOOL_INFO_UTI := org.llvm.flang 50 | endif 51 | 52 | #TOOL_INFO_VERSION := $(word 3,$(shell grep "FLANG_VERSION " \ 53 | # $(PROJ_OBJ_DIR)/$(FLANG_LEVEL)/include/flang/Basic/Version.inc)) 54 | 55 | ifdef LLVM_SUBMIT_VERSION 56 | TOOL_INFO_BUILD_VERSION := $(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) 57 | else 58 | TOOL_INFO_BUILD_VERSION := 59 | endif 60 | endif 61 | 62 | # Translate make variable to define when building a "production" Cling. 63 | ifdef FLANG_IS_PRODUCTION 64 | CPP.Defines += -DFLANG_IS_PRODUCTION 65 | endif 66 | --------------------------------------------------------------------------------