diff options
author | arphaman <arphaman@gmail.com> | 2013-09-20 15:59:20 +0100 |
---|---|---|
committer | arphaman <arphaman@gmail.com> | 2013-09-20 15:59:20 +0100 |
commit | 6ba4866e1096d45a83a5d92ecac7e902b897f3e9 (patch) | |
tree | 206c403933ef651bb3524a57e9f43ac5641a6b65 | |
parent | f87f0988b80f3a886d7b93d93d6e31ecd15b8f01 (diff) | |
download | flang-6ba4866e1096d45a83a5d92ecac7e902b897f3e9.tar.gz |
added sema for COMMON
-rw-r--r-- | include/flang/AST/Decl.h | 30 | ||||
-rw-r--r-- | include/flang/AST/StorageSet.h | 12 | ||||
-rw-r--r-- | include/flang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | include/flang/Sema/Scope.h | 24 | ||||
-rw-r--r-- | include/flang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 19 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/Scope.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaEquivalence.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Spec.cpp | 47 | ||||
-rw-r--r-- | test/Sema/common.f95 | 10 |
11 files changed, 145 insertions, 26 deletions
diff --git a/include/flang/AST/Decl.h b/include/flang/AST/Decl.h index cbe8698894..e8755cd7e3 100644 --- a/include/flang/AST/Decl.h +++ b/include/flang/AST/Decl.h @@ -37,7 +37,9 @@ class IdentifierInfo; class StoredDeclsMap; class TypeLoc; class BlockStmt; +class StorageSet; class EquivalenceSet; +class CommonBlockSet; // Decls class DeclContext; @@ -937,15 +939,15 @@ private: /// \brief The initializer for this variable. mutable Expr *Init; - /// \brief The equivalence set for this variable. - EquivalenceSet *EquivSet; + /// \brief The storage set for this variable. + StorageSet *Storage; friend class ASTContext; // ASTContext creates these. protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *ID, QualType T) - : DeclaratorDecl(DK, DC, IdLoc, ID, T), Init(nullptr), EquivSet(nullptr) {} + : DeclaratorDecl(DK, DC, IdLoc, ID, T), Init(nullptr), Storage(nullptr) {} public: static VarDecl *Create(ASTContext &C, DeclContext *DC, @@ -980,12 +982,12 @@ public: void MutateIntoParameter(Expr *Value); void MarkUsedAsVariable (SourceLocation Loc); - EquivalenceSet *getEquivalenceSet() const { return EquivSet; } - bool hasEquivalenceSet() const { - return EquivSet != nullptr; + StorageSet *getStorageSet() const { return Storage; } + bool hasStorageSet() const { + return Storage != nullptr; } - void setEquivalenceSet(EquivalenceSet *E) { - EquivSet = E; + void setStorageSet(StorageSet *S) { + Storage = S; } // Implement isa/cast/dyncast/etc. @@ -1004,13 +1006,23 @@ public: }; class CommonBlockDecl : public NamedDecl { + CommonBlockSet *Set; + CommonBlockDecl(DeclContext *DC, SourceLocation IDLoc, const IdentifierInfo *IDInfo) - : NamedDecl(CommonBlock, DC, IDLoc, DeclarationName(IDInfo)) {} + : NamedDecl(CommonBlock, DC, IDLoc, DeclarationName(IDInfo)), + Set(nullptr) {} public: static CommonBlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IDLoc, const IdentifierInfo *IDInfo); + CommonBlockSet *getStorageSet() const { + return Set; + } + void setStorageSet(CommonBlockSet *S) { + Set = S; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CommonBlockDecl *D) { return true; } static bool classofKind(Kind K) { return K == CommonBlock; } diff --git a/include/flang/AST/StorageSet.h b/include/flang/AST/StorageSet.h index 1e454761b4..de28e508d5 100644 --- a/include/flang/AST/StorageSet.h +++ b/include/flang/AST/StorageSet.h @@ -20,6 +20,7 @@ namespace flang { class ASTContext; class VarDecl; +class CommonBlockDecl; class Expr; /// StorageSet - A @@ -89,16 +90,23 @@ public: private: Object *Objects; unsigned ObjectCount; + CommonBlockDecl *Decl; - CommonBlockSet(ASTContext &C, ArrayRef<Object> objects); + CommonBlockSet(CommonBlockDecl *CBDecl); public: - static CommonBlockSet *Create(ASTContext &C, ArrayRef<Object> Objects); + static CommonBlockSet *Create(flang::ASTContext &C, CommonBlockDecl *CBDecl); + + void setObjects(ASTContext &C, ArrayRef<Object> objects); ArrayRef<Object> getObjects() const { return ArrayRef<Object>(Objects, ObjectCount); } + CommonBlockDecl *getDecl() const { + return Decl; + } + static bool classof(const StorageSet* S) { return S->getStorageSetClass() == CommonBlockSetClass; } diff --git a/include/flang/Basic/DiagnosticSemaKinds.td b/include/flang/Basic/DiagnosticSemaKinds.td index f6218e9759..e155baca95 100644 --- a/include/flang/Basic/DiagnosticSemaKinds.td +++ b/include/flang/Basic/DiagnosticSemaKinds.td @@ -286,6 +286,8 @@ def err_spec_dimension_already_array : Error< "the specification statement 'dimension' cannot be applied to the array variable %0">; def err_spec_qual_reapplication : Error< "the specification statement '%0' cannot be applied to the variable %1 more than once">; +def err_spec_not_applicable_to_common_block : Error< + "the specification statement '%0' cannot be applied to a variable in common block">; def warn_equivalence_same_object : Warning< "this equivalence connection uses the same object">; @@ -298,7 +300,6 @@ def err_equivalence_conflicting_offsets : Error< def note_equivalence_prev_offset : Note< "previous memory offset was defined here">; - def err_format_without_stmt_label : Error< "'FORMAT' statement is missing a statement label">; diff --git a/include/flang/Sema/Scope.h b/include/flang/Sema/Scope.h index 983d5136a8..3fff72d0b2 100644 --- a/include/flang/Sema/Scope.h +++ b/include/flang/Sema/Scope.h @@ -310,10 +310,27 @@ public: /// statement. /// class CommonBlockScope { +public: + typedef llvm::SmallDenseMap<const IdentifierInfo*, CommonBlockDecl*> BlockMappingTy; +private: CommonBlockDecl *UnnamedBlock; - llvm::SmallDenseMap<const IdentifierInfo*, CommonBlockDecl*> Blocks; + BlockMappingTy Blocks; public: + bool hasUnnamed() const { + return UnnamedBlock != nullptr; + } + CommonBlockDecl *getUnnamed() const { + return UnnamedBlock; + } + + BlockMappingTy::const_iterator beginNamed() const { + return Blocks.begin(); + } + BlockMappingTy::const_iterator endNamed() const { + return Blocks.end(); + } + CommonBlockDecl *find(const IdentifierInfo *IDInfo); CommonBlockDecl *findOrInsert(ASTContext &C, DeclContext *DC, @@ -321,6 +338,8 @@ public: const IdentifierInfo *IDInfo); }; +class CommonBlockSetBuilder; + /// The scope which helps to apply specification statements class SpecificationScope { @@ -374,7 +393,8 @@ public: const IdentifierInfo *IDInfo, CommonBlockDecl *Block); - void ApplyCommonSpecs(Sema &Visitor); + void ApplyCommonSpecs(Sema &Visitor, + CommonBlockSetBuilder &Builder); }; /// The scope of a translation unit (a single file) diff --git a/include/flang/Sema/Sema.h b/include/flang/Sema/Sema.h index 42de56bc31..75262a4a4d 100644 --- a/include/flang/Sema/Sema.h +++ b/include/flang/Sema/Sema.h @@ -210,7 +210,8 @@ public: bool ApplyCommonSpecification(SourceLocation Loc, SourceLocation IDLoc, const IdentifierInfo *IDInfo, - CommonBlockDecl *Block); + CommonBlockDecl *Block, + CommonBlockSetBuilder &Builder); QualType ActOnTypeName(ASTContext &C, DeclSpec &DS); VarDecl *ActOnKindSelector(ASTContext &C, SourceLocation IDLoc, diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 8d80506e65..bc294d731b 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -299,6 +299,25 @@ EquivalenceSet *EquivalenceSet::Create(ASTContext &C, ArrayRef<Object> Objects) } //===----------------------------------------------------------------------===// +// Common Statement +//===----------------------------------------------------------------------===// + +CommonBlockSet::CommonBlockSet(CommonBlockDecl *CBDecl) + : StorageSet(CommonBlockSetClass), Decl(CBDecl), + ObjectCount(0) { } + +CommonBlockSet *CommonBlockSet::Create(ASTContext &C, CommonBlockDecl *CBDecl) { + return new(C) CommonBlockSet(CBDecl); +} + +void CommonBlockSet::setObjects(ASTContext &C, ArrayRef<Object> objects) { + ObjectCount = objects.size(); + Objects = new(C) Object[ObjectCount]; + for(size_t I = 0; I < ObjectCount; ++I) + Objects[I] = objects[I]; +} + +//===----------------------------------------------------------------------===// // Data Statement //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 8a2cd310ce..1a1976c4a3 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -41,10 +41,15 @@ void CodeGenFunction::EmitVarDecl(const VarDecl *D) { D->isArgument() || D->isFunctionResult()) return; - if(D->hasEquivalenceSet()) { - auto Set = EmitEquivalenceSet(D->getEquivalenceSet()); - auto Ptr = EmitEquivalenceSetObject(Set, D); - LocalVariables.insert(std::make_pair(D, Ptr)); + if(D->hasStorageSet()) { + if(auto E = dyn_cast<EquivalenceSet>(D->getStorageSet())) { + auto Set = EmitEquivalenceSet(E); + auto Ptr = EmitEquivalenceSetObject(Set, D); + LocalVariables.insert(std::make_pair(D, Ptr)); + } else if(auto C = dyn_cast<CommonBlockSet>(D->getStorageSet())) { + // FIXME + } else + llvm_unreachable("invalid storage set"); return; } diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp index 6401aed4a3..2446cb33b6 100644 --- a/lib/Sema/Scope.cpp +++ b/lib/Sema/Scope.cpp @@ -14,6 +14,7 @@ #include "flang/Sema/Scope.h" #include "flang/AST/Expr.h" +#include "flang/AST/StorageSet.h" #include <limits> namespace flang { @@ -165,14 +166,19 @@ CommonBlockDecl *CommonBlockScope::findOrInsert(ASTContext &C, DeclContext *DC, SourceLocation IDLoc, const IdentifierInfo *IDInfo) { if(!IDInfo) { - if(!UnnamedBlock) + if(!UnnamedBlock) { UnnamedBlock = CommonBlockDecl::Create(C, DC, IDLoc, IDInfo); + auto Set = CommonBlockSet::Create(C, UnnamedBlock); + UnnamedBlock->setStorageSet(Set); + } return UnnamedBlock; } auto Result = Blocks.find(IDInfo); if(Result != Blocks.end()) return Result->second; auto Block = CommonBlockDecl::Create(C, DC, IDLoc, IDInfo); + auto Set = CommonBlockSet::Create(C, Block); + Block->setStorageSet(Set); Blocks.insert(std::make_pair(IDInfo, Block)); return Block; } diff --git a/lib/Sema/SemaEquivalence.cpp b/lib/Sema/SemaEquivalence.cpp index 9a72ec41cd..07d2a2fe91 100644 --- a/lib/Sema/SemaEquivalence.cpp +++ b/lib/Sema/SemaEquivalence.cpp @@ -99,7 +99,7 @@ bool SetCreator::CreateSet(ASTContext &C) { auto Set = EquivalenceSet::Create(C, Objects); for(auto I : Objects) - I.Var->setEquivalenceSet(Set); + I.Var->setStorageSet(Set); return true; } diff --git a/lib/Sema/Spec.cpp b/lib/Sema/Spec.cpp index 9f8131191e..dc66d912db 100644 --- a/lib/Sema/Spec.cpp +++ b/lib/Sema/Spec.cpp @@ -19,6 +19,7 @@ #include "flang/AST/Decl.h" #include "flang/AST/Expr.h" #include "flang/AST/Stmt.h" +#include "flang/AST/StorageSet.h" #include "flang/Basic/Diagnostic.h" #include "llvm/Support/raw_ostream.h" @@ -157,6 +158,13 @@ bool Sema::ApplySaveSpecification(SourceLocation Loc, SourceLocation IDLoc, bool Sema::ApplySaveSpecification(SourceLocation Loc, SourceLocation IDLoc, VarDecl *VD) { + if(VD->hasStorageSet()) { + if(auto CBSet = dyn_cast<CommonBlockSet>(VD->getStorageSet())) { + Diags.Report(Loc, diag::err_spec_not_applicable_to_common_block) + << "save" << getTokenRange(IDLoc); + return true; + } + } auto Type = VD->getType(); auto Quals = Type.getQualifiers(); if(Quals.hasAttributeSpec(Qualifiers::AS_save)) { @@ -186,17 +194,44 @@ void SpecificationScope::AddCommonSpec(SourceLocation Loc, SourceLocation IDLoc, CommonSpecs.push_back(Spec); } -void SpecificationScope::ApplyCommonSpecs(Sema &Visitor) { +class CommonBlockSetBuilder { +public: + llvm::SmallDenseMap<CommonBlockDecl*, + SmallVector<CommonBlockSet::Object, 16>, 8> Sets; + + void Add(CommonBlockDecl *CBDecl, CommonBlockSet::Object Object) { + Sets.insert(std::make_pair(CBDecl,SmallVector<CommonBlockSet::Object, 16>())).first->second.push_back(Object); + } + + void CreateSets(ASTContext &C) { + for(auto Set : Sets) + Set.first->getStorageSet()->setObjects(C, Set.second); + } +}; + +void SpecificationScope::ApplyCommonSpecs(Sema &Visitor, CommonBlockSetBuilder &Builder) { for(auto Spec : CommonSpecs) Visitor.ApplyCommonSpecification(Spec.Loc, Spec.IDLoc, - Spec.IDInfo, Spec.Block); + Spec.IDInfo, Spec.Block, + Builder); } bool Sema::ApplyCommonSpecification(SourceLocation Loc, SourceLocation IDLoc, const IdentifierInfo *IDInfo, - CommonBlockDecl *Block) { + CommonBlockDecl *Block, CommonBlockSetBuilder &Builder) { auto VD = GetVariableForSpecification(Loc, IDInfo, IDLoc); if(!VD) return true; + if(VD->hasStorageSet()) { + if(auto CBSet = dyn_cast<CommonBlockSet>(VD->getStorageSet())) { + Diags.Report(Loc, diag::err_spec_qual_reapplication) + << "common" << IDInfo + << getTokenRange(IDLoc); + return true; + } + // FIXME: COMMON + EQUIVALENCE + } + Builder.Add(Block, CommonBlockSet::Object(VD)); + VD->setStorageSet(Block->getStorageSet()); return false; } @@ -205,7 +240,11 @@ void Sema::ActOnSpecificationPart() { ActOnFunctionSpecificationPart(); CurSpecScope->ApplyDimensionSpecs(*this); - CurSpecScope->ApplyCommonSpecs(*this); + + CommonBlockSetBuilder CBBuilder; + CurSpecScope->ApplyCommonSpecs(*this, CBBuilder); + CBBuilder.CreateSets(Context); + CurSpecScope->ApplySaveSpecs(*this); } diff --git a/test/Sema/common.f95 b/test/Sema/common.f95 index 00a3f4f807..ae61691290 100644 --- a/test/Sema/common.f95 +++ b/test/Sema/common.f95 @@ -27,5 +27,13 @@ end subroutine sub3 integer i common /a/i - save i ! expected-error {{}} + save i ! expected-error {{the specification statement 'save' cannot be applied to a variable in common block}} +end + +subroutine sub4 + integer i,j + common i + common /a/i,j ! expected-error {{the specification statement 'common' cannot be applied to the variable 'i' more than once}} + common j ! expected-error {{the specification statement 'common' cannot be applied to the variable 'j' more than once}} + common /b/i ! expected-error {{the specification statement 'common' cannot be applied to the variable 'i' more than once}} end |