From: Erich Keane Date: Tue, 10 Jul 2018 20:46:46 +0000 (+0000) Subject: [NFC] Switch CodeGenFunction to use value init instead of member init lists X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1437ede97caf39872f7378aabe147c80a76a5719;p=clang [NFC] Switch CodeGenFunction to use value init instead of member init lists The member init list for the sole constructor for CodeGenFunction has gotten out of hand, so this patch moves the non-parameter-dependent initializations into the member value inits. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336726 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index ac317a7769..edb6be0608 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -168,6 +168,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet DependentAddressSpaceTypes; mutable llvm::FoldingSet VectorTypes; + mutable llvm::FoldingSet DependentVectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet FunctionProtoTypes; @@ -1321,6 +1322,11 @@ public: /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, VectorType::VectorKind VecKind) const; + /// Return the unique reference to the type for a dependently sized vector of + /// the specified element type. + QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr, + SourceLocation AttrLoc, + VectorType::VectorKind VecKind) const; /// Return the unique reference to an extended vector type /// of the specified element type and size. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 3e6090d312..0d2b670507 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DependentVectorType, { + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) + DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); }) +DEF_TRAVERSE_TYPELOC(DependentVectorType, { + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + // FIXME: size and attributes // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ExtVectorType, { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index dbe96a00f5..551921e663 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1590,6 +1590,7 @@ protected: class VectorTypeBitfields { friend class VectorType; + friend class DependentVectorType; unsigned : NumTypeBits; @@ -3079,6 +3080,51 @@ public: } }; +/// Represents a vector type where either the type or sizeis dependent. +//// +/// For example: +/// \code +/// template +/// class vector { +/// typedef T __attribute__((vector_size(Size))) type; +/// } +/// \endcode +class DependentVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + const ASTContext &Context; + QualType ElementType; + Expr *SizeExpr; + SourceLocation Loc; + + DependentVectorType(const ASTContext &Context, QualType ElementType, + QualType CanonType, Expr *SizeExpr, SourceLocation Loc, + VectorType::VectorKind vecKind); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return Loc; } + VectorType::VectorKind getVectorKind() const { + return VectorType::VectorKind(VectorTypeBits.VecKind); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentVector; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType ElementType, Expr *SizeExpr, + VectorType::VectorKind VecKind); +}; + /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 53d5a1a627..6772a88b6b 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1798,6 +1798,12 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc { }; +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class DependentVectorTypeLoc + : public InheritingConcreteTypeLoc {}; + // FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc(T1); + const auto *Vec2 = cast(T2); + if (Vec1->getVectorKind() != Vec2->getVectorKind()) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(), + Vec2->getSizeExpr())) + return false; + if (!IsStructurallyEquivalent(Context, Vec1->getElementType(), + Vec2->getElementType())) + return false; + break; + } + case Type::Vector: case Type::ExtVector: { const auto *Vec1 = cast(T1); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index d8c435991e..341ea5a338 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -539,7 +539,9 @@ private: void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType, const FunctionDecl *FD = nullptr); void mangleNeonVectorType(const VectorType *T); + void mangleNeonVectorType(const DependentVectorType *T); void mangleAArch64NeonVectorType(const VectorType *T); + void mangleAArch64NeonVectorType(const DependentVectorType *T); void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); void mangleMemberExprBase(const Expr *base, bool isArrow); @@ -1930,6 +1932,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::VariableArray: case Type::DependentSizedArray: case Type::DependentAddressSpace: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -3000,6 +3003,11 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) { Out << BaseName << EltName; } +void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) { + llvm_unreachable( + "Mangling for Dependent Sized Neon Vector not yet implemented"); +} + static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) { switch (EltType->getKind()) { case BuiltinType::SChar: @@ -3067,6 +3075,10 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) { ("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str(); Out << TypeName.length() << TypeName; } +void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) { + llvm_unreachable( + "Mangling for Dependent Sized AArch64 Neon Vector not yet implemented"); +} // GNU extension: vector types // ::= @@ -3097,6 +3109,32 @@ void CXXNameMangler::mangleType(const VectorType *T) { else mangleType(T->getElementType()); } + +void CXXNameMangler::mangleType(const DependentVectorType *T) { + if ((T->getVectorKind() == VectorType::NeonVector || + T->getVectorKind() == VectorType::NeonPolyVector)) { + llvm::Triple Target = getASTContext().getTargetInfo().getTriple(); + llvm::Triple::ArchType Arch = + getASTContext().getTargetInfo().getTriple().getArch(); + if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) && + !Target.isOSDarwin()) + mangleAArch64NeonVectorType(T); + else + mangleNeonVectorType(T); + return; + } + + Out << "Dv"; + mangleExpression(T->getSizeExpr()); + Out << '_'; + if (T->getVectorKind() == VectorType::AltiVecPixel) + Out << 'p'; + else if (T->getVectorKind() == VectorType::AltiVecBool) + Out << 'b'; + else + mangleType(T->getElementType()); +} + void CXXNameMangler::mangleType(const ExtVectorType *T) { mangleType(static_cast(T)); } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 32c26270ec..f9cd24ce9a 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -2514,6 +2514,16 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T, Qualifiers Quals, SourceRange Range) { mangleType(static_cast(T), Quals, Range); } + +void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T, + Qualifiers, SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent-sized vector type yet"); + Diags.Report(Range.getBegin(), DiagID) << Range; +} + void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T, Qualifiers, SourceRange Range) { DiagnosticsEngine &Diags = Context.getDiags(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ddb45868ec..b25965786d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -177,6 +177,28 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID, E->Profile(ID, Context, true); } +DependentVectorType::DependentVectorType(const ASTContext &Context, + QualType ElementType, + QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, + VectorType::VectorKind VecKind) + : Type(DependentVector, CanonType, /*Dependent=*/true, + /*InstantiationDependent=*/true, + ElementType->isVariablyModifiedType(), + ElementType->containsUnexpandedParameterPack() || + (SizeExpr && SizeExpr->containsUnexpandedParameterPack())), + Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) { + VectorTypeBits.VecKind = VecKind; +} + +void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, + QualType ElementType, Expr *SizeExpr, + VectorType::VectorKind VecKind) { + ID.AddPointer(ElementType.getAsOpaquePtr()); + SizeExpr->Profile(ID, Context, true); +} + DependentSizedExtVectorType::DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType, @@ -3783,6 +3805,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index b424b24574..aad52d5e1d 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -242,6 +242,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::RValueReference: case Type::MemberPointer: case Type::DependentAddressSpace: + case Type::DependentVector: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -640,7 +641,55 @@ void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) { printAfter(T->getElementType(), OS); -} +} + +void TypePrinter::printDependentVectorBefore(const DependentVectorType *T, + raw_ostream &OS) { + switch (T->getVectorKind()) { + case VectorType::AltiVecPixel: + OS << "__vector __pixel "; + break; + case VectorType::AltiVecBool: + OS << "__vector __bool "; + printBefore(T->getElementType(), OS); + break; + case VectorType::AltiVecVector: + OS << "__vector "; + printBefore(T->getElementType(), OS); + break; + case VectorType::NeonVector: + OS << "__attribute__((neon_vector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << "))) "; + printBefore(T->getElementType(), OS); + break; + case VectorType::NeonPolyVector: + OS << "__attribute__((neon_polyvector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << "))) "; + printBefore(T->getElementType(), OS); + break; + case VectorType::GenericVector: { + // FIXME: We prefer to print the size directly here, but have no way + // to get the size of the type. + OS << "__attribute__((__vector_size__("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, nullptr, Policy); + OS << " * sizeof("; + print(T->getElementType(), OS, StringRef()); + OS << ")))) "; + printBefore(T->getElementType(), OS); + break; + } + } +} + +void TypePrinter::printDependentVectorAfter(const DependentVectorType *T, + raw_ostream &OS) { + printAfter(T->getElementType(), OS); +} void TypePrinter::printExtVectorBefore(const ExtVectorType *T, raw_ostream &OS) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 9ccc0910c3..99af1a18e8 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -65,25 +65,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(), CGBuilderInserterTy(this)), - CurFn(nullptr), ReturnValue(Address::invalid()), - CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), - IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), - SawAsmBlock(false), IsOutlinedSEHHelper(false), BlockInfo(nullptr), - BlockPointer(nullptr), LambdaThisCaptureField(nullptr), - NormalCleanupDest(Address::invalid()), NextCleanupDestIndex(1), - FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), - EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()), - DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), - PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), - CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), - NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr), - CXXABIThisValue(nullptr), CXXThisValue(nullptr), - CXXStructorImplicitParamDecl(nullptr), - CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), - CurLexicalScope(nullptr), TerminateLandingPad(nullptr), - TerminateHandler(nullptr), TrapBB(nullptr), LargestVectorWidth(0), - ShouldEmitLifetimeMarkers( - shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { + SanOpts(CGM.getLangOpts().Sanitize), DebugInfo(CGM.getModuleDebugInfo()), + PGO(cgm), ShouldEmitLifetimeMarkers(shouldEmitLifetimeMarkers( + CGM.getCodeGenOpts(), CGM.getLangOpts())) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b2bcd1cfbd..d6deb65582 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -214,7 +214,7 @@ public: const Decl *CurCodeDecl; const CGFunctionInfo *CurFnInfo; QualType FnRetTy; - llvm::Function *CurFn; + llvm::Function *CurFn = nullptr; // Holds coroutine data if the current function is a coroutine. We use a // wrapper to manage its lifetime, so that we don't have to define CGCoroData @@ -242,7 +242,7 @@ public: /// ReturnValue - The temporary alloca to hold the return /// value. This is invalid iff the function has no return value. - Address ReturnValue; + Address ReturnValue = Address::invalid(); /// Return true if a label was seen in the current scope. bool hasLabelBeenSeenInCurrentScope() const { @@ -321,7 +321,7 @@ public: /// Captured 'this' type. FieldDecl *CXXThisFieldDecl; }; - CGCapturedStmtInfo *CapturedStmtInfo; + CGCapturedStmtInfo *CapturedStmtInfo = nullptr; /// RAII for correct setting/restoring of CapturedStmtInfo. class CGCapturedStmtRAII { @@ -366,7 +366,7 @@ public: SanitizerSet SanOpts; /// True if CodeGen currently emits code implementing sanitizer checks. - bool IsSanitizerScope; + bool IsSanitizerScope = false; /// RAII object to set/unset CodeGenFunction::IsSanitizerScope. class SanitizerScope { @@ -378,26 +378,26 @@ public: /// In C++, whether we are code generating a thunk. This controls whether we /// should emit cleanups. - bool CurFuncIsThunk; + bool CurFuncIsThunk = false; /// In ARC, whether we should autorelease the return value. - bool AutoreleaseResult; + bool AutoreleaseResult = false; /// Whether we processed a Microsoft-style asm block during CodeGen. These can /// potentially set the return value. - bool SawAsmBlock; + bool SawAsmBlock = false; const FunctionDecl *CurSEHParent = nullptr; /// True if the current function is an outlined SEH helper. This can be a /// finally block or filter expression. - bool IsOutlinedSEHHelper; + bool IsOutlinedSEHHelper = false; - const CodeGen::CGBlockInfo *BlockInfo; - llvm::Value *BlockPointer; + const CodeGen::CGBlockInfo *BlockInfo = nullptr; + llvm::Value *BlockPointer = nullptr; llvm::DenseMap LambdaCaptureFields; - FieldDecl *LambdaThisCaptureField; + FieldDecl *LambdaThisCaptureField = nullptr; /// A mapping from NRVO variables to the flags used to indicate /// when the NRVO has been applied to this variable. @@ -434,23 +434,23 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest; + Address NormalCleanupDest = Address::invalid(); - unsigned NextCleanupDestIndex; + unsigned NextCleanupDestIndex = 1; /// FirstBlockInfo - The head of a singly-linked-list of block layouts. - CGBlockInfo *FirstBlockInfo; + CGBlockInfo *FirstBlockInfo = nullptr; /// EHResumeBlock - Unified block containing a call to llvm.eh.resume. - llvm::BasicBlock *EHResumeBlock; + llvm::BasicBlock *EHResumeBlock = nullptr; /// The exception slot. All landing pads write the current exception pointer /// into this alloca. - llvm::Value *ExceptionSlot; + llvm::Value *ExceptionSlot = nullptr; /// The selector slot. Under the MandatoryCleanup model, all landing pads /// write the current selector value into this alloca. - llvm::AllocaInst *EHSelectorSlot; + llvm::AllocaInst *EHSelectorSlot = nullptr; /// A stack of exception code slots. Entering an __except block pushes a slot /// on the stack and leaving pops one. The __exception_code() intrinsic loads @@ -1087,17 +1087,17 @@ public: private: CGDebugInfo *DebugInfo; - bool DisableDebugInfo; + bool DisableDebugInfo = false; /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid /// calling llvm.stacksave for multiple VLAs in the same scope. - bool DidCallStackSave; + bool DidCallStackSave = false; /// IndirectBranch - The first time an indirect goto is seen we create a block /// with an indirect branch. Every time we see the address of a label taken, /// we add the label to the indirect goto. Every subsequent indirect goto is /// codegen'd as a jump to the IndirectBranch's basic block. - llvm::IndirectBrInst *IndirectBranch; + llvm::IndirectBrInst *IndirectBranch = nullptr; /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C /// decls. @@ -1247,13 +1247,13 @@ private: /// SwitchInsn - This is nearest current switch instruction. It is null if /// current context is not in a switch. - llvm::SwitchInst *SwitchInsn; + llvm::SwitchInst *SwitchInsn = nullptr; /// The branch weights of SwitchInsn when doing instrumentation based PGO. - SmallVector *SwitchWeights; + SmallVector *SwitchWeights = nullptr; /// CaseRangeBlock - This block holds if condition check for last case /// statement range in current switch instruction. - llvm::BasicBlock *CaseRangeBlock; + llvm::BasicBlock *CaseRangeBlock = nullptr; /// OpaqueLValues - Keeps track of the current set of opaque value /// expressions. @@ -1270,13 +1270,13 @@ private: /// A block containing a single 'unreachable' instruction. Created /// lazily by getUnreachableBlock(). - llvm::BasicBlock *UnreachableBlock; + llvm::BasicBlock *UnreachableBlock = nullptr; /// Counts of the number return expressions in the function. - unsigned NumReturnExprs; + unsigned NumReturnExprs = 0; /// Count the number of simple (constant) return expressions in the function. - unsigned NumSimpleReturnExprs; + unsigned NumSimpleReturnExprs = 0; /// The last regular (non-return) debug location (breakpoint) in the function. SourceLocation LastStopPoint; @@ -1396,9 +1396,9 @@ public: private: /// CXXThisDecl - When generating code for a C++ member function, /// this will hold the implicit 'this' declaration. - ImplicitParamDecl *CXXABIThisDecl; - llvm::Value *CXXABIThisValue; - llvm::Value *CXXThisValue; + ImplicitParamDecl *CXXABIThisDecl = nullptr; + llvm::Value *CXXABIThisValue = nullptr; + llvm::Value *CXXThisValue = nullptr; CharUnits CXXABIThisAlignment; CharUnits CXXThisAlignment; @@ -1416,16 +1416,16 @@ private: /// CXXStructorImplicitParamDecl - When generating code for a constructor or /// destructor, this will hold the implicit argument (e.g. VTT). - ImplicitParamDecl *CXXStructorImplicitParamDecl; - llvm::Value *CXXStructorImplicitParamValue; + ImplicitParamDecl *CXXStructorImplicitParamDecl = nullptr; + llvm::Value *CXXStructorImplicitParamValue = nullptr; /// OutermostConditional - Points to the outermost active /// conditional control. This is used so that we know if a /// temporary should be destroyed conditionally. - ConditionalEvaluation *OutermostConditional; + ConditionalEvaluation *OutermostConditional = nullptr; /// The current lexical scope. - LexicalScope *CurLexicalScope; + LexicalScope *CurLexicalScope = nullptr; /// The current source location that should be used for exception /// handling code. @@ -1456,16 +1456,16 @@ private: CurCodeDecl && CurCodeDecl->getAttr()); } - llvm::BasicBlock *TerminateLandingPad; - llvm::BasicBlock *TerminateHandler; - llvm::BasicBlock *TrapBB; + llvm::BasicBlock *TerminateLandingPad = nullptr; + llvm::BasicBlock *TerminateHandler = nullptr; + llvm::BasicBlock *TrapBB = nullptr; /// Terminate funclets keyed by parent funclet pad. llvm::MapVector TerminateFunclets; /// Largest vector width used in ths function. Will be used to create a /// function attribute. - unsigned LargestVectorWidth; + unsigned LargestVectorWidth = 0; /// True if we need emit the life-time markers. const bool ShouldEmitLifetimeMarkers; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 68a5196f6b..72ee8474f5 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5346,6 +5346,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType( + const DependentVectorType *T) { + return Visit(T->getElementType()); +} + bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { return Visit(T->getElementType()); } diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fd4197ce2a..4e2fa31f9d 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1837,6 +1837,55 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, return Sema::TDK_NonDeducedMismatch; } + case Type::DependentVector: { + const DependentVectorType *VectorParam = cast(Param); + + if (const VectorType *VectorArg = dyn_cast(Arg)) { + // Perform deduction on the element types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, VectorParam->getElementType(), + VectorArg->getElementType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the vector size, if we can. + NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false); + ArgSize = VectorArg->getNumElements(); + // Note that we use the "array bound" rules here; just like in that + // case, we don't have any particular type for the vector size, but + // we can provide one if necessary. + return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize, + S.Context.IntTy, true, Info, + Deduced); + } + + if (const DependentVectorType *VectorArg = + dyn_cast(Arg)) { + // Perform deduction on the element types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, VectorParam->getElementType(), + VectorArg->getElementType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the vector size, if we can. + NonTypeTemplateParmDecl *NTTP = + getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced); + } + + return Sema::TDK_NonDeducedMismatch; + } + // (clang extension) // // T __attribute__(((ext_vector_type(N)))) @@ -5227,6 +5276,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, OnlyDeduced, Depth, Used); break; + case Type::DependentVector: { + const DependentVectorType *VecType = cast(T); + MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced, + Depth, Used); + MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth, + Used); + break; + } case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast(T); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 978c1cc015..90cdf3290a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2294,6 +2294,58 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } +QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, + SourceLocation AttrLoc) { + // The base type must be integer (not Boolean or enumeration) or float, and + // can't already be a vector. + if (!CurType->isDependentType() && + (!CurType->isBuiltinType() || CurType->isBooleanType() || + (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) { + Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType; + return QualType(); + } + + if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent()) + return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, + VectorType::GenericVector); + + llvm::APSInt VecSize(32); + if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_type) + << "vector_size" << AANT_ArgumentIntegerConstant + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (CurType->isDependentType()) + return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, + VectorType::GenericVector); + + unsigned VectorSize = static_cast(VecSize.getZExtValue() * 8); + unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); + + if (VectorSize == 0) { + Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange(); + return QualType(); + } + + // vecSize is specified in bytes - convert to bits. + if (VectorSize % TypeSize) { + Diag(AttrLoc, diag::err_attribute_invalid_size) + << SizeExpr->getSourceRange(); + return QualType(); + } + + if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) { + Diag(AttrLoc, diag::err_attribute_size_too_large) + << SizeExpr->getSourceRange(); + return QualType(); + } + + return Context.getVectorType(CurType, VectorSize / TypeSize, + VectorType::GenericVector); +} + /// Build an ext-vector type. /// /// Run the required checks for the extended vector type. @@ -6929,52 +6981,30 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Attr.setInvalid(); return; } - Expr *sizeExpr = static_cast(Attr.getArgAsExpr(0)); - llvm::APSInt vecSize(32); - if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || - !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) - << Attr.getName() << AANT_ArgumentIntegerConstant - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - // The base type must be integer (not Boolean or enumeration) or float, and - // can't already be a vector. - if (!CurType->isBuiltinType() || CurType->isBooleanType() || - (!CurType->isIntegerType() && !CurType->isRealFloatingType())) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; - Attr.setInvalid(); - return; - } - unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); - // vecSize is specified in bytes - convert to bits. - unsigned vectorSize = static_cast(vecSize.getZExtValue() * 8); - // the vector size needs to be an integral multiple of the type size. - if (vectorSize % typeSize) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) { - S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; - } - if (vectorSize == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) - << sizeExpr->getSourceRange(); - Attr.setInvalid(); - return; + Expr *SizeExpr; + // Special case where the argument is a template id. + if (Attr.isArgIdent(0)) { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Id; + Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); + + ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc, + Id, false, false); + + if (Size.isInvalid()) + return; + SizeExpr = Size.get(); + } else { + SizeExpr = Attr.getArgAsExpr(0); } - // Success! Instantiate the vector type, the number of elements is > 0, and - // not required to be a power of 2, unlike GCC. - CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, - VectorType::GenericVector); + QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc()); + if (!T.isNull()) + CurType = T; + else + Attr.setInvalid(); } /// Process the OpenCL-like ext_vector_type attribute when it occurs on diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 66c947abb3..a933b6774b 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -818,6 +818,15 @@ public: QualType RebuildVectorType(QualType ElementType, unsigned NumElements, VectorType::VectorKind VecKind); + /// Build a new potentially dependently-sized extended vector type + /// given the element type and number of elements. + /// + /// By default, performs semantic analysis when building the vector type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr, + SourceLocation AttributeLoc, + VectorType::VectorKind); + /// Build a new extended vector type given the element type and /// number of elements. /// @@ -4746,6 +4755,43 @@ TreeTransform::TransformDependentSizedArrayType(TypeLocBuilder &TLB, return Result; } +template +QualType TreeTransform::TransformDependentVectorType( + TypeLocBuilder &TLB, DependentVectorTypeLoc TL) { + const DependentVectorType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(T->getElementType()); + if (ElementType.isNull()) + return QualType(); + + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); + Size = SemaRef.ActOnConstantExpression(Size); + if (Size.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() || + Size.get() != T->getSizeExpr()) { + Result = getDerived().RebuildDependentVectorType( + ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind()); + if (Result.isNull()) + return QualType(); + } + + // Result might be dependent or not. + if (isa(Result)) { + DependentVectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } else { + VectorTypeLoc NewTL = TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } + + return Result; +} + template QualType TreeTransform::TransformDependentSizedExtVectorType( TypeLocBuilder &TLB, @@ -12377,6 +12423,13 @@ TreeTransform::RebuildVectorType(QualType ElementType, return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind); } +template +QualType TreeTransform::RebuildDependentVectorType( + QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc, + VectorType::VectorKind VecKind) { + return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc); +} + template QualType TreeTransform::RebuildExtVectorType(QualType ElementType, unsigned NumElements, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 78ca5f7406..0f6beddbe5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6371,6 +6371,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getPipeType(ElementType, ReadOnly); } + case TYPE_DEPENDENT_SIZED_VECTOR: { + unsigned Idx = 0; + QualType ElementType = readType(*Loc.F, Record, Idx); + Expr *SizeExpr = ReadExpr(*Loc.F); + SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); + unsigned VecKind = Record[Idx]; + + return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc, + (VectorType::VectorKind)VecKind); + } + case TYPE_DEPENDENT_SIZED_EXT_VECTOR: { unsigned Idx = 0; @@ -6551,6 +6562,10 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } +void TypeLocReader::VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { + TL.setNameLoc(ReadSourceLocation()); +} + void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index bc569d17f2..02a077fcb7 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -455,6 +455,14 @@ ASTTypeWriter::VisitDependentSizedExtVectorType( Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } +void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) { + Record.AddTypeRef(T->getElementType()); + Record.AddStmt(T->getSizeExpr()); + Record.AddSourceLocation(T->getAttributeLoc()); + Record.push_back(T->getVectorKind()); + Code = TYPE_DEPENDENT_SIZED_VECTOR; +} + void ASTTypeWriter::VisitDependentAddressSpaceType( const DependentAddressSpaceType *T) { @@ -676,6 +684,10 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } +void TypeLocWriter::VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); } diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 8fe24a32c8..56a8a6db5b 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -291,3 +291,46 @@ const int &reference_to_vec_element = vi4(1).x; // PR12649 typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}} + +namespace Templates { +template +struct TemplateVectorType { + typedef Elt __attribute__((__vector_size__(Size))) type; +}; + +template +struct PR15730 { + typedef T __attribute__((vector_size(N * sizeof(T)))) type; + typedef T __attribute__((vector_size(8192))) type2; + typedef T __attribute__((vector_size(3))) type3; +}; + +void Init() { + const TemplateVectorType::type Works = {}; + const TemplateVectorType::type Works2 = {}; + // expected-error@298 {{invalid vector element type 'bool'}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type NoBool; + // expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type NoComplex; + // expected-error@298 {{vector size not an integral multiple of component size}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type BadSize; + // expected-error@298 {{vector size too large}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type TooLarge; + // expected-error@298 {{zero vector size}} + // expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType' requested here}} + const TemplateVectorType::type Zero; + + // expected-error@304 {{vector size too large}} + // expected-error@305 {{vector size not an integral multiple of component size}} + // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}} + const PR15730<8, int>::type PR15730_1 = {}; + // expected-error@304 {{vector size too large}} + // expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}} + const PR15730<8, char>::type2 PR15730_2 = {}; +} + +} // namespace Templates diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index b61dff3238..499d9abf9a 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1772,6 +1772,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type) +DEFAULT_TYPELOC_IMPL(DependentVector, Type) DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) DEFAULT_TYPELOC_IMPL(Vector, Type) DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)