Decl *Sema::ActOnEntityDecl(ASTContext &C, const QualType &T, SourceLocation IDLoc, const IdentifierInfo *IDInfo) { auto Quals = T.getQualifiers(); if(Quals.hasAttributeSpec(Qualifiers::AS_external)) return ActOnExternalEntityDecl(C, T, IDLoc, IDInfo); else if(Quals.hasAttributeSpec(Qualifiers::AS_intrinsic)) return ActOnIntrinsicEntityDecl(C, T, IDLoc, IDInfo); if (auto Prev = LookupIdentifier(IDInfo)) { FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev); if(auto VD = dyn_cast<VarDecl>(Prev)) { if(VD->isArgument() && VD->getType().isNull()) { VD->setType(T); return VD; } else if(VD->isFunctionResult()) FD = CurrentContextAsFunction(); } if(FD && (FD->isNormalFunction() || FD->isExternal())) { if(FD->getType().isNull() || FD->getType()->isVoidType()) { SetFunctionType(FD, T, IDLoc, SourceRange()); //Fixme: proper loc and range return FD; } else { Diags.Report(IDLoc, diag::err_func_return_type_already_specified) << IDInfo; return nullptr; } } Diags.Report(IDLoc, diag::err_redefinition) << IDInfo; Diags.Report(Prev->getLocation(), diag::note_previous_definition); return nullptr; } VarDecl *VD = VarDecl::Create(C, CurContext, IDLoc, IDInfo, T); CurContext->addDecl(VD); if(!T.isNull()) { auto SubT = T; if(T->isArrayType()) { CheckArrayTypeDeclarationCompability(T->asArrayType(), VD); SubT = T->asArrayType()->getElementType(); VD->MarkUsedAsVariable(IDLoc); } else if(SubT->isCharacterType()) CheckCharacterLengthDeclarationCompability(SubT, VD); } return VD; }
void CodeGenFunction::EmitVarDecl(const VarDecl *D) { if(D->isParameter() || D->isArgument() || D->isFunctionResult()) return; 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 CB = dyn_cast<CommonBlockSet>(D->getStorageSet())) EmitCommonBlock(CB); else llvm_unreachable("invalid storage set"); return; } llvm::Value *Ptr; auto Type = D->getType(); if(Type.hasAttributeSpec(Qualifiers::AS_save) && !IsMainProgram) { Ptr = CGM.EmitGlobalVariable(CurFn->getName(), D); HasSavedVariables = true; } else { if(Type->isArrayType()) Ptr = CreateArrayAlloca(Type, D->getName()); else Ptr = Builder.CreateAlloca(ConvertTypeForMem(Type), nullptr, D->getName()); } LocalVariables.insert(std::make_pair(D, Ptr)); }
Decl *Sema::ActOnIntrinsicEntityDecl(ASTContext &C, QualType T, SourceLocation IDLoc, const IdentifierInfo *IDInfo) { auto FuncResult = IntrinsicFunctionMapping.Resolve(IDInfo); if(FuncResult.IsInvalid) { Diags.Report(IDLoc, diag::err_intrinsic_invalid_func) << IDInfo << getTokenRange(IDLoc); return nullptr; } QualType Type = T.isNull()? C.RealTy : T; if (auto Prev = LookupIdentifier(IDInfo)) { auto Quals = getDeclQualifiers(Prev); if(Quals.hasAttributeSpec(Qualifiers::AS_intrinsic)) { Diags.Report(IDLoc, diag::err_duplicate_attr_spec) << DeclSpec::getSpecifierName(Qualifiers::AS_intrinsic); return Prev; } auto VD = dyn_cast<VarDecl>(Prev); if(VD && VD->isUnusedSymbol()) { Type = VD->getType(); CurContext->removeDecl(VD); } else { DiagnoseRedefinition(IDLoc, IDInfo, Prev); return nullptr; } } auto Decl = IntrinsicFunctionDecl::Create(C, CurContext, IDLoc, IDInfo, Type, FuncResult.Function); CurContext->addDecl(Decl); return Decl; }
Decl *Sema::ActOnExternalEntityDecl(ASTContext &C, QualType T, SourceLocation IDLoc, const IdentifierInfo *IDInfo) { SourceLocation TypeLoc; VarDecl *ArgumentExternal = nullptr; if (auto Prev = LookupIdentifier(IDInfo)) { auto Quals = getDeclQualifiers(Prev); if(Quals.hasAttributeSpec(Qualifiers::AS_external)) { Diags.Report(IDLoc, diag::err_duplicate_attr_spec) << DeclSpec::getSpecifierName(Qualifiers::AS_external); return Prev; } // apply EXTERNAL to an unused symbol or an argument. auto VD = dyn_cast<VarDecl>(Prev); if(VD && (VD->isUnusedSymbol() || VD->isArgument()) ) { T = VD->getType(); TypeLoc = VD->getLocation(); CurContext->removeDecl(VD); if(VD->isArgument()) ArgumentExternal = VD; } else { DiagnoseRedefinition(IDLoc, IDInfo, Prev); return nullptr; } } if(T.isNull()) T = C.VoidTy; DeclarationNameInfo DeclName(IDInfo,IDLoc); auto Decl = FunctionDecl::Create(C, ArgumentExternal? FunctionDecl::ExternalArgument : FunctionDecl::External, CurContext, DeclName, T); SetFunctionType(Decl, T, TypeLoc, SourceRange()); //FIXME: proper loc, and range CurContext->addDecl(Decl); if(ArgumentExternal) ArgumentExternal->setType(C.getFunctionType(Decl)); return Decl; }