diff options
Diffstat (limited to 'lib/AST')
73 files changed, 4244 insertions, 3673 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index c05b160b8e..f9cbf331b2 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -1,9 +1,8 @@ //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -176,6 +175,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { MakeFloat(); setFloat(RHS.getFloat()); break; + case FixedPoint: { + APFixedPoint FXCopy = RHS.getFixedPoint(); + MakeFixedPoint(std::move(FXCopy)); + break; + } case Vector: MakeVector(); setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, @@ -233,6 +237,8 @@ void APValue::DestroyDataAndMakeUninit() { ((APSInt*)(char*)Data.buffer)->~APSInt(); else if (Kind == Float) ((APFloat*)(char*)Data.buffer)->~APFloat(); + else if (Kind == FixedPoint) + ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); else if (Kind == Vector) ((Vec*)(char*)Data.buffer)->~Vec(); else if (Kind == ComplexInt) @@ -268,6 +274,8 @@ bool APValue::needsCleanup() const { return getInt().needsCleanup(); case Float: return getFloat().needsCleanup(); + case FixedPoint: + return getFixedPoint().getValue().needsCleanup(); case ComplexFloat: assert(getComplexFloatImag().needsCleanup() == getComplexFloatReal().needsCleanup() && @@ -321,6 +329,9 @@ void APValue::dump(raw_ostream &OS) const { case Float: OS << "Float: " << GetApproxValue(getFloat()); return; + case FixedPoint: + OS << "FixedPoint : " << getFixedPoint(); + return; case Vector: OS << "Vector: "; getVectorElt(0).dump(OS); @@ -397,6 +408,9 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ case APValue::Float: Out << GetApproxValue(getFloat()); return; + case APValue::FixedPoint: + Out << getFixedPoint(); + return; case APValue::Vector: { Out << '{'; QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); @@ -600,6 +614,26 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { return Result; } +bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const { + if (isInt()) { + Result = getInt(); + return true; + } + + if (isLValue() && isNullPointer()) { + Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); + return true; + } + + if (isLValue() && !getLValueBase()) { + Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); + return true; + } + + return false; +} + const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data.buffer)->Base; diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp index 55033b238c..6bba8f1f80 100644 --- a/lib/AST/ASTConsumer.cpp +++ b/lib/AST/ASTConsumer.cpp @@ -1,9 +1,8 @@ //===--- ASTConsumer.cpp - Abstract interface for reading ASTs --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 21b6f36e9a..d0a790cad4 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1,9 +1,8 @@ //===- ASTContext.cpp - Context to hold long-lived AST nodes --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -95,38 +94,18 @@ using namespace clang; -unsigned ASTContext::NumImplicitDefaultConstructors; -unsigned ASTContext::NumImplicitDefaultConstructorsDeclared; -unsigned ASTContext::NumImplicitCopyConstructors; -unsigned ASTContext::NumImplicitCopyConstructorsDeclared; -unsigned ASTContext::NumImplicitMoveConstructors; -unsigned ASTContext::NumImplicitMoveConstructorsDeclared; -unsigned ASTContext::NumImplicitCopyAssignmentOperators; -unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; -unsigned ASTContext::NumImplicitMoveAssignmentOperators; -unsigned ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; -unsigned ASTContext::NumImplicitDestructors; -unsigned ASTContext::NumImplicitDestructorsDeclared; - enum FloatingRank { Float16Rank, HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { - if (!CommentsLoaded && ExternalSource) { - ExternalSource->ReadComments(); - -#ifndef NDEBUG - ArrayRef<RawComment *> RawComments = Comments.getComments(); - assert(std::is_sorted(RawComments.begin(), RawComments.end(), - BeforeThanCompare<RawComment>(SourceMgr))); -#endif - - CommentsLoaded = true; - } - assert(D); + // If we already tried to load comments but there are none, + // we won't find anything. + if (CommentsLoaded && Comments.getComments().empty()) + return nullptr; + // User can not attach documentation to implicit declarations. if (D->isImplicit()) return nullptr; @@ -176,12 +155,6 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { isa<TemplateTemplateParmDecl>(D)) return nullptr; - ArrayRef<RawComment *> RawComments = Comments.getComments(); - - // If there are no comments anywhere, we won't find anything. - if (RawComments.empty()) - return nullptr; - // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple // declarators, thus use declaration starting location as the "declaration @@ -220,6 +193,23 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (DeclLoc.isInvalid() || !DeclLoc.isFileID()) return nullptr; + if (!CommentsLoaded && ExternalSource) { + ExternalSource->ReadComments(); + +#ifndef NDEBUG + ArrayRef<RawComment *> RawComments = Comments.getComments(); + assert(std::is_sorted(RawComments.begin(), RawComments.end(), + BeforeThanCompare<RawComment>(SourceMgr))); +#endif + + CommentsLoaded = true; + } + + ArrayRef<RawComment *> RawComments = Comments.getComments(); + // If there are no comments anywhere, we won't find anything. + if (RawComments.empty()) + return nullptr; + // Find the comment that occurs just after this declaration. ArrayRef<RawComment *>::iterator Comment; { @@ -1391,24 +1381,6 @@ ASTContext::setTemplateOrSpecializationInfo(VarDecl *Inst, TemplateOrInstantiation[Inst] = TSI; } -FunctionDecl *ASTContext::getClassScopeSpecializationPattern( - const FunctionDecl *FD){ - assert(FD && "Specialization is 0"); - llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos - = ClassScopeSpecializationPattern.find(FD); - if (Pos == ClassScopeSpecializationPattern.end()) - return nullptr; - - return Pos->second; -} - -void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, - FunctionDecl *Pattern) { - assert(FD && "Specialization is 0"); - assert(Pattern && "Class scope specialization pattern is 0"); - ClassScopeSpecializationPattern[FD] = Pattern; -} - NamedDecl * ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) { auto Pos = InstantiatedFromUsingDecl.find(UUD); @@ -1610,8 +1582,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); if (const auto *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasGlobalStorage() && !ForAlignof) - Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + if (VD->hasGlobalStorage() && !ForAlignof) { + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize)); + } } } @@ -1916,8 +1890,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; case BuiltinType::Float16: case BuiltinType::Half: - Width = Target->getHalfWidth(); - Align = Target->getHalfAlign(); + if (Target->hasFloat16Type() || !getLangOpts().OpenMP || + !getLangOpts().OpenMPIsDevice) { + Width = Target->getHalfWidth(); + Align = Target->getHalfAlign(); + } else { + assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + "Expected OpenMP device compilation."); + Width = AuxTarget->getHalfWidth(); + Align = AuxTarget->getHalfAlign(); + } break; case BuiltinType::Float: Width = Target->getFloatWidth(); @@ -1932,8 +1914,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = Target->getLongDoubleAlign(); break; case BuiltinType::Float128: - Width = Target->getFloat128Width(); - Align = Target->getFloat128Align(); + if (Target->hasFloat128Type() || !getLangOpts().OpenMP || + !getLangOpts().OpenMPIsDevice) { + Width = Target->getFloat128Width(); + Align = Target->getFloat128Align(); + } else { + assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice && + "Expected OpenMP device compilation."); + Width = AuxTarget->getFloat128Width(); + Align = AuxTarget->getFloat128Align(); + } break; case BuiltinType::NullPtr: Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) @@ -2233,7 +2223,8 @@ unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const { /// getAlignOfGlobalVar - Return the alignment in bits that should be given /// to a global variable of the specified type. unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { - return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign()); + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign(TypeSize)); } /// getAlignOfGlobalVarInChars - Return the alignment in characters that @@ -2574,7 +2565,7 @@ ASTContext::getBlockVarCopyInit(const VarDecl*VD) const { return {nullptr, false}; } -/// Set the copy inialization expression of a block var decl. +/// Set the copy initialization expression of a block var decl. void ASTContext::setBlockVarCopyInit(const VarDecl*VD, Expr *CopyExpr, bool CanThrow) { assert(VD && CopyExpr && "Passed null params"); @@ -2772,7 +2763,7 @@ QualType ASTContext::getFunctionTypeWithExceptionSpec( // Anything else must be a function type. Rebuild it with the new exception // specification. - const auto *Proto = cast<FunctionProtoType>(Orig); + const auto *Proto = Orig->getAs<FunctionProtoType>(); return getFunctionType( Proto->getReturnType(), Proto->getParamTypes(), Proto->getExtProtoInfo().withExceptionSpec(ESI)); @@ -5609,6 +5600,12 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const { return -1; } +int ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const { + if (&getFloatTypeSemantics(LHS) == &getFloatTypeSemantics(RHS)) + return 0; + return getFloatingTypeOrder(LHS, RHS); +} + /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This /// routine will assert if passed a built-in type that isn't an integer or enum, /// or if it is not canonicalized. @@ -8581,7 +8578,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto->isVariadic() != rproto->isVariadic()) return {}; - if (lproto->getTypeQuals() != rproto->getTypeQuals()) + if (lproto->getMethodQuals() != rproto->getMethodQuals()) return {}; SmallVector<FunctionProtoType::ExtParameterInfo, 4> newParamInfos; @@ -9518,6 +9515,10 @@ QualType ASTContext::GetBuiltinType(unsigned Id, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs) const { const char *TypeStr = BuiltinInfo.getTypeString(Id); + if (TypeStr[0] == '\0') { + Error = GE_Missing_type; + return {}; + } SmallVector<QualType, 8> ArgTypes; @@ -9553,10 +9554,12 @@ QualType ASTContext::GetBuiltinType(unsigned Id, assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); - FunctionType::ExtInfo EI(CC_C); + bool Variadic = (TypeStr[0] == '.'); + + FunctionType::ExtInfo EI( + getDefaultCallingConvention(Variadic, /*IsCXXMethod=*/false)); if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true); - bool Variadic = (TypeStr[0] == '.'); // We really shouldn't be making a no-proto type here. if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus) @@ -9784,12 +9787,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return false; } else if (isa<PragmaCommentDecl>(D)) return true; - else if (isa<OMPThreadPrivateDecl>(D)) - return true; else if (isa<PragmaDetectMismatchDecl>(D)) return true; else if (isa<OMPThreadPrivateDecl>(D)) return !D->getDeclContext()->isDependentContext(); + else if (isa<OMPAllocateDecl>(D)) + return !D->getDeclContext()->isDependentContext(); else if (isa<OMPDeclareReductionDecl>(D)) return !D->getDeclContext()->isDependentContext(); else if (isa<ImportDecl>(D)) @@ -9978,8 +9981,10 @@ VTableContextBase *ASTContext::getVTableContext() { return VTContext.get(); } -MangleContext *ASTContext::createMangleContext() { - switch (Target->getCXXABI().getKind()) { +MangleContext *ASTContext::createMangleContext(const TargetInfo *T) { + if (!T) + T = Target; + switch (T->getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: @@ -10010,8 +10015,7 @@ size_t ASTContext::getSideTableAllocatedMemory() const { llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + llvm::capacity_in_bytes(OverriddenMethods) + llvm::capacity_in_bytes(Types) + - llvm::capacity_in_bytes(VariableArrayTypes) + - llvm::capacity_in_bytes(ClassScopeSpecializationPattern); + llvm::capacity_in_bytes(VariableArrayTypes); } /// getIntTypeForBitwidth - @@ -10485,7 +10489,13 @@ unsigned char ASTContext::getFixedPointIBits(QualType Ty) const { } FixedPointSemantics ASTContext::getFixedPointSemantics(QualType Ty) const { - assert(Ty->isFixedPointType()); + assert((Ty->isFixedPointType() || Ty->isIntegerType()) && + "Can only get the fixed point semantics for a " + "fixed point or integer type."); + if (Ty->isIntegerType()) + return FixedPointSemantics::GetIntegerSemantics(getIntWidth(Ty), + Ty->isSignedIntegerType()); + bool isSigned = Ty->isSignedFixedPointType(); return FixedPointSemantics( static_cast<unsigned>(getTypeSize(Ty)), getFixedPointScale(Ty), isSigned, @@ -10502,3 +10512,38 @@ APFixedPoint ASTContext::getFixedPointMin(QualType Ty) const { assert(Ty->isFixedPointType()); return APFixedPoint::getMin(getFixedPointSemantics(Ty)); } + +QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { + assert(Ty->isUnsignedFixedPointType() && + "Expected unsigned fixed point type"); + const auto *BTy = Ty->getAs<BuiltinType>(); + + switch (BTy->getKind()) { + case BuiltinType::UShortAccum: + return ShortAccumTy; + case BuiltinType::UAccum: + return AccumTy; + case BuiltinType::ULongAccum: + return LongAccumTy; + case BuiltinType::SatUShortAccum: + return SatShortAccumTy; + case BuiltinType::SatUAccum: + return SatAccumTy; + case BuiltinType::SatULongAccum: + return SatLongAccumTy; + case BuiltinType::UShortFract: + return ShortFractTy; + case BuiltinType::UFract: + return FractTy; + case BuiltinType::ULongFract: + return LongFractTy; + case BuiltinType::SatUShortFract: + return SatShortFractTy; + case BuiltinType::SatUFract: + return SatFractTy; + case BuiltinType::SatULongFract: + return SatLongFractTy; + default: + llvm_unreachable("Unexpected unsigned fixed point type"); + } +} diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index dd05855585..61900aa4ac 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -1,9 +1,8 @@ //===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index b52ec21943..f8938512af 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1,9 +1,8 @@ //===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -13,20 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDumperUtils.h" -#include "clang/AST/Attr.h" -#include "clang/AST/AttrVisitor.h" -#include "clang/AST/CommentVisitor.h" -#include "clang/AST/DeclCXX.h" +#include "clang/AST/ASTNodeTraverser.h" #include "clang/AST/DeclLookups.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/LocInfoType.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/TemplateArgumentVisitor.h" #include "clang/AST/TextNodeDumper.h" -#include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" @@ -40,339 +28,46 @@ using namespace clang::comments; namespace { - class ASTDumper - : public ConstDeclVisitor<ASTDumper>, - public ConstStmtVisitor<ASTDumper>, - public ConstCommentVisitor<ASTDumper, void, const FullComment *>, - public TypeVisitor<ASTDumper>, - public ConstAttrVisitor<ASTDumper>, - public ConstTemplateArgumentVisitor<ASTDumper> { - - TextNodeDumper NodeDumper; - - raw_ostream &OS; - - /// The policy to use for printing; can be defaulted. - PrintingPolicy PrintPolicy; - - /// Indicates whether we should trigger deserialization of nodes that had - /// not already been loaded. - bool Deserialize = false; - - const bool ShowColors; - - /// Dump a child of the current node. - template<typename Fn> void dumpChild(Fn DoDumpChild) { - NodeDumper.AddChild(DoDumpChild); - } - template <typename Fn> void dumpChild(StringRef Label, Fn DoDumpChild) { - NodeDumper.AddChild(Label, DoDumpChild); - } - - public: - ASTDumper(raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM) - : ASTDumper(OS, Traits, SM, - SM && SM->getDiagnostics().getShowColors()) {} - - ASTDumper(raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM, bool ShowColors) - : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {} - ASTDumper(raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM, bool ShowColors, - const PrintingPolicy &PrintPolicy) - : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS), - PrintPolicy(PrintPolicy), ShowColors(ShowColors) {} - - void setDeserialize(bool D) { Deserialize = D; } - - void dumpDecl(const Decl *D); - void dumpStmt(const Stmt *S, StringRef Label = {}); - - // Utilities - void dumpTypeAsChild(QualType T); - void dumpTypeAsChild(const Type *T); - void dumpDeclContext(const DeclContext *DC); - void dumpLookups(const DeclContext *DC, bool DumpDecls); - void dumpAttr(const Attr *A); - - // C++ Utilities - void dumpCXXCtorInitializer(const CXXCtorInitializer *Init); - void dumpTemplateParameters(const TemplateParameterList *TPL); - void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI); - void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, - const Decl *From = nullptr, - const char *Label = nullptr); - void dumpTemplateArgumentList(const TemplateArgumentList &TAL); - void dumpTemplateArgument(const TemplateArgument &A, - SourceRange R = SourceRange(), - const Decl *From = nullptr, - const char *Label = nullptr); - template <typename SpecializationDecl> - void dumpTemplateDeclSpecialization(const SpecializationDecl *D, - bool DumpExplicitInst, - bool DumpRefOnly); - template <typename TemplateDecl> - void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); - - // Objective-C utilities. - void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams); - - // Types - void VisitComplexType(const ComplexType *T) { - dumpTypeAsChild(T->getElementType()); - } - void VisitLocInfoType(const LocInfoType *T) { - dumpTypeAsChild(T->getTypeSourceInfo()->getType()); - } - void VisitPointerType(const PointerType *T) { - dumpTypeAsChild(T->getPointeeType()); - } - void VisitBlockPointerType(const BlockPointerType *T) { - dumpTypeAsChild(T->getPointeeType()); - } - void VisitReferenceType(const ReferenceType *T) { - dumpTypeAsChild(T->getPointeeType()); - } - void VisitMemberPointerType(const MemberPointerType *T) { - dumpTypeAsChild(T->getClass()); - dumpTypeAsChild(T->getPointeeType()); - } - void VisitArrayType(const ArrayType *T) { - dumpTypeAsChild(T->getElementType()); - } - void VisitVariableArrayType(const VariableArrayType *T) { - VisitArrayType(T); - dumpStmt(T->getSizeExpr()); - } - void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { - dumpTypeAsChild(T->getElementType()); - dumpStmt(T->getSizeExpr()); - } - void VisitDependentSizedExtVectorType( - const DependentSizedExtVectorType *T) { - dumpTypeAsChild(T->getElementType()); - dumpStmt(T->getSizeExpr()); - } - void VisitVectorType(const VectorType *T) { - dumpTypeAsChild(T->getElementType()); - } - void VisitFunctionType(const FunctionType *T) { - dumpTypeAsChild(T->getReturnType()); - } - void VisitFunctionProtoType(const FunctionProtoType *T) { - VisitFunctionType(T); - for (QualType PT : T->getParamTypes()) - dumpTypeAsChild(PT); - if (T->getExtProtoInfo().Variadic) - dumpChild([=] { OS << "..."; }); - } - void VisitTypeOfExprType(const TypeOfExprType *T) { - dumpStmt(T->getUnderlyingExpr()); - } - void VisitDecltypeType(const DecltypeType *T) { - dumpStmt(T->getUnderlyingExpr()); - } - void VisitUnaryTransformType(const UnaryTransformType *T) { - dumpTypeAsChild(T->getBaseType()); - } - void VisitAttributedType(const AttributedType *T) { - // FIXME: AttrKind - dumpTypeAsChild(T->getModifiedType()); - } - void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { - dumpTypeAsChild(T->getReplacedParameter()); - } - void VisitSubstTemplateTypeParmPackType( - const SubstTemplateTypeParmPackType *T) { - dumpTypeAsChild(T->getReplacedParameter()); - dumpTemplateArgument(T->getArgumentPack()); - } - void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { - for (auto &Arg : *T) - dumpTemplateArgument(Arg); - if (T->isTypeAlias()) - dumpTypeAsChild(T->getAliasedType()); - } - void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - dumpTypeAsChild(T->getPointeeType()); - } - void VisitAtomicType(const AtomicType *T) { - dumpTypeAsChild(T->getValueType()); - } - void VisitPipeType(const PipeType *T) { - dumpTypeAsChild(T->getElementType()); - } - void VisitAdjustedType(const AdjustedType *T) { - dumpTypeAsChild(T->getOriginalType()); - } - void VisitPackExpansionType(const PackExpansionType *T) { - if (!T->isSugared()) - dumpTypeAsChild(T->getPattern()); - } - // FIXME: ElaboratedType, DependentNameType, - // DependentTemplateSpecializationType, ObjCObjectType - - // Decls - void VisitLabelDecl(const LabelDecl *D); - void VisitTypedefDecl(const TypedefDecl *D); - void VisitEnumDecl(const EnumDecl *D); - void VisitRecordDecl(const RecordDecl *D); - void VisitEnumConstantDecl(const EnumConstantDecl *D); - void VisitIndirectFieldDecl(const IndirectFieldDecl *D); - void VisitFunctionDecl(const FunctionDecl *D); - void VisitFieldDecl(const FieldDecl *D); - void VisitVarDecl(const VarDecl *D); - void VisitDecompositionDecl(const DecompositionDecl *D); - void VisitBindingDecl(const BindingDecl *D); - void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D); - void VisitImportDecl(const ImportDecl *D); - void VisitPragmaCommentDecl(const PragmaCommentDecl *D); - void VisitPragmaDetectMismatchDecl(const PragmaDetectMismatchDecl *D); - void VisitCapturedDecl(const CapturedDecl *D); - - // OpenMP decls - void VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); - void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D); - void VisitOMPRequiresDecl(const OMPRequiresDecl *D); - void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D); - - // C++ Decls - void VisitNamespaceDecl(const NamespaceDecl *D); - void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D); - void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); - void VisitTypeAliasDecl(const TypeAliasDecl *D); - void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D); - void VisitCXXRecordDecl(const CXXRecordDecl *D); - void VisitStaticAssertDecl(const StaticAssertDecl *D); - void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); - void VisitClassTemplateDecl(const ClassTemplateDecl *D); - void VisitClassTemplateSpecializationDecl( - const ClassTemplateSpecializationDecl *D); - void VisitClassTemplatePartialSpecializationDecl( - const ClassTemplatePartialSpecializationDecl *D); - void VisitClassScopeFunctionSpecializationDecl( - const ClassScopeFunctionSpecializationDecl *D); - void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D); - void VisitVarTemplateDecl(const VarTemplateDecl *D); - void VisitVarTemplateSpecializationDecl( - const VarTemplateSpecializationDecl *D); - void VisitVarTemplatePartialSpecializationDecl( - const VarTemplatePartialSpecializationDecl *D); - void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); - void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); - void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); - void VisitUsingDecl(const UsingDecl *D); - void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); - void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); - void VisitUsingShadowDecl(const UsingShadowDecl *D); - void VisitConstructorUsingShadowDecl(const ConstructorUsingShadowDecl *D); - void VisitLinkageSpecDecl(const LinkageSpecDecl *D); - void VisitAccessSpecDecl(const AccessSpecDecl *D); - void VisitFriendDecl(const FriendDecl *D); - - // ObjC Decls - void VisitObjCIvarDecl(const ObjCIvarDecl *D); - void VisitObjCMethodDecl(const ObjCMethodDecl *D); - void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D); - void VisitObjCCategoryDecl(const ObjCCategoryDecl *D); - void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D); - void VisitObjCProtocolDecl(const ObjCProtocolDecl *D); - void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); - void VisitObjCImplementationDecl(const ObjCImplementationDecl *D); - void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); - void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); - void Visit(const BlockDecl::Capture &C); - void VisitBlockDecl(const BlockDecl *D); +class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> { - // Stmts. - void VisitDeclStmt(const DeclStmt *Node); - void VisitAttributedStmt(const AttributedStmt *Node); - void VisitCXXCatchStmt(const CXXCatchStmt *Node); - void VisitCapturedStmt(const CapturedStmt *Node); + TextNodeDumper NodeDumper; - // OpenMP - void Visit(const OMPClause *C); - void VisitOMPExecutableDirective(const OMPExecutableDirective *Node); + raw_ostream &OS; - // Exprs - void VisitInitListExpr(const InitListExpr *ILE); - void VisitBlockExpr(const BlockExpr *Node); - void VisitOpaqueValueExpr(const OpaqueValueExpr *Node); - void VisitGenericSelectionExpr(const GenericSelectionExpr *E); + const bool ShowColors; - // C++ - void VisitLambdaExpr(const LambdaExpr *Node) { - dumpDecl(Node->getLambdaClass()); - } - void VisitSizeOfPackExpr(const SizeOfPackExpr *Node); - - // ObjC - void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); - - // Comments. - void dumpComment(const Comment *C, const FullComment *FC); - - void VisitExpressionTemplateArgument(const TemplateArgument &TA) { - dumpStmt(TA.getAsExpr()); - } - void VisitPackTemplateArgument(const TemplateArgument &TA) { - for (const auto &TArg : TA.pack_elements()) - dumpTemplateArgument(TArg); - } +public: + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) + : ASTDumper(OS, Traits, SM, SM && SM->getDiagnostics().getShowColors()) {} -// Implements Visit methods for Attrs. -#include "clang/AST/AttrNodeTraverse.inc" - }; -} + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM, bool ShowColors) + : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {} + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM, bool ShowColors, + const PrintingPolicy &PrintPolicy) + : NodeDumper(OS, ShowColors, SM, PrintPolicy, Traits), OS(OS), + ShowColors(ShowColors) {} -//===----------------------------------------------------------------------===// -// Utilities -//===----------------------------------------------------------------------===// + TextNodeDumper &doGetNodeDelegate() { return NodeDumper; } -void ASTDumper::dumpTypeAsChild(QualType T) { - SplitQualType SQT = T.split(); - if (!SQT.Quals.hasQualifiers()) - return dumpTypeAsChild(SQT.Ty); + void dumpLookups(const DeclContext *DC, bool DumpDecls); - dumpChild([=] { - NodeDumper.Visit(T); - dumpTypeAsChild(T.split().Ty); - }); -} + template <typename SpecializationDecl> + void dumpTemplateDeclSpecialization(const SpecializationDecl *D, + bool DumpExplicitInst, bool DumpRefOnly); + template <typename TemplateDecl> + void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); -void ASTDumper::dumpTypeAsChild(const Type *T) { - dumpChild([=] { - NodeDumper.Visit(T); - if (!T) - return; - TypeVisitor<ASTDumper>::Visit(T); - - QualType SingleStepDesugar = - T->getLocallyUnqualifiedSingleStepDesugaredType(); - if (SingleStepDesugar != QualType(T, 0)) - dumpTypeAsChild(SingleStepDesugar); - }); -} - -void ASTDumper::dumpDeclContext(const DeclContext *DC) { - if (!DC) - return; - - for (auto *D : (Deserialize ? DC->decls() : DC->noload_decls())) - dumpDecl(D); - - if (DC->hasExternalLexicalStorage()) { - dumpChild([=] { - ColorScope Color(OS, ShowColors, UndeserializedColor); - OS << "<undeserialized declarations>"; - }); - } -} + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); + void VisitClassTemplateDecl(const ClassTemplateDecl *D); + void VisitVarTemplateDecl(const VarTemplateDecl *D); +}; +} // namespace void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { - dumpChild([=] { + NodeDumper.AddChild([=] { OS << "StoredDeclsMap "; NodeDumper.dumpBareDeclRef(cast<Decl>(DC)); @@ -384,14 +79,14 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage(); - auto Range = Deserialize + auto Range = getDeserialize() ? Primary->lookups() : Primary->noload_lookups(/*PreserveInternalState=*/true); for (auto I = Range.begin(), E = Range.end(); I != E; ++I) { DeclarationName Name = I.getLookupName(); DeclContextLookupResult R = *I; - dumpChild([=] { + NodeDumper.AddChild([=] { OS << "DeclarationName "; { ColorScope Color(OS, ShowColors, DeclNameColor); @@ -400,7 +95,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI) { - dumpChild([=] { + NodeDumper.AddChild([=] { NodeDumper.dumpBareDeclRef(*RI); if ((*RI)->isHidden()) @@ -412,7 +107,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) { if (Decl *Prev = D->getPreviousDecl()) DumpWithPrev(Prev); - dumpDecl(D); + Visit(D); }; DumpWithPrev(*RI); } @@ -422,7 +117,7 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { } if (HasUndeserializedLookups) { - dumpChild([=] { + NodeDumper.AddChild([=] { ColorScope Color(OS, ShowColors, UndeserializedColor); OS << "<undeserialized lookups>"; }); @@ -430,560 +125,12 @@ void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) { }); } -void ASTDumper::dumpAttr(const Attr *A) { - dumpChild([=] { - NodeDumper.Visit(A); - ConstAttrVisitor<ASTDumper>::Visit(A); - }); -} - -//===----------------------------------------------------------------------===// -// C++ Utilities -//===----------------------------------------------------------------------===// - -void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) { - dumpChild([=] { - NodeDumper.Visit(Init); - dumpStmt(Init->getInit()); - }); -} - -void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) { - if (!TPL) - return; - - for (TemplateParameterList::const_iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) - dumpDecl(*I); -} - -void ASTDumper::dumpTemplateArgumentListInfo( - const TemplateArgumentListInfo &TALI) { - for (unsigned i = 0, e = TALI.size(); i < e; ++i) - dumpTemplateArgumentLoc(TALI[i]); -} - -void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A, - const Decl *From, const char *Label) { - dumpTemplateArgument(A.getArgument(), A.getSourceRange(), From, Label); -} - -void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { - for (unsigned i = 0, e = TAL.size(); i < e; ++i) - dumpTemplateArgument(TAL[i]); -} - -void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R, - const Decl *From, const char *Label) { - dumpChild([=] { - NodeDumper.Visit(A, R, From, Label); - ConstTemplateArgumentVisitor<ASTDumper>::Visit(A); - }); -} - -//===----------------------------------------------------------------------===// -// Objective-C Utilities -//===----------------------------------------------------------------------===// -void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) { - if (!typeParams) - return; - - for (auto typeParam : *typeParams) { - dumpDecl(typeParam); - } -} - -//===----------------------------------------------------------------------===// -// Decl dumping methods. -//===----------------------------------------------------------------------===// - -void ASTDumper::dumpDecl(const Decl *D) { - dumpChild([=] { - NodeDumper.Visit(D); - if (!D) - return; - - ConstDeclVisitor<ASTDumper>::Visit(D); - - for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); I != E; - ++I) - dumpAttr(*I); - - if (const FullComment *Comment = - D->getASTContext().getLocalCommentForDeclUncached(D)) - dumpComment(Comment, Comment); - - // Decls within functions are visited by the body. - if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) { - auto DC = dyn_cast<DeclContext>(D); - if (DC && - (DC->hasExternalLexicalStorage() || - (Deserialize ? DC->decls_begin() != DC->decls_end() - : DC->noload_decls_begin() != DC->noload_decls_end()))) - dumpDeclContext(DC); - } - }); -} - -void ASTDumper::VisitLabelDecl(const LabelDecl *D) { NodeDumper.dumpName(D); } - -void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getUnderlyingType()); - if (D->isModulePrivate()) - OS << " __module_private__"; - dumpTypeAsChild(D->getUnderlyingType()); -} - -void ASTDumper::VisitEnumDecl(const EnumDecl *D) { - if (D->isScoped()) { - if (D->isScopedUsingClassTag()) - OS << " class"; - else - OS << " struct"; - } - NodeDumper.dumpName(D); - if (D->isModulePrivate()) - OS << " __module_private__"; - if (D->isFixed()) - NodeDumper.dumpType(D->getIntegerType()); -} - -void ASTDumper::VisitRecordDecl(const RecordDecl *D) { - OS << ' ' << D->getKindName(); - NodeDumper.dumpName(D); - if (D->isModulePrivate()) - OS << " __module_private__"; - if (D->isCompleteDefinition()) - OS << " definition"; -} - -void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - if (const Expr *Init = D->getInitExpr()) - dumpStmt(Init); -} - -void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - - for (auto *Child : D->chain()) - NodeDumper.dumpDeclRef(Child); -} - -void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - - StorageClass SC = D->getStorageClass(); - if (SC != SC_None) - OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); - if (D->isInlineSpecified()) - OS << " inline"; - if (D->isVirtualAsWritten()) - OS << " virtual"; - if (D->isModulePrivate()) - OS << " __module_private__"; - - if (D->isPure()) - OS << " pure"; - if (D->isDefaulted()) { - OS << " default"; - if (D->isDeleted()) - OS << "_delete"; - } - if (D->isDeletedAsWritten()) - OS << " delete"; - if (D->isTrivial()) - OS << " trivial"; - - if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) { - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - switch (EPI.ExceptionSpec.Type) { - default: break; - case EST_Unevaluated: - OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl; - break; - case EST_Uninstantiated: - OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate; - break; - } - } - - if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { - if (MD->size_overridden_methods() != 0) { - auto dumpOverride = [=](const CXXMethodDecl *D) { - SplitQualType T_split = D->getType().split(); - OS << D << " " << D->getParent()->getName() - << "::" << D->getNameAsString() << " '" - << QualType::getAsString(T_split, PrintPolicy) << "'"; - }; - - dumpChild([=] { - auto Overrides = MD->overridden_methods(); - OS << "Overrides: [ "; - dumpOverride(*Overrides.begin()); - for (const auto *Override : - llvm::make_range(Overrides.begin() + 1, Overrides.end())) { - OS << ", "; - dumpOverride(Override); - } - OS << " ]"; - }); - } - } - - if (const auto *FTSI = D->getTemplateSpecializationInfo()) - dumpTemplateArgumentList(*FTSI->TemplateArguments); - - if (!D->param_begin() && D->getNumParams()) - dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; }); - else - for (const ParmVarDecl *Parameter : D->parameters()) - dumpDecl(Parameter); - - if (const auto *C = dyn_cast<CXXConstructorDecl>(D)) - for (const auto *I : C->inits()) - dumpCXXCtorInitializer(I); - - if (D->doesThisDeclarationHaveABody()) - dumpStmt(D->getBody()); -} - -void ASTDumper::VisitFieldDecl(const FieldDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - if (D->isMutable()) - OS << " mutable"; - if (D->isModulePrivate()) - OS << " __module_private__"; - - if (D->isBitField()) - dumpStmt(D->getBitWidth()); - if (Expr *Init = D->getInClassInitializer()) - dumpStmt(Init); -} - -void ASTDumper::VisitVarDecl(const VarDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - StorageClass SC = D->getStorageClass(); - if (SC != SC_None) - OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); - switch (D->getTLSKind()) { - case VarDecl::TLS_None: break; - case VarDecl::TLS_Static: OS << " tls"; break; - case VarDecl::TLS_Dynamic: OS << " tls_dynamic"; break; - } - if (D->isModulePrivate()) - OS << " __module_private__"; - if (D->isNRVOVariable()) - OS << " nrvo"; - if (D->isInline()) - OS << " inline"; - if (D->isConstexpr()) - OS << " constexpr"; - if (D->hasInit()) { - switch (D->getInitStyle()) { - case VarDecl::CInit: OS << " cinit"; break; - case VarDecl::CallInit: OS << " callinit"; break; - case VarDecl::ListInit: OS << " listinit"; break; - } - dumpStmt(D->getInit()); - } -} - -void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) { - VisitVarDecl(D); - for (auto *B : D->bindings()) - dumpDecl(B); -} - -void ASTDumper::VisitBindingDecl(const BindingDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - if (auto *E = D->getBinding()) - dumpStmt(E); -} - -void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { - dumpStmt(D->getAsmString()); -} - -void ASTDumper::VisitImportDecl(const ImportDecl *D) { - OS << ' ' << D->getImportedModule()->getFullModuleName(); -} - -void ASTDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) { - OS << ' '; - switch (D->getCommentKind()) { - case PCK_Unknown: llvm_unreachable("unexpected pragma comment kind"); - case PCK_Compiler: OS << "compiler"; break; - case PCK_ExeStr: OS << "exestr"; break; - case PCK_Lib: OS << "lib"; break; - case PCK_Linker: OS << "linker"; break; - case PCK_User: OS << "user"; break; - } - StringRef Arg = D->getArg(); - if (!Arg.empty()) - OS << " \"" << Arg << "\""; -} - -void ASTDumper::VisitPragmaDetectMismatchDecl( - const PragmaDetectMismatchDecl *D) { - OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\""; -} - -void ASTDumper::VisitCapturedDecl(const CapturedDecl *D) { - dumpStmt(D->getBody()); -} - -//===----------------------------------------------------------------------===// -// OpenMP Declarations -//===----------------------------------------------------------------------===// - -void ASTDumper::VisitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { - for (auto *E : D->varlists()) - dumpStmt(E); -} - -void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - OS << " combiner"; - NodeDumper.dumpPointer(D->getCombiner()); - if (const auto *Initializer = D->getInitializer()) { - OS << " initializer"; - NodeDumper.dumpPointer(Initializer); - switch (D->getInitializerKind()) { - case OMPDeclareReductionDecl::DirectInit: - OS << " omp_priv = "; - break; - case OMPDeclareReductionDecl::CopyInit: - OS << " omp_priv ()"; - break; - case OMPDeclareReductionDecl::CallInit: - break; - } - } - - dumpStmt(D->getCombiner()); - if (const auto *Initializer = D->getInitializer()) - dumpStmt(Initializer); -} - -void ASTDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) { - for (auto *C : D->clauselists()) { - dumpChild([=] { - if (!C) { - ColorScope Color(OS, ShowColors, NullColor); - OS << "<<<NULL>>> OMPClause"; - return; - } - { - ColorScope Color(OS, ShowColors, AttrColor); - StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); - OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() - << ClauseName.drop_front() << "Clause"; - } - NodeDumper.dumpPointer(C); - NodeDumper.dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); - }); - } -} - -void ASTDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - dumpStmt(D->getInit()); -} - -//===----------------------------------------------------------------------===// -// C++ Declarations -//===----------------------------------------------------------------------===// - -void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) { - NodeDumper.dumpName(D); - if (D->isInline()) - OS << " inline"; - if (!D->isOriginalNamespace()) - NodeDumper.dumpDeclRef(D->getOriginalNamespace(), "original"); -} - -void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { - OS << ' '; - NodeDumper.dumpBareDeclRef(D->getNominatedNamespace()); -} - -void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpDeclRef(D->getAliasedNamespace()); -} - -void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getUnderlyingType()); - dumpTypeAsChild(D->getUnderlyingType()); -} - -void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { - NodeDumper.dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); - dumpDecl(D->getTemplatedDecl()); -} - -void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { - VisitRecordDecl(D); - if (!D->isCompleteDefinition()) - return; - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "DefinitionData"; - } -#define FLAG(fn, name) if (D->fn()) OS << " " #name; - FLAG(isParsingBaseSpecifiers, parsing_base_specifiers); - - FLAG(isGenericLambda, generic); - FLAG(isLambda, lambda); - - FLAG(canPassInRegisters, pass_in_registers); - FLAG(isEmpty, empty); - FLAG(isAggregate, aggregate); - FLAG(isStandardLayout, standard_layout); - FLAG(isTriviallyCopyable, trivially_copyable); - FLAG(isPOD, pod); - FLAG(isTrivial, trivial); - FLAG(isPolymorphic, polymorphic); - FLAG(isAbstract, abstract); - FLAG(isLiteral, literal); - - FLAG(hasUserDeclaredConstructor, has_user_declared_ctor); - FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor); - FLAG(hasMutableFields, has_mutable_fields); - FLAG(hasVariantMembers, has_variant_members); - FLAG(allowConstDefaultInit, can_const_default_init); - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "DefaultConstructor"; - } - FLAG(hasDefaultConstructor, exists); - FLAG(hasTrivialDefaultConstructor, trivial); - FLAG(hasNonTrivialDefaultConstructor, non_trivial); - FLAG(hasUserProvidedDefaultConstructor, user_provided); - FLAG(hasConstexprDefaultConstructor, constexpr); - FLAG(needsImplicitDefaultConstructor, needs_implicit); - FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr); - }); - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "CopyConstructor"; - } - FLAG(hasSimpleCopyConstructor, simple); - FLAG(hasTrivialCopyConstructor, trivial); - FLAG(hasNonTrivialCopyConstructor, non_trivial); - FLAG(hasUserDeclaredCopyConstructor, user_declared); - FLAG(hasCopyConstructorWithConstParam, has_const_param); - FLAG(needsImplicitCopyConstructor, needs_implicit); - FLAG(needsOverloadResolutionForCopyConstructor, - needs_overload_resolution); - if (!D->needsOverloadResolutionForCopyConstructor()) - FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted); - FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param); - }); - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "MoveConstructor"; - } - FLAG(hasMoveConstructor, exists); - FLAG(hasSimpleMoveConstructor, simple); - FLAG(hasTrivialMoveConstructor, trivial); - FLAG(hasNonTrivialMoveConstructor, non_trivial); - FLAG(hasUserDeclaredMoveConstructor, user_declared); - FLAG(needsImplicitMoveConstructor, needs_implicit); - FLAG(needsOverloadResolutionForMoveConstructor, - needs_overload_resolution); - if (!D->needsOverloadResolutionForMoveConstructor()) - FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted); - }); - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "CopyAssignment"; - } - FLAG(hasTrivialCopyAssignment, trivial); - FLAG(hasNonTrivialCopyAssignment, non_trivial); - FLAG(hasCopyAssignmentWithConstParam, has_const_param); - FLAG(hasUserDeclaredCopyAssignment, user_declared); - FLAG(needsImplicitCopyAssignment, needs_implicit); - FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution); - FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param); - }); - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "MoveAssignment"; - } - FLAG(hasMoveAssignment, exists); - FLAG(hasSimpleMoveAssignment, simple); - FLAG(hasTrivialMoveAssignment, trivial); - FLAG(hasNonTrivialMoveAssignment, non_trivial); - FLAG(hasUserDeclaredMoveAssignment, user_declared); - FLAG(needsImplicitMoveAssignment, needs_implicit); - FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution); - }); - - dumpChild([=] { - { - ColorScope Color(OS, ShowColors, DeclKindNameColor); - OS << "Destructor"; - } - FLAG(hasSimpleDestructor, simple); - FLAG(hasIrrelevantDestructor, irrelevant); - FLAG(hasTrivialDestructor, trivial); - FLAG(hasNonTrivialDestructor, non_trivial); - FLAG(hasUserDeclaredDestructor, user_declared); - FLAG(needsImplicitDestructor, needs_implicit); - FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution); - if (!D->needsOverloadResolutionForDestructor()) - FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted); - }); - }); - - for (const auto &I : D->bases()) { - dumpChild([=] { - if (I.isVirtual()) - OS << "virtual "; - NodeDumper.dumpAccessSpecifier(I.getAccessSpecifier()); - NodeDumper.dumpType(I.getType()); - if (I.isPackExpansion()) - OS << "..."; - }); - } -} - -void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { - dumpStmt(D->getAssertExpr()); - dumpStmt(D->getMessage()); -} - template <typename SpecializationDecl> void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D, bool DumpExplicitInst, bool DumpRefOnly) { bool DumpedAny = false; - for (auto *RedeclWithBadType : D->redecls()) { + for (const auto *RedeclWithBadType : D->redecls()) { // FIXME: The redecls() range sometimes has elements of a less-specific // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives // us TagDecls, and should give CXXRecordDecls). @@ -1007,7 +154,7 @@ void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D, if (DumpRefOnly) NodeDumper.dumpDeclRef(Redecl); else - dumpDecl(Redecl); + Visit(Redecl); DumpedAny = true; break; case TSK_ExplicitSpecialization: @@ -1022,12 +169,11 @@ void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D, template <typename TemplateDecl> void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) { - NodeDumper.dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - dumpDecl(D->getTemplatedDecl()); + Visit(D->getTemplatedDecl()); - for (auto *Child : D->specializations()) + for (const auto *Child : D->specializations()) dumpTemplateDeclSpecialization(Child, DumpExplicitInst, !D->isCanonicalDecl()); } @@ -1043,500 +189,10 @@ void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { dumpTemplateDecl(D, false); } -void ASTDumper::VisitClassTemplateSpecializationDecl( - const ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); - dumpTemplateArgumentList(D->getTemplateArgs()); -} - -void ASTDumper::VisitClassTemplatePartialSpecializationDecl( - const ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); - dumpTemplateParameters(D->getTemplateParameters()); -} - -void ASTDumper::VisitClassScopeFunctionSpecializationDecl( - const ClassScopeFunctionSpecializationDecl *D) { - dumpDecl(D->getSpecialization()); - if (D->hasExplicitTemplateArgs()) - dumpTemplateArgumentListInfo(D->templateArgs()); -} - void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D, false); } -void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { - NodeDumper.dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); -} - -void ASTDumper::VisitVarTemplateSpecializationDecl( - const VarTemplateSpecializationDecl *D) { - dumpTemplateArgumentList(D->getTemplateArgs()); - VisitVarDecl(D); -} - -void ASTDumper::VisitVarTemplatePartialSpecializationDecl( - const VarTemplatePartialSpecializationDecl *D) { - dumpTemplateParameters(D->getTemplateParameters()); - VisitVarTemplateSpecializationDecl(D); -} - -void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { - if (D->wasDeclaredWithTypename()) - OS << " typename"; - else - OS << " class"; - OS << " depth " << D->getDepth() << " index " << D->getIndex(); - if (D->isParameterPack()) - OS << " ..."; - NodeDumper.dumpName(D); - if (D->hasDefaultArgument()) - dumpTemplateArgument(D->getDefaultArgument(), SourceRange(), - D->getDefaultArgStorage().getInheritedFrom(), - D->defaultArgumentWasInherited() ? "inherited from" - : "previous"); -} - -void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { - NodeDumper.dumpType(D->getType()); - OS << " depth " << D->getDepth() << " index " << D->getIndex(); - if (D->isParameterPack()) - OS << " ..."; - NodeDumper.dumpName(D); - if (D->hasDefaultArgument()) - dumpTemplateArgument(D->getDefaultArgument(), SourceRange(), - D->getDefaultArgStorage().getInheritedFrom(), - D->defaultArgumentWasInherited() ? "inherited from" - : "previous"); -} - -void ASTDumper::VisitTemplateTemplateParmDecl( - const TemplateTemplateParmDecl *D) { - OS << " depth " << D->getDepth() << " index " << D->getIndex(); - if (D->isParameterPack()) - OS << " ..."; - NodeDumper.dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); - if (D->hasDefaultArgument()) - dumpTemplateArgumentLoc( - D->getDefaultArgument(), D->getDefaultArgStorage().getInheritedFrom(), - D->defaultArgumentWasInherited() ? "inherited from" : "previous"); -} - -void ASTDumper::VisitUsingDecl(const UsingDecl *D) { - OS << ' '; - if (D->getQualifier()) - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); - OS << D->getNameAsString(); -} - -void ASTDumper::VisitUnresolvedUsingTypenameDecl( - const UnresolvedUsingTypenameDecl *D) { - OS << ' '; - if (D->getQualifier()) - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); - OS << D->getNameAsString(); -} - -void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { - OS << ' '; - if (D->getQualifier()) - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); - OS << D->getNameAsString(); - NodeDumper.dumpType(D->getType()); -} - -void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { - OS << ' '; - NodeDumper.dumpBareDeclRef(D->getTargetDecl()); - if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) - dumpTypeAsChild(TD->getTypeForDecl()); -} - -void ASTDumper::VisitConstructorUsingShadowDecl( - const ConstructorUsingShadowDecl *D) { - if (D->constructsVirtualBase()) - OS << " virtual"; - - dumpChild([=] { - OS << "target "; - NodeDumper.dumpBareDeclRef(D->getTargetDecl()); - }); - - dumpChild([=] { - OS << "nominated "; - NodeDumper.dumpBareDeclRef(D->getNominatedBaseClass()); - OS << ' '; - NodeDumper.dumpBareDeclRef(D->getNominatedBaseClassShadowDecl()); - }); - - dumpChild([=] { - OS << "constructed "; - NodeDumper.dumpBareDeclRef(D->getConstructedBaseClass()); - OS << ' '; - NodeDumper.dumpBareDeclRef(D->getConstructedBaseClassShadowDecl()); - }); -} - -void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { - switch (D->getLanguage()) { - case LinkageSpecDecl::lang_c: OS << " C"; break; - case LinkageSpecDecl::lang_cxx: OS << " C++"; break; - } -} - -void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { - OS << ' '; - NodeDumper.dumpAccessSpecifier(D->getAccess()); -} - -void ASTDumper::VisitFriendDecl(const FriendDecl *D) { - if (TypeSourceInfo *T = D->getFriendType()) - NodeDumper.dumpType(T->getType()); - else - dumpDecl(D->getFriendDecl()); -} - -//===----------------------------------------------------------------------===// -// Obj-C Declarations -//===----------------------------------------------------------------------===// - -void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - if (D->getSynthesize()) - OS << " synthesize"; - - switch (D->getAccessControl()) { - case ObjCIvarDecl::None: - OS << " none"; - break; - case ObjCIvarDecl::Private: - OS << " private"; - break; - case ObjCIvarDecl::Protected: - OS << " protected"; - break; - case ObjCIvarDecl::Public: - OS << " public"; - break; - case ObjCIvarDecl::Package: - OS << " package"; - break; - } -} - -void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { - if (D->isInstanceMethod()) - OS << " -"; - else - OS << " +"; - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getReturnType()); - - if (D->isThisDeclarationADefinition()) { - dumpDeclContext(D); - } else { - for (const ParmVarDecl *Parameter : D->parameters()) - dumpDecl(Parameter); - } - - if (D->isVariadic()) - dumpChild([=] { OS << "..."; }); - - if (D->hasBody()) - dumpStmt(D->getBody()); -} - -void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) { - NodeDumper.dumpName(D); - switch (D->getVariance()) { - case ObjCTypeParamVariance::Invariant: - break; - - case ObjCTypeParamVariance::Covariant: - OS << " covariant"; - break; - - case ObjCTypeParamVariance::Contravariant: - OS << " contravariant"; - break; - } - - if (D->hasExplicitBound()) - OS << " bounded"; - NodeDumper.dumpType(D->getUnderlyingType()); -} - -void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpDeclRef(D->getClassInterface()); - NodeDumper.dumpDeclRef(D->getImplementation()); - for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(), - E = D->protocol_end(); - I != E; ++I) - NodeDumper.dumpDeclRef(*I); - dumpObjCTypeParamList(D->getTypeParamList()); -} - -void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpDeclRef(D->getClassInterface()); - NodeDumper.dumpDeclRef(D->getCategoryDecl()); -} - -void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { - NodeDumper.dumpName(D); - - for (auto *Child : D->protocols()) - NodeDumper.dumpDeclRef(Child); -} - -void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpDeclRef(D->getSuperClass(), "super"); - - NodeDumper.dumpDeclRef(D->getImplementation()); - for (auto *Child : D->protocols()) - NodeDumper.dumpDeclRef(Child); - dumpObjCTypeParamList(D->getTypeParamListAsWritten()); -} - -void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpDeclRef(D->getSuperClass(), "super"); - NodeDumper.dumpDeclRef(D->getClassInterface()); - for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(), - E = D->init_end(); - I != E; ++I) - dumpCXXCtorInitializer(*I); -} - -void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpDeclRef(D->getClassInterface()); -} - -void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { - NodeDumper.dumpName(D); - NodeDumper.dumpType(D->getType()); - - if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) - OS << " required"; - else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional) - OS << " optional"; - - ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); - if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { - if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly) - OS << " readonly"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) - OS << " assign"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite) - OS << " readwrite"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_retain) - OS << " retain"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_copy) - OS << " copy"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) - OS << " nonatomic"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic) - OS << " atomic"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_weak) - OS << " weak"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_strong) - OS << " strong"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) - OS << " unsafe_unretained"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_class) - OS << " class"; - if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) - NodeDumper.dumpDeclRef(D->getGetterMethodDecl(), "getter"); - if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) - NodeDumper.dumpDeclRef(D->getSetterMethodDecl(), "setter"); - } -} - -void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { - NodeDumper.dumpName(D->getPropertyDecl()); - if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) - OS << " synthesize"; - else - OS << " dynamic"; - NodeDumper.dumpDeclRef(D->getPropertyDecl()); - NodeDumper.dumpDeclRef(D->getPropertyIvarDecl()); -} - -void ASTDumper::Visit(const BlockDecl::Capture &C) { - dumpChild([=] { - NodeDumper.Visit(C); - if (C.hasCopyExpr()) - dumpStmt(C.getCopyExpr()); - }); -} - -void ASTDumper::VisitBlockDecl(const BlockDecl *D) { - for (auto I : D->parameters()) - dumpDecl(I); - - if (D->isVariadic()) - dumpChild([=]{ OS << "..."; }); - - if (D->capturesCXXThis()) - dumpChild([=]{ OS << "capture this"; }); - - for (const auto &I : D->captures()) - Visit(I); - dumpStmt(D->getBody()); -} - -//===----------------------------------------------------------------------===// -// Stmt dumping methods. -//===----------------------------------------------------------------------===// - -void ASTDumper::dumpStmt(const Stmt *S, StringRef Label) { - dumpChild(Label, [=] { - NodeDumper.Visit(S); - - if (!S) { - return; - } - - ConstStmtVisitor<ASTDumper>::Visit(S); - - // Some statements have custom mechanisms for dumping their children. - if (isa<DeclStmt>(S) || isa<GenericSelectionExpr>(S)) { - return; - } - - for (const Stmt *SubStmt : S->children()) - dumpStmt(SubStmt); - }); -} - -void ASTDumper::VisitDeclStmt(const DeclStmt *Node) { - for (DeclStmt::const_decl_iterator I = Node->decl_begin(), - E = Node->decl_end(); - I != E; ++I) - dumpDecl(*I); -} - -void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) { - for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(), - E = Node->getAttrs().end(); - I != E; ++I) - dumpAttr(*I); -} - -void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) { - dumpDecl(Node->getExceptionDecl()); -} - -void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) { - dumpDecl(Node->getCapturedDecl()); -} - -//===----------------------------------------------------------------------===// -// OpenMP dumping methods. -//===----------------------------------------------------------------------===// - -void ASTDumper::Visit(const OMPClause *C) { - dumpChild([=] { - NodeDumper.Visit(C); - for (auto *S : C->children()) - dumpStmt(S); - }); -} - -void ASTDumper::VisitOMPExecutableDirective( - const OMPExecutableDirective *Node) { - for (const auto *C : Node->clauses()) - Visit(C); -} - -//===----------------------------------------------------------------------===// -// Expr dumping methods. -//===----------------------------------------------------------------------===// - - -void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { - if (auto *Filler = ILE->getArrayFiller()) { - dumpStmt(Filler, "array_filler"); - } -} - -void ASTDumper::VisitBlockExpr(const BlockExpr *Node) { - dumpDecl(Node->getBlockDecl()); -} - -void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { - if (Expr *Source = Node->getSourceExpr()) - dumpStmt(Source); -} - -void ASTDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { - if (E->isResultDependent()) - OS << " result_dependent"; - dumpStmt(E->getControllingExpr()); - dumpTypeAsChild(E->getControllingExpr()->getType()); // FIXME: remove - - for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) { - dumpChild([=] { - if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) { - OS << "case "; - NodeDumper.dumpType(TSI->getType()); - } else { - OS << "default"; - } - - if (!E->isResultDependent() && E->getResultIndex() == I) - OS << " selected"; - - if (const TypeSourceInfo *TSI = E->getAssocTypeSourceInfo(I)) - dumpTypeAsChild(TSI->getType()); - dumpStmt(E->getAssocExpr(I)); - }); - } -} - -//===----------------------------------------------------------------------===// -// C++ Expressions -//===----------------------------------------------------------------------===// - -void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { - if (Node->isPartiallySubstituted()) - for (const auto &A : Node->getPartialArguments()) - dumpTemplateArgument(A); -} - -//===----------------------------------------------------------------------===// -// Obj-C Expressions -//===----------------------------------------------------------------------===// - -void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { - if (const VarDecl *CatchParam = Node->getCatchParamDecl()) - dumpDecl(CatchParam); -} - -//===----------------------------------------------------------------------===// -// Comments -//===----------------------------------------------------------------------===// - -void ASTDumper::dumpComment(const Comment *C, const FullComment *FC) { - dumpChild([=] { - NodeDumper.Visit(C, FC); - if (!C) { - return; - } - ConstCommentVisitor<ASTDumper, void, const FullComment *>::visit(C, FC); - for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); - I != E; ++I) - dumpComment(*I, FC); - }); -} - //===----------------------------------------------------------------------===// // Type method implementations //===----------------------------------------------------------------------===// @@ -1551,7 +207,7 @@ LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); } LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const { ASTDumper Dumper(OS, nullptr, nullptr); - Dumper.dumpTypeAsChild(*this); + Dumper.Visit(*this); } LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); } @@ -1572,7 +228,7 @@ LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize) const { ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &SM, SM.getDiagnostics().getShowColors(), Ctx.getPrintingPolicy()); P.setDeserialize(Deserialize); - P.dumpDecl(this); + P.Visit(this); } LLVM_DUMP_METHOD void Decl::dumpColor() const { @@ -1580,7 +236,7 @@ LLVM_DUMP_METHOD void Decl::dumpColor() const { ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(), /*ShowColors*/ true, Ctx.getPrintingPolicy()); - P.dumpDecl(this); + P.Visit(this); } LLVM_DUMP_METHOD void DeclContext::dumpLookups() const { @@ -1611,22 +267,22 @@ LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const { LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { ASTDumper P(OS, nullptr, &SM); - P.dumpStmt(this); + P.Visit(this); } LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const { ASTDumper P(OS, nullptr, nullptr); - P.dumpStmt(this); + P.Visit(this); } LLVM_DUMP_METHOD void Stmt::dump() const { ASTDumper P(llvm::errs(), nullptr, nullptr); - P.dumpStmt(this); + P.Visit(this); } LLVM_DUMP_METHOD void Stmt::dumpColor() const { ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); - P.dumpStmt(this); + P.Visit(this); } //===----------------------------------------------------------------------===// @@ -1648,7 +304,7 @@ void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, if (!FC) return; ASTDumper D(OS, Traits, SM); - D.dumpComment(FC, FC); + D.Visit(FC, FC); } LLVM_DUMP_METHOD void Comment::dumpColor() const { @@ -1656,5 +312,5 @@ LLVM_DUMP_METHOD void Comment::dumpColor() const { if (!FC) return; ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); - D.dumpComment(FC, FC); + D.Visit(FC, FC); } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 44832557e9..1ac4870cab 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1,9 +1,8 @@ //===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -135,25 +134,6 @@ namespace clang { To->setIsUsed(); } - // FIXME: Temporary until every import returns Expected. - template <> - LLVM_NODISCARD Error - ASTImporter::importInto(SourceLocation &To, const SourceLocation &From) { - To = Import(From); - if (From.isValid() && To.isInvalid()) - return llvm::make_error<ImportError>(); - return Error::success(); - } - // FIXME: Temporary until every import returns Expected. - template <> - LLVM_NODISCARD Error - ASTImporter::importInto(QualType &To, const QualType &From) { - To = Import(From); - if (!From.isNull() && To.isNull()) - return llvm::make_error<ImportError>(); - return Error::success(); - } - class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>, public DeclVisitor<ASTNodeImporter, ExpectedDecl>, public StmtVisitor<ASTNodeImporter, ExpectedStmt> { @@ -168,32 +148,20 @@ namespace clang { // Use this to import pointers of specific type. template <typename ImportT> LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) { - auto ToI = Importer.Import(From); - if (!ToI && From) - return make_error<ImportError>(); - To = cast_or_null<ImportT>(ToI); - return Error::success(); - // FIXME: This should be the final code. - //auto ToOrErr = Importer.Import(From); - //if (ToOrErr) { - // To = cast_or_null<ImportT>(*ToOrErr); - //} - //return ToOrErr.takeError(); + auto ToOrErr = Importer.Import_New(From); + if (ToOrErr) + To = cast_or_null<ImportT>(*ToOrErr); + return ToOrErr.takeError(); } // Call the import function of ASTImporter for a baseclass of type `T` and // cast the return value to `T`. template <typename T> Expected<T *> import(T *From) { - auto *To = Importer.Import(From); - if (!To && From) - return make_error<ImportError>(); - return cast_or_null<T>(To); - // FIXME: This should be the final code. - //auto ToOrErr = Importer.Import(From); - //if (!ToOrErr) - // return ToOrErr.takeError(); - //return cast_or_null<T>(*ToOrErr); + auto ToOrErr = Importer.Import_New(From); + if (!ToOrErr) + return ToOrErr.takeError(); + return cast_or_null<T>(*ToOrErr); } template <typename T> @@ -204,13 +172,15 @@ namespace clang { // Call the import function of ASTImporter for type `T`. template <typename T> Expected<T> import(const T &From) { - T To = Importer.Import(From); - T DefaultT; - if (To == DefaultT && !(From == DefaultT)) - return make_error<ImportError>(); - return To; - // FIXME: This should be the final code. - //return Importer.Import(From); + return Importer.Import_New(From); + } + + // Import an Optional<T> by importing the contained T, if any. + template<typename T> + Expected<Optional<T>> import(Optional<T> From) { + if (!From) + return Optional<T>(); + return import(*From); } template <class T> @@ -293,8 +263,7 @@ namespace clang { return true; // Already imported. ToD = CreateFun(std::forward<Args>(args)...); // Keep track of imported Decls. - Importer.MapImported(FromD, ToD); - Importer.AddToLookupTable(ToD); + Importer.RegisterImportedDecl(FromD, ToD); InitializeImportedDecl(FromD, ToD); return false; // A new Decl is created. } @@ -302,14 +271,31 @@ namespace clang { void InitializeImportedDecl(Decl *FromD, Decl *ToD) { ToD->IdentifierNamespace = FromD->IdentifierNamespace; if (FromD->hasAttrs()) - for (const Attr *FromAttr : FromD->getAttrs()) - ToD->addAttr(Importer.Import(FromAttr)); + for (const Attr *FromAttr : FromD->getAttrs()) { + // FIXME: Return of the error here is not possible until store of + // import errors is implemented. + auto ToAttrOrErr = import(FromAttr); + if (ToAttrOrErr) + ToD->addAttr(*ToAttrOrErr); + else + llvm::consumeError(ToAttrOrErr.takeError()); + } if (FromD->isUsed()) ToD->setIsUsed(); if (FromD->isImplicit()) ToD->setImplicit(); } + // Check if we have found an existing definition. Returns with that + // definition if yes, otherwise returns null. + Decl *FindAndMapDefinition(FunctionDecl *D, FunctionDecl *FoundFunction) { + const FunctionDecl *Definition = nullptr; + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody(Definition)) + return Importer.MapImported(D, const_cast<FunctionDecl *>(Definition)); + return nullptr; + } + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} @@ -412,8 +398,6 @@ namespace clang { Error ImportDefinition( ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind = IDK_Default); - Expected<TemplateParameterList *> ImportTemplateParameterList( - TemplateParameterList *Params); Error ImportTemplateArguments( const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs); @@ -438,6 +422,11 @@ namespace clang { Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); + Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD); + + template <typename T> + bool hasSameVisibilityContext(T *Found, T *From); + bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); @@ -548,6 +537,7 @@ namespace clang { // Importing expressions ExpectedStmt VisitExpr(Expr *E); ExpectedStmt VisitVAArgExpr(VAArgExpr *E); + ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); @@ -649,15 +639,6 @@ namespace clang { FunctionDecl *FromFD); }; -// FIXME: Temporary until every import returns Expected. -template <> -Expected<TemplateName> ASTNodeImporter::import(const TemplateName &From) { - TemplateName To = Importer.Import(From); - if (To.isNull() && !From.isNull()) - return make_error<ImportError>(); - return To; -} - template <typename InContainerTy> Error ASTNodeImporter::ImportTemplateArgumentListInfo( SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, @@ -1698,15 +1679,10 @@ Error ASTNodeImporter::ImportImplicitMethods( static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, ASTImporter &Importer) { if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) { - Decl *ToTypedef = Importer.Import(FromTypedef); - if (!ToTypedef) - return make_error<ImportError>(); - To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(ToTypedef)); - // FIXME: This should be the final code. - //if (Expected<Decl *> ToTypedefOrErr = Importer.Import(FromTypedef)) - // To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr)); - //else - // return ToTypedefOrErr.takeError(); + if (ExpectedDecl ToTypedefOrErr = Importer.Import_New(FromTypedef)) + To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr)); + else + return ToTypedefOrErr.takeError(); } return Error::success(); } @@ -1798,6 +1774,9 @@ Error ASTNodeImporter::ImportDefinition( ToData.HasDeclaredCopyAssignmentWithConstParam = FromData.HasDeclaredCopyAssignmentWithConstParam; + // Copy over the data stored in RecordDeclBits + ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions()); + SmallVector<CXXBaseSpecifier *, 4> Bases; for (const auto &Base1 : FromCXX->bases()) { ExpectedType TyOrErr = import(Base1.getType()); @@ -1903,40 +1882,6 @@ Error ASTNodeImporter::ImportDefinition( return Error::success(); } -// FIXME: Remove this, use `import` instead. -Expected<TemplateParameterList *> ASTNodeImporter::ImportTemplateParameterList( - TemplateParameterList *Params) { - SmallVector<NamedDecl *, 4> ToParams(Params->size()); - if (Error Err = ImportContainerChecked(*Params, ToParams)) - return std::move(Err); - - Expr *ToRequiresClause; - if (Expr *const R = Params->getRequiresClause()) { - if (Error Err = importInto(ToRequiresClause, R)) - return std::move(Err); - } else { - ToRequiresClause = nullptr; - } - - auto ToTemplateLocOrErr = import(Params->getTemplateLoc()); - if (!ToTemplateLocOrErr) - return ToTemplateLocOrErr.takeError(); - auto ToLAngleLocOrErr = import(Params->getLAngleLoc()); - if (!ToLAngleLocOrErr) - return ToLAngleLocOrErr.takeError(); - auto ToRAngleLocOrErr = import(Params->getRAngleLoc()); - if (!ToRAngleLocOrErr) - return ToRAngleLocOrErr.takeError(); - - return TemplateParameterList::Create( - Importer.getToContext(), - *ToTemplateLocOrErr, - *ToLAngleLocOrErr, - ToParams, - *ToRAngleLocOrErr, - ToRequiresClause); -} - Error ASTNodeImporter::ImportTemplateArguments( const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl<TemplateArgument> &ToArgs) { @@ -2011,6 +1956,12 @@ bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, } bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { + // Eliminate a potential failure point where we attempt to re-import + // something we're trying to import while completing ToEnum. + if (Decl *ToOrigin = Importer.GetOriginalDecl(ToEnum)) + if (auto *ToOriginEnum = dyn_cast<EnumDecl>(ToOrigin)) + ToEnum = ToOriginEnum; + StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer)); @@ -2500,7 +2451,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { } if (!ConflictingDecls.empty()) { - Name = Importer.HandleNameConflict(Name, DC, IDNS, + Name = Importer.HandleNameConflict(SearchName, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) @@ -2548,26 +2499,6 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Decl::FOK_None; } - // If this record has a definition in the translation unit we're coming from, - // but this particular declaration is not that definition, import the - // definition and map to that. - TagDecl *Definition = D->getDefinition(); - if (Definition && Definition != D && - // Friend template declaration must be imported on its own. - !IsFriendTemplate && - // In contrast to a normal CXXRecordDecl, the implicit - // CXXRecordDecl of ClassTemplateSpecializationDecl is its redeclaration. - // The definition of the implicit CXXRecordDecl in this case is the - // ClassTemplateSpecializationDecl itself. Thus, we start with an extra - // condition in order to be able to import the implict Decl. - !D->isImplicit()) { - ExpectedDecl ImportedDefOrErr = import(Definition); - if (!ImportedDefOrErr) - return ImportedDefOrErr.takeError(); - - return Importer.MapImported(D, *ImportedDefOrErr); - } - // Import the major distinguishing characteristics of this record. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2596,7 +2527,8 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { auto FoundDecls = Importer.findDeclsInToCtx(DC, SearchName); if (!FoundDecls.empty()) { - // We're going to have to compare D against potentially conflicting Decls, so complete it. + // We're going to have to compare D against potentially conflicting Decls, + // so complete it. if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition()) D->getASTContext().getExternalSource()->CompleteType(D); } @@ -2945,6 +2877,30 @@ ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { return FoundSpec; } +Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, + FunctionDecl *ToFD) { + if (Stmt *FromBody = FromFD->getBody()) { + if (ExpectedStmt ToBodyOrErr = import(FromBody)) + ToFD->setBody(*ToBodyOrErr); + else + return ToBodyOrErr.takeError(); + } + return Error::success(); +} + +template <typename T> +bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) { + if (From->hasExternalFormalLinkage()) + return Found->hasExternalFormalLinkage(); + if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl()) + return false; + if (From->isInAnonymousNamespace()) + return Found->isInAnonymousNamespace(); + else + return !Found->isInAnonymousNamespace() && + !Found->hasExternalFormalLinkage(); +} + ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D); @@ -2968,7 +2924,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ToD) return ToD; - const FunctionDecl *FoundByLookup = nullptr; + FunctionDecl *FoundByLookup = nullptr; FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate(); // If this is a function template specialization, then try to find the same @@ -2982,8 +2938,8 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (!FoundFunctionOrErr) return FoundFunctionOrErr.takeError(); if (FunctionDecl *FoundFunction = *FoundFunctionOrErr) { - if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody()) - return Importer.MapImported(D, FoundFunction); + if (Decl *Def = FindAndMapDefinition(D, FoundFunction)) + return Def; FoundByLookup = FoundFunction; } } @@ -2998,33 +2954,27 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { continue; if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) { - if (FoundFunction->hasExternalFormalLinkage() && - D->hasExternalFormalLinkage()) { - if (IsStructuralMatch(D, FoundFunction)) { - const FunctionDecl *Definition = nullptr; - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody(Definition)) { - return Importer.MapImported( - D, const_cast<FunctionDecl *>(Definition)); - } - FoundByLookup = FoundFunction; - break; - } + if (!hasSameVisibilityContext(FoundFunction, D)) + continue; - // FIXME: Check for overloading more carefully, e.g., by boosting - // Sema::IsOverload out to the AST library. + if (IsStructuralMatch(D, FoundFunction)) { + if (Decl *Def = FindAndMapDefinition(D, FoundFunction)) + return Def; + FoundByLookup = FoundFunction; + break; + } + // FIXME: Check for overloading more carefully, e.g., by boosting + // Sema::IsOverload out to the AST library. - // Function overloading is okay in C++. - if (Importer.getToContext().getLangOpts().CPlusPlus) - continue; + // Function overloading is okay in C++. + if (Importer.getToContext().getLangOpts().CPlusPlus) + continue; - // Complain about inconsistent function types. - Importer.ToDiag(Loc, diag::err_odr_function_type_inconsistent) + // Complain about inconsistent function types. + Importer.ToDiag(Loc, diag::warn_odr_function_type_inconsistent) << Name << D->getType() << FoundFunction->getType(); - Importer.ToDiag(FoundFunction->getLocation(), - diag::note_odr_value_here) + Importer.ToDiag(FoundFunction->getLocation(), diag::note_odr_value_here) << FoundFunction->getType(); - } } ConflictingDecls.push_back(FoundDecl); @@ -3039,6 +2989,25 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } + // We do not allow more than one in-class declaration of a function. This is + // because AST clients like VTableBuilder asserts on this. VTableBuilder + // assumes there is only one in-class declaration. Building a redecl + // chain would result in more than one in-class declaration for + // overrides (even if they are part of the same redecl chain inside the + // derived class.) + if (FoundByLookup) { + if (isa<CXXMethodDecl>(FoundByLookup)) { + if (D->getLexicalDeclContext() == D->getDeclContext()) { + if (!D->doesThisDeclarationHaveABody()) + return Importer.MapImported(D, FoundByLookup); + else { + // Let's continue and build up the redecl chain in this case. + // FIXME Merge the functions into one decl. + } + } + } + } + DeclarationNameInfo NameInfo(Name, Loc); // Import additional name location/type info. if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) @@ -3092,12 +3061,28 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FromConstructor->isExplicit(), D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) return ToFunction; - } else if (isa<CXXDestructorDecl>(D)) { + } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) { + + auto Imp = + importSeq(const_cast<FunctionDecl *>(FromDtor->getOperatorDelete()), + FromDtor->getOperatorDeleteThisArg()); + + if (!Imp) + return Imp.takeError(); + + FunctionDecl *ToOperatorDelete; + Expr *ToThisArg; + std::tie(ToOperatorDelete, ToThisArg) = *Imp; + if (GetImportedOrCreateDecl<CXXDestructorDecl>( ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit())) return ToFunction; + + CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction); + + ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast<CXXConversionDecl>(D)) { if (GetImportedOrCreateDecl<CXXConversionDecl>( @@ -3184,12 +3169,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } if (D->doesThisDeclarationHaveABody()) { - if (Stmt *FromBody = D->getBody()) { - if (ExpectedStmt ToBodyOrErr = import(FromBody)) - ToFunction->setBody(*ToBodyOrErr); - else - return ToBodyOrErr.takeError(); - } + Error Err = ImportFunctionDeclBody(D, ToFunction); + + if (Err) + return std::move(Err); } // FIXME: Other bits to merge? @@ -3292,7 +3275,7 @@ ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { } // FIXME: Why is this case not handled with calling HandleNameConflict? - Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); @@ -3363,7 +3346,7 @@ ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { continue; // FIXME: Why is this case not handled with calling HandleNameConflict? - Importer.ToDiag(Loc, diag::err_odr_field_type_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); @@ -3394,9 +3377,6 @@ ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { // FIXME here we leak `NamedChain` which is allocated before return ToIndirectField; - for (const auto *Attr : D->attrs()) - ToIndirectField->addAttr(Importer.Import(Attr)); - ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIndirectField); @@ -3451,7 +3431,7 @@ ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>(); for (unsigned I = 0; I < D->NumTPLists; I++) { - if (auto ListOrErr = ImportTemplateParameterList(FromTPLists[I])) + if (auto ListOrErr = import(FromTPLists[I])) ToTPLists[I] = *ListOrErr; else return ListOrErr.takeError(); @@ -3497,7 +3477,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { return FoundIvar; } - Importer.ToDiag(Loc, diag::err_odr_ivar_type_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_ivar_type_inconsistent) << Name << D->getType() << FoundIvar->getType(); Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); @@ -3564,58 +3544,56 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { continue; if (auto *FoundVar = dyn_cast<VarDecl>(FoundDecl)) { - // We have found a variable that we may need to merge with. Check it. - if (FoundVar->hasExternalFormalLinkage() && - D->hasExternalFormalLinkage()) { - if (Importer.IsStructurallyEquivalent(D->getType(), - FoundVar->getType())) { - - // The VarDecl in the "From" context has a definition, but in the - // "To" context we already have a definition. - VarDecl *FoundDef = FoundVar->getDefinition(); - if (D->isThisDeclarationADefinition() && FoundDef) - // FIXME Check for ODR error if the two definitions have - // different initializers? - return Importer.MapImported(D, FoundDef); - - // The VarDecl in the "From" context has an initializer, but in the - // "To" context we already have an initializer. - const VarDecl *FoundDInit = nullptr; - if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit)) - // FIXME Diagnose ODR error if the two initializers are different? - return Importer.MapImported(D, const_cast<VarDecl*>(FoundDInit)); + if (!hasSameVisibilityContext(FoundVar, D)) + continue; + if (Importer.IsStructurallyEquivalent(D->getType(), + FoundVar->getType())) { + + // The VarDecl in the "From" context has a definition, but in the + // "To" context we already have a definition. + VarDecl *FoundDef = FoundVar->getDefinition(); + if (D->isThisDeclarationADefinition() && FoundDef) + // FIXME Check for ODR error if the two definitions have + // different initializers? + return Importer.MapImported(D, FoundDef); + + // The VarDecl in the "From" context has an initializer, but in the + // "To" context we already have an initializer. + const VarDecl *FoundDInit = nullptr; + if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit)) + // FIXME Diagnose ODR error if the two initializers are different? + return Importer.MapImported(D, const_cast<VarDecl*>(FoundDInit)); + + FoundByLookup = FoundVar; + break; + } + + const ArrayType *FoundArray + = Importer.getToContext().getAsArrayType(FoundVar->getType()); + const ArrayType *TArray + = Importer.getToContext().getAsArrayType(D->getType()); + if (FoundArray && TArray) { + if (isa<IncompleteArrayType>(FoundArray) && + isa<ConstantArrayType>(TArray)) { + // Import the type. + if (auto TyOrErr = import(D->getType())) + FoundVar->setType(*TyOrErr); + else + return TyOrErr.takeError(); FoundByLookup = FoundVar; break; + } else if (isa<IncompleteArrayType>(TArray) && + isa<ConstantArrayType>(FoundArray)) { + FoundByLookup = FoundVar; + break; } - - const ArrayType *FoundArray - = Importer.getToContext().getAsArrayType(FoundVar->getType()); - const ArrayType *TArray - = Importer.getToContext().getAsArrayType(D->getType()); - if (FoundArray && TArray) { - if (isa<IncompleteArrayType>(FoundArray) && - isa<ConstantArrayType>(TArray)) { - // Import the type. - if (auto TyOrErr = import(D->getType())) - FoundVar->setType(*TyOrErr); - else - return TyOrErr.takeError(); - - FoundByLookup = FoundVar; - break; - } else if (isa<IncompleteArrayType>(TArray) && - isa<ConstantArrayType>(FoundArray)) { - FoundByLookup = FoundVar; - break; - } - } - - Importer.ToDiag(Loc, diag::err_odr_variable_type_inconsistent) - << Name << D->getType() << FoundVar->getType(); - Importer.ToDiag(FoundVar->getLocation(), diag::note_odr_value_here) - << FoundVar->getType(); } + + Importer.ToDiag(Loc, diag::warn_odr_variable_type_inconsistent) + << Name << D->getType() << FoundVar->getType(); + Importer.ToDiag(FoundVar->getLocation(), diag::note_odr_value_here) + << FoundVar->getType(); } ConflictingDecls.push_back(FoundDecl); @@ -3777,7 +3755,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Check return types. if (!Importer.IsStructurallyEquivalent(D->getReturnType(), FoundMethod->getReturnType())) { - Importer.ToDiag(Loc, diag::err_odr_objc_method_result_type_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_objc_method_result_type_inconsistent) << D->isInstanceMethod() << Name << D->getReturnType() << FoundMethod->getReturnType(); Importer.ToDiag(FoundMethod->getLocation(), @@ -3789,7 +3767,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Check the number of parameters. if (D->param_size() != FoundMethod->param_size()) { - Importer.ToDiag(Loc, diag::err_odr_objc_method_num_params_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_objc_method_num_params_inconsistent) << D->isInstanceMethod() << Name << D->param_size() << FoundMethod->param_size(); Importer.ToDiag(FoundMethod->getLocation(), @@ -3806,7 +3784,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { if (!Importer.IsStructurallyEquivalent((*P)->getType(), (*FoundP)->getType())) { Importer.FromDiag((*P)->getLocation(), - diag::err_odr_objc_method_param_type_inconsistent) + diag::warn_odr_objc_method_param_type_inconsistent) << D->isInstanceMethod() << Name << (*P)->getType() << (*FoundP)->getType(); Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) @@ -3819,7 +3797,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Check variadic/non-variadic. // Check the number of parameters. if (D->isVariadic() != FoundMethod->isVariadic()) { - Importer.ToDiag(Loc, diag::err_odr_objc_method_variadic_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_objc_method_variadic_inconsistent) << D->isInstanceMethod() << Name; Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) @@ -4364,7 +4342,7 @@ Error ASTNodeImporter::ImportDefinition( if ((bool)FromSuper != (bool)ToSuper || (FromSuper && !declaresSameEntity(FromSuper, ToSuper))) { Importer.ToDiag(To->getLocation(), - diag::err_odr_objc_superclass_inconsistent) + diag::warn_odr_objc_superclass_inconsistent) << To->getDeclName(); if (ToSuper) Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass) @@ -4633,7 +4611,7 @@ ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) { Importer.ToDiag(Impl->getLocation(), - diag::err_odr_objc_superclass_inconsistent) + diag::warn_odr_objc_superclass_inconsistent) << Iface->getDeclName(); // FIXME: It would be nice to have the location of the superclass // below. @@ -4681,7 +4659,7 @@ ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Check property types. if (!Importer.IsStructurallyEquivalent(D->getType(), FoundProp->getType())) { - Importer.ToDiag(Loc, diag::err_odr_objc_property_type_inconsistent) + Importer.ToDiag(Loc, diag::warn_odr_objc_property_type_inconsistent) << Name << D->getType() << FoundProp->getType(); Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); @@ -4788,7 +4766,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { // vs. @dynamic). if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) { Importer.ToDiag(ToImpl->getLocation(), - diag::err_odr_objc_property_impl_kind_inconsistent) + diag::warn_odr_objc_property_impl_kind_inconsistent) << Property->getDeclName() << (ToImpl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); @@ -4804,7 +4782,7 @@ ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize && Ivar != ToImpl->getPropertyIvarDecl()) { Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(), - diag::err_odr_objc_synthesize_ivar_inconsistent) + diag::warn_odr_objc_synthesize_ivar_inconsistent) << Property->getDeclName() << ToImpl->getPropertyIvarDecl()->getDeclName() << Ivar->getDeclName(); @@ -4888,8 +4866,7 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { return LocationOrErr.takeError(); // Import template parameters. - auto TemplateParamsOrErr = ImportTemplateParameterList( - D->getTemplateParameters()); + auto TemplateParamsOrErr = import(D->getTemplateParameters()); if (!TemplateParamsOrErr) return TemplateParamsOrErr.takeError(); @@ -4905,31 +4882,20 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { return ToD; } -// Returns the definition for a (forward) declaration of a ClassTemplateDecl, if +// Returns the definition for a (forward) declaration of a TemplateDecl, if // it has any definition in the redecl chain. -static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) { - CXXRecordDecl *ToTemplatedDef = D->getTemplatedDecl()->getDefinition(); +template <typename T> static auto getTemplateDefinition(T *D) -> T * { + assert(D->getTemplatedDecl() && "Should be called on templates only"); + auto *ToTemplatedDef = D->getTemplatedDecl()->getDefinition(); if (!ToTemplatedDef) return nullptr; - ClassTemplateDecl *TemplateWithDef = - ToTemplatedDef->getDescribedClassTemplate(); - return TemplateWithDef; + auto *TemplateWithDef = ToTemplatedDef->getDescribedTemplate(); + return cast_or_null<T>(TemplateWithDef); } ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { bool IsFriend = D->getFriendObjectKind() != Decl::FOK_None; - // If this template has a definition in the translation unit we're coming - // from, but this particular declaration is not that definition, import the - // definition and map to that. - ClassTemplateDecl *Definition = getDefinition(D); - if (Definition && Definition != D && !IsFriend) { - if (ExpectedDecl ImportedDefOrErr = import(Definition)) - return Importer.MapImported(D, *ImportedDefOrErr); - else - return ImportedDefOrErr.takeError(); - } - // Import the major distinguishing characteristics of this class template. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -4956,7 +4922,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (FoundTemplate) { if (IsStructuralMatch(D, FoundTemplate)) { - ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate); + ClassTemplateDecl *TemplateWithDef = + getTemplateDefinition(FoundTemplate); if (D->isThisDeclarationADefinition() && TemplateWithDef) { return Importer.MapImported(D, TemplateWithDef); } @@ -4986,8 +4953,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { return std::move(Err); // Create the class template declaration itself. - auto TemplateParamsOrErr = ImportTemplateParameterList( - D->getTemplateParameters()); + auto TemplateParamsOrErr = import(D->getTemplateParameters()); if (!TemplateParamsOrErr) return TemplateParamsOrErr.takeError(); @@ -5019,6 +4985,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // and this time the lookup finds the previous fwd friend class template. // In this case we must set up the previous decl for the templated decl. if (!ToTemplated->getPreviousDecl()) { + assert(FoundByLookup->getTemplatedDecl() && + "Found decl must have its templated decl set"); CXXRecordDecl *PrevTemplated = FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); if (ToTemplated != PrevTemplated) @@ -5041,17 +5009,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { - // If this record has a definition in the translation unit we're coming from, - // but this particular declaration is not that definition, import the - // definition and map to that. - TagDecl *Definition = D->getDefinition(); - if (Definition && Definition != D) { - if (ExpectedDecl ImportedDefOrErr = import(Definition)) - return Importer.MapImported(D, *ImportedDefOrErr); - else - return ImportedDefOrErr.takeError(); - } - ClassTemplateDecl *ClassTemplate; if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate())) return std::move(Err); @@ -5069,154 +5026,140 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Try to find an existing specialization with these template arguments. void *InsertPos = nullptr; - ClassTemplateSpecializationDecl *D2 = nullptr; + ClassTemplateSpecializationDecl *PrevDecl = nullptr; ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast<ClassTemplatePartialSpecializationDecl>(D); if (PartialSpec) - D2 = ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos); + PrevDecl = + ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos); else - D2 = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); - ClassTemplateSpecializationDecl * const PrevDecl = D2; - RecordDecl *FoundDef = D2 ? D2->getDefinition() : nullptr; - if (FoundDef) { - if (!D->isCompleteDefinition()) { - // The "From" translation unit only had a forward declaration; call it - // the same declaration. - // TODO Handle the redecl chain properly! - return Importer.MapImported(D, FoundDef); - } - - if (IsStructuralMatch(D, FoundDef)) { - - Importer.MapImported(D, FoundDef); - - // Import those those default field initializers which have been - // instantiated in the "From" context, but not in the "To" context. - for (auto *FromField : D->fields()) { - auto ToOrErr = import(FromField); - if (!ToOrErr) - // FIXME: return the error? - consumeError(ToOrErr.takeError()); + PrevDecl = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); + + if (PrevDecl) { + if (IsStructuralMatch(D, PrevDecl)) { + if (D->isThisDeclarationADefinition() && PrevDecl->getDefinition()) { + Importer.MapImported(D, PrevDecl->getDefinition()); + // Import those default field initializers which have been + // instantiated in the "From" context, but not in the "To" context. + for (auto *FromField : D->fields()) + Importer.Import(FromField); + + // Import those methods which have been instantiated in the + // "From" context, but not in the "To" context. + for (CXXMethodDecl *FromM : D->methods()) + Importer.Import(FromM); + + // TODO Import instantiated default arguments. + // TODO Import instantiated exception specifications. + // + // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint + // what else could be fused during an AST merge. + return PrevDecl; } + } else { // ODR violation. + // FIXME HandleNameConflict + return nullptr; + } + } - // Import those methods which have been instantiated in the - // "From" context, but not in the "To" context. - for (CXXMethodDecl *FromM : D->methods()) { - auto ToOrErr = import(FromM); - if (!ToOrErr) - // FIXME: return the error? - consumeError(ToOrErr.takeError()); - } + // Import the location of this declaration. + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + ExpectedSLoc IdLocOrErr = import(D->getLocation()); + if (!IdLocOrErr) + return IdLocOrErr.takeError(); - // TODO Import instantiated default arguments. - // TODO Import instantiated exception specifications. - // - // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint what - // else could be fused during an AST merge. + // Create the specialization. + ClassTemplateSpecializationDecl *D2 = nullptr; + if (PartialSpec) { + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); + if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) + return std::move(Err); - return FoundDef; - } - } else { // We either couldn't find any previous specialization in the "To" - // context, or we found one but without definition. Let's create a - // new specialization and register that at the class template. + QualType CanonInjType; + if (Error Err = importInto( + CanonInjType, PartialSpec->getInjectedSpecializationType())) + return std::move(Err); + CanonInjType = CanonInjType.getCanonicalType(); + + auto ToTPListOrErr = import(PartialSpec->getTemplateParameters()); + if (!ToTPListOrErr) + return ToTPListOrErr.takeError(); + + if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, + cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) + return D2; - // Import the location of this declaration. - ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); - if (!BeginLocOrErr) - return BeginLocOrErr.takeError(); - ExpectedSLoc IdLocOrErr = import(D->getLocation()); - if (!IdLocOrErr) - return IdLocOrErr.takeError(); - - if (PartialSpec) { - // Import TemplateArgumentListInfo. - TemplateArgumentListInfo ToTAInfo; - const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); - if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) - return std::move(Err); + // Update InsertPos, because preceding import calls may have invalidated + // it by adding new specializations. + if (!ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos)) + // Add this partial specialization to the class template. + ClassTemplate->AddPartialSpecialization( + cast<ClassTemplatePartialSpecializationDecl>(D2), InsertPos); - QualType CanonInjType; - if (Error Err = importInto( - CanonInjType, PartialSpec->getInjectedSpecializationType())) - return std::move(Err); - CanonInjType = CanonInjType.getCanonicalType(); + } else { // Not a partial specialization. + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, + PrevDecl)) + return D2; - auto ToTPListOrErr = ImportTemplateParameterList( - PartialSpec->getTemplateParameters()); - if (!ToTPListOrErr) - return ToTPListOrErr.takeError(); + // Update InsertPos, because preceding import calls may have invalidated + // it by adding new specializations. + if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos)) + // Add this specialization to the class template. + ClassTemplate->AddSpecialization(D2, InsertPos); + } - if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( - D2, D, Importer.getToContext(), D->getTagKind(), DC, - *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate, - llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), - ToTAInfo, CanonInjType, - cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) - return D2; + D2->setSpecializationKind(D->getSpecializationKind()); - // Update InsertPos, because preceding import calls may have invalidated - // it by adding new specializations. - if (!ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos)) - // Add this partial specialization to the class template. - ClassTemplate->AddPartialSpecialization( - cast<ClassTemplatePartialSpecializationDecl>(D2), InsertPos); + // Set the context of this specialization/instantiation. + D2->setLexicalDeclContext(LexicalDC); - } else { // Not a partial specialization. - if (GetImportedOrCreateDecl( - D2, D, Importer.getToContext(), D->getTagKind(), DC, - *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, - PrevDecl)) - return D2; + // Add to the DC only if it was an explicit specialization/instantiation. + if (D2->isExplicitInstantiationOrSpecialization()) { + LexicalDC->addDeclInternal(D2); + } - // Update InsertPos, because preceding import calls may have invalidated - // it by adding new specializations. - if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos)) - // Add this specialization to the class template. - ClassTemplate->AddSpecialization(D2, InsertPos); - } + // Import the qualifier, if any. + if (auto LocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*LocOrErr); + else + return LocOrErr.takeError(); - D2->setSpecializationKind(D->getSpecializationKind()); + if (auto *TSI = D->getTypeAsWritten()) { + if (auto TInfoOrErr = import(TSI)) + D2->setTypeAsWritten(*TInfoOrErr); + else + return TInfoOrErr.takeError(); - // Import the qualifier, if any. - if (auto LocOrErr = import(D->getQualifierLoc())) - D2->setQualifierInfo(*LocOrErr); + if (auto LocOrErr = import(D->getTemplateKeywordLoc())) + D2->setTemplateKeywordLoc(*LocOrErr); else return LocOrErr.takeError(); - if (auto *TSI = D->getTypeAsWritten()) { - if (auto TInfoOrErr = import(TSI)) - D2->setTypeAsWritten(*TInfoOrErr); - else - return TInfoOrErr.takeError(); - - if (auto LocOrErr = import(D->getTemplateKeywordLoc())) - D2->setTemplateKeywordLoc(*LocOrErr); - else - return LocOrErr.takeError(); - - if (auto LocOrErr = import(D->getExternLoc())) - D2->setExternLoc(*LocOrErr); - else - return LocOrErr.takeError(); - } - - if (D->getPointOfInstantiation().isValid()) { - if (auto POIOrErr = import(D->getPointOfInstantiation())) - D2->setPointOfInstantiation(*POIOrErr); - else - return POIOrErr.takeError(); - } + if (auto LocOrErr = import(D->getExternLoc())) + D2->setExternLoc(*LocOrErr); + else + return LocOrErr.takeError(); + } - D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); + if (D->getPointOfInstantiation().isValid()) { + if (auto POIOrErr = import(D->getPointOfInstantiation())) + D2->setPointOfInstantiation(*POIOrErr); + else + return POIOrErr.takeError(); + } - // Set the context of this specialization/instantiation. - D2->setLexicalDeclContext(LexicalDC); + D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); - // Add to the DC only if it was an explicit specialization/instantiation. - if (D2->isExplicitInstantiationOrSpecialization()) { - LexicalDC->addDeclInternal(D2); - } - } if (D->isCompleteDefinition()) if (Error Err = ImportDefinition(D, D2)) return std::move(Err); @@ -5296,8 +5239,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { return std::move(Err); // Create the variable template declaration itself. - auto TemplateParamsOrErr = ImportTemplateParameterList( - D->getTemplateParameters()); + auto TemplateParamsOrErr = import(D->getTemplateParameters()); if (!TemplateParamsOrErr) return TemplateParamsOrErr.takeError(); @@ -5402,8 +5344,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( *FromTAArgsAsWritten, ArgInfos)) return std::move(Err); - auto ToTPListOrErr = ImportTemplateParameterList( - FromPartial->getTemplateParameters()); + auto ToTPListOrErr = import(FromPartial->getTemplateParameters()); if (!ToTPListOrErr) return ToTPListOrErr.takeError(); @@ -5481,32 +5422,37 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ToD) return ToD; + const FunctionTemplateDecl *FoundByLookup = nullptr; + // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. + // FIXME Split this into a separate function. if (!LexicalDC->isFunctionOrMethod()) { - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (auto *FoundFunction = - dyn_cast<FunctionTemplateDecl>(FoundDecl)) { - if (FoundFunction->hasExternalFormalLinkage() && + if (auto *FoundTemplate = dyn_cast<FunctionTemplateDecl>(FoundDecl)) { + if (FoundTemplate->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { - if (IsStructuralMatch(D, FoundFunction)) { - Importer.MapImported(D, FoundFunction); - // FIXME: Actually try to merge the body and other attributes. - return FoundFunction; + if (IsStructuralMatch(D, FoundTemplate)) { + FunctionTemplateDecl *TemplateWithDef = + getTemplateDefinition(FoundTemplate); + if (D->isThisDeclarationADefinition() && TemplateWithDef) { + return Importer.MapImported(D, TemplateWithDef); + } + FoundByLookup = FoundTemplate; + break; } + // TODO: handle conflicting names } } - // TODO: handle conflicting names } } - auto ParamsOrErr = ImportTemplateParameterList( - D->getTemplateParameters()); + auto ParamsOrErr = import(D->getTemplateParameters()); if (!ParamsOrErr) return ParamsOrErr.takeError(); @@ -5520,10 +5466,25 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); + ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(ToFunc); + + if (FoundByLookup) { + auto *Recent = + const_cast<FunctionTemplateDecl *>(FoundByLookup->getMostRecentDecl()); + if (!TemplatedFD->getPreviousDecl()) { + assert(FoundByLookup->getTemplatedDecl() && + "Found decl must have its templated decl set"); + auto *PrevTemplated = + FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); + if (TemplatedFD != PrevTemplated) + TemplatedFD->setPreviousDecl(PrevTemplated); + } + ToFunc->setPreviousDecl(Recent); + } + return ToFunc; } @@ -6079,6 +6040,33 @@ ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { E->isMicrosoftABI()); } +ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) { + auto Imp = importSeq(E->getCond(), E->getLHS(), E->getRHS(), + E->getBuiltinLoc(), E->getRParenLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCond; + Expr *ToLHS; + Expr *ToRHS; + SourceLocation ToBuiltinLoc, ToRParenLoc; + QualType ToType; + std::tie(ToCond, ToLHS, ToRHS, ToBuiltinLoc, ToRParenLoc, ToType) = *Imp; + + ExprValueKind VK = E->getValueKind(); + ExprObjectKind OK = E->getObjectKind(); + + bool TypeDependent = ToCond->isTypeDependent(); + bool ValueDependent = ToCond->isValueDependent(); + + // The value of CondIsTrue only matters if the value is not + // condition-dependent. + bool CondIsTrue = !E->isConditionDependent() && E->isConditionTrue(); + + return new (Importer.getToContext()) + ChooseExpr(ToBuiltinLoc, ToCond, ToLHS, ToRHS, ToType, VK, OK, + ToRParenLoc, CondIsTrue, TypeDependent, ValueDependent); +} ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { ExpectedType TypeOrErr = import(E->getType()); @@ -6898,7 +6886,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { FunctionDecl *ToOperatorNew, *ToOperatorDelete; SourceRange ToTypeIdParens, ToSourceRange, ToDirectInitRange; - Expr *ToArraySize, *ToInitializer; + Optional<Expr *> ToArraySize; + Expr *ToInitializer; QualType ToType; TypeSourceInfo *ToAllocatedTypeSourceInfo; std::tie( @@ -7051,15 +7040,19 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { DeclarationNameInfo ToMemberNameInfo(ToName, ToLoc); + TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - // FIXME: handle template arguments - return make_error<ImportError>(ImportError::UnsupportedConstruct); + if (Error Err = + ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), + E->template_arguments(), ToTAInfo)) + return std::move(Err); + ResInfo = &ToTAInfo; } return MemberExpr::Create( Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl, - ToMemberNameInfo, nullptr, ToType, E->getValueKind(), E->getObjectKind()); + ToMemberNameInfo, ResInfo, ToType, E->getValueKind(), E->getObjectKind()); } ExpectedStmt @@ -7337,13 +7330,9 @@ ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { // NOTE: lambda classes are created with BeingDefined flag set up. // It means that ImportDefinition doesn't work for them and we should fill it // manually. - if (ToClass->isBeingDefined()) { - for (auto FromField : FromClass->fields()) { - auto ToFieldOrErr = import(FromField); - if (!ToFieldOrErr) - return ToFieldOrErr.takeError(); - } - } + if (ToClass->isBeingDefined()) + if (Error Err = ImportDeclContext(FromClass, /*ForceImport = */ true)) + return std::move(Err); auto ToCallOpOrErr = import(E->getCallOperator()); if (!ToCallOpOrErr) @@ -7624,13 +7613,6 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTImporter::~ASTImporter() = default; -Expected<QualType> ASTImporter::Import_New(QualType FromT) { - QualType ToT = Import(FromT); - if (ToT.isNull() && !FromT.isNull()) - return make_error<ImportError>(); - return ToT; -} - Optional<unsigned> ASTImporter::getFieldIndex(Decl *F) { assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) && "Try to get field index for non-field."); @@ -7682,9 +7664,20 @@ void ASTImporter::AddToLookupTable(Decl *ToD) { LookupTable->add(ToND); } -QualType ASTImporter::Import(QualType FromT) { +Expected<Decl *> ASTImporter::ImportImpl(Decl *FromD) { + // Import the decl using ASTNodeImporter. + ASTNodeImporter Importer(*this); + return Importer.Visit(FromD); +} + +void ASTImporter::RegisterImportedDecl(Decl *FromD, Decl *ToD) { + MapImported(FromD, ToD); + AddToLookupTable(ToD); +} + +Expected<QualType> ASTImporter::Import_New(QualType FromT) { if (FromT.isNull()) - return {}; + return QualType{}; const Type *FromTy = FromT.getTypePtr(); @@ -7697,46 +7690,64 @@ QualType ASTImporter::Import(QualType FromT) { // Import the type ASTNodeImporter Importer(*this); ExpectedType ToTOrErr = Importer.Visit(FromTy); - if (!ToTOrErr) { - llvm::consumeError(ToTOrErr.takeError()); - return {}; - } + if (!ToTOrErr) + return ToTOrErr.takeError(); // Record the imported type. ImportedTypes[FromTy] = (*ToTOrErr).getTypePtr(); return ToContext.getQualifiedType(*ToTOrErr, FromT.getLocalQualifiers()); } +QualType ASTImporter::Import(QualType From) { + llvm::Expected<QualType> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; +} Expected<TypeSourceInfo *> ASTImporter::Import_New(TypeSourceInfo *FromTSI) { - TypeSourceInfo *ToTSI = Import(FromTSI); - if (!ToTSI && FromTSI) - return llvm::make_error<ImportError>(); - return ToTSI; -} -TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { if (!FromTSI) return FromTSI; // FIXME: For now we just create a "trivial" type source info based // on the type and a single location. Implement a real version of this. - QualType T = Import(FromTSI->getType()); - if (T.isNull()) - return nullptr; + ExpectedType TOrErr = Import_New(FromTSI->getType()); + if (!TOrErr) + return TOrErr.takeError(); + ExpectedSLoc BeginLocOrErr = Import_New(FromTSI->getTypeLoc().getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); - return ToContext.getTrivialTypeSourceInfo( - T, Import(FromTSI->getTypeLoc().getBeginLoc())); + return ToContext.getTrivialTypeSourceInfo(*TOrErr, *BeginLocOrErr); +} +TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *From) { + llvm::Expected<TypeSourceInfo *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; } Expected<Attr *> ASTImporter::Import_New(const Attr *FromAttr) { - return Import(FromAttr); -} -Attr *ASTImporter::Import(const Attr *FromAttr) { Attr *ToAttr = FromAttr->clone(ToContext); - // NOTE: Import of SourceRange may fail. - ToAttr->setRange(Import(FromAttr->getRange())); + if (auto ToRangeOrErr = Import_New(FromAttr->getRange())) + ToAttr->setRange(*ToRangeOrErr); + else + return ToRangeOrErr.takeError(); + return ToAttr; } +Attr *ASTImporter::Import(const Attr *From) { + llvm::Expected<Attr *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; +} Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { auto Pos = ImportedDecls.find(FromD); @@ -7746,17 +7757,17 @@ Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { return nullptr; } -Expected<Decl *> ASTImporter::Import_New(Decl *FromD) { - Decl *ToD = Import(FromD); - if (!ToD && FromD) - return llvm::make_error<ImportError>(); - return ToD; +TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { + auto FromDPos = ImportedFromDecls.find(ToD); + if (FromDPos == ImportedFromDecls.end()) + return nullptr; + return FromDPos->second->getTranslationUnitDecl(); } -Decl *ASTImporter::Import(Decl *FromD) { + +Expected<Decl *> ASTImporter::Import_New(Decl *FromD) { if (!FromD) return nullptr; - ASTNodeImporter Importer(*this); // Check whether we've already imported this declaration. Decl *ToD = GetAlreadyImportedOrNull(FromD); @@ -7766,13 +7777,20 @@ Decl *ASTImporter::Import(Decl *FromD) { return ToD; } - // Import the type. - ExpectedDecl ToDOrErr = Importer.Visit(FromD); - if (!ToDOrErr) { - llvm::consumeError(ToDOrErr.takeError()); + // Import the declaration. + ExpectedDecl ToDOrErr = ImportImpl(FromD); + if (!ToDOrErr) + return ToDOrErr; + ToD = *ToDOrErr; + + // FIXME Use getImportDeclErrorIfAny() here (and return with the error) once + // the error handling is finished in GetImportedOrCreateSpecialDecl(). + if (!ToD) { return nullptr; } - ToD = *ToDOrErr; + + // Make sure that ImportImpl registered the imported decl. + assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); // Once the decl is connected to the existing declarations, i.e. when the // redecl chain is properly set then we populate the lookup again. @@ -7783,16 +7801,25 @@ Decl *ASTImporter::Import(Decl *FromD) { Imported(FromD, ToD); updateFlags(FromD, ToD); - return ToD; + return ToDOrErr; +} +Decl *ASTImporter::Import(Decl *From) { + llvm::Expected<Decl *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; } Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; - auto *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); - if (!ToDC) - return nullptr; + ExpectedDecl ToDCOrErr = Import_New(cast<Decl>(FromDC)); + if (!ToDCOrErr) + return ToDCOrErr.takeError(); + auto *ToDC = cast<DeclContext>(*ToDCOrErr); // When we're using a record/enum/Objective-C class/protocol as a context, we // need it to have a definition. @@ -7846,29 +7873,25 @@ Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) { } Expected<Expr *> ASTImporter::Import_New(Expr *FromE) { - Expr *ToE = Import(FromE); - if (!ToE && FromE) - return llvm::make_error<ImportError>(); - return ToE; + if (ExpectedStmt ToSOrErr = Import_New(cast_or_null<Stmt>(FromE))) + return cast_or_null<Expr>(*ToSOrErr); + else + return ToSOrErr.takeError(); } -Expr *ASTImporter::Import(Expr *FromE) { - if (!FromE) - return nullptr; - - return cast_or_null<Expr>(Import(cast<Stmt>(FromE))); +Expr *ASTImporter::Import(Expr *From) { + llvm::Expected<Expr *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; } Expected<Stmt *> ASTImporter::Import_New(Stmt *FromS) { - Stmt *ToS = Import(FromS); - if (!ToS && FromS) - return llvm::make_error<ImportError>(); - return ToS; -} -Stmt *ASTImporter::Import(Stmt *FromS) { if (!FromS) return nullptr; - // Check whether we've already imported this declaration. + // Check whether we've already imported this statement. llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS); if (Pos != ImportedStmts.end()) return Pos->second; @@ -7876,10 +7899,8 @@ Stmt *ASTImporter::Import(Stmt *FromS) { // Import the statement. ASTNodeImporter Importer(*this); ExpectedStmt ToSOrErr = Importer.Visit(FromS); - if (!ToSOrErr) { - llvm::consumeError(ToSOrErr.takeError()); - return nullptr; - } + if (!ToSOrErr) + return ToSOrErr; if (auto *ToE = dyn_cast<Expr>(*ToSOrErr)) { auto *FromE = cast<Expr>(FromS); @@ -7894,77 +7915,84 @@ Stmt *ASTImporter::Import(Stmt *FromS) { FromE->containsUnexpandedParameterPack()); } - // Record the imported declaration. + // Record the imported statement object. ImportedStmts[FromS] = *ToSOrErr; - return *ToSOrErr; + return ToSOrErr; +} +Stmt *ASTImporter::Import(Stmt *From) { + llvm::Expected<Stmt *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; } Expected<NestedNameSpecifier *> ASTImporter::Import_New(NestedNameSpecifier *FromNNS) { - NestedNameSpecifier *ToNNS = Import(FromNNS); - if (!ToNNS && FromNNS) - return llvm::make_error<ImportError>(); - return ToNNS; -} -NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (!FromNNS) return nullptr; - NestedNameSpecifier *prefix = Import(FromNNS->getPrefix()); + NestedNameSpecifier *Prefix; + if (Error Err = importInto(Prefix, FromNNS->getPrefix())) + return std::move(Err); switch (FromNNS->getKind()) { case NestedNameSpecifier::Identifier: - if (IdentifierInfo *II = Import(FromNNS->getAsIdentifier())) { - return NestedNameSpecifier::Create(ToContext, prefix, II); - } - return nullptr; + assert(FromNNS->getAsIdentifier() && "NNS should contain identifier."); + return NestedNameSpecifier::Create(ToContext, Prefix, + Import(FromNNS->getAsIdentifier())); case NestedNameSpecifier::Namespace: - if (auto *NS = - cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { - return NestedNameSpecifier::Create(ToContext, prefix, NS); - } - return nullptr; + if (ExpectedDecl NSOrErr = Import_New(FromNNS->getAsNamespace())) { + return NestedNameSpecifier::Create(ToContext, Prefix, + cast<NamespaceDecl>(*NSOrErr)); + } else + return NSOrErr.takeError(); case NestedNameSpecifier::NamespaceAlias: - if (auto *NSAD = - cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) { - return NestedNameSpecifier::Create(ToContext, prefix, NSAD); - } - return nullptr; + if (ExpectedDecl NSADOrErr = Import_New(FromNNS->getAsNamespaceAlias())) + return NestedNameSpecifier::Create(ToContext, Prefix, + cast<NamespaceAliasDecl>(*NSADOrErr)); + else + return NSADOrErr.takeError(); case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); case NestedNameSpecifier::Super: - if (auto *RD = - cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) { - return NestedNameSpecifier::SuperSpecifier(ToContext, RD); - } - return nullptr; + if (ExpectedDecl RDOrErr = Import_New(FromNNS->getAsRecordDecl())) + return NestedNameSpecifier::SuperSpecifier(ToContext, + cast<CXXRecordDecl>(*RDOrErr)); + else + return RDOrErr.takeError(); case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - QualType T = Import(QualType(FromNNS->getAsType(), 0u)); - if (!T.isNull()) { - bool bTemplate = FromNNS->getKind() == - NestedNameSpecifier::TypeSpecWithTemplate; - return NestedNameSpecifier::Create(ToContext, prefix, - bTemplate, T.getTypePtr()); - } + case NestedNameSpecifier::TypeSpecWithTemplate: + if (Expected<QualType> TyOrErr = + Import_New(QualType(FromNNS->getAsType(), 0u))) { + bool TSTemplate = + FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate; + return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate, + TyOrErr->getTypePtr()); + } else { + return TyOrErr.takeError(); } - return nullptr; } llvm_unreachable("Invalid nested name specifier kind"); } +NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *From) { + llvm::Expected<NestedNameSpecifier *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; +} Expected<NestedNameSpecifierLoc> ASTImporter::Import_New(NestedNameSpecifierLoc FromNNS) { - NestedNameSpecifierLoc ToNNS = Import(FromNNS); - return ToNNS; -} -NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { // Copied from NestedNameSpecifier mostly. SmallVector<NestedNameSpecifierLoc , 8> NestedNames; NestedNameSpecifierLoc NNS = FromNNS; @@ -7980,84 +8008,93 @@ NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { while (!NestedNames.empty()) { NNS = NestedNames.pop_back_val(); - NestedNameSpecifier *Spec = Import(NNS.getNestedNameSpecifier()); - if (!Spec) - return NestedNameSpecifierLoc(); + NestedNameSpecifier *Spec; + if (Error Err = importInto(Spec, NNS.getNestedNameSpecifier())) + return std::move(Err); NestedNameSpecifier::SpecifierKind Kind = Spec->getKind(); + + SourceLocation ToLocalBeginLoc, ToLocalEndLoc; + if (Kind != NestedNameSpecifier::Super) { + if (Error Err = importInto(ToLocalBeginLoc, NNS.getLocalBeginLoc())) + return std::move(Err); + + if (Kind != NestedNameSpecifier::Global) + if (Error Err = importInto(ToLocalEndLoc, NNS.getLocalEndLoc())) + return std::move(Err); + } + switch (Kind) { case NestedNameSpecifier::Identifier: - Builder.Extend(getToContext(), - Spec->getAsIdentifier(), - Import(NNS.getLocalBeginLoc()), - Import(NNS.getLocalEndLoc())); + Builder.Extend(getToContext(), Spec->getAsIdentifier(), ToLocalBeginLoc, + ToLocalEndLoc); break; case NestedNameSpecifier::Namespace: - Builder.Extend(getToContext(), - Spec->getAsNamespace(), - Import(NNS.getLocalBeginLoc()), - Import(NNS.getLocalEndLoc())); + Builder.Extend(getToContext(), Spec->getAsNamespace(), ToLocalBeginLoc, + ToLocalEndLoc); break; case NestedNameSpecifier::NamespaceAlias: - Builder.Extend(getToContext(), - Spec->getAsNamespaceAlias(), - Import(NNS.getLocalBeginLoc()), - Import(NNS.getLocalEndLoc())); + Builder.Extend(getToContext(), Spec->getAsNamespaceAlias(), + ToLocalBeginLoc, ToLocalEndLoc); break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { + SourceLocation ToTLoc; + if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc())) + return std::move(Err); TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo( - QualType(Spec->getAsType(), 0)); - Builder.Extend(getToContext(), - Import(NNS.getLocalBeginLoc()), - TSI->getTypeLoc(), - Import(NNS.getLocalEndLoc())); + QualType(Spec->getAsType(), 0), ToTLoc); + Builder.Extend(getToContext(), ToLocalBeginLoc, TSI->getTypeLoc(), + ToLocalEndLoc); break; } case NestedNameSpecifier::Global: - Builder.MakeGlobal(getToContext(), Import(NNS.getLocalBeginLoc())); + Builder.MakeGlobal(getToContext(), ToLocalBeginLoc); break; case NestedNameSpecifier::Super: { - SourceRange ToRange = Import(NNS.getSourceRange()); - Builder.MakeSuper(getToContext(), - Spec->getAsRecordDecl(), - ToRange.getBegin(), - ToRange.getEnd()); + auto ToSourceRangeOrErr = Import_New(NNS.getSourceRange()); + if (!ToSourceRangeOrErr) + return ToSourceRangeOrErr.takeError(); + + Builder.MakeSuper(getToContext(), Spec->getAsRecordDecl(), + ToSourceRangeOrErr->getBegin(), + ToSourceRangeOrErr->getEnd()); } } } return Builder.getWithLocInContext(getToContext()); } +NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc From) { + llvm::Expected<NestedNameSpecifierLoc> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; +} Expected<TemplateName> ASTImporter::Import_New(TemplateName From) { - TemplateName To = Import(From); - if (To.isNull() && !From.isNull()) - return llvm::make_error<ImportError>(); - return To; -} -TemplateName ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: - if (auto *ToTemplate = - cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl()))) - return TemplateName(ToTemplate); - - return {}; + if (ExpectedDecl ToTemplateOrErr = Import_New(From.getAsTemplateDecl())) + return TemplateName(cast<TemplateDecl>(*ToTemplateOrErr)); + else + return ToTemplateOrErr.takeError(); case TemplateName::OverloadedTemplate: { OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate(); UnresolvedSet<2> ToTemplates; for (auto *I : *FromStorage) { - if (auto *To = cast_or_null<NamedDecl>(Import(I))) - ToTemplates.addDecl(To); + if (auto ToOrErr = Import_New(I)) + ToTemplates.addDecl(cast<NamedDecl>(*ToOrErr)); else - return {}; + return ToOrErr.takeError(); } return ToContext.getOverloadedTemplateName(ToTemplates.begin(), ToTemplates.end()); @@ -8065,107 +8102,119 @@ TemplateName ASTImporter::Import(TemplateName From) { case TemplateName::QualifiedTemplate: { QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName(); - NestedNameSpecifier *Qualifier = Import(QTN->getQualifier()); - if (!Qualifier) - return {}; - - if (auto *ToTemplate = - cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl()))) - return ToContext.getQualifiedTemplateName(Qualifier, - QTN->hasTemplateKeyword(), - ToTemplate); - - return {}; + auto QualifierOrErr = Import_New(QTN->getQualifier()); + if (!QualifierOrErr) + return QualifierOrErr.takeError(); + + if (ExpectedDecl ToTemplateOrErr = Import_New(From.getAsTemplateDecl())) + return ToContext.getQualifiedTemplateName( + *QualifierOrErr, QTN->hasTemplateKeyword(), + cast<TemplateDecl>(*ToTemplateOrErr)); + else + return ToTemplateOrErr.takeError(); } case TemplateName::DependentTemplate: { DependentTemplateName *DTN = From.getAsDependentTemplateName(); - NestedNameSpecifier *Qualifier = Import(DTN->getQualifier()); - if (!Qualifier) - return {}; + auto QualifierOrErr = Import_New(DTN->getQualifier()); + if (!QualifierOrErr) + return QualifierOrErr.takeError(); if (DTN->isIdentifier()) { - return ToContext.getDependentTemplateName(Qualifier, + return ToContext.getDependentTemplateName(*QualifierOrErr, Import(DTN->getIdentifier())); } - return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator()); + return ToContext.getDependentTemplateName(*QualifierOrErr, + DTN->getOperator()); } case TemplateName::SubstTemplateTemplateParm: { - SubstTemplateTemplateParmStorage *subst - = From.getAsSubstTemplateTemplateParm(); - auto *param = - cast_or_null<TemplateTemplateParmDecl>(Import(subst->getParameter())); - if (!param) - return {}; + SubstTemplateTemplateParmStorage *Subst = + From.getAsSubstTemplateTemplateParm(); + ExpectedDecl ParamOrErr = Import_New(Subst->getParameter()); + if (!ParamOrErr) + return ParamOrErr.takeError(); - TemplateName replacement = Import(subst->getReplacement()); - if (replacement.isNull()) - return {}; + auto ReplacementOrErr = Import_New(Subst->getReplacement()); + if (!ReplacementOrErr) + return ReplacementOrErr.takeError(); - return ToContext.getSubstTemplateTemplateParm(param, replacement); + return ToContext.getSubstTemplateTemplateParm( + cast<TemplateTemplateParmDecl>(*ParamOrErr), *ReplacementOrErr); } case TemplateName::SubstTemplateTemplateParmPack: { SubstTemplateTemplateParmPackStorage *SubstPack = From.getAsSubstTemplateTemplateParmPack(); - auto *Param = - cast_or_null<TemplateTemplateParmDecl>( - Import(SubstPack->getParameterPack())); - if (!Param) - return {}; + ExpectedDecl ParamOrErr = Import_New(SubstPack->getParameterPack()); + if (!ParamOrErr) + return ParamOrErr.takeError(); ASTNodeImporter Importer(*this); - Expected<TemplateArgument> ArgPack - = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); - if (!ArgPack) { - llvm::consumeError(ArgPack.takeError()); - return {}; - } + auto ArgPackOrErr = + Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); + if (!ArgPackOrErr) + return ArgPackOrErr.takeError(); - return ToContext.getSubstTemplateTemplateParmPack(Param, *ArgPack); + return ToContext.getSubstTemplateTemplateParmPack( + cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr); } } llvm_unreachable("Invalid template name kind"); } +TemplateName ASTImporter::Import(TemplateName From) { + llvm::Expected<TemplateName> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; +} Expected<SourceLocation> ASTImporter::Import_New(SourceLocation FromLoc) { - SourceLocation ToLoc = Import(FromLoc); - if (ToLoc.isInvalid() && !FromLoc.isInvalid()) - return llvm::make_error<ImportError>(); - return ToLoc; -} -SourceLocation ASTImporter::Import(SourceLocation FromLoc) { if (FromLoc.isInvalid()) - return {}; + return SourceLocation{}; SourceManager &FromSM = FromContext.getSourceManager(); + bool IsBuiltin = FromSM.isWrittenInBuiltinFile(FromLoc); std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); - FileID ToFileID = Import(Decomposed.first); - if (ToFileID.isInvalid()) - return {}; + Expected<FileID> ToFileIDOrErr = Import_New(Decomposed.first, IsBuiltin); + if (!ToFileIDOrErr) + return ToFileIDOrErr.takeError(); SourceManager &ToSM = ToContext.getSourceManager(); - return ToSM.getComposedLoc(ToFileID, Decomposed.second); + return ToSM.getComposedLoc(*ToFileIDOrErr, Decomposed.second); +} +SourceLocation ASTImporter::Import(SourceLocation From) { + llvm::Expected<SourceLocation> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; } Expected<SourceRange> ASTImporter::Import_New(SourceRange FromRange) { - SourceRange ToRange = Import(FromRange); - return ToRange; + SourceLocation ToBegin, ToEnd; + if (Error Err = importInto(ToBegin, FromRange.getBegin())) + return std::move(Err); + if (Error Err = importInto(ToEnd, FromRange.getEnd())) + return std::move(Err); + + return SourceRange(ToBegin, ToEnd); } -SourceRange ASTImporter::Import(SourceRange FromRange) { - return SourceRange(Import(FromRange.getBegin()), Import(FromRange.getEnd())); +SourceRange ASTImporter::Import(SourceRange From) { + llvm::Expected<SourceRange> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; } -Expected<FileID> ASTImporter::Import_New(FileID FromID) { - FileID ToID = Import(FromID); - if (ToID.isInvalid() && FromID.isValid()) - return llvm::make_error<ImportError>(); - return ToID; -} -FileID ASTImporter::Import(FileID FromID) { +Expected<FileID> ASTImporter::Import_New(FileID FromID, bool IsBuiltin) { llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID); if (Pos != ImportedFileIDs.end()) return Pos->second; @@ -8178,38 +8227,59 @@ FileID ASTImporter::Import(FileID FromID) { FileID ToID; if (FromSLoc.isExpansion()) { const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion(); - SourceLocation ToSpLoc = Import(FromEx.getSpellingLoc()); - SourceLocation ToExLocS = Import(FromEx.getExpansionLocStart()); + ExpectedSLoc ToSpLoc = Import_New(FromEx.getSpellingLoc()); + if (!ToSpLoc) + return ToSpLoc.takeError(); + ExpectedSLoc ToExLocS = Import_New(FromEx.getExpansionLocStart()); + if (!ToExLocS) + return ToExLocS.takeError(); unsigned TokenLen = FromSM.getFileIDSize(FromID); SourceLocation MLoc; if (FromEx.isMacroArgExpansion()) { - MLoc = ToSM.createMacroArgExpansionLoc(ToSpLoc, ToExLocS, TokenLen); + MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, TokenLen); } else { - SourceLocation ToExLocE = Import(FromEx.getExpansionLocEnd()); - MLoc = ToSM.createExpansionLoc(ToSpLoc, ToExLocS, ToExLocE, TokenLen, - FromEx.isExpansionTokenRange()); + if (ExpectedSLoc ToExLocE = Import_New(FromEx.getExpansionLocEnd())) + MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, TokenLen, + FromEx.isExpansionTokenRange()); + else + return ToExLocE.takeError(); } ToID = ToSM.getFileID(MLoc); } else { - // Include location of this file. - SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); - const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); - if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { - // FIXME: We probably want to use getVirtualFile(), so we don't hit the - // disk again - // FIXME: We definitely want to re-use the existing MemoryBuffer, rather - // than mmap the files several times. - const FileEntry *Entry = - ToFileManager.getFile(Cache->OrigEntry->getName()); - if (!Entry) - return {}; - ToID = ToSM.createFileID(Entry, ToIncludeLoc, - FromSLoc.getFile().getFileCharacteristic()); - } else { + + if (!IsBuiltin) { + // Include location of this file. + ExpectedSLoc ToIncludeLoc = + Import_New(FromSLoc.getFile().getIncludeLoc()); + if (!ToIncludeLoc) + return ToIncludeLoc.takeError(); + + if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { + // FIXME: We probably want to use getVirtualFile(), so we don't hit the + // disk again + // FIXME: We definitely want to re-use the existing MemoryBuffer, rather + // than mmap the files several times. + const FileEntry *Entry = + ToFileManager.getFile(Cache->OrigEntry->getName()); + // FIXME: The filename may be a virtual name that does probably not + // point to a valid file and we get no Entry here. In this case try with + // the memory buffer below. + if (Entry) + ToID = ToSM.createFileID(Entry, *ToIncludeLoc, + FromSLoc.getFile().getFileCharacteristic()); + } + } + + if (ToID.isInvalid() || IsBuiltin) { // FIXME: We want to re-use the existing MemoryBuffer! - const llvm::MemoryBuffer *FromBuf = - Cache->getBuffer(FromContext.getDiagnostics(), FromSM); + bool Invalid = true; + const llvm::MemoryBuffer *FromBuf = Cache->getBuffer( + FromContext.getDiagnostics(), FromSM, SourceLocation{}, &Invalid); + if (!FromBuf || Invalid) + // FIXME: Use a new error kind? + return llvm::make_error<ImportError>(ImportError::Unknown); + std::unique_ptr<llvm::MemoryBuffer> ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); @@ -8218,127 +8288,163 @@ FileID ASTImporter::Import(FileID FromID) { } } + assert(ToID.isValid() && "Unexpected invalid fileID was created."); + ImportedFileIDs[FromID] = ToID; return ToID; } +FileID ASTImporter::Import(FileID From, bool IsBuiltin) { + llvm::Expected<FileID> To = Import_New(From, IsBuiltin); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; +} Expected<CXXCtorInitializer *> ASTImporter::Import_New(CXXCtorInitializer *From) { - CXXCtorInitializer *To = Import(From); - if (!To && From) - return llvm::make_error<ImportError>(); - return To; -} -CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { - Expr *ToExpr = Import(From->getInit()); - if (!ToExpr && From->getInit()) - return nullptr; + ExpectedExpr ToExprOrErr = Import_New(From->getInit()); + if (!ToExprOrErr) + return ToExprOrErr.takeError(); + + auto LParenLocOrErr = Import_New(From->getLParenLoc()); + if (!LParenLocOrErr) + return LParenLocOrErr.takeError(); + + auto RParenLocOrErr = Import_New(From->getRParenLoc()); + if (!RParenLocOrErr) + return RParenLocOrErr.takeError(); if (From->isBaseInitializer()) { - TypeSourceInfo *ToTInfo = Import(From->getTypeSourceInfo()); - if (!ToTInfo && From->getTypeSourceInfo()) - return nullptr; + auto ToTInfoOrErr = Import_New(From->getTypeSourceInfo()); + if (!ToTInfoOrErr) + return ToTInfoOrErr.takeError(); + + SourceLocation EllipsisLoc; + if (From->isPackExpansion()) + if (Error Err = importInto(EllipsisLoc, From->getEllipsisLoc())) + return std::move(Err); return new (ToContext) CXXCtorInitializer( - ToContext, ToTInfo, From->isBaseVirtual(), Import(From->getLParenLoc()), - ToExpr, Import(From->getRParenLoc()), - From->isPackExpansion() ? Import(From->getEllipsisLoc()) - : SourceLocation()); + ToContext, *ToTInfoOrErr, From->isBaseVirtual(), *LParenLocOrErr, + *ToExprOrErr, *RParenLocOrErr, EllipsisLoc); } else if (From->isMemberInitializer()) { - auto *ToField = cast_or_null<FieldDecl>(Import(From->getMember())); - if (!ToField && From->getMember()) - return nullptr; + ExpectedDecl ToFieldOrErr = Import_New(From->getMember()); + if (!ToFieldOrErr) + return ToFieldOrErr.takeError(); + + auto MemberLocOrErr = Import_New(From->getMemberLocation()); + if (!MemberLocOrErr) + return MemberLocOrErr.takeError(); return new (ToContext) CXXCtorInitializer( - ToContext, ToField, Import(From->getMemberLocation()), - Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); + ToContext, cast_or_null<FieldDecl>(*ToFieldOrErr), *MemberLocOrErr, + *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr); } else if (From->isIndirectMemberInitializer()) { - auto *ToIField = cast_or_null<IndirectFieldDecl>( - Import(From->getIndirectMember())); - if (!ToIField && From->getIndirectMember()) - return nullptr; + ExpectedDecl ToIFieldOrErr = Import_New(From->getIndirectMember()); + if (!ToIFieldOrErr) + return ToIFieldOrErr.takeError(); + + auto MemberLocOrErr = Import_New(From->getMemberLocation()); + if (!MemberLocOrErr) + return MemberLocOrErr.takeError(); return new (ToContext) CXXCtorInitializer( - ToContext, ToIField, Import(From->getMemberLocation()), - Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); + ToContext, cast_or_null<IndirectFieldDecl>(*ToIFieldOrErr), + *MemberLocOrErr, *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr); } else if (From->isDelegatingInitializer()) { - TypeSourceInfo *ToTInfo = Import(From->getTypeSourceInfo()); - if (!ToTInfo && From->getTypeSourceInfo()) - return nullptr; + auto ToTInfoOrErr = Import_New(From->getTypeSourceInfo()); + if (!ToTInfoOrErr) + return ToTInfoOrErr.takeError(); return new (ToContext) - CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()), - ToExpr, Import(From->getRParenLoc())); + CXXCtorInitializer(ToContext, *ToTInfoOrErr, *LParenLocOrErr, + *ToExprOrErr, *RParenLocOrErr); } else { - return nullptr; + // FIXME: assert? + return make_error<ImportError>(); } } +CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { + llvm::Expected<CXXCtorInitializer *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; +} Expected<CXXBaseSpecifier *> -ASTImporter::Import_New(const CXXBaseSpecifier *From) { - CXXBaseSpecifier *To = Import(From); - if (!To && From) - return llvm::make_error<ImportError>(); - return To; -} -CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { +ASTImporter::Import_New(const CXXBaseSpecifier *BaseSpec) { auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); if (Pos != ImportedCXXBaseSpecifiers.end()) return Pos->second; + Expected<SourceRange> ToSourceRange = Import_New(BaseSpec->getSourceRange()); + if (!ToSourceRange) + return ToSourceRange.takeError(); + Expected<TypeSourceInfo *> ToTSI = Import_New(BaseSpec->getTypeSourceInfo()); + if (!ToTSI) + return ToTSI.takeError(); + ExpectedSLoc ToEllipsisLoc = Import_New(BaseSpec->getEllipsisLoc()); + if (!ToEllipsisLoc) + return ToEllipsisLoc.takeError(); CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier( - Import(BaseSpec->getSourceRange()), - BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(), - BaseSpec->getAccessSpecifierAsWritten(), - Import(BaseSpec->getTypeSourceInfo()), - Import(BaseSpec->getEllipsisLoc())); + *ToSourceRange, BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(), + BaseSpec->getAccessSpecifierAsWritten(), *ToTSI, *ToEllipsisLoc); ImportedCXXBaseSpecifiers[BaseSpec] = Imported; return Imported; } +CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *From) { + llvm::Expected<CXXBaseSpecifier *> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return nullptr; +} Error ASTImporter::ImportDefinition_New(Decl *From) { Decl *To = Import(From); if (!To) return llvm::make_error<ImportError>(); - if (auto *FromDC = cast<DeclContext>(From)) { - ASTNodeImporter Importer(*this); + auto *FromDC = cast<DeclContext>(From); + ASTNodeImporter Importer(*this); - if (auto *ToRecord = dyn_cast<RecordDecl>(To)) { - if (!ToRecord->getDefinition()) { - return Importer.ImportDefinition( - cast<RecordDecl>(FromDC), ToRecord, - ASTNodeImporter::IDK_Everything); - } + if (auto *ToRecord = dyn_cast<RecordDecl>(To)) { + if (!ToRecord->getDefinition()) { + return Importer.ImportDefinition( + cast<RecordDecl>(FromDC), ToRecord, + ASTNodeImporter::IDK_Everything); } + } - if (auto *ToEnum = dyn_cast<EnumDecl>(To)) { - if (!ToEnum->getDefinition()) { - return Importer.ImportDefinition( - cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything); - } + if (auto *ToEnum = dyn_cast<EnumDecl>(To)) { + if (!ToEnum->getDefinition()) { + return Importer.ImportDefinition( + cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything); } + } - if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { - if (!ToIFace->getDefinition()) { - return Importer.ImportDefinition( - cast<ObjCInterfaceDecl>(FromDC), ToIFace, - ASTNodeImporter::IDK_Everything); - } + if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { + if (!ToIFace->getDefinition()) { + return Importer.ImportDefinition( + cast<ObjCInterfaceDecl>(FromDC), ToIFace, + ASTNodeImporter::IDK_Everything); } + } - if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { - if (!ToProto->getDefinition()) { - return Importer.ImportDefinition( - cast<ObjCProtocolDecl>(FromDC), ToProto, - ASTNodeImporter::IDK_Everything); - } + if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { + if (!ToProto->getDefinition()) { + return Importer.ImportDefinition( + cast<ObjCProtocolDecl>(FromDC), ToProto, + ASTNodeImporter::IDK_Everything); } - - return Importer.ImportDeclContext(FromDC, true); } - return Error::success(); + return Importer.ImportDeclContext(FromDC, true); } void ASTImporter::ImportDefinition(Decl *From) { @@ -8347,57 +8453,52 @@ void ASTImporter::ImportDefinition(Decl *From) { } Expected<DeclarationName> ASTImporter::Import_New(DeclarationName FromName) { - DeclarationName ToName = Import(FromName); - if (!ToName && FromName) - return llvm::make_error<ImportError>(); - return ToName; -} -DeclarationName ASTImporter::Import(DeclarationName FromName) { if (!FromName) - return {}; + return DeclarationName{}; switch (FromName.getNameKind()) { case DeclarationName::Identifier: - return Import(FromName.getAsIdentifierInfo()); + return DeclarationName(Import(FromName.getAsIdentifierInfo())); case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: - return Import(FromName.getObjCSelector()); + if (auto ToSelOrErr = Import_New(FromName.getObjCSelector())) + return DeclarationName(*ToSelOrErr); + else + return ToSelOrErr.takeError(); case DeclarationName::CXXConstructorName: { - QualType T = Import(FromName.getCXXNameType()); - if (T.isNull()) - return {}; - - return ToContext.DeclarationNames.getCXXConstructorName( - ToContext.getCanonicalType(T)); + if (auto ToTyOrErr = Import_New(FromName.getCXXNameType())) + return ToContext.DeclarationNames.getCXXConstructorName( + ToContext.getCanonicalType(*ToTyOrErr)); + else + return ToTyOrErr.takeError(); } case DeclarationName::CXXDestructorName: { - QualType T = Import(FromName.getCXXNameType()); - if (T.isNull()) - return {}; - - return ToContext.DeclarationNames.getCXXDestructorName( - ToContext.getCanonicalType(T)); + if (auto ToTyOrErr = Import_New(FromName.getCXXNameType())) + return ToContext.DeclarationNames.getCXXDestructorName( + ToContext.getCanonicalType(*ToTyOrErr)); + else + return ToTyOrErr.takeError(); } case DeclarationName::CXXDeductionGuideName: { - auto *Template = cast_or_null<TemplateDecl>( - Import(FromName.getCXXDeductionGuideTemplate())); - if (!Template) - return {}; - return ToContext.DeclarationNames.getCXXDeductionGuideName(Template); + if (auto ToTemplateOrErr = + Import_New(FromName.getCXXDeductionGuideTemplate())) + return ToContext.DeclarationNames.getCXXDeductionGuideName( + cast<TemplateDecl>(*ToTemplateOrErr)); + else + return ToTemplateOrErr.takeError(); } case DeclarationName::CXXConversionFunctionName: { - QualType T = Import(FromName.getCXXNameType()); - if (T.isNull()) - return {}; - - return ToContext.DeclarationNames.getCXXConversionFunctionName( - ToContext.getCanonicalType(T)); + if (auto ToTyOrErr = Import_New(FromName.getCXXNameType())) + return ToContext.DeclarationNames.getCXXConversionFunctionName( + ToContext.getCanonicalType(*ToTyOrErr)); + else + return ToTyOrErr.takeError(); } case DeclarationName::CXXOperatorName: @@ -8406,7 +8507,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { case DeclarationName::CXXLiteralOperatorName: return ToContext.DeclarationNames.getCXXLiteralOperatorName( - Import(FromName.getCXXLiteralIdentifier())); + Import(FromName.getCXXLiteralIdentifier())); case DeclarationName::CXXUsingDirective: // FIXME: STATICS! @@ -8415,6 +8516,14 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { llvm_unreachable("Invalid DeclarationName Kind!"); } +DeclarationName ASTImporter::Import(DeclarationName From) { + llvm::Expected<DeclarationName> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; +} IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { if (!FromId) @@ -8429,14 +8538,8 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { } Expected<Selector> ASTImporter::Import_New(Selector FromSel) { - Selector ToSel = Import(FromSel); - if (ToSel.isNull() && !FromSel.isNull()) - return llvm::make_error<ImportError>(); - return ToSel; -} -Selector ASTImporter::Import(Selector FromSel) { if (FromSel.isNull()) - return {}; + return Selector{}; SmallVector<IdentifierInfo *, 4> Idents; Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0))); @@ -8452,6 +8555,14 @@ DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name, unsigned NumDecls) { return Name; } +Selector ASTImporter::Import(Selector From) { + llvm::Expected<Selector> To = Import_New(From); + if (To) + return *To; + else + llvm::consumeError(To.takeError()); + return {}; +} DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) { if (LastDiagFromFrom) @@ -8496,15 +8607,24 @@ Decl *ASTImporter::MapImported(Decl *From, Decl *To) { if (Pos != ImportedDecls.end()) return Pos->second; ImportedDecls[From] = To; + // This mapping should be maintained only in this function. Therefore do not + // check for additional consistency. + ImportedFromDecls[To] = From; return To; } bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, bool Complain) { - llvm::DenseMap<const Type *, const Type *>::iterator Pos - = ImportedTypes.find(From.getTypePtr()); - if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To)) - return true; + llvm::DenseMap<const Type *, const Type *>::iterator Pos = + ImportedTypes.find(From.getTypePtr()); + if (Pos != ImportedTypes.end()) { + if (ExpectedType ToFromOrErr = Import_New(From)) { + if (ToContext.hasSameType(*ToFromOrErr, To)) + return true; + } else { + llvm::consumeError(ToFromOrErr.takeError()); + } + } StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, getStructuralEquivalenceKind(*this), false, diff --git a/lib/AST/ASTImporterLookupTable.cpp b/lib/AST/ASTImporterLookupTable.cpp index fbcd4f5cb3..2c0c284c06 100644 --- a/lib/AST/ASTImporterLookupTable.cpp +++ b/lib/AST/ASTImporterLookupTable.cpp @@ -1,9 +1,8 @@ //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ASTStructuralEquivalence.cpp b/lib/AST/ASTStructuralEquivalence.cpp index d19b89bb95..71bbd82481 100644 --- a/lib/AST/ASTStructuralEquivalence.cpp +++ b/lib/AST/ASTStructuralEquivalence.cpp @@ -1,9 +1,8 @@ //===- ASTStructuralEquivalence.cpp ---------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -297,6 +296,32 @@ static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine structural equivalence based on the ExtInfo of functions. This +/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling +/// conventions bits but must not compare some other bits. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + FunctionType::ExtInfo EI1, + FunctionType::ExtInfo EI2) { + // Compatible functions must have compatible calling conventions. + if (EI1.getCC() != EI2.getCC()) + return false; + + // Regparm is part of the calling convention. + if (EI1.getHasRegParm() != EI2.getHasRegParm()) + return false; + if (EI1.getRegParm() != EI2.getRegParm()) + return false; + + if (EI1.getProducesResult() != EI2.getProducesResult()) + return false; + if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs()) + return false; + if (EI1.getNoCfCheck() != EI2.getNoCfCheck()) + return false; + + return true; +} + /// Determine structural equivalence of two types. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, QualType T1, QualType T2) { @@ -503,7 +528,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Proto1->isVariadic() != Proto2->isVariadic()) return false; - if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) + if (Proto1->getMethodQuals() != Proto2->getMethodQuals()) return false; // Check exceptions, this information is lost in canonical type. @@ -540,7 +565,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), Function2->getReturnType())) return false; - if (Function1->getExtInfo() != Function2->getExtInfo()) + if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(), + Function2->getExtInfo())) return false; break; } @@ -834,10 +860,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, IdentifierInfo *Name2 = Field2->getIdentifier(); if (!::IsStructurallyEquivalent(Name1, Name2)) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2( + Owner2->getLocation(), + Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) << Field2->getDeclName(); @@ -850,10 +875,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, Field1->getType(), Field2->getType())) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2( + Owner2->getLocation(), + Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); @@ -865,10 +889,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field1->isBitField() != Field2->isBitField()) { if (Context.Complain) { - Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2( + Owner2->getLocation(), + Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); if (Field1->isBitField()) { Context.Diag1(Field1->getLocation(), diag::note_odr_bit_field) @@ -895,9 +918,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Bits1 != Bits2) { if (Context.Complain) { Context.Diag2(Owner2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(Owner2); Context.Diag2(Field2->getLocation(), diag::note_odr_bit_field) << Field2->getDeclName() << Field2->getType() << Bits2; @@ -966,10 +988,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { if (D1->isUnion() != D2->isUnion()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(D1->getLocation(), diag::note_odr_tag_kind_here) << D1->getDeclName() << (unsigned)D1->getTagKind(); @@ -1046,7 +1066,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases) << D2CXX->getNumBases(); @@ -1065,7 +1087,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Base2->getType())) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Base2->getBeginLoc(), diag::note_odr_base) << Base2->getType() << Base2->getSourceRange(); @@ -1079,7 +1102,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Base1->isVirtual() != Base2->isVirtual()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Base2->getBeginLoc(), diag::note_odr_virtual_base) << Base2->isVirtual() << Base2->getSourceRange(); @@ -1092,15 +1116,16 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // Check the friends for consistency. CXXRecordDecl::friend_iterator Friend2 = D2CXX->friend_begin(), - Friend2End = D2CXX->friend_end(); + Friend2End = D2CXX->friend_end(); for (CXXRecordDecl::friend_iterator Friend1 = D1CXX->friend_begin(), - Friend1End = D1CXX->friend_end(); + Friend1End = D1CXX->friend_end(); Friend1 != Friend1End; ++Friend1, ++Friend2) { if (Friend2 == Friend2End) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::warn_odr_tag_type_inconsistent) - << Context.ToCtx.getTypeDeclType(D2CXX); + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2CXX); Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend); Context.Diag2(D2->getLocation(), diag::note_odr_missing_friend); } @@ -1109,8 +1134,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, *Friend1, *Friend2)) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.ToCtx.getTypeDeclType(D2CXX); + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2CXX); Context.Diag1((*Friend1)->getFriendLoc(), diag::note_odr_friend); Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend); } @@ -1120,8 +1147,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Friend2 != Friend2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.ToCtx.getTypeDeclType(D2); + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2); Context.Diag2((*Friend2)->getFriendLoc(), diag::note_odr_friend); Context.Diag1(D1->getLocation(), diag::note_odr_missing_friend); } @@ -1129,7 +1158,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } } else if (D1CXX->getNumBases() > 0) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); const CXXBaseSpecifier *Base1 = D1CXX->bases_begin(); Context.Diag1(Base1->getBeginLoc(), diag::note_odr_base) @@ -1149,9 +1180,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field2 == Field2End) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(Field1->getLocation(), diag::note_odr_field) << Field1->getDeclName() << Field1->getType(); @@ -1166,10 +1196,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Field2 != Field2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); @@ -1200,9 +1228,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (EC2 == EC2End) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator) << EC1->getDeclName() << EC1->getInitVal().toString(10); @@ -1217,9 +1244,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, !IsStructurallyEquivalent(EC1->getIdentifier(), EC2->getIdentifier())) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) << EC2->getDeclName() << EC2->getInitVal().toString(10); @@ -1232,10 +1258,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (EC2 != EC2End) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), - Context.ErrorOnTagTypeMismatch - ? diag::err_odr_tag_type_inconsistent - : diag::warn_odr_tag_type_inconsistent) + Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) << Context.ToCtx.getTypeDeclType(D2); Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator) << EC2->getDeclName() << EC2->getInitVal().toString(10); @@ -1253,7 +1277,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Params1->size() != Params2->size()) { if (Context.Complain) { Context.Diag2(Params2->getTemplateLoc(), - diag::err_odr_different_num_template_parameters) + Context.getApplicableDiagnostic( + diag::err_odr_different_num_template_parameters)) << Params1->size() << Params2->size(); Context.Diag1(Params1->getTemplateLoc(), diag::note_odr_template_parameter_list); @@ -1265,7 +1290,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) { if (Context.Complain) { Context.Diag2(Params2->getParam(I)->getLocation(), - diag::err_odr_different_template_parameter_kind); + Context.getApplicableDiagnostic( + diag::err_odr_different_template_parameter_kind)); Context.Diag1(Params1->getParam(I)->getLocation(), diag::note_odr_template_parameter_here); } @@ -1285,7 +1311,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, TemplateTypeParmDecl *D2) { if (D1->isParameterPack() != D2->isParameterPack()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_parameter_pack_non_pack)) << D2->isParameterPack(); Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) << D1->isParameterPack(); @@ -1301,7 +1329,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, NonTypeTemplateParmDecl *D2) { if (D1->isParameterPack() != D2->isParameterPack()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_parameter_pack_non_pack)) << D2->isParameterPack(); Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) << D1->isParameterPack(); @@ -1313,7 +1343,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) { if (Context.Complain) { Context.Diag2(D2->getLocation(), - diag::err_odr_non_type_parameter_type_inconsistent) + Context.getApplicableDiagnostic( + diag::err_odr_non_type_parameter_type_inconsistent)) << D2->getType() << D1->getType(); Context.Diag1(D1->getLocation(), diag::note_odr_value_here) << D1->getType(); @@ -1329,7 +1360,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, TemplateTemplateParmDecl *D2) { if (D1->isParameterPack() != D2->isParameterPack()) { if (Context.Complain) { - Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_parameter_pack_non_pack)) << D2->isParameterPack(); Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) << D1->isParameterPack(); @@ -1485,6 +1518,52 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) { return Index; } +unsigned StructuralEquivalenceContext::getApplicableDiagnostic( + unsigned ErrorDiagnostic) { + if (ErrorOnTagTypeMismatch) + return ErrorDiagnostic; + + switch (ErrorDiagnostic) { + case diag::err_odr_variable_type_inconsistent: + return diag::warn_odr_variable_type_inconsistent; + case diag::err_odr_variable_multiple_def: + return diag::warn_odr_variable_multiple_def; + case diag::err_odr_function_type_inconsistent: + return diag::warn_odr_function_type_inconsistent; + case diag::err_odr_tag_type_inconsistent: + return diag::warn_odr_tag_type_inconsistent; + case diag::err_odr_field_type_inconsistent: + return diag::warn_odr_field_type_inconsistent; + case diag::err_odr_ivar_type_inconsistent: + return diag::warn_odr_ivar_type_inconsistent; + case diag::err_odr_objc_superclass_inconsistent: + return diag::warn_odr_objc_superclass_inconsistent; + case diag::err_odr_objc_method_result_type_inconsistent: + return diag::warn_odr_objc_method_result_type_inconsistent; + case diag::err_odr_objc_method_num_params_inconsistent: + return diag::warn_odr_objc_method_num_params_inconsistent; + case diag::err_odr_objc_method_param_type_inconsistent: + return diag::warn_odr_objc_method_param_type_inconsistent; + case diag::err_odr_objc_method_variadic_inconsistent: + return diag::warn_odr_objc_method_variadic_inconsistent; + case diag::err_odr_objc_property_type_inconsistent: + return diag::warn_odr_objc_property_type_inconsistent; + case diag::err_odr_objc_property_impl_kind_inconsistent: + return diag::warn_odr_objc_property_impl_kind_inconsistent; + case diag::err_odr_objc_synthesize_ivar_inconsistent: + return diag::warn_odr_objc_synthesize_ivar_inconsistent; + case diag::err_odr_different_num_template_parameters: + return diag::warn_odr_different_num_template_parameters; + case diag::err_odr_different_template_parameter_kind: + return diag::warn_odr_different_template_parameter_kind; + case diag::err_odr_parameter_pack_non_pack: + return diag::warn_odr_parameter_pack_non_pack; + case diag::err_odr_non_type_parameter_type_inconsistent: + return diag::warn_odr_non_type_parameter_type_inconsistent; + } + llvm_unreachable("Diagnostic kind not handled in preceding switch"); +} + bool StructuralEquivalenceContext::IsEquivalent(Decl *D1, Decl *D2) { // Ensure that the implementation functions (all static functions in this TU) @@ -1624,6 +1703,12 @@ bool StructuralEquivalenceContext::CheckKindSpecificEquivalence( } } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) { if (FunctionDecl *FD2 = dyn_cast<FunctionDecl>(D2)) { + if (FD1->isOverloadedOperator()) { + if (!FD2->isOverloadedOperator()) + return false; + if (FD1->getOverloadedOperator() != FD2->getOverloadedOperator()) + return false; + } if (!::IsStructurallyEquivalent(FD1->getIdentifier(), FD2->getIdentifier())) return false; diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp index 461084ce70..ba1581bd3f 100644 --- a/lib/AST/ASTTypeTraits.cpp +++ b/lib/AST/ASTTypeTraits.cpp @@ -1,9 +1,8 @@ //===--- ASTTypeTraits.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -38,6 +37,9 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { { NKI_None, "Type" }, #define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" }, #include "clang/AST/TypeNodes.def" + { NKI_None, "OMPClause" }, +#define OPENMP_CLAUSE(TextualSpelling, Class) {NKI_OMPClause, #Class}, +#include "clang/Basic/OpenMPKinds.def" }; bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { @@ -104,6 +106,19 @@ ASTNodeKind ASTNodeKind::getFromNode(const Type &T) { #include "clang/AST/TypeNodes.def" } llvm_unreachable("invalid type kind"); + } + +ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) { + switch (C.getClauseKind()) { +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: return ASTNodeKind(NKI_##Class); +#include "clang/Basic/OpenMPKinds.def" + case OMPC_threadprivate: + case OMPC_uniform: + case OMPC_unknown: + llvm_unreachable("unexpected OpenMP clause kind"); + } + llvm_unreachable("invalid stmt kind"); } void DynTypedNode::print(llvm::raw_ostream &OS, @@ -152,6 +167,8 @@ SourceRange DynTypedNode::getSourceRange() const { return D->getSourceRange(); if (const Stmt *S = get<Stmt>()) return S->getSourceRange(); + if (const auto *C = get<OMPClause>()) + return SourceRange(C->getBeginLoc(), C->getEndLoc()); return SourceRange(); } diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp index b06b50c9b4..0ef925ec1c 100644 --- a/lib/AST/AttrImpl.cpp +++ b/lib/AST/AttrImpl.cpp @@ -1,9 +1,8 @@ //===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h index 06295b5817..31cb369187 100644 --- a/lib/AST/CXXABI.h +++ b/lib/AST/CXXABI.h @@ -1,9 +1,8 @@ //===----- CXXABI.h - Interface to C++ ABIs ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index ddb350e72b..ecf451b175 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -1,9 +1,8 @@ //===- CXXInheritance.cpp - C++ Inheritance -------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -487,6 +486,21 @@ bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier, return false; } +bool CXXRecordDecl::FindOMPMapperMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + DeclarationName Name) { + RecordDecl *BaseRecord = + Specifier->getType()->castAs<RecordType>()->getDecl(); + + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPMapper)) + return true; + } + + return false; +} + bool CXXRecordDecl:: FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, @@ -540,8 +554,7 @@ void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides = Overrides[OverriddenSubobject]; - if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(), - Overriding) == SubobjectOverrides.end()) + if (llvm::find(SubobjectOverrides, Overriding) == SubobjectOverrides.end()) SubobjectOverrides.push_back(Overriding); } diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index 0d759e226c..25339c7901 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -1,9 +1,8 @@ //===--- Comment.cpp - Comment AST node implementation --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp index 5ec7586a47..2b648cbb1d 100644 --- a/lib/AST/CommentBriefParser.cpp +++ b/lib/AST/CommentBriefParser.cpp @@ -1,9 +1,8 @@ //===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/CommentCommandTraits.cpp b/lib/AST/CommentCommandTraits.cpp index 7378a7c3ac..b306fcbb15 100644 --- a/lib/AST/CommentCommandTraits.cpp +++ b/lib/AST/CommentCommandTraits.cpp @@ -1,9 +1,8 @@ //===--- CommentCommandTraits.cpp - Comment command properties --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp index c43275318d..19485f6018 100644 --- a/lib/AST/CommentLexer.cpp +++ b/lib/AST/CommentLexer.cpp @@ -1,9 +1,8 @@ //===--- CommentLexer.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index 7f70b95e98..c7f8aa7e16 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -1,9 +1,8 @@ //===--- CommentParser.cpp - Doxygen comment parser -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 88588a7a89..067b3ae422 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -1,9 +1,8 @@ //===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/ComparisonCategories.cpp b/lib/AST/ComparisonCategories.cpp index 87f51facc5..ee4c1b0443 100644 --- a/lib/AST/ComparisonCategories.cpp +++ b/lib/AST/ComparisonCategories.cpp @@ -1,9 +1,8 @@ //===- ComparisonCategories.cpp - Three Way Comparison Data -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/DataCollection.cpp b/lib/AST/DataCollection.cpp index c2ecabe8e6..8e67c101de 100644 --- a/lib/AST/DataCollection.cpp +++ b/lib/AST/DataCollection.cpp @@ -1,9 +1,8 @@ //===-- DataCollection.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 5536358b1e..19fd3882bd 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1,9 +1,8 @@ //===- Decl.cpp - Declaration AST Node Implementation ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -568,7 +567,14 @@ static bool isSingleLineLanguageLinkage(const Decl &D) { return false; } -static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { +/// Determine whether D is declared in the purview of a named module. +static bool isInModulePurview(const NamedDecl *D) { + if (auto *M = D->getOwningModule()) + return M->isModulePurview(); + return false; +} + +static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { // FIXME: Handle isModulePrivate. switch (D->getModuleOwnershipKind()) { case Decl::ModuleOwnershipKind::Unowned: @@ -576,8 +582,7 @@ static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { return false; case Decl::ModuleOwnershipKind::Visible: case Decl::ModuleOwnershipKind::VisibleWhenImported: - if (auto *M = D->getOwningModule()) - return M->Kind == Module::ModuleInterfaceUnit; + return isInModulePurview(D); } llvm_unreachable("unexpected module ownership kind"); } @@ -587,9 +592,8 @@ static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { // as "module-internal linkage", which means that they have internal linkage // formally but can be indirectly accessed from outside the module via inline // functions and templates defined within the module. - if (auto *M = D->getOwningModule()) - if (M->Kind == Module::ModuleInterfaceUnit) - return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); + if (isInModulePurview(D)) + return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); return LinkageInfo::internal(); } @@ -599,15 +603,25 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { // - A name declared at namespace scope that does not have internal linkage // by the previous rules and that is introduced by a non-exported // declaration has module linkage. - if (auto *M = D->getOwningModule()) - if (M->Kind == Module::ModuleInterfaceUnit) - if (!isExportedFromModuleIntefaceUnit( - cast<NamedDecl>(D->getCanonicalDecl()))) - return LinkageInfo(ModuleLinkage, DefaultVisibility, false); + if (isInModulePurview(D) && !isExportedFromModuleInterfaceUnit( + cast<NamedDecl>(D->getCanonicalDecl()))) + return LinkageInfo(ModuleLinkage, DefaultVisibility, false); return LinkageInfo::external(); } +static StorageClass getStorageClass(const Decl *D) { + if (auto *TD = dyn_cast<TemplateDecl>(D)) + D = TD->getTemplatedDecl(); + if (D) { + if (auto *VD = dyn_cast<VarDecl>(D)) + return VD->getStorageClass(); + if (auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getStorageClass(); + } + return SC_None; +} + LinkageInfo LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, LVComputationKind computation, @@ -619,24 +633,28 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // C++ [basic.link]p3: // A name having namespace scope (3.3.6) has internal linkage if it // is the name of - // - an object, reference, function or function template that is - // explicitly declared static; or, - // (This bullet corresponds to C99 6.2.2p3.) + + if (getStorageClass(D->getCanonicalDecl()) == SC_Static) { + // - a variable, variable template, function, or function template + // that is explicitly declared static; or + // (This bullet corresponds to C99 6.2.2p3.) + return getInternalLinkageFor(D); + } + if (const auto *Var = dyn_cast<VarDecl>(D)) { - // Explicitly declared static. - if (Var->getStorageClass() == SC_Static) - return getInternalLinkageFor(Var); - - // - a non-inline, non-volatile object or reference that is explicitly - // declared const or constexpr and neither explicitly declared extern - // nor previously declared to have external linkage; or (there is no - // equivalent in C99) - // The C++ modules TS adds "non-exported" to this list. + // - a non-template variable of non-volatile const-qualified type, unless + // - it is explicitly declared extern, or + // - it is inline or exported, or + // - it was previously declared and the prior declaration did not have + // internal linkage + // (There is no equivalent in C99.) if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() && !Var->getType().isVolatileQualified() && !Var->isInline() && - !isExportedFromModuleIntefaceUnit(Var)) { + !isExportedFromModuleInterfaceUnit(Var) && + !isa<VarTemplateSpecializationDecl>(Var) && + !Var->getDescribedVarTemplate()) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) return getLVForDecl(PrevVar, computation); @@ -656,14 +674,6 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (PrevVar->getStorageClass() == SC_Static) return getInternalLinkageFor(Var); } - } else if (const FunctionDecl *Function = D->getAsFunction()) { - // C++ [temp]p4: - // A non-member function template can have internal linkage; any - // other template name shall have external linkage. - - // Explicitly declared static. - if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return getInternalLinkageFor(Function); } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); @@ -672,6 +682,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, } assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); + // FIXME: This gives internal linkage to names that should have no linkage + // (those not covered by [basic.link]p6). if (D->isInAnonymousNamespace()) { const auto *Var = dyn_cast<VarDecl>(D); const auto *Func = dyn_cast<FunctionDecl>(D); @@ -731,10 +743,20 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // C++ [basic.link]p4: - // A name having namespace scope has external linkage if it is the - // name of + // A name having namespace scope that has not been given internal linkage + // above and that is the name of + // [...bullets...] + // has its linkage determined as follows: + // - if the enclosing namespace has internal linkage, the name has + // internal linkage; [handled above] + // - otherwise, if the declaration of the name is attached to a named + // module and is not exported, the name has module linkage; + // - otherwise, the name has external linkage. + // LV is currently set up to handle the last two bullets. // - // - an object or reference, unless it has internal linkage; or + // The bullets are: + + // - a variable; or if (const auto *Var = dyn_cast<VarDecl>(D)) { // GCC applies the following optimization to variables and static // data members, but not to functions: @@ -780,7 +802,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, mergeTemplateLV(LV, spec, computation); } - // - a function, unless it has internal linkage; or + // - a function; or } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) { // In theory, we can modify the function's LV by the LV of its // type unless it has C linkage (see comment above about variables @@ -834,7 +856,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, mergeTemplateLV(LV, spec, computation); } - // - an enumerator belonging to an enumeration with external linkage; + // FIXME: This is not part of the C++ standard any more. + // - an enumerator belonging to an enumeration with external linkage; or } else if (isa<EnumConstantDecl>(D)) { LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), computation); @@ -842,16 +865,16 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, return LinkageInfo::none(); LV.merge(EnumLV); - // - a template, unless it is a function template that has - // internal linkage (Clause 14); + // - a template } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) { bool considerVisibility = !hasExplicitVisibilityAlready(computation); LinkageInfo tempLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); LV.mergeMaybeWithVisibility(tempLV, considerVisibility); - // - a namespace (7.3), unless it is declared within an unnamed - // namespace. + // An unnamed namespace or a namespace declared directly or indirectly + // within an unnamed namespace has internal linkage. All other namespaces + // have external linkage. // // We handled names in anonymous namespaces above. } else if (isa<NamespaceDecl>(D)) { @@ -1508,6 +1531,11 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { } return InternalLinkage ? M->Parent : nullptr; } + + case Module::PrivateModuleFragment: + // The private module fragment is part of its containing module for linkage + // purposes. + return M->Parent; } llvm_unreachable("unknown module kind"); @@ -1532,10 +1560,16 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); - // For ObjC methods, look through categories and use the interface as context. + // For ObjC methods and properties, look through categories and use the + // interface as context. if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) if (auto *ID = MD->getClassInterface()) Ctx = ID; + if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) { + if (auto *MD = PD->getGetterMethodDecl()) + if (auto *ID = MD->getClassInterface()) + Ctx = ID; + } if (Ctx->isFunctionOrMethod()) { printName(OS); @@ -2380,48 +2414,61 @@ bool VarDecl::isNonEscapingByref() const { } VarDecl *VarDecl::getTemplateInstantiationPattern() const { - // If it's a variable template specialization, find the template or partial - // specialization from which it was instantiated. - if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) { - auto From = VDTemplSpec->getInstantiatedFrom(); - if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { - while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) { - if (NewVTD->isMemberSpecialization()) - break; - VTD = NewVTD; - } - return getDefinitionOrSelf(VTD->getTemplatedDecl()); - } - if (auto *VTPSD = - From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { - while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) { - if (NewVTPSD->isMemberSpecialization()) - break; - VTPSD = NewVTPSD; - } - return getDefinitionOrSelf<VarDecl>(VTPSD); - } - } + const VarDecl *VD = this; - if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + // If this is an instantiated member, walk back to the template from which + // it was instantiated. + if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) { if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { - VarDecl *VD = getInstantiatedFromStaticDataMember(); + VD = VD->getInstantiatedFromStaticDataMember(); while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) VD = NewVD; - return getDefinitionOrSelf(VD); } } - if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { - while (VarTemplate->getInstantiatedFromMemberTemplate()) { - if (VarTemplate->isMemberSpecialization()) + // If it's an instantiated variable template specialization, find the + // template or partial specialization from which it was instantiated. + if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(VD)) { + if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) { + auto From = VDTemplSpec->getInstantiatedFrom(); + if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { + while (!VTD->isMemberSpecialization()) { + auto *NewVTD = VTD->getInstantiatedFromMemberTemplate(); + if (!NewVTD) + break; + VTD = NewVTD; + } + return getDefinitionOrSelf(VTD->getTemplatedDecl()); + } + if (auto *VTPSD = + From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { + while (!VTPSD->isMemberSpecialization()) { + auto *NewVTPSD = VTPSD->getInstantiatedFromMember(); + if (!NewVTPSD) + break; + VTPSD = NewVTPSD; + } + return getDefinitionOrSelf<VarDecl>(VTPSD); + } + } + } + + // If this is the pattern of a variable template, find where it was + // instantiated from. FIXME: Is this necessary? + if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) { + while (!VarTemplate->isMemberSpecialization()) { + auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate(); + if (!NewVT) break; - VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); + VarTemplate = NewVT; } return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); } - return nullptr; + + if (VD == this) + return nullptr; + return getDefinitionOrSelf(const_cast<VarDecl*>(VD)); } VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { @@ -2441,6 +2488,17 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { return TSK_Undeclared; } +TemplateSpecializationKind +VarDecl::getTemplateSpecializationKindForInstantiation() const { + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getTemplateSpecializationKind(); + + if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) + return Spec->getSpecializationKind(); + + return TSK_Undeclared; +} + SourceLocation VarDecl::getPointOfInstantiation() const { if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) return Spec->getPointOfInstantiation(); @@ -2501,15 +2559,14 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, if (VarTemplateSpecializationDecl *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) { Spec->setSpecializationKind(TSK); - if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && Spec->getPointOfInstantiation().isInvalid()) { Spec->setPointOfInstantiation(PointOfInstantiation); if (ASTMutationListener *L = getASTContext().getASTMutationListener()) L->InstantiationRequested(this); } - } - - if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { + } else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { MSI->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && MSI->getPointOfInstantiation().isInvalid()) { @@ -2982,16 +3039,20 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } -/// Returns a value indicating whether this function -/// corresponds to a builtin function. +/// Returns a value indicating whether this function corresponds to a builtin +/// function. /// -/// The function corresponds to a built-in function if it is -/// declared at translation scope or within an extern "C" block and -/// its name matches with the name of a builtin. The returned value -/// will be 0 for functions that do not correspond to a builtin, a -/// value of type \c Builtin::ID if in the target-independent range -/// \c [1,Builtin::First), or a target-specific builtin value. -unsigned FunctionDecl::getBuiltinID() const { +/// The function corresponds to a built-in function if it is declared at +/// translation scope or within an extern "C" block and its name matches with +/// the name of a builtin. The returned value will be 0 for functions that do +/// not correspond to a builtin, a value of type \c Builtin::ID if in the +/// target-independent range \c [1,Builtin::First), or a target-specific builtin +/// value. +/// +/// \param ConsiderWrapperFunctions If true, we should consider wrapper +/// functions as their wrapped builtins. This shouldn't be done in general, but +/// it's useful in Sema to diagnose calls to wrappers based on their semantics. +unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { if (!getIdentifier()) return 0; @@ -3019,7 +3080,7 @@ unsigned FunctionDecl::getBuiltinID() const { // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. - if (hasAttr<OverloadableAttr>()) + if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>()) return 0; if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) @@ -3030,7 +3091,7 @@ unsigned FunctionDecl::getBuiltinID() const { // function or whether it just has the same name. // If this is a static function, it's not a builtin. - if (getStorageClass() == SC_Static) + if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static) return 0; // OpenCL v1.2 s6.9.f - The library functions defined in @@ -3337,7 +3398,13 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { } MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { - return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>(); + if (auto *MSI = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSI; + if (auto *FTSI = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) + return FTSI->getMemberSpecializationInfo(); + return nullptr; } void @@ -3356,6 +3423,8 @@ FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const { } void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { + assert(TemplateOrSpecialization.isNull() && + "Member function is already a specialization"); TemplateOrSpecialization = Template; } @@ -3364,19 +3433,15 @@ bool FunctionDecl::isImplicitlyInstantiable() const { if (isInvalidDecl()) return false; - switch (getTemplateSpecializationKind()) { + switch (getTemplateSpecializationKindForInstantiation()) { case TSK_Undeclared: case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: return false; case TSK_ImplicitInstantiation: return true; - // It is possible to instantiate TSK_ExplicitSpecialization kind - // if the FunctionDecl has a class scope specialization pattern. - case TSK_ExplicitSpecialization: - return getClassScopeSpecializationPattern() != nullptr; - case TSK_ExplicitInstantiationDeclaration: // Handled below. break; @@ -3399,26 +3464,12 @@ bool FunctionDecl::isImplicitlyInstantiable() const { } bool FunctionDecl::isTemplateInstantiation() const { - switch (getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return false; - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - return true; - } - llvm_unreachable("All TSK values handled."); + // FIXME: Remove this, it's not clear what it means. (Which template + // specialization kind?) + return clang::isTemplateInstantiation(getTemplateSpecializationKind()); } FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { - // Handle class scope explicit specialization special case. - if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { - if (auto *Spec = getClassScopeSpecializationPattern()) - return getDefinitionOrSelf(Spec); - return nullptr; - } - // If this is a generic lambda call operator specialization, its // instantiation pattern is always its primary template's pattern // even if its primary template was instantiated from another @@ -3434,21 +3485,28 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } + if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) { + if (!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind())) + return nullptr; + return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom())); + } + + if (!clang::isTemplateInstantiation(getTemplateSpecializationKind())) + return nullptr; + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { - while (Primary->getInstantiatedFromMemberTemplate()) { - // If we have hit a point where the user provided a specialization of - // this template, we're done looking. - if (Primary->isMemberSpecialization()) + // If we hit a point where the user provided a specialization of this + // template, we're done looking. + while (!Primary->isMemberSpecialization()) { + auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate(); + if (!NewPrimary) break; - Primary = Primary->getInstantiatedFromMemberTemplate(); + Primary = NewPrimary; } return getDefinitionOrSelf(Primary->getTemplatedDecl()); } - if (auto *MFD = getInstantiatedFromMemberFunction()) - return getDefinitionOrSelf(MFD); - return nullptr; } @@ -3456,15 +3514,11 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization .dyn_cast<FunctionTemplateSpecializationInfo*>()) { - return Info->Template.getPointer(); + return Info->getTemplate(); } return nullptr; } -FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { - return getASTContext().getClassScopeSpecializationPattern(this); -} - FunctionTemplateSpecializationInfo * FunctionDecl::getTemplateSpecializationInfo() const { return TemplateOrSpecialization @@ -3499,15 +3553,19 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, TemplateSpecializationKind TSK, const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation PointOfInstantiation) { + assert((TemplateOrSpecialization.isNull() || + TemplateOrSpecialization.is<MemberSpecializationInfo *>()) && + "Member function is already a specialization"); assert(TSK != TSK_Undeclared && "Must specify the type of function template specialization"); - FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); - if (!Info) - Info = FunctionTemplateSpecializationInfo::Create(C, this, Template, TSK, - TemplateArgs, - TemplateArgsAsWritten, - PointOfInstantiation); + assert((TemplateOrSpecialization.isNull() || + TSK == TSK_ExplicitSpecialization) && + "Member specialization must be an explicit specialization"); + FunctionTemplateSpecializationInfo *Info = + FunctionTemplateSpecializationInfo::Create( + C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten, + PointOfInstantiation, + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()); TemplateOrSpecialization = Info; Template->addSpecialization(Info, InsertPos); } @@ -3558,14 +3616,47 @@ DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const { // For a function template specialization, query the specialization // information object. - FunctionTemplateSpecializationInfo *FTSInfo - = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); - if (FTSInfo) + if (FunctionTemplateSpecializationInfo *FTSInfo = + TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) return FTSInfo->getTemplateSpecializationKind(); - MemberSpecializationInfo *MSInfo - = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); - if (MSInfo) + if (MemberSpecializationInfo *MSInfo = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSInfo->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +TemplateSpecializationKind +FunctionDecl::getTemplateSpecializationKindForInstantiation() const { + // This is the same as getTemplateSpecializationKind(), except that for a + // function that is both a function template specialization and a member + // specialization, we prefer the member specialization information. Eg: + // + // template<typename T> struct A { + // template<typename U> void f() {} + // template<> void f<int>() {} + // }; + // + // For A<int>::f<int>(): + // * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization + // * getTemplateSpecializationKindForInstantiation() will return + // TSK_ImplicitInstantiation + // + // This reflects the facts that A<int>::f<int> is an explicit specialization + // of A<int>::f, and that A<int>::f<int> should be implicitly instantiated + // from A::f<int> if a definition is needed. + if (FunctionTemplateSpecializationInfo *FTSInfo = + TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) { + if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo()) + return MSInfo->getTemplateSpecializationKind(); + return FTSInfo->getTemplateSpecializationKind(); + } + + if (MemberSpecializationInfo *MSInfo = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) return MSInfo->getTemplateSpecializationKind(); return TSK_Undeclared; @@ -3673,6 +3764,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BImemcmp: return Builtin::BImemcmp; + case Builtin::BI__builtin_bcmp: + case Builtin::BIbcmp: + return Builtin::BIbcmp; + case Builtin::BI__builtin_strncpy: case Builtin::BI__builtin___strncpy_chk: case Builtin::BIstrncpy: @@ -3713,6 +3808,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BImemmove; else if (FnInfo->isStr("memcmp")) return Builtin::BImemcmp; + else if (FnInfo->isStr("bcmp")) + return Builtin::BIbcmp; else if (FnInfo->isStr("strncpy")) return Builtin::BIstrncpy; else if (FnInfo->isStr("strncmp")) @@ -4260,6 +4357,7 @@ BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc) setBlockMissingReturnType(true); setIsConversionFromLambda(false); setDoesNotEscape(false); + setCanAvoidCopyToHeap(false); } void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index b83082e9eb..f40896da48 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1,9 +1,8 @@ //===- DeclBase.cpp - Declaration AST Node Implementation -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -355,7 +354,8 @@ bool Decl::isInAnonymousNamespace() const { } bool Decl::isInStdNamespace() const { - return getDeclContext()->isStdNamespace(); + const DeclContext *DC = getDeclContext(); + return DC && DC->isStdNamespace(); } TranslationUnitDecl *Decl::getTranslationUnitDecl() { @@ -431,22 +431,6 @@ bool Decl::isReferenced() const { return false; } -bool Decl::isExported() const { - if (isModulePrivate()) - return false; - // Namespaces are always exported. - if (isa<TranslationUnitDecl>(this) || isa<NamespaceDecl>(this)) - return true; - // Otherwise, this is a strictly lexical check. - for (auto *DC = getLexicalDeclContext(); DC; DC = DC->getLexicalParent()) { - if (cast<Decl>(DC)->isModulePrivate()) - return false; - if (isa<ExportDecl>(DC)) - return true; - } - return false; -} - ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const { const Decl *Definition = nullptr; if (auto *ID = dyn_cast<ObjCInterfaceDecl>(this)) { @@ -781,6 +765,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case OMPDeclareReduction: return IDNS_OMPReduction; + case OMPDeclareMapper: + return IDNS_OMPMapper; + // Never have names. case Friend: case FriendTemplate: @@ -810,6 +797,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCategoryImpl: case Import: case OMPThreadPrivate: + case OMPAllocate: case OMPRequires: case OMPCapturedExpr: case Empty: @@ -1054,6 +1042,18 @@ DeclContext *DeclContext::getLookupParent() { return getParent(); } +const BlockDecl *DeclContext::getInnermostBlockDecl() const { + const DeclContext *Ctx = this; + + do { + if (Ctx->isClosure()) + return cast<BlockDecl>(Ctx); + Ctx = Ctx->getParent(); + } while (Ctx); + + return nullptr; +} + bool DeclContext::isInlineNamespace() const { return isNamespace() && cast<NamespaceDecl>(this)->isInline(); @@ -1164,6 +1164,7 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::Block: case Decl::Captured: case Decl::OMPDeclareReduction: + case Decl::OMPDeclareMapper: // There is only one DeclContext for these entities. return this; @@ -1175,13 +1176,15 @@ DeclContext *DeclContext::getPrimaryContext() { return this; case Decl::ObjCInterface: - if (auto *Def = cast<ObjCInterfaceDecl>(this)->getDefinition()) - return Def; + if (auto *OID = dyn_cast<ObjCInterfaceDecl>(this)) + if (auto *Def = OID->getDefinition()) + return Def; return this; case Decl::ObjCProtocol: - if (auto *Def = cast<ObjCProtocolDecl>(this)->getDefinition()) - return Def; + if (auto *OPD = dyn_cast<ObjCProtocolDecl>(this)) + if (auto *Def = OPD->getDefinition()) + return Def; return this; case Decl::ObjCCategory: diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 31ffeb0dcd..d7eae5ad1e 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -1,9 +1,8 @@ //===- DeclCXX.cpp - C++ Declaration AST Node Implementation --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -992,6 +991,17 @@ void CXXRecordDecl::addedMember(Decl *D) { setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs); Data.HasIrrelevantDestructor = false; + + if (isUnion()) { + data().DefaultedCopyConstructorIsDeleted = true; + data().DefaultedMoveConstructorIsDeleted = true; + data().DefaultedMoveAssignmentIsDeleted = true; + data().DefaultedDestructorIsDeleted = true; + data().NeedOverloadResolutionForCopyConstructor = true; + data().NeedOverloadResolutionForMoveConstructor = true; + data().NeedOverloadResolutionForMoveAssignment = true; + data().NeedOverloadResolutionForDestructor = true; + } } else if (!Context.getLangOpts().ObjCAutoRefCount) { setHasObjectMember(true); } @@ -1411,13 +1421,30 @@ void CXXRecordDecl::getCaptureFields( TemplateParameterList * CXXRecordDecl::getGenericLambdaTemplateParameterList() const { - if (!isLambda()) return nullptr; + if (!isGenericLambda()) return nullptr; CXXMethodDecl *CallOp = getLambdaCallOperator(); if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) return Tmpl->getTemplateParameters(); return nullptr; } +ArrayRef<NamedDecl *> +CXXRecordDecl::getLambdaExplicitTemplateParameters() const { + TemplateParameterList *List = getGenericLambdaTemplateParameterList(); + if (!List) + return {}; + + assert(std::is_partitioned(List->begin(), List->end(), + [](const NamedDecl *D) { return !D->isImplicit(); }) + && "Explicit template params should be ordered before implicit ones"); + + const auto ExplicitEnd = std::lower_bound(List->begin(), List->end(), false, + [](const NamedDecl *D, bool) { + return !D->isImplicit(); + }); + return llvm::makeArrayRef(List->begin(), ExplicitEnd); +} + Decl *CXXRecordDecl::getLambdaContextDecl() const { assert(isLambda() && "Not a lambda closure type!"); ExternalASTSource *Source = getParentASTContext().getExternalSource(); @@ -1586,8 +1613,8 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { for (unsigned I = 0, E = Convs.size(); I != E; ++I) { if (Convs[I].getDecl() == ConvDecl) { Convs.erase(I); - assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end() - && "conversion was found multiple times in unresolved set"); + assert(llvm::find(Convs, ConvDecl) == Convs.end() && + "conversion was found multiple times in unresolved set"); return; } } @@ -2081,8 +2108,13 @@ bool CXXMethodDecl::isUsualDeallocationFunction( return false; // In C++17 onwards, all potential usual deallocation functions are actual - // usual deallocation functions. - if (Context.getLangOpts().AlignedAllocation) + // usual deallocation functions. Honor this behavior when post-C++14 + // deallocation functions are offered as extensions too. + // FIXME(EricWF): Destrying Delete should be a language option. How do we + // handle when destroying delete is used prior to C++17? + if (Context.getLangOpts().CPlusPlus17 || + Context.getLangOpts().AlignedAllocation || + isDestroyingOperatorDelete()) return true; // This function is a usual deallocation function if there are no @@ -2177,7 +2209,7 @@ QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl) { ASTContext &C = Decl->getASTContext(); QualType ClassTy = C.getTypeDeclType(Decl); - ClassTy = C.getQualifiedType(ClassTy, FPT->getTypeQuals()); + ClassTy = C.getQualifiedType(ClassTy, FPT->getMethodQuals()); return C.getPointerType(ClassTy); } diff --git a/lib/AST/DeclFriend.cpp b/lib/AST/DeclFriend.cpp index 08fbed3615..8ec1dea84d 100644 --- a/lib/AST/DeclFriend.cpp +++ b/lib/AST/DeclFriend.cpp @@ -1,9 +1,8 @@ //===- DeclFriend.cpp - C++ Friend Declaration AST Node Implementation ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp index f74ef9bbb8..27dbdaab6f 100644 --- a/lib/AST/DeclGroup.cpp +++ b/lib/AST/DeclGroup.cpp @@ -1,9 +1,8 @@ //===- DeclGroup.cpp - Classes for representing groups of Decls -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 1ed7fc71b0..bf748fbab8 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -1,9 +1,8 @@ //===- DeclObjC.cpp - ObjC Declaration AST Node Implementation ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -1642,7 +1641,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { if (!layout.empty()) { // Order synthesized ivars by their size. - std::stable_sort(layout.begin(), layout.end()); + llvm::stable_sort(layout); unsigned Ix = 0, EIx = layout.size(); if (!data().IvarList) { data().IvarList = layout[0].Ivar; Ix++; diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp index b77a67cbf3..af321280d4 100644 --- a/lib/AST/DeclOpenMP.cpp +++ b/lib/AST/DeclOpenMP.cpp @@ -1,9 +1,8 @@ //===--- DeclOpenMP.cpp - Declaration OpenMP AST Node Implementation ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file @@ -54,6 +53,49 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) { } //===----------------------------------------------------------------------===// +// OMPAllocateDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPAllocateDecl::anchor() { } + +OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, ArrayRef<Expr *> VL, + ArrayRef<OMPClause *> CL) { + OMPAllocateDecl *D = new ( + C, DC, additionalSizeToAlloc<Expr *, OMPClause *>(VL.size(), CL.size())) + OMPAllocateDecl(OMPAllocate, DC, L); + D->NumVars = VL.size(); + D->setVars(VL); + D->NumClauses = CL.size(); + D->setClauses(CL); + return D; +} + +OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NVars, + unsigned NClauses) { + OMPAllocateDecl *D = + new (C, ID, additionalSizeToAlloc<Expr *, OMPClause *>(NVars, NClauses)) + OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation()); + D->NumVars = NVars; + D->NumClauses = NClauses; + return D; +} + +void OMPAllocateDecl::setVars(ArrayRef<Expr *> VL) { + assert(VL.size() == NumVars && + "Number of variables is not the same as the preallocated buffer"); + std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>()); +} + +void OMPAllocateDecl::setClauses(ArrayRef<OMPClause *> CL) { + assert(CL.size() == NumClauses && + "Number of variables is not the same as the preallocated buffer"); + std::uninitialized_copy(CL.begin(), CL.end(), + getTrailingObjects<OMPClause *>()); +} + +//===----------------------------------------------------------------------===// // OMPRequiresDecl Implementation. //===----------------------------------------------------------------------===// @@ -124,6 +166,66 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const { } //===----------------------------------------------------------------------===// +// OMPDeclareMapperDecl Implementation. +//===----------------------------------------------------------------------===// + +void OMPDeclareMapperDecl::anchor() {} + +OMPDeclareMapperDecl * +OMPDeclareMapperDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, + DeclarationName Name, QualType T, + DeclarationName VarName, + OMPDeclareMapperDecl *PrevDeclInScope) { + return new (C, DC) OMPDeclareMapperDecl(OMPDeclareMapper, DC, L, Name, T, + VarName, PrevDeclInScope); +} + +OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned N) { + auto *D = new (C, ID) + OMPDeclareMapperDecl(OMPDeclareMapper, /*DC=*/nullptr, SourceLocation(), + DeclarationName(), QualType(), DeclarationName(), + /*PrevDeclInScope=*/nullptr); + if (N) { + auto **ClauseStorage = C.Allocate<OMPClause *>(N); + D->Clauses = llvm::makeMutableArrayRef<OMPClause *>(ClauseStorage, N); + } + return D; +} + +/// Creates an array of clauses to this mapper declaration and intializes +/// them. The space used to store clause pointers is dynamically allocated, +/// because we do not know the number of clauses when creating +/// OMPDeclareMapperDecl +void OMPDeclareMapperDecl::CreateClauses(ASTContext &C, + ArrayRef<OMPClause *> CL) { + assert(Clauses.empty() && "Number of clauses should be 0 on initialization"); + size_t NumClauses = CL.size(); + if (NumClauses) { + auto **ClauseStorage = C.Allocate<OMPClause *>(NumClauses); + Clauses = llvm::makeMutableArrayRef<OMPClause *>(ClauseStorage, NumClauses); + setClauses(CL); + } +} + +void OMPDeclareMapperDecl::setClauses(ArrayRef<OMPClause *> CL) { + assert(CL.size() == Clauses.size() && + "Number of clauses is not the same as the preallocated buffer"); + std::uninitialized_copy(CL.begin(), CL.end(), Clauses.data()); +} + +OMPDeclareMapperDecl *OMPDeclareMapperDecl::getPrevDeclInScope() { + return cast_or_null<OMPDeclareMapperDecl>( + PrevDeclInScope.get(getASTContext().getExternalSource())); +} + +const OMPDeclareMapperDecl *OMPDeclareMapperDecl::getPrevDeclInScope() const { + return cast_or_null<OMPDeclareMapperDecl>( + PrevDeclInScope.get(getASTContext().getExternalSource())); +} + +//===----------------------------------------------------------------------===// // OMPCapturedExprDecl Implementation. //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 517851f9ee..325400e463 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -1,9 +1,8 @@ //===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -16,6 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -100,11 +100,14 @@ namespace { void VisitUsingDecl(UsingDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); + void VisitOMPAllocateDecl(OMPAllocateDecl *D); void VisitOMPRequiresDecl(OMPRequiresDecl *D); void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); + void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); - void printTemplateParameters(const TemplateParameterList *Params); + void printTemplateParameters(const TemplateParameterList *Params, + bool OmitTemplateKW = false); void printTemplateArguments(const TemplateArgumentList &Args, const TemplateParameterList *Params = nullptr); void prettyPrintAttributes(Decl *D); @@ -125,6 +128,18 @@ void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, Printer.Visit(const_cast<Decl*>(this)); } +void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, + bool OmitTemplateKW) const { + print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW); +} + +void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, + const PrintingPolicy &Policy, + bool OmitTemplateKW) const { + DeclPrinter Printer(Out, Policy, Context); + Printer.printTemplateParameters(this, OmitTemplateKW); +} + static QualType GetBaseType(QualType T) { // FIXME: This should be on the Type class! QualType BaseType = T; @@ -424,7 +439,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { // FIXME: Need to be able to tell the DeclPrinter when const char *Terminator = nullptr; if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) || - isa<OMPRequiresDecl>(*D)) + isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) || + isa<OMPAllocateDecl>(*D)) Terminator = nullptr; else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) Terminator = nullptr; @@ -986,25 +1002,35 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) { +void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, + bool OmitTemplateKW) { assert(Params); - Out << "template <"; + if (!OmitTemplateKW) + Out << "template "; + Out << '<'; - for (unsigned i = 0, e = Params->size(); i != e; ++i) { - if (i != 0) + bool NeedComma = false; + for (const Decl *Param : *Params) { + if (Param->isImplicit()) + continue; + + if (NeedComma) Out << ", "; + else + NeedComma = true; - const Decl *Param = Params->getParam(i); if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { if (TTP->wasDeclaredWithTypename()) - Out << "typename "; + Out << "typename"; else - Out << "class "; + Out << "class"; if (TTP->isParameterPack()) - Out << "..."; + Out << " ..."; + else if (!TTP->getName().empty()) + Out << ' '; Out << *TTP; @@ -1029,7 +1055,9 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) { } } - Out << "> "; + Out << '>'; + if (!OmitTemplateKW) + Out << ' '; } void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args, @@ -1389,6 +1417,13 @@ void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) { /// PrintObjCPropertyDecl - print a property declaration. /// +/// Print attributes in the following order: +/// - class +/// - nonatomic | atomic +/// - assign | retain | strong | copy | weak | unsafe_unretained +/// - readwrite | readonly +/// - getter & setter +/// - nullability void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required) Out << "@required\n"; @@ -1400,58 +1435,69 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { Out << "@property"; if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) { bool first = true; - Out << " ("; - if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_readonly) { - Out << (first ? ' ' : ',') << "readonly"; + Out << "("; + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_class) { + Out << (first ? "" : ", ") << "class"; first = false; } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { - Out << (first ? ' ' : ',') << "getter = "; - PDecl->getGetterName().print(Out); + if (PDecl->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_nonatomic) { + Out << (first ? "" : ", ") << "nonatomic"; first = false; } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { - Out << (first ? ' ' : ',') << "setter = "; - PDecl->getSetterName().print(Out); + if (PDecl->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_atomic) { + Out << (first ? "" : ", ") << "atomic"; first = false; } if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) { - Out << (first ? ' ' : ',') << "assign"; + Out << (first ? "" : ", ") << "assign"; first = false; } - - if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_readwrite) { - Out << (first ? ' ' : ',') << "readwrite"; - first = false; - } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) { - Out << (first ? ' ' : ',') << "retain"; + Out << (first ? "" : ", ") << "retain"; first = false; } if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) { - Out << (first ? ' ' : ',') << "strong"; + Out << (first ? "" : ", ") << "strong"; first = false; } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { - Out << (first ? ' ' : ',') << "copy"; + Out << (first ? "" : ", ") << "copy"; + first = false; + } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) { + Out << (first ? "" : ", ") << "weak"; + first = false; + } + if (PDecl->getPropertyAttributes() + & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) { + Out << (first ? "" : ", ") << "unsafe_unretained"; first = false; } if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_nonatomic) { - Out << (first ? ' ' : ',') << "nonatomic"; + ObjCPropertyDecl::OBJC_PR_readwrite) { + Out << (first ? "" : ", ") << "readwrite"; first = false; } if (PDecl->getPropertyAttributes() & - ObjCPropertyDecl::OBJC_PR_atomic) { - Out << (first ? ' ' : ',') << "atomic"; + ObjCPropertyDecl::OBJC_PR_readonly) { + Out << (first ? "" : ", ") << "readonly"; + first = false; + } + + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) { + Out << (first ? "" : ", ") << "getter = "; + PDecl->getGetterName().print(Out); + first = false; + } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) { + Out << (first ? "" : ", ") << "setter = "; + PDecl->getSetterName().print(Out); first = false; } @@ -1461,25 +1507,24 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { if (*nullability == NullabilityKind::Unspecified && (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_null_resettable)) { - Out << (first ? ' ' : ',') << "null_resettable"; + Out << (first ? "" : ", ") << "null_resettable"; } else { - Out << (first ? ' ' : ',') + Out << (first ? "" : ", ") << getNullabilitySpelling(*nullability, true); } first = false; } } - if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_class) { - Out << (first ? ' ' : ',') << "class"; - first = false; - } - (void) first; // Silence dead store warning due to idiomatic code. - Out << " )"; + Out << ")"; } - Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(T). - getAsString(Policy) << ' ' << *PDecl; + std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T). + getAsString(Policy); + Out << ' ' << TypeStr; + if (!StringRef(TypeStr).endswith("*")) + Out << ' '; + Out << *PDecl; if (Policy.PolishForDeclaration) Out << ';'; } @@ -1546,6 +1591,26 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { } } +void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { + Out << "#pragma omp allocate"; + if (!D->varlist_empty()) { + for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(), + E = D->varlist_end(); + I != E; ++I) { + Out << (I == D->varlist_begin() ? '(' : ','); + NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl(); + ND->printQualifiedName(Out); + } + Out << ")"; + } + if (!D->clauselist_empty()) { + Out << " "; + OMPClausePrinter Printer(Out, Policy); + for (OMPClause *C : D->clauselists()) + Printer.Visit(C); + } +} + void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { Out << "#pragma omp requires "; if (!D->clauselist_empty()) { @@ -1598,6 +1663,25 @@ void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { } } +void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { + if (!D->isInvalidDecl()) { + Out << "#pragma omp declare mapper ("; + D->printName(Out); + Out << " : "; + D->getType().print(Out, Policy); + Out << " "; + Out << D->getVarName(); + Out << ")"; + if (!D->clauselist_empty()) { + OMPClausePrinter Printer(Out, Policy); + for (auto *C : D->clauselists()) { + Out << " "; + Printer.Visit(C); + } + } + } +} + void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { D->getInit()->printPretty(Out, nullptr, Policy, Indentation); } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 76f29dac16..3c4cf72f7f 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -1,9 +1,8 @@ //===- DeclTemplate.cpp - Template Declaration AST Node Implementation ----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -688,22 +687,20 @@ TemplateArgumentList::CreateCopy(ASTContext &Context, return new (Mem) TemplateArgumentList(Args); } -FunctionTemplateSpecializationInfo * -FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, - FunctionTemplateDecl *Template, - TemplateSpecializationKind TSK, - const TemplateArgumentList *TemplateArgs, - const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation POI) { +FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create( + ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, + MemberSpecializationInfo *MSInfo) { const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; if (TemplateArgsAsWritten) ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C, *TemplateArgsAsWritten); - return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK, - TemplateArgs, - ArgsAsWritten, - POI); + void *Mem = + C.Allocate(totalSizeToAlloc<MemberSpecializationInfo *>(MSInfo ? 1 : 0)); + return new (Mem) FunctionTemplateSpecializationInfo( + FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo); } //===----------------------------------------------------------------------===// @@ -936,7 +933,7 @@ ClassScopeFunctionSpecializationDecl * ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) ClassScopeFunctionSpecializationDecl( - nullptr, SourceLocation(), nullptr, false, TemplateArgumentListInfo()); + nullptr, SourceLocation(), nullptr, nullptr); } //===----------------------------------------------------------------------===// @@ -957,6 +954,7 @@ VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, VarDecl *Decl) { + AdoptTemplateParameterList(Params, DC); return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl); } diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index f2c152f918..273a1fec09 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -1,9 +1,8 @@ //===- DeclarationName.cpp - Declaration names implementation -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 7cdd3b2c2a..cf488850d3 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1,9 +1,8 @@ //===--- Expr.cpp - Expression AST Node Implementation --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -1359,6 +1358,8 @@ Decl *Expr::getReferencedDeclOfCallee() { return DRE->getDecl(); if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE)) return ME->getMemberDecl(); + if (auto *BE = dyn_cast<BlockExpr>(CEE)) + return BE->getBlockDecl(); return nullptr; } @@ -1677,7 +1678,7 @@ bool CastExpr::CastConsistency() const { auto Ty = getType(); auto SETy = getSubExpr()->getType(); assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); - if (isRValue()) { + if (/*isRValue()*/ !Ty->getPointeeType().isNull()) { Ty = Ty->getPointeeType(); SETy = SETy->getPointeeType(); } @@ -1717,6 +1718,8 @@ bool CastExpr::CastConsistency() const { case CK_ZeroToOCLOpaqueType: case CK_IntToOCLSampler: case CK_FixedPointCast: + case CK_FixedPointToIntegral: + case CK_IntegralToFixedPoint: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; @@ -2557,205 +2560,197 @@ QualType Expr::findBoundMemberType(const Expr *expr) { return QualType(); } -Expr* Expr::IgnoreParens() { - Expr* E = this; - while (true) { - if (ParenExpr* P = dyn_cast<ParenExpr>(E)) { - E = P->getSubExpr(); - continue; - } - if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) { - if (P->getOpcode() == UO_Extension) { - E = P->getSubExpr(); - continue; - } - } - if (GenericSelectionExpr* P = dyn_cast<GenericSelectionExpr>(E)) { - if (!P->isResultDependent()) { - E = P->getResultExpr(); - continue; - } - } - if (ChooseExpr* P = dyn_cast<ChooseExpr>(E)) { - if (!P->isConditionDependent()) { - E = P->getChosenSubExpr(); - continue; - } - } - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) { - E = CE->getSubExpr(); - continue; - } - return E; - } +static Expr *IgnoreImpCastsSingleStep(Expr *E) { + if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) + return ICE->getSubExpr(); + + if (auto *FE = dyn_cast<FullExpr>(E)) + return FE->getSubExpr(); + + return E; } -/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr -/// or CastExprs or ImplicitCastExprs, returning their operand. -Expr *Expr::IgnoreParenCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast<CastExpr>(E)) { - E = P->getSubExpr(); - continue; - } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { - E = NTTP->getReplacement(); - continue; - } - if (FullExpr *FE = dyn_cast<FullExpr>(E)) { - E = FE->getSubExpr(); - continue; - } - return E; - } +static Expr *IgnoreImpCastsExtraSingleStep(Expr *E) { + // FIXME: Skip MaterializeTemporaryExpr and SubstNonTypeTemplateParmExpr in + // addition to what IgnoreImpCasts() skips to account for the current + // behaviour of IgnoreParenImpCasts(). + Expr *SubE = IgnoreImpCastsSingleStep(E); + if (SubE != E) + return SubE; + + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) + return MTE->GetTemporaryExpr(); + + if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) + return NTTP->getReplacement(); + + return E; } -Expr *Expr::IgnoreCasts() { - Expr *E = this; - while (true) { - if (CastExpr *P = dyn_cast<CastExpr>(E)) { - E = P->getSubExpr(); - continue; - } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { - E = NTTP->getReplacement(); - continue; - } - if (FullExpr *FE = dyn_cast<FullExpr>(E)) { - E = FE->getSubExpr(); - continue; - } - return E; +static Expr *IgnoreCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast<CastExpr>(E)) + return CE->getSubExpr(); + + if (auto *FE = dyn_cast<FullExpr>(E)) + return FE->getSubExpr(); + + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) + return MTE->GetTemporaryExpr(); + + if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) + return NTTP->getReplacement(); + + return E; +} + +static Expr *IgnoreLValueCastsSingleStep(Expr *E) { + // Skip what IgnoreCastsSingleStep skips, except that only + // lvalue-to-rvalue casts are skipped. + if (auto *CE = dyn_cast<CastExpr>(E)) + if (CE->getCastKind() != CK_LValueToRValue) + return E; + + return IgnoreCastsSingleStep(E); +} + +static Expr *IgnoreBaseCastsSingleStep(Expr *E) { + if (auto *CE = dyn_cast<CastExpr>(E)) + if (CE->getCastKind() == CK_DerivedToBase || + CE->getCastKind() == CK_UncheckedDerivedToBase || + CE->getCastKind() == CK_NoOp) + return CE->getSubExpr(); + + return E; +} + +static Expr *IgnoreImplicitSingleStep(Expr *E) { + Expr *SubE = IgnoreImpCastsSingleStep(E); + if (SubE != E) + return SubE; + + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) + return MTE->GetTemporaryExpr(); + + if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E)) + return BTE->getSubExpr(); + + return E; +} + +static Expr *IgnoreParensSingleStep(Expr *E) { + if (auto *PE = dyn_cast<ParenExpr>(E)) + return PE->getSubExpr(); + + if (auto *UO = dyn_cast<UnaryOperator>(E)) { + if (UO->getOpcode() == UO_Extension) + return UO->getSubExpr(); + } + + else if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) { + if (!GSE->isResultDependent()) + return GSE->getResultExpr(); + } + + else if (auto *CE = dyn_cast<ChooseExpr>(E)) { + if (!CE->isConditionDependent()) + return CE->getChosenSubExpr(); } + + else if (auto *CE = dyn_cast<ConstantExpr>(E)) + return CE->getSubExpr(); + + return E; } -/// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue -/// casts. This is intended purely as a temporary workaround for code -/// that hasn't yet been rewritten to do the right thing about those -/// casts, and may disappear along with the last internal use. -Expr *Expr::IgnoreParenLValueCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (CastExpr *P = dyn_cast<CastExpr>(E)) { - if (P->getCastKind() == CK_LValueToRValue) { - E = P->getSubExpr(); - continue; - } - } else if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } else if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { - E = NTTP->getReplacement(); - continue; - } else if (FullExpr *FE = dyn_cast<FullExpr>(E)) { - E = FE->getSubExpr(); - continue; - } - break; +static Expr *IgnoreNoopCastsSingleStep(const ASTContext &Ctx, Expr *E) { + if (auto *CE = dyn_cast<CastExpr>(E)) { + // We ignore integer <-> casts that are of the same width, ptr<->ptr and + // ptr<->int casts of the same width. We also ignore all identity casts. + Expr *SubExpr = CE->getSubExpr(); + bool IsIdentityCast = + Ctx.hasSameUnqualifiedType(E->getType(), SubExpr->getType()); + bool IsSameWidthCast = + (E->getType()->isPointerType() || E->getType()->isIntegralType(Ctx)) && + (SubExpr->getType()->isPointerType() || + SubExpr->getType()->isIntegralType(Ctx)) && + (Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SubExpr->getType())); + + if (IsIdentityCast || IsSameWidthCast) + return SubExpr; } + + else if (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) + return NTTP->getReplacement(); + return E; } -Expr *Expr::ignoreParenBaseCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (CastExpr *CE = dyn_cast<CastExpr>(E)) { - if (CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase || - CE->getCastKind() == CK_NoOp) { - E = CE->getSubExpr(); - continue; - } - } +static Expr *IgnoreExprNodesImpl(Expr *E) { return E; } +template <typename FnTy, typename... FnTys> +static Expr *IgnoreExprNodesImpl(Expr *E, FnTy &&Fn, FnTys &&... Fns) { + return IgnoreExprNodesImpl(Fn(E), std::forward<FnTys>(Fns)...); +} - return E; +/// Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, +/// Recursively apply each of the functions to E until reaching a fixed point. +/// Note that a null E is valid; in this case nothing is done. +template <typename... FnTys> +static Expr *IgnoreExprNodes(Expr *E, FnTys &&... Fns) { + Expr *LastE = nullptr; + while (E != LastE) { + LastE = E; + E = IgnoreExprNodesImpl(E, std::forward<FnTys>(Fns)...); } + return E; +} + +Expr *Expr::IgnoreImpCasts() { + return IgnoreExprNodes(this, IgnoreImpCastsSingleStep); +} + +Expr *Expr::IgnoreCasts() { + return IgnoreExprNodes(this, IgnoreCastsSingleStep); +} + +Expr *Expr::IgnoreImplicit() { + return IgnoreExprNodes(this, IgnoreImplicitSingleStep); +} + +Expr *Expr::IgnoreParens() { + return IgnoreExprNodes(this, IgnoreParensSingleStep); } Expr *Expr::IgnoreParenImpCasts() { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) { - E = P->getSubExpr(); - continue; - } - if (MaterializeTemporaryExpr *Materialize - = dyn_cast<MaterializeTemporaryExpr>(E)) { - E = Materialize->GetTemporaryExpr(); - continue; - } - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { - E = NTTP->getReplacement(); - continue; - } - return E; - } + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreImpCastsExtraSingleStep); +} + +Expr *Expr::IgnoreParenCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, IgnoreCastsSingleStep); } Expr *Expr::IgnoreConversionOperator() { - if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(this)) { + if (auto *MCE = dyn_cast<CXXMemberCallExpr>(this)) { if (MCE->getMethodDecl() && isa<CXXConversionDecl>(MCE->getMethodDecl())) return MCE->getImplicitObjectArgument(); } return this; } -/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the -/// value (including ptr->int casts of the same size). Strip off any -/// ParenExpr or CastExprs, returning their operand. -Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { - Expr *E = this; - while (true) { - E = E->IgnoreParens(); - - if (CastExpr *P = dyn_cast<CastExpr>(E)) { - // We ignore integer <-> casts that are of the same width, ptr<->ptr and - // ptr<->int casts of the same width. We also ignore all identity casts. - Expr *SE = P->getSubExpr(); - - if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) { - E = SE; - continue; - } - - if ((E->getType()->isPointerType() || - E->getType()->isIntegralType(Ctx)) && - (SE->getType()->isPointerType() || - SE->getType()->isIntegralType(Ctx)) && - Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) { - E = SE; - continue; - } - } +Expr *Expr::IgnoreParenLValueCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreLValueCastsSingleStep); +} - if (SubstNonTypeTemplateParmExpr *NTTP - = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { - E = NTTP->getReplacement(); - continue; - } +Expr *Expr::ignoreParenBaseCasts() { + return IgnoreExprNodes(this, IgnoreParensSingleStep, + IgnoreBaseCastsSingleStep); +} - return E; - } +Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) { + return IgnoreExprNodes(this, IgnoreParensSingleStep, [&Ctx](Expr *E) { + return IgnoreNoopCastsSingleStep(Ctx, E); + }); } bool Expr::isDefaultArgument() const { @@ -3775,55 +3770,95 @@ void ShuffleVectorExpr::setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs) { memcpy(SubExprs, Exprs.data(), sizeof(Expr *) * Exprs.size()); } -GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef<TypeSourceInfo*> AssocTypes, - ArrayRef<Expr*> AssocExprs, - SourceLocation DefaultLoc, - SourceLocation RParenLoc, - bool ContainsUnexpandedParameterPack, - unsigned ResultIndex) - : Expr(GenericSelectionExprClass, - AssocExprs[ResultIndex]->getType(), - AssocExprs[ResultIndex]->getValueKind(), - AssocExprs[ResultIndex]->getObjectKind(), - AssocExprs[ResultIndex]->isTypeDependent(), - AssocExprs[ResultIndex]->isValueDependent(), - AssocExprs[ResultIndex]->isInstantiationDependent(), - ContainsUnexpandedParameterPack), - AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]), - SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]), - NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), - GenericLoc(GenericLoc), DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { - SubExprs[CONTROLLING] = ControllingExpr; - assert(AssocTypes.size() == AssocExprs.size()); - std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes); - std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); -} - -GenericSelectionExpr::GenericSelectionExpr(const ASTContext &Context, - SourceLocation GenericLoc, Expr *ControllingExpr, - ArrayRef<TypeSourceInfo*> AssocTypes, - ArrayRef<Expr*> AssocExprs, - SourceLocation DefaultLoc, - SourceLocation RParenLoc, - bool ContainsUnexpandedParameterPack) - : Expr(GenericSelectionExprClass, - Context.DependentTy, - VK_RValue, - OK_Ordinary, - /*isTypeDependent=*/true, - /*isValueDependent=*/true, - /*isInstantiationDependent=*/true, - ContainsUnexpandedParameterPack), - AssocTypes(new (Context) TypeSourceInfo*[AssocTypes.size()]), - SubExprs(new (Context) Stmt*[END_EXPR+AssocExprs.size()]), - NumAssocs(AssocExprs.size()), ResultIndex(-1U), GenericLoc(GenericLoc), - DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { - SubExprs[CONTROLLING] = ControllingExpr; - assert(AssocTypes.size() == AssocExprs.size()); - std::copy(AssocTypes.begin(), AssocTypes.end(), this->AssocTypes); - std::copy(AssocExprs.begin(), AssocExprs.end(), SubExprs+END_EXPR); +GenericSelectionExpr::GenericSelectionExpr( + const ASTContext &, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef<TypeSourceInfo *> AssocTypes, ArrayRef<Expr *> AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, unsigned ResultIndex) + : Expr(GenericSelectionExprClass, AssocExprs[ResultIndex]->getType(), + AssocExprs[ResultIndex]->getValueKind(), + AssocExprs[ResultIndex]->getObjectKind(), + AssocExprs[ResultIndex]->isTypeDependent(), + AssocExprs[ResultIndex]->isValueDependent(), + AssocExprs[ResultIndex]->isInstantiationDependent(), + ContainsUnexpandedParameterPack), + NumAssocs(AssocExprs.size()), ResultIndex(ResultIndex), + DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + assert(AssocTypes.size() == AssocExprs.size() && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + assert(ResultIndex < NumAssocs && "ResultIndex is out-of-bounds!"); + + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects<Stmt *>()[ControllingIndex] = ControllingExpr; + std::copy(AssocExprs.begin(), AssocExprs.end(), + getTrailingObjects<Stmt *>() + AssocExprStartIndex); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects<TypeSourceInfo *>()); +} + +GenericSelectionExpr::GenericSelectionExpr( + const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef<TypeSourceInfo *> AssocTypes, ArrayRef<Expr *> AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack) + : Expr(GenericSelectionExprClass, Context.DependentTy, VK_RValue, + OK_Ordinary, + /*isTypeDependent=*/true, + /*isValueDependent=*/true, + /*isInstantiationDependent=*/true, ContainsUnexpandedParameterPack), + NumAssocs(AssocExprs.size()), ResultIndex(ResultDependentIndex), + DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) { + assert(AssocTypes.size() == AssocExprs.size() && + "Must have the same number of association expressions" + " and TypeSourceInfo!"); + + GenericSelectionExprBits.GenericLoc = GenericLoc; + getTrailingObjects<Stmt *>()[ControllingIndex] = ControllingExpr; + std::copy(AssocExprs.begin(), AssocExprs.end(), + getTrailingObjects<Stmt *>() + AssocExprStartIndex); + std::copy(AssocTypes.begin(), AssocTypes.end(), + getTrailingObjects<TypeSourceInfo *>()); +} + +GenericSelectionExpr::GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs) + : Expr(GenericSelectionExprClass, Empty), NumAssocs(NumAssocs) {} + +GenericSelectionExpr *GenericSelectionExpr::Create( + const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef<TypeSourceInfo *> AssocTypes, ArrayRef<Expr *> AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, unsigned ResultIndex) { + unsigned NumAssocs = AssocExprs.size(); + void *Mem = Context.Allocate( + totalSizeToAlloc<Stmt *, TypeSourceInfo *>(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr( + Context, GenericLoc, ControllingExpr, AssocTypes, AssocExprs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack, ResultIndex); +} + +GenericSelectionExpr *GenericSelectionExpr::Create( + const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, + ArrayRef<TypeSourceInfo *> AssocTypes, ArrayRef<Expr *> AssocExprs, + SourceLocation DefaultLoc, SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack) { + unsigned NumAssocs = AssocExprs.size(); + void *Mem = Context.Allocate( + totalSizeToAlloc<Stmt *, TypeSourceInfo *>(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr( + Context, GenericLoc, ControllingExpr, AssocTypes, AssocExprs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack); +} + +GenericSelectionExpr * +GenericSelectionExpr::CreateEmpty(const ASTContext &Context, + unsigned NumAssocs) { + void *Mem = Context.Allocate( + totalSizeToAlloc<Stmt *, TypeSourceInfo *>(1 + NumAssocs, NumAssocs), + alignof(GenericSelectionExpr)); + return new (Mem) GenericSelectionExpr(EmptyShell(), NumAssocs); } //===----------------------------------------------------------------------===// diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 3891f45c7f..bbf7e044aa 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -1,9 +1,8 @@ //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -98,7 +97,8 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens, - Expr *ArraySize, InitializationStyle InitializationStyle, + Optional<Expr *> ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange DirectInitRange) @@ -113,7 +113,7 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, "Only NoInit can have no initializer!"); CXXNewExprBits.IsGlobalNew = IsGlobalNew; - CXXNewExprBits.IsArray = ArraySize != nullptr; + CXXNewExprBits.IsArray = ArraySize.hasValue(); CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment; CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; CXXNewExprBits.StoredInitializationStyle = @@ -123,12 +123,14 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, CXXNewExprBits.NumPlacementArgs = PlacementArgs.size(); if (ArraySize) { - if (ArraySize->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (ArraySize->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; + if (Expr *SizeExpr = *ArraySize) { + if (SizeExpr->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (SizeExpr->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + } - getTrailingObjects<Stmt *>()[arraySizeOffset()] = ArraySize; + getTrailingObjects<Stmt *>()[arraySizeOffset()] = *ArraySize; } if (Initializer) { @@ -180,11 +182,11 @@ CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, SourceRange TypeIdParens, - Expr *ArraySize, InitializationStyle InitializationStyle, - Expr *Initializer, QualType Ty, - TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, - SourceRange DirectInitRange) { - bool IsArray = ArraySize != nullptr; + Optional<Expr *> ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, + SourceRange Range, SourceRange DirectInitRange) { + bool IsArray = ArraySize.hasValue(); bool HasInit = Initializer != nullptr; unsigned NumPlacementArgs = PlacementArgs.size(); bool IsParenTypeId = TypeIdParens.isValid(); @@ -1205,7 +1207,11 @@ CXXMethodDecl *LambdaExpr::getCallOperator() const { TemplateParameterList *LambdaExpr::getTemplateParameterList() const { CXXRecordDecl *Record = getLambdaClass(); return Record->getGenericLambdaTemplateParameterList(); +} +ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const { + const CXXRecordDecl *Record = getLambdaClass(); + return Record->getLambdaExplicitTemplateParameters(); } CompoundStmt *LambdaExpr::getBody() const { diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index e1d6a1c9ed..560f556023 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -1,9 +1,8 @@ //===- ExprClassification.cpp - Expression AST Node Implementation --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index da093ff22c..11e753c077 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1,9 +1,8 @@ //===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -44,6 +43,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/FixedPoint.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" @@ -613,6 +613,15 @@ namespace { } return *this; } + + OptionalDiagnostic &operator<<(const APFixedPoint &FX) { + if (Diag) { + SmallVector<char, 32> Buffer; + FX.toString(Buffer); + *Diag << StringRef(Buffer.data(), Buffer.size()); + } + return *this; + } }; /// A cleanup, and a flag indicating whether it is lifetime-extended. @@ -707,6 +716,10 @@ namespace { EvaluatingObject(Decl, {CallIndex, Version})); } + /// If we're currently speculatively evaluating, the outermost call stack + /// depth at which we can mutate state, otherwise 0. + unsigned SpeculativeEvaluationDepth = 0; + /// The current array initialization index, if we're performing array /// initialization. uint64_t ArrayInitIndex = -1; @@ -719,9 +732,6 @@ namespace { /// fold (not just why it's not strictly a constant expression)? bool HasFoldFailureDiagnostic; - /// Whether or not we're currently speculatively evaluating. - bool IsSpeculativelyEvaluating; - /// Whether or not we're in a context where the front end requires a /// constant value. bool InConstantContext; @@ -786,7 +796,7 @@ namespace { BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), - HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), + HasFoldFailureDiagnostic(false), InConstantContext(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { @@ -814,14 +824,20 @@ namespace { return false; } - CallStackFrame *getCallFrame(unsigned CallIndex) { - assert(CallIndex && "no call index in getCallFrame"); + std::pair<CallStackFrame *, unsigned> + getCallFrameAndDepth(unsigned CallIndex) { + assert(CallIndex && "no call index in getCallFrameAndDepth"); // We will eventually hit BottomFrame, which has Index 1, so Frame can't // be null in this loop. + unsigned Depth = CallStackDepth; CallStackFrame *Frame = CurrentCall; - while (Frame->Index > CallIndex) + while (Frame->Index > CallIndex) { Frame = Frame->Caller; - return (Frame->Index == CallIndex) ? Frame : nullptr; + --Depth; + } + if (Frame->Index == CallIndex) + return {Frame, Depth}; + return {nullptr, 0}; } bool nextStep(const Stmt *S) { @@ -1102,12 +1118,12 @@ namespace { class SpeculativeEvaluationRAII { EvalInfo *Info = nullptr; Expr::EvalStatus OldStatus; - bool OldIsSpeculativelyEvaluating; + unsigned OldSpeculativeEvaluationDepth; void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { Info = Other.Info; OldStatus = Other.OldStatus; - OldIsSpeculativelyEvaluating = Other.OldIsSpeculativelyEvaluating; + OldSpeculativeEvaluationDepth = Other.OldSpeculativeEvaluationDepth; Other.Info = nullptr; } @@ -1116,7 +1132,7 @@ namespace { return; Info->EvalStatus = OldStatus; - Info->IsSpeculativelyEvaluating = OldIsSpeculativelyEvaluating; + Info->SpeculativeEvaluationDepth = OldSpeculativeEvaluationDepth; } public: @@ -1125,9 +1141,9 @@ namespace { SpeculativeEvaluationRAII( EvalInfo &Info, SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr) : Info(&Info), OldStatus(Info.EvalStatus), - OldIsSpeculativelyEvaluating(Info.IsSpeculativelyEvaluating) { + OldSpeculativeEvaluationDepth(Info.SpeculativeEvaluationDepth) { Info.EvalStatus.Diag = NewDiag; - Info.IsSpeculativelyEvaluating = true; + Info.SpeculativeEvaluationDepth = Info.CallStackDepth + 1; } SpeculativeEvaluationRAII(const SpeculativeEvaluationRAII &Other) = delete; @@ -1613,6 +1629,14 @@ static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result, EvalInfo &Info); static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); +/// Evaluate an integer or fixed point expression into an APResult. +static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result, + EvalInfo &Info); + +/// Evaluate only a fixed point expression into an APResult. +static bool EvaluateFixedPoint(const Expr *E, APFixedPoint &Result, + EvalInfo &Info); + //===----------------------------------------------------------------------===// // Misc utilities //===----------------------------------------------------------------------===// @@ -1726,6 +1750,8 @@ static bool IsGlobalLValue(APValue::LValueBase B) { case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: return true; + case Expr::ObjCBoxedExprClass: + return cast<ObjCBoxedExpr>(E)->isExpressibleAsConstantInitializer(); case Expr::CallExprClass: return IsStringLiteralCall(cast<CallExpr>(E)); // For GCC compatibility, &&label has static storage duration. @@ -2027,6 +2053,9 @@ static bool HandleConversionToBool(const APValue &Val, bool &Result) { case APValue::Int: Result = Val.getInt().getBoolValue(); return true; + case APValue::FixedPoint: + Result = Val.getFixedPoint().getBoolValue(); + return true; case APValue::Float: Result = !Val.getFloat().isZero(); return true; @@ -2668,9 +2697,11 @@ static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, } // Expand a string literal into an array of characters. -static void expandStringLiteral(EvalInfo &Info, const Expr *Lit, +// +// FIXME: This is inefficient; we should probably introduce something similar +// to the LLVM ConstantDataArray to make this cheaper. +static void expandStringLiteral(EvalInfo &Info, const StringLiteral *S, APValue &Result) { - const StringLiteral *S = cast<StringLiteral>(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); assert(CAT && "string literal isn't an array"); @@ -2864,18 +2895,6 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, ObjType = CAT->getElementType(); - // An array object is represented as either an Array APValue or as an - // LValue which refers to a string literal. - if (O->isLValue()) { - assert(I == N - 1 && "extracting subobject of character?"); - assert(!O->hasLValuePath() || O->getLValuePath().empty()); - if (handler.AccessKind != AK_Read) - expandStringLiteral(Info, O->getLValueBase().get<const Expr *>(), - *O); - else - return handler.foundString(*O, ObjType, Index); - } - if (O->getArrayInitializedElts() > Index) O = &O->getArrayInitializedElt(Index); else if (handler.AccessKind != AK_Read) { @@ -2988,11 +3007,6 @@ struct ExtractSubobjectHandler { Result = APValue(Value); return true; } - bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { - Result = APValue(extractStringLiteralCharacter( - Info, Subobj.getLValueBase().get<const Expr *>(), Character)); - return true; - } }; } // end anonymous namespace @@ -3050,9 +3064,6 @@ struct ModifySubobjectHandler { Value = NewVal.getFloat(); return true; } - bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { - llvm_unreachable("shouldn't encounter string elements with ExpandArrays"); - } }; } // end anonymous namespace @@ -3134,8 +3145,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } CallStackFrame *Frame = nullptr; + unsigned Depth = 0; if (LVal.getLValueCallIndex()) { - Frame = Info.getCallFrame(LVal.getLValueCallIndex()); + std::tie(Frame, Depth) = + Info.getCallFrameAndDepth(LVal.getLValueCallIndex()); if (!Frame) { Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1) << AK << LVal.Base.is<const ValueDecl*>(); @@ -3326,7 +3339,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, // to be read here (but take care with 'mutable' fields). if ((Frame && Info.getLangOpts().CPlusPlus14 && Info.EvalStatus.HasSideEffects) || - (AK != AK_Read && Info.IsSpeculativelyEvaluating)) + (AK != AK_Read && Depth < Info.SpeculativeEvaluationDepth)) return CompleteObject(); return CompleteObject(BaseVal, BaseType, LifetimeStartedInEvaluation); @@ -3366,12 +3379,27 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, CompleteObject LitObj(&Lit, Base->getType(), false); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); } else if (isa<StringLiteral>(Base) || isa<PredefinedExpr>(Base)) { - // We represent a string literal array as an lvalue pointing at the - // corresponding expression, rather than building an array of chars. - // FIXME: Support ObjCEncodeExpr, MakeStringConstant - APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); - CompleteObject StrObj(&Str, Base->getType(), false); - return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal); + // Special-case character extraction so we don't have to construct an + // APValue for the whole string. + assert(LVal.Designator.Entries.size() <= 1 && + "Can only read characters from string literals"); + if (LVal.Designator.Entries.empty()) { + // Fail for now for LValue to RValue conversion of an array. + // (This shouldn't show up in C/C++, but it could be triggered by a + // weird EvaluateAsRValue call from a tool.) + Info.FFDiag(Conv); + return false; + } + if (LVal.Designator.isOnePastTheEnd()) { + if (Info.getLangOpts().CPlusPlus11) + Info.FFDiag(Conv, diag::note_constexpr_access_past_end) << AK_Read; + else + Info.FFDiag(Conv); + return false; + } + uint64_t CharIndex = LVal.Designator.Entries[0].ArrayIndex; + RVal = APValue(extractStringLiteralCharacter(Info, Base, CharIndex)); + return true; } } @@ -3497,9 +3525,6 @@ struct CompoundAssignSubobjectHandler { LVal.moveInto(Subobj); return true; } - bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { - llvm_unreachable("shouldn't encounter string elements here"); - } }; } // end anonymous namespace @@ -3648,9 +3673,6 @@ struct IncDecSubobjectHandler { LVal.moveInto(Subobj); return true; } - bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { - llvm_unreachable("shouldn't encounter string elements here"); - } }; } // end anonymous namespace @@ -5783,6 +5805,8 @@ public: bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { + if (E->isExpressibleAsConstantInitializer()) + return Success(E); if (Info.noteFailure()) EvaluateIgnoredValue(Info, E->getSubExpr()); return Error(E); @@ -7130,8 +7154,7 @@ namespace { : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} bool Success(const APValue &V, const Expr *E) { - assert((V.isArray() || V.isLValue()) && - "expected array or string literal"); + assert(V.isArray() && "expected array"); Result = V; return true; } @@ -7162,6 +7185,10 @@ namespace { bool VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, APValue *Value, QualType Type); + bool VisitStringLiteral(const StringLiteral *E) { + expandStringLiteral(Info, E, Result); + return true; + } }; } // end anonymous namespace @@ -7194,14 +7221,8 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...] // an appropriately-typed string literal enclosed in braces. - if (E->isStringLiteralInit()) { - LValue LV; - if (!EvaluateLValue(E->getInit(0), LV, Info)) - return false; - APValue Val; - LV.moveInto(Val); - return Success(Val, E); - } + if (E->isStringLiteralInit()) + return Visit(E->getInit(0)); bool Success = true; @@ -7490,53 +7511,27 @@ class FixedPointExprEvaluator FixedPointExprEvaluator(EvalInfo &info, APValue &result) : ExprEvaluatorBaseTy(info), Result(result) {} - bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { - assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); - assert(SI.isSigned() == E->getType()->isSignedFixedPointType() && - "Invalid evaluation result."); - assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && - "Invalid evaluation result."); - Result = APValue(SI); - return true; - } - bool Success(const llvm::APSInt &SI, const Expr *E) { - return Success(SI, E, Result); - } - - bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { - assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); - assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && - "Invalid evaluation result."); - Result = APValue(APSInt(I)); - Result.getInt().setIsUnsigned(E->getType()->isUnsignedFixedPointType()); - return true; - } bool Success(const llvm::APInt &I, const Expr *E) { - return Success(I, E, Result); + return Success( + APFixedPoint(I, Info.Ctx.getFixedPointSemantics(E->getType())), E); } - bool Success(uint64_t Value, const Expr *E, APValue &Result) { - assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); - Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); - return true; - } bool Success(uint64_t Value, const Expr *E) { - return Success(Value, E, Result); - } - - bool Success(CharUnits Size, const Expr *E) { - return Success(Size.getQuantity(), E); + return Success( + APFixedPoint(Value, Info.Ctx.getFixedPointSemantics(E->getType())), E); } bool Success(const APValue &V, const Expr *E) { - if (V.isLValue() || V.isAddrLabelDiff()) { - Result = V; - return true; - } - return Success(V.getInt(), E); + return Success(V.getFixedPoint(), E); } - bool ZeroInitialization(const Expr *E) { return Success(0, E); } + bool Success(const APFixedPoint &V, const Expr *E) { + assert(E->getType()->isFixedPointType() && "Invalid evaluation result."); + assert(V.getWidth() == Info.Ctx.getIntWidth(E->getType()) && + "Invalid evaluation result."); + Result = APValue(V); + return true; + } //===--------------------------------------------------------------------===// // Visitor Methods @@ -7546,7 +7541,9 @@ class FixedPointExprEvaluator return Success(E->getValue(), E); } + bool VisitCastExpr(const CastExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); + bool VisitBinaryOperator(const BinaryOperator *E); }; } // end anonymous namespace @@ -7578,6 +7575,36 @@ static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { return true; } +static bool EvaluateFixedPoint(const Expr *E, APFixedPoint &Result, + EvalInfo &Info) { + if (E->getType()->isFixedPointType()) { + APValue Val; + if (!FixedPointExprEvaluator(Info, Val).Visit(E)) + return false; + if (!Val.isFixedPoint()) + return false; + + Result = Val.getFixedPoint(); + return true; + } + return false; +} + +static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result, + EvalInfo &Info) { + if (E->getType()->isIntegerType()) { + auto FXSema = Info.Ctx.getFixedPointSemantics(E->getType()); + APSInt Val; + if (!EvaluateInteger(E, Val, Info)) + return false; + Result = APFixedPoint(Val, FXSema); + return true; + } else if (E->getType()->isFixedPointType()) { + return EvaluateFixedPoint(E, Result, Info); + } + return false; +} + /// Check whether the given declaration can be directly converted to an integral /// rvalue. If not, no diagnostic is produced; there are other things we can /// try. @@ -7783,19 +7810,37 @@ EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) { } /// EvaluateBuiltinConstantPForLValue - Determine the result of -/// __builtin_constant_p when applied to the given lvalue. +/// __builtin_constant_p when applied to the given pointer. /// -/// An lvalue is only "constant" if it is a pointer or reference to the first -/// character of a string literal. -template<typename LValue> -static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) { - const Expr *E = LV.getLValueBase().template dyn_cast<const Expr*>(); - return E && isa<StringLiteral>(E) && LV.getLValueOffset().isZero(); +/// A pointer is only "constant" if it is null (or a pointer cast to integer) +/// or it points to the first character of a string literal. +static bool EvaluateBuiltinConstantPForLValue(const APValue &LV) { + APValue::LValueBase Base = LV.getLValueBase(); + if (Base.isNull()) { + // A null base is acceptable. + return true; + } else if (const Expr *E = Base.dyn_cast<const Expr *>()) { + if (!isa<StringLiteral>(E)) + return false; + return LV.getLValueOffset().isZero(); + } else { + // Any other base is not constant enough for GCC. + return false; + } } /// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to /// GCC as we can manage. -static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { +static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) { + // This evaluation is not permitted to have side-effects, so evaluate it in + // a speculative evaluation context. + SpeculativeEvaluationRAII SpeculativeEval(Info); + + // Constant-folding is always enabled for the operand of __builtin_constant_p + // (even when the enclosing evaluation context otherwise requires a strict + // language-specific constant expression). + FoldConstant Fold(Info, true); + QualType ArgType = Arg->getType(); // __builtin_constant_p always has one operand. The rules which gcc follows @@ -7803,34 +7848,30 @@ static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { // // - If the operand is of integral, floating, complex or enumeration type, // and can be folded to a known value of that type, it returns 1. - // - If the operand and can be folded to a pointer to the first character - // of a string literal (or such a pointer cast to an integral type), it - // returns 1. + // - If the operand can be folded to a pointer to the first character + // of a string literal (or such a pointer cast to an integral type) + // or to a null pointer or an integer cast to a pointer, it returns 1. // // Otherwise, it returns 0. // // FIXME: GCC also intends to return 1 for literals of aggregate types, but - // its support for this does not currently work. - if (ArgType->isIntegralOrEnumerationType()) { - Expr::EvalResult Result; - if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects) + // its support for this did not work prior to GCC 9 and is not yet well + // understood. + if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() || + ArgType->isAnyComplexType() || ArgType->isPointerType() || + ArgType->isNullPtrType()) { + APValue V; + if (!::EvaluateAsRValue(Info, Arg, V)) { + Fold.keepDiagnostics(); return false; + } - APValue &V = Result.Val; - if (V.getKind() == APValue::Int) - return true; + // For a pointer (possibly cast to integer), there are special rules. if (V.getKind() == APValue::LValue) return EvaluateBuiltinConstantPForLValue(V); - } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) { - return Arg->isEvaluatable(Ctx); - } else if (ArgType->isPointerType() || Arg->isGLValue()) { - LValue LV; - Expr::EvalStatus Status; - EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); - if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info) - : EvaluatePointer(Arg, LV, Info)) && - !Status.HasSideEffects) - return EvaluateBuiltinConstantPForLValue(LV); + + // Otherwise, any constant value is good enough. + return V.getKind() != APValue::Uninitialized; } // Anything else isn't considered to be sufficiently constant. @@ -8164,6 +8205,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, default: return ExprEvaluatorBaseTy::VisitCallExpr(E); + case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: { // The type was checked when we built the expression. unsigned Type = @@ -8239,20 +8281,22 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, } case Builtin::BI__builtin_constant_p: { - auto Arg = E->getArg(0); - if (EvaluateBuiltinConstantP(Info.Ctx, Arg)) + const Expr *Arg = E->getArg(0); + if (EvaluateBuiltinConstantP(Info, Arg)) return Success(true, E); - auto ArgTy = Arg->IgnoreImplicit()->getType(); - if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) && - !ArgTy->isAggregateType() && !ArgTy->isPointerType()) { - // We can delay calculation of __builtin_constant_p until after - // inlining. Note: This diagnostic won't be shown to the user. - Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); - return false; + if (Info.InConstantContext || Arg->HasSideEffects(Info.Ctx)) { + // Outside a constant context, eagerly evaluate to false in the presence + // of side-effects in order to avoid -Wunsequenced false-positives in + // a branch on __builtin_constant_p(expr). + return Success(false, E); } - return Success(false, E); + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); + return false; } + case Builtin::BI__builtin_is_constant_evaluated: + return Success(Info.InConstantContext, E); + case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: @@ -8411,6 +8455,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BIstrncmp: case Builtin::BIwcsncmp: case Builtin::BImemcmp: + case Builtin::BIbcmp: case Builtin::BIwmemcmp: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) @@ -8425,6 +8470,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_strncmp: case Builtin::BI__builtin_wcsncmp: case Builtin::BI__builtin_memcmp: + case Builtin::BI__builtin_bcmp: case Builtin::BI__builtin_wmemcmp: { LValue String1, String2; if (!EvaluatePointer(E->getArg(0), String1, Info) || @@ -8455,7 +8501,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, QualType CharTy2 = String2.Designator.getType(Info.Ctx); bool IsRawByte = BuiltinOp == Builtin::BImemcmp || - BuiltinOp == Builtin::BI__builtin_memcmp; + BuiltinOp == Builtin::BIbcmp || + BuiltinOp == Builtin::BI__builtin_memcmp || + BuiltinOp == Builtin::BI__builtin_bcmp; assert(IsRawByte || (Info.Ctx.hasSameUnqualifiedType( @@ -8523,10 +8571,12 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(0, E); } - bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && - BuiltinOp != Builtin::BIwmemcmp && - BuiltinOp != Builtin::BI__builtin_memcmp && - BuiltinOp != Builtin::BI__builtin_wmemcmp); + bool StopAtNull = + (BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIbcmp && + BuiltinOp != Builtin::BIwmemcmp && + BuiltinOp != Builtin::BI__builtin_memcmp && + BuiltinOp != Builtin::BI__builtin_bcmp && + BuiltinOp != Builtin::BI__builtin_wmemcmp); bool IsWide = BuiltinOp == Builtin::BIwcscmp || BuiltinOp == Builtin::BIwcsncmp || BuiltinOp == Builtin::BIwmemcmp || @@ -9123,6 +9173,22 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, return Success(CCR::Equal, E); } + if (LHSTy->isFixedPointType() || RHSTy->isFixedPointType()) { + APFixedPoint LHSFX(Info.Ctx.getFixedPointSemantics(LHSTy)); + APFixedPoint RHSFX(Info.Ctx.getFixedPointSemantics(RHSTy)); + + bool LHSOK = EvaluateFixedPointOrInteger(E->getLHS(), LHSFX, Info); + if (!LHSOK && !Info.noteFailure()) + return false; + if (!EvaluateFixedPointOrInteger(E->getRHS(), RHSFX, Info) || !LHSOK) + return false; + if (LHSFX < RHSFX) + return Success(CCR::Less, E); + if (LHSFX > RHSFX) + return Success(CCR::Greater, E); + return Success(CCR::Equal, E); + } + if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { ComplexValue LHS, RHS; bool LHSOK; @@ -9739,6 +9805,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AddressSpaceConversion: case CK_IntToOCLSampler: case CK_FixedPointCast: + case CK_IntegralToFixedPoint: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -9773,12 +9840,25 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return Success(IntResult, E); } + case CK_FixedPointToIntegral: { + APFixedPoint Src(Info.Ctx.getFixedPointSemantics(SrcType)); + if (!EvaluateFixedPoint(SubExpr, Src, Info)) + return false; + bool Overflowed; + llvm::APSInt Result = Src.convertToInt( + Info.Ctx.getIntWidth(DestType), + DestType->isSignedIntegerOrEnumerationType(), &Overflowed); + if (Overflowed && !HandleOverflow(Info, E, Result, DestType)) + return false; + return Success(Result, E); + } + case CK_FixedPointToBoolean: { // Unsigned padding does not affect this. APValue Val; if (!Evaluate(Val, Info, SubExpr)) return false; - return Success(Val.getInt().getBoolValue(), E); + return Success(Val.getFixedPoint().getBoolValue(), E); } case CK_IntegralCast: { @@ -9821,13 +9901,12 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return true; } - uint64_t V; - if (LV.isNullPointer()) - V = Info.Ctx.getTargetNullPointerValue(SrcType); - else - V = LV.getLValueOffset().getQuantity(); + APSInt AsInt; + APValue V; + LV.moveInto(V); + if (!V.toIntegralConstant(AsInt, SrcType, Info.Ctx)) + llvm_unreachable("Can't cast this!"); - APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } @@ -9898,16 +9977,13 @@ bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { return Visit(E->getSubExpr()); case UO_Minus: { if (!Visit(E->getSubExpr())) return false; - if (!Result.isInt()) return Error(E); - const APSInt &Value = Result.getInt(); - if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) { - SmallString<64> S; - FixedPointValueToString(S, Value, - Info.Ctx.getTypeInfo(E->getType()).Width); - Info.CCEDiag(E, diag::note_constexpr_overflow) << S << E->getType(); - if (Info.noteUndefinedBehavior()) return false; - } - return Success(-Value, E); + if (!Result.isFixedPoint()) + return Error(E); + bool Overflowed; + APFixedPoint Negated = Result.getFixedPoint().negate(&Overflowed); + if (Overflowed && !HandleOverflow(Info, E, Negated, E->getType())) + return false; + return Success(Negated, E); } case UO_LNot: { bool bres; @@ -9918,6 +9994,75 @@ bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } } +bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) { + const Expr *SubExpr = E->getSubExpr(); + QualType DestType = E->getType(); + assert(DestType->isFixedPointType() && + "Expected destination type to be a fixed point type"); + auto DestFXSema = Info.Ctx.getFixedPointSemantics(DestType); + + switch (E->getCastKind()) { + case CK_FixedPointCast: { + APFixedPoint Src(Info.Ctx.getFixedPointSemantics(SubExpr->getType())); + if (!EvaluateFixedPoint(SubExpr, Src, Info)) + return false; + bool Overflowed; + APFixedPoint Result = Src.convert(DestFXSema, &Overflowed); + if (Overflowed && !HandleOverflow(Info, E, Result, DestType)) + return false; + return Success(Result, E); + } + case CK_IntegralToFixedPoint: { + APSInt Src; + if (!EvaluateInteger(SubExpr, Src, Info)) + return false; + + bool Overflowed; + APFixedPoint IntResult = APFixedPoint::getFromIntValue( + Src, Info.Ctx.getFixedPointSemantics(DestType), &Overflowed); + + if (Overflowed && !HandleOverflow(Info, E, IntResult, DestType)) + return false; + + return Success(IntResult, E); + } + case CK_NoOp: + case CK_LValueToRValue: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + default: + return Error(E); + } +} + +bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + FixedPointSemantics ResultFXSema = + Info.Ctx.getFixedPointSemantics(E->getType()); + + APFixedPoint LHSFX(Info.Ctx.getFixedPointSemantics(LHS->getType())); + if (!EvaluateFixedPointOrInteger(LHS, LHSFX, Info)) + return false; + APFixedPoint RHSFX(Info.Ctx.getFixedPointSemantics(RHS->getType())); + if (!EvaluateFixedPointOrInteger(RHS, RHSFX, Info)) + return false; + + switch (E->getOpcode()) { + case BO_Add: { + bool AddOverflow, ConversionOverflow; + APFixedPoint Result = LHSFX.add(RHSFX, &AddOverflow) + .convert(ResultFXSema, &ConversionOverflow); + if ((AddOverflow || ConversionOverflow) && + !HandleOverflow(Info, E, Result, E->getType())) + return false; + return Success(Result, E); + } + default: + return false; + } + llvm_unreachable("Should've exited before this"); +} + //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// @@ -10282,6 +10427,8 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntToOCLSampler: case CK_FixedPointCast: case CK_FixedPointToBoolean: + case CK_FixedPointToIntegral: + case CK_IntegralToFixedPoint: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: @@ -10929,6 +11076,23 @@ static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, return true; } +static bool EvaluateAsFixedPoint(const Expr *E, Expr::EvalResult &ExprResult, + const ASTContext &Ctx, + Expr::SideEffectsKind AllowSideEffects, + EvalInfo &Info) { + if (!E->getType()->isFixedPointType()) + return false; + + if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info)) + return false; + + if (!ExprResult.Val.isFixedPoint() || + hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) + return false; + + return true; +} + /// EvaluateAsRValue - Return true if this is a constant which we can fold using /// any crazy technique (that has nothing to do with language standards) that /// we want to. If this function returns true, it returns the folded constant @@ -10954,6 +11118,12 @@ bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); } +bool Expr::EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects) const { + EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info); +} + bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { if (!getType()->isRealFloatingType()) @@ -10986,6 +11156,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, const ASTContext &Ctx) const { EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; EvalInfo Info(Ctx, Result, EM); + Info.InConstantContext = true; + if (!::Evaluate(Result.Val, Info, this)) return false; @@ -11626,6 +11798,7 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, const Expr *This) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + Info.InConstantContext = true; LValue ThisVal; const LValue *ThisPtr = nullptr; @@ -11709,6 +11882,7 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpressionUnevaluated); + Info.InConstantContext = true; // Fabricate a call stack frame to give the arguments a plausible cover story. ArrayRef<const Expr*> Args; diff --git a/lib/AST/ExprObjC.cpp b/lib/AST/ExprObjC.cpp index e1a23f5985..53d0e873f8 100644 --- a/lib/AST/ExprObjC.cpp +++ b/lib/AST/ExprObjC.cpp @@ -1,9 +1,8 @@ //===- ExprObjC.cpp - (ObjC) Expression AST Node Implementation -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -293,6 +292,32 @@ void ObjCMessageExpr::getSelectorLocs( SelLocs.push_back(getSelectorLoc(i)); } + +QualType ObjCMessageExpr::getCallReturnType(ASTContext &Ctx) const { + if (const ObjCMethodDecl *MD = getMethodDecl()) { + QualType QT = MD->getReturnType(); + if (QT == Ctx.getObjCInstanceType()) { + // instancetype corresponds to expression types. + return getType(); + } + return QT; + } + + // Expression type might be different from an expected call return type, + // as expression type would never be a reference even if call returns a + // reference. Reconstruct the original expression type. + QualType QT = getType(); + switch (getValueKind()) { + case VK_LValue: + return Ctx.getLValueReferenceType(QT); + case VK_XValue: + return Ctx.getRValueReferenceType(QT); + case VK_RValue: + return QT; + } + llvm_unreachable("Unsupported ExprValueKind"); +} + SourceRange ObjCMessageExpr::getReceiverRange() const { switch (getReceiverKind()) { case Instance: @@ -352,6 +377,11 @@ Stmt::child_range ObjCMessageExpr::children() { reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); } +Stmt::const_child_range ObjCMessageExpr::children() const { + auto Children = const_cast<ObjCMessageExpr *>(this)->children(); + return const_child_range(Children.begin(), Children.end()); +} + StringRef ObjCBridgedCastExpr::getBridgeKindName() const { switch (getBridgeKind()) { case OBC_Bridge: diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index 12e6bfc041..0075247bb1 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -1,9 +1,8 @@ //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -57,7 +56,12 @@ LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, } auto *ND = cast<NamedDecl>(DC); DeclarationName Name = ND->getDeclName(); - Source<DeclarationName> SourceName = ReverseImporter.Import(Name); + auto SourceNameOrErr = ReverseImporter.Import_New(Name); + if (!SourceNameOrErr) { + llvm::consumeError(SourceNameOrErr.takeError()); + return nullptr; + } + Source<DeclarationName> SourceName = *SourceNameOrErr; DeclContext::lookup_result SearchResult = SourceParentDC.get()->lookup(SourceName.get()); size_t SearchResultSize = SearchResult.size(); @@ -111,7 +115,7 @@ public: /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin /// map is kept up to date. Also set the appropriate flags. - Decl *Imported(Decl *From, Decl *To) override { + void Imported(Decl *From, Decl *To) override { if (auto *ToDC = dyn_cast<DeclContext>(To)) { const bool LoggingEnabled = Parent.LoggingEnabled(); if (LoggingEnabled) @@ -154,7 +158,6 @@ public: ToContainer->getPrimaryContext()->setMustBuildLookupTable(); assert(Parent.CanComplete(ToContainer)); } - return To; } ASTImporter &GetReverse() { return Reverse; } }; @@ -356,9 +359,13 @@ void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) { template <typename DeclTy> static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { - for (auto *Spec : D->specializations()) - if (!Importer->Import(Spec)) + for (auto *Spec : D->specializations()) { + auto ImportedSpecOrError = Importer->Import_New(Spec); + if (!ImportedSpecOrError) { + llvm::consumeError(ImportedSpecOrError.takeError()); return true; + } + } return false; } @@ -385,15 +392,21 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, Candidates.push_back(C); }; - ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse, - Source<const DeclContext *> SourceDC) -> bool { - DeclarationName FromName = Reverse.Import(Name); - DeclContextLookupResult Result = SourceDC.get()->lookup(FromName); - for (NamedDecl *FromD : Result) { - FilterFoundDecl(std::make_pair(FromD, &Forward)); - } - return false; - }); + ForEachMatchingDC(DC, + [&](ASTImporter &Forward, ASTImporter &Reverse, + Source<const DeclContext *> SourceDC) -> bool { + auto FromNameOrErr = Reverse.Import_New(Name); + if (!FromNameOrErr) { + llvm::consumeError(FromNameOrErr.takeError()); + return false; + } + DeclContextLookupResult Result = + SourceDC.get()->lookup(*FromNameOrErr); + for (NamedDecl *FromD : Result) { + FilterFoundDecl(std::make_pair(FromD, &Forward)); + } + return false; + }); if (Candidates.empty()) return false; @@ -402,7 +415,10 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, for (const Candidate &C : Candidates) { Decl *LookupRes = C.first.get(); ASTImporter *Importer = C.second; - NamedDecl *ND = cast_or_null<NamedDecl>(Importer->Import(LookupRes)); + auto NDOrErr = Importer->Import_New(LookupRes); + assert(NDOrErr); + (void)static_cast<bool>(NDOrErr); + NamedDecl *ND = cast_or_null<NamedDecl>(*NDOrErr); assert(ND); // If we don't import specialization, they are not available via lookup // because the lookup result is imported TemplateDecl and it does not @@ -424,9 +440,12 @@ void ExternalASTMerger::FindExternalLexicalDecls( Source<const DeclContext *> SourceDC) -> bool { for (const Decl *SourceDecl : SourceDC.get()->decls()) { if (IsKindWeWant(SourceDecl->getKind())) { - Decl *ImportedDecl = Forward.Import(const_cast<Decl *>(SourceDecl)); - assert(!ImportedDecl || IsSameDC(ImportedDecl->getDeclContext(), DC)); - (void)ImportedDecl; + auto ImportedDeclOrErr = Forward.Import_New(SourceDecl); + if (ImportedDeclOrErr) + assert(!(*ImportedDeclOrErr) || + IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC)); + else + llvm::consumeError(ImportedDeclOrErr.takeError()); } } return false; diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp index 40829c2e24..7301027574 100644 --- a/lib/AST/ExternalASTSource.cpp +++ b/lib/AST/ExternalASTSource.cpp @@ -1,9 +1,8 @@ //===- ExternalASTSource.cpp - Abstract External AST Interface ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/FormatString.cpp b/lib/AST/FormatString.cpp index 04bd48f14a..578d5bc567 100644 --- a/lib/AST/FormatString.cpp +++ b/lib/AST/FormatString.cpp @@ -1,9 +1,8 @@ // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*- // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -224,6 +223,9 @@ clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, if (I != E && *I == 'h') { ++I; lmKind = LengthModifier::AsChar; + } else if (I != E && *I == 'l' && LO.OpenCL) { + ++I; + lmKind = LengthModifier::AsShortLong; } else { lmKind = LengthModifier::AsShort; } @@ -488,7 +490,8 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { } ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { - if (K != SpecificTy) // Won't be a valid vector element type. + // Check for valid vector element types. + if (T.isNull()) return ArgType::Invalid(); QualType Vec = C.getExtVectorType(T, NumElts); @@ -573,6 +576,8 @@ analyze_format_string::LengthModifier::toString() const { return "hh"; case AsShort: return "h"; + case AsShortLong: + return "hl"; case AsLong: // or AsWideChar return "l"; case AsLongLong: @@ -708,13 +713,18 @@ void OptionalAmount::toString(raw_ostream &os) const { } } -bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { +bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, + const LangOptions &LO) const { switch (LM.getKind()) { case LengthModifier::None: return true; // Handle most integer flags case LengthModifier::AsShort: + // Length modifier only applies to FP vectors. + if (LO.OpenCL && CS.isDoubleArg()) + return !VectorNumElts.isInvalid(); + if (Target.getTriple().isOSMSVCRT()) { switch (CS.getKind()) { case ConversionSpecifier::cArg: @@ -753,8 +763,18 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { return false; } + case LengthModifier::AsShortLong: + return LO.OpenCL && !VectorNumElts.isInvalid(); + // Handle 'l' flag case LengthModifier::AsLong: // or AsWideChar + if (CS.isDoubleArg()) { + // Invalid for OpenCL FP scalars. + if (LO.OpenCL && VectorNumElts.isInvalid()) + return false; + return true; + } + switch (CS.getKind()) { case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: @@ -765,14 +785,6 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { case ConversionSpecifier::UArg: case ConversionSpecifier::xArg: case ConversionSpecifier::XArg: - case ConversionSpecifier::aArg: - case ConversionSpecifier::AArg: - case ConversionSpecifier::fArg: - case ConversionSpecifier::FArg: - case ConversionSpecifier::eArg: - case ConversionSpecifier::EArg: - case ConversionSpecifier::gArg: - case ConversionSpecifier::GArg: case ConversionSpecifier::nArg: case ConversionSpecifier::cArg: case ConversionSpecifier::sArg: @@ -879,6 +891,7 @@ bool FormatSpecifier::hasStandardLengthModifier() const { case LengthModifier::AsInt3264: case LengthModifier::AsInt64: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: // ??? return false; } llvm_unreachable("Invalid LengthModifier Kind!"); diff --git a/lib/AST/InheritViz.cpp b/lib/AST/InheritViz.cpp index 0b82da133f..4b3d5bee56 100644 --- a/lib/AST/InheritViz.cpp +++ b/lib/AST/InheritViz.cpp @@ -1,9 +1,8 @@ //===- InheritViz.cpp - Graphviz visualization for inheritance --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp index 64580edf00..727a905d08 100644 --- a/lib/AST/ItaniumCXXABI.cpp +++ b/lib/AST/ItaniumCXXABI.cpp @@ -1,9 +1,8 @@ //===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 98c843db31..1eb5460dd6 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1,9 +1,8 @@ //===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -61,7 +60,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { } const DeclContext *DC = D->getDeclContext(); - if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC)) { + if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) || + isa<OMPDeclareMapperDecl>(DC)) { return getEffectiveDeclContext(cast<Decl>(DC)); } @@ -486,6 +486,7 @@ private: const AbiTagList *AdditionalAbiTags); void mangleBlockForPrefix(const BlockDecl *Block); void mangleUnqualifiedBlock(const BlockDecl *Block); + void mangleTemplateParamDecl(const NamedDecl *Decl); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, const AbiTagList *AdditionalAbiTags, @@ -1372,7 +1373,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // <unnamed-type-name> ::= <closure-type-name> // // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ - // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'. + // <lambda-sig> ::= <template-param-decl>* <parameter-type>+ + // # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (Record->isLambda() && Record->getLambdaManglingNumber()) { assert(!AdditionalAbiTags && @@ -1503,7 +1505,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) { - Qualifiers MethodQuals = Method->getTypeQualifiers(); + Qualifiers MethodQuals = Method->getMethodQualifiers(); // We do not consider restrict a distinguishing attribute for overloading // purposes so we must not mangle it. MethodQuals.removeRestrict(); @@ -1678,6 +1680,24 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { Out << '_'; } +// <template-param-decl> +// ::= Ty # template type parameter +// ::= Tn <type> # template non-type parameter +// ::= Tt <template-param-decl>* E # template template parameter +void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) { + if (isa<TemplateTypeParmDecl>(Decl)) { + Out << "Ty"; + } else if (auto *Tn = dyn_cast<NonTypeTemplateParmDecl>(Decl)) { + Out << "Tn"; + mangleType(Tn->getType()); + } else if (auto *Tt = dyn_cast<TemplateTemplateParmDecl>(Decl)) { + Out << "Tt"; + for (auto *Param : *Tt->getTemplateParameters()) + mangleTemplateParamDecl(Param); + Out << "E"; + } +} + void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // If the context of a closure type is an initializer for a class member // (static or nonstatic), it is encoded in a qualified name with a final @@ -1705,6 +1725,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { } Out << "Ul"; + for (auto *D : Lambda->getLambdaExplicitTemplateParameters()) + mangleTemplateParamDecl(D); const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()-> getAs<FunctionProtoType>(); mangleBareFunctionType(Proto, /*MangleReturnType=*/false, @@ -2735,7 +2757,7 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { // Mangle CV-qualifiers, if present. These are 'this' qualifiers, // e.g. "const" in "int (A::*)() const". - mangleQualifiers(T->getTypeQuals()); + mangleQualifiers(T->getMethodQuals()); // Mangle instantiation-dependent exception-specification, if present, // per cxx-abi-dev proposal on 2016-10-11. @@ -2833,7 +2855,10 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto, if (auto *Attr = FD->getParamDecl(I)->getAttr<PassObjectSizeAttr>()) { // Attr can only take 1 character, so we can hardcode the length below. assert(Attr->getType() <= 9 && Attr->getType() >= 0); - Out << "U17pass_object_size" << Attr->getType(); + if (Attr->isDynamic()) + Out << "U25pass_dynamic_object_size" << Attr->getType(); + else + Out << "U17pass_object_size" << Attr->getType(); } } } diff --git a/lib/AST/Linkage.h b/lib/AST/Linkage.h index 8ad748bcc4..4e913540de 100644 --- a/lib/AST/Linkage.h +++ b/lib/AST/Linkage.h @@ -1,9 +1,8 @@ //===----- Linkage.h - Linkage calculation-related utilities ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp index bb29bffc1b..03ebf98a7f 100644 --- a/lib/AST/Mangle.cpp +++ b/lib/AST/Mangle.cpp @@ -1,9 +1,8 @@ //===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index 3b417c1352..4dc4156df9 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -1,9 +1,8 @@ //===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 92e9679e49..db18121030 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1,9 +1,8 @@ //===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -97,7 +96,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) { } const DeclContext *DC = D->getDeclContext(); - if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC)) { + if (isa<CapturedDecl>(DC) || isa<OMPDeclareReductionDecl>(DC) || + isa<OMPDeclareMapperDecl>(DC)) { return getEffectiveDeclContext(cast<Decl>(DC)); } @@ -267,7 +267,7 @@ class MicrosoftCXXNameMangler { typedef llvm::DenseMap<const void *, unsigned> ArgBackRefMap; ArgBackRefMap TypeBackReferences; - typedef std::set<int> PassObjectSizeArgsSet; + typedef std::set<std::pair<int, bool>> PassObjectSizeArgsSet; PassObjectSizeArgsSet PassObjectSizeArgs; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -1242,15 +1242,8 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, case OO_Array_Delete: Out << "?_V"; break; // <operator-name> ::= ?__L # co_await case OO_Coawait: Out << "?__L"; break; - - case OO_Spaceship: { - // FIXME: Once MS picks a mangling, use it. - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this three-way comparison operator yet"); - Diags.Report(Loc, DiagID); - break; - } + // <operator-name> ::= ?__M # <=> + case OO_Spaceship: Out << "?__M"; break; case OO_Conditional: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -1268,8 +1261,7 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) { // <source name> ::= <identifier> @ - BackRefVec::iterator Found = - std::find(NameBackReferences.begin(), NameBackReferences.end(), Name); + BackRefVec::iterator Found = llvm::find(NameBackReferences, Name); if (Found == NameBackReferences.end()) { if (NameBackReferences.size() < 10) NameBackReferences.push_back(Name); @@ -1761,14 +1753,16 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, void MicrosoftCXXNameMangler::manglePassObjectSizeArg( const PassObjectSizeAttr *POSA) { int Type = POSA->getType(); + bool Dynamic = POSA->isDynamic(); - auto Iter = PassObjectSizeArgs.insert(Type).first; + auto Iter = PassObjectSizeArgs.insert({Type, Dynamic}).first; auto *TypePtr = (const void *)&*Iter; ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); if (Found == TypeBackReferences.end()) { - mangleArtificialTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type), - {"__clang"}); + std::string Name = + Dynamic ? "__pass_dynamic_object_size" : "__pass_object_size"; + mangleArtificialTagType(TTK_Enum, Name + llvm::utostr(Type), {"__clang"}); if (TypeBackReferences.size() < 10) { size_t Size = TypeBackReferences.size(); @@ -1937,8 +1931,9 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, // ::= _M # unsigned __int128 // ::= _N # bool // _O # <array in parameter> - // ::= _T # __float80 (Intel) + // ::= _Q # char8_t // ::= _S # char16_t + // ::= _T # __float80 (Intel) // ::= _U # char32_t // ::= _W # wchar_t // ::= _Z # __float80 (Digital Mars) @@ -1999,6 +1994,9 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, case BuiltinType::Bool: Out << "_N"; break; + case BuiltinType::Char8: + Out << "_Q"; + break; case BuiltinType::Char16: Out << "_S"; break; @@ -2094,7 +2092,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: - case BuiltinType::Char8: case BuiltinType::Float128: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( @@ -2112,7 +2109,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers, // Structors only appear in decls, so at this point we know it's not a // structor type. // FIXME: This may not be lambda-friendly. - if (T->getTypeQuals() || T->getRefQualifier() != RQ_None) { + if (T->getMethodQuals() || T->getRefQualifier() != RQ_None) { Out << "$$A8@@"; mangleFunctionType(T, /*D=*/nullptr, /*ForceThisQuals=*/true); } else { @@ -2161,7 +2158,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. if (HasThisQuals) { - Qualifiers Quals = Proto->getTypeQuals(); + Qualifiers Quals = Proto->getMethodQuals(); manglePointerExtQualifiers(Quals, /*PointeeType=*/QualType()); mangleRefQualifier(Proto->getRefQualifier()); mangleQualifiers(Quals, /*IsMember=*/false); @@ -3457,8 +3454,7 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, } else { const char SpecialChars[] = {',', '/', '\\', ':', '.', ' ', '\n', '\t', '\'', '-'}; - const char *Pos = - std::find(std::begin(SpecialChars), std::end(SpecialChars), Byte); + const char *Pos = llvm::find(SpecialChars, Byte); if (Pos != std::end(SpecialChars)) { Mangler.getStream() << '?' << (Pos - std::begin(SpecialChars)); } else { diff --git a/lib/AST/NSAPI.cpp b/lib/AST/NSAPI.cpp index 5b8300893e..5104dc59d6 100644 --- a/lib/AST/NSAPI.cpp +++ b/lib/AST/NSAPI.cpp @@ -1,9 +1,8 @@ //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 42f6a133d7..09d8510258 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -1,9 +1,8 @@ //===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/ODRHash.cpp b/lib/AST/ODRHash.cpp index a4c344ce0a..9d484bd5de 100644 --- a/lib/AST/ODRHash.cpp +++ b/lib/AST/ODRHash.cpp @@ -1,9 +1,8 @@ //===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -704,14 +703,36 @@ public: void VisitType(const Type *T) {} void VisitAdjustedType(const AdjustedType *T) { - AddQualType(T->getOriginalType()); - AddQualType(T->getAdjustedType()); + QualType Original = T->getOriginalType(); + QualType Adjusted = T->getAdjustedType(); + + // The original type and pointee type can be the same, as in the case of + // function pointers decaying to themselves. Set a bool and only process + // the type once, to prevent doubling the work. + SplitQualType split = Adjusted.split(); + if (auto Pointer = dyn_cast<PointerType>(split.Ty)) { + if (Pointer->getPointeeType() == Original) { + Hash.AddBoolean(true); + ID.AddInteger(split.Quals.getAsOpaqueValue()); + AddQualType(Original); + VisitType(T); + return; + } + } + + // The original type and pointee type are different, such as in the case + // of a array decaying to an element pointer. Set a bool to false and + // process both types. + Hash.AddBoolean(false); + AddQualType(Original); + AddQualType(Adjusted); + VisitType(T); } void VisitDecayedType(const DecayedType *T) { - AddQualType(T->getDecayedType()); - AddQualType(T->getPointeeType()); + // getDecayedType and getPointeeType are derived from getAdjustedType + // and don't need to be separately processed. VisitAdjustedType(T); } diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp index 76098f15bf..5bd4ad81bf 100644 --- a/lib/AST/OpenMPClause.cpp +++ b/lib/AST/OpenMPClause.cpp @@ -1,9 +1,8 @@ //===- OpenMPClause.cpp - Classes for OpenMP clauses ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -74,6 +73,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_final: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: + case OMPC_allocate: case OMPC_collapse: case OMPC_private: case OMPC_shared: @@ -145,6 +146,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_num_threads: case OMPC_safelen: case OMPC_simdlen: + case OMPC_allocator: + case OMPC_allocate: case OMPC_collapse: case OMPC_private: case OMPC_shared: @@ -698,6 +701,25 @@ OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C, return new (Mem) OMPInReductionClause(N); } +OMPAllocateClause * +OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, Expr *Allocator, + SourceLocation ColonLoc, SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + // Allocate space for private variables and initializer expressions. + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size())); + auto *Clause = new (Mem) OMPAllocateClause(StartLoc, LParenLoc, Allocator, + ColonLoc, EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPAllocateClause *OMPAllocateClause::CreateEmpty(const ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N)); + return new (Mem) OMPAllocateClause(N); +} + OMPFlushClause *OMPFlushClause::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -791,24 +813,23 @@ unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber( return TotalNum; } -OMPMapClause * -OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, - MappableExprComponentListsRef ComponentLists, - ArrayRef<OpenMPMapModifierKind> MapModifiers, - ArrayRef<SourceLocation> MapModifiersLoc, - OpenMPMapClauseKind Type, bool TypeIsImplicit, - SourceLocation TypeLoc) { - unsigned NumVars = Vars.size(); - unsigned NumUniqueDeclarations = - getUniqueDeclarationsTotalNumber(Declarations); - unsigned NumComponentLists = ComponentLists.size(); - unsigned NumComponents = getComponentsTotalNumber(ComponentLists); +OMPMapClause *OMPMapClause::Create( + const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs, + ArrayRef<OpenMPMapModifierKind> MapModifiers, + ArrayRef<SourceLocation> MapModifiersLoc, + NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, + OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc) { + OMPMappableExprListSizeTy Sizes; + Sizes.NumVars = Vars.size(); + Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); + Sizes.NumComponentLists = ComponentLists.size(); + Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: - // NumVars x Expr* - we have an original list expression for each clause list - // entry. + // 2 x NumVars x Expr* - we have an original list expression and an associated + // user-defined mapper for each clause list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the @@ -819,47 +840,47 @@ OMPMapClause::Create(const ASTContext &C, SourceLocation StartLoc, void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); - OMPMapClause *Clause = new (Mem) OMPMapClause( - MapModifiers, MapModifiersLoc, Type, TypeIsImplicit, TypeLoc, StartLoc, - LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, NumComponentLists, - NumComponents); + 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + OMPMapClause *Clause = new (Mem) + OMPMapClause(MapModifiers, MapModifiersLoc, UDMQualifierLoc, MapperId, + Type, TypeIsImplicit, TypeLoc, Locs, Sizes); Clause->setVarRefs(Vars); + Clause->setUDMapperRefs(UDMapperRefs); Clause->setClauseInfo(Declarations, ComponentLists); Clause->setMapType(Type); Clause->setMapLoc(TypeLoc); return Clause; } -OMPMapClause *OMPMapClause::CreateEmpty(const ASTContext &C, unsigned NumVars, - unsigned NumUniqueDeclarations, - unsigned NumComponentLists, - unsigned NumComponents) { +OMPMapClause * +OMPMapClause::CreateEmpty(const ASTContext &C, + const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); - return new (Mem) OMPMapClause(NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); -} - -OMPToClause *OMPToClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> Vars, - ArrayRef<ValueDecl *> Declarations, - MappableExprComponentListsRef ComponentLists) { - unsigned NumVars = Vars.size(); - unsigned NumUniqueDeclarations = - getUniqueDeclarationsTotalNumber(Declarations); - unsigned NumComponentLists = ComponentLists.size(); - unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + return new (Mem) OMPMapClause(Sizes); +} + +OMPToClause *OMPToClause::Create( + const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs, + NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) { + OMPMappableExprListSizeTy Sizes; + Sizes.NumVars = Vars.size(); + Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); + Sizes.NumComponentLists = ComponentLists.size(); + Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: - // NumVars x Expr* - we have an original list expression for each clause list - // entry. + // 2 x NumVars x Expr* - we have an original list expression and an associated + // user-defined mapper for each clause list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the @@ -870,45 +891,43 @@ OMPToClause *OMPToClause::Create(const ASTContext &C, SourceLocation StartLoc, void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); + 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); - OMPToClause *Clause = new (Mem) - OMPToClause(StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + auto *Clause = new (Mem) OMPToClause(UDMQualifierLoc, MapperId, Locs, Sizes); Clause->setVarRefs(Vars); + Clause->setUDMapperRefs(UDMapperRefs); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C, unsigned NumVars, - unsigned NumUniqueDeclarations, - unsigned NumComponentLists, - unsigned NumComponents) { +OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C, + const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); - return new (Mem) OMPToClause(NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); -} - -OMPFromClause * -OMPFromClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, - MappableExprComponentListsRef ComponentLists) { - unsigned NumVars = Vars.size(); - unsigned NumUniqueDeclarations = - getUniqueDeclarationsTotalNumber(Declarations); - unsigned NumComponentLists = ComponentLists.size(); - unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + return new (Mem) OMPToClause(Sizes); +} + +OMPFromClause *OMPFromClause::Create( + const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars, + ArrayRef<ValueDecl *> Declarations, + MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs, + NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) { + OMPMappableExprListSizeTy Sizes; + Sizes.NumVars = Vars.size(); + Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); + Sizes.NumComponentLists = ComponentLists.size(); + Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: - // NumVars x Expr* - we have an original list expression for each clause list - // entry. + // 2 x NumVars x Expr* - we have an original list expression and an associated + // user-defined mapper for each clause list entry. // NumUniqueDeclarations x ValueDecl* - unique base declarations associated // with each component list. // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the @@ -919,29 +938,29 @@ OMPFromClause::Create(const ASTContext &C, SourceLocation StartLoc, void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); + 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); - OMPFromClause *Clause = new (Mem) - OMPFromClause(StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + auto *Clause = + new (Mem) OMPFromClause(UDMQualifierLoc, MapperId, Locs, Sizes); Clause->setVarRefs(Vars); + Clause->setUDMapperRefs(UDMapperRefs); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars, - unsigned NumUniqueDeclarations, - unsigned NumComponentLists, - unsigned NumComponents) { +OMPFromClause * +OMPFromClause::CreateEmpty(const ASTContext &C, + const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); - return new (Mem) OMPFromClause(NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + return new (Mem) OMPFromClause(Sizes); } void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) { @@ -957,15 +976,15 @@ void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) { } OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create( - const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> Vars, ArrayRef<Expr *> PrivateVars, - ArrayRef<Expr *> Inits, ArrayRef<ValueDecl *> Declarations, + const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars, + ArrayRef<Expr *> PrivateVars, ArrayRef<Expr *> Inits, + ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists) { - unsigned NumVars = Vars.size(); - unsigned NumUniqueDeclarations = - getUniqueDeclarationsTotalNumber(Declarations); - unsigned NumComponentLists = ComponentLists.size(); - unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + OMPMappableExprListSizeTy Sizes; + Sizes.NumVars = Vars.size(); + Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); + Sizes.NumComponentLists = ComponentLists.size(); + Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // 3 x NumVars x Expr* - we have an original list expression for each clause @@ -980,12 +999,11 @@ OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create( void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - 3 * NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); + 3 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); - OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause( - StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause(Locs, Sizes); Clause->setVarRefs(Vars); Clause->setPrivateCopies(PrivateVars); @@ -994,29 +1012,28 @@ OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create( return Clause; } -OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty( - const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, - unsigned NumComponentLists, unsigned NumComponents) { +OMPUseDevicePtrClause * +OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C, + const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - 3 * NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); - return new (Mem) OMPUseDevicePtrClause(NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + 3 * Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + return new (Mem) OMPUseDevicePtrClause(Sizes); } OMPIsDevicePtrClause * -OMPIsDevicePtrClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, +OMPIsDevicePtrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists) { - unsigned NumVars = Vars.size(); - unsigned NumUniqueDeclarations = - getUniqueDeclarationsTotalNumber(Declarations); - unsigned NumComponentLists = ComponentLists.size(); - unsigned NumComponents = getComponentsTotalNumber(ComponentLists); + OMPMappableExprListSizeTy Sizes; + Sizes.NumVars = Vars.size(); + Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations); + Sizes.NumComponentLists = ComponentLists.size(); + Sizes.NumComponents = getComponentsTotalNumber(ComponentLists); // We need to allocate: // NumVars x Expr* - we have an original list expression for each clause list @@ -1031,28 +1048,27 @@ OMPIsDevicePtrClause::Create(const ASTContext &C, SourceLocation StartLoc, void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); + Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); - OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause( - StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(Locs, Sizes); Clause->setVarRefs(Vars); Clause->setClauseInfo(Declarations, ComponentLists); return Clause; } -OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty( - const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations, - unsigned NumComponentLists, unsigned NumComponents) { +OMPIsDevicePtrClause * +OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C, + const OMPMappableExprListSizeTy &Sizes) { void *Mem = C.Allocate( totalSizeToAlloc<Expr *, ValueDecl *, unsigned, OMPClauseMappableExprCommon::MappableComponent>( - NumVars, NumUniqueDeclarations, - NumUniqueDeclarations + NumComponentLists, NumComponents)); - return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations, - NumComponentLists, NumComponents); + Sizes.NumVars, Sizes.NumUniqueDeclarations, + Sizes.NumUniqueDeclarations + Sizes.NumComponentLists, + Sizes.NumComponents)); + return new (Mem) OMPIsDevicePtrClause(Sizes); } //===----------------------------------------------------------------------===// @@ -1091,6 +1107,12 @@ void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) { + OS << "allocator("; + Node->getAllocator()->printPretty(OS, nullptr, Policy, 0); + OS << ")"; +} + void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { OS << "collapse("; Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0); @@ -1261,6 +1283,21 @@ void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { } } +void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) { + if (Node->varlist_empty()) + return; + OS << "allocate"; + if (Expr *Allocator = Node->getAllocator()) { + OS << "("; + Allocator->printPretty(OS, nullptr, Policy, 0); + OS << ":"; + VisitOMPClauseList(Node, ' '); + } else { + VisitOMPClauseList(Node, '('); + } + OS << ")"; +} + void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) { if (!Node->varlist_empty()) { OS << "private"; @@ -1432,6 +1469,14 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) { OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapTypeModifier(I)); + if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_mapper) { + OS << '('; + NestedNameSpecifier *MapperNNS = + Node->getMapperQualifierLoc().getNestedNameSpecifier(); + if (MapperNNS) + MapperNNS->print(OS, Policy); + OS << Node->getMapperIdInfo() << ')'; + } OS << ','; } } @@ -1446,7 +1491,19 @@ void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) { void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { if (!Node->varlist_empty()) { OS << "to"; - VisitOMPClauseList(Node, '('); + DeclarationNameInfo MapperId = Node->getMapperIdInfo(); + if (MapperId.getName() && !MapperId.getName().isEmpty()) { + OS << '('; + OS << "mapper("; + NestedNameSpecifier *MapperNNS = + Node->getMapperQualifierLoc().getNestedNameSpecifier(); + if (MapperNNS) + MapperNNS->print(OS, Policy); + OS << MapperId << "):"; + VisitOMPClauseList(Node, ' '); + } else { + VisitOMPClauseList(Node, '('); + } OS << ")"; } } @@ -1454,7 +1511,19 @@ void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) { void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) { if (!Node->varlist_empty()) { OS << "from"; - VisitOMPClauseList(Node, '('); + DeclarationNameInfo MapperId = Node->getMapperIdInfo(); + if (MapperId.getName() && !MapperId.getName().isEmpty()) { + OS << '('; + OS << "mapper("; + NestedNameSpecifier *MapperNNS = + Node->getMapperQualifierLoc().getNestedNameSpecifier(); + if (MapperNNS) + MapperNNS->print(OS, Policy); + OS << MapperId << "):"; + VisitOMPClauseList(Node, ' '); + } else { + VisitOMPClauseList(Node, '('); + } OS << ")"; } } diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp index 88c178aa37..e09b5bbe75 100644 --- a/lib/AST/ParentMap.cpp +++ b/lib/AST/ParentMap.cpp @@ -1,9 +1,8 @@ //===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/PrintfFormatString.cpp b/lib/AST/PrintfFormatString.cpp index e0a0c5b758..a1207aae5a 100644 --- a/lib/AST/PrintfFormatString.cpp +++ b/lib/AST/PrintfFormatString.cpp @@ -1,9 +1,8 @@ //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -316,7 +315,11 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, case 'f': k = ConversionSpecifier::fArg; break; case 'g': k = ConversionSpecifier::gArg; break; case 'i': k = ConversionSpecifier::iArg; break; - case 'n': k = ConversionSpecifier::nArg; break; + case 'n': + // Not handled, but reserved in OpenCL. + if (!LO.OpenCL) + k = ConversionSpecifier::nArg; + break; case 'o': k = ConversionSpecifier::oArg; break; case 'p': k = ConversionSpecifier::pArg; break; case 's': k = ConversionSpecifier::sArg; break; @@ -487,10 +490,12 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, // GNU extension. return Ctx.LongLongTy; case LengthModifier::None: + case LengthModifier::AsShortLong: return Ctx.IntTy; case LengthModifier::AsInt32: return ArgType(Ctx.IntTy, "__int32"); - case LengthModifier::AsChar: return ArgType::AnyCharTy; + case LengthModifier::AsChar: + return ArgType::AnyCharTy; case LengthModifier::AsShort: return Ctx.ShortTy; case LengthModifier::AsLong: return Ctx.LongTy; case LengthModifier::AsLongLong: @@ -521,6 +526,7 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, // GNU extension. return Ctx.UnsignedLongLongTy; case LengthModifier::None: + case LengthModifier::AsShortLong: return Ctx.UnsignedIntTy; case LengthModifier::AsInt32: return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); @@ -550,6 +556,18 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, } if (CS.isDoubleArg()) { + if (!VectorNumElts.isInvalid()) { + switch (LM.getKind()) { + case LengthModifier::AsShort: + return Ctx.HalfTy; + case LengthModifier::AsShortLong: + return Ctx.FloatTy; + case LengthModifier::AsLong: + default: + return Ctx.DoubleTy; + } + } + if (LM.getKind() == LengthModifier::AsLongDouble) return Ctx.LongDoubleTy; return Ctx.DoubleTy; @@ -583,6 +601,8 @@ ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, case LengthModifier::AsInt64: case LengthModifier::AsWide: return ArgType::Invalid(); + case LengthModifier::AsShortLong: + llvm_unreachable("only used for OpenCL which doesn not handle nArg"); } } @@ -761,10 +781,13 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: + LM.setKind(VectorNumElts.isInvalid() ? + LengthModifier::None : LengthModifier::AsShortLong); + break; case BuiltinType::Double: - LM.setKind(LengthModifier::None); + LM.setKind(VectorNumElts.isInvalid() ? + LengthModifier::None : LengthModifier::AsLong); break; - case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: @@ -797,7 +820,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, namedTypeToLengthModifier(QT, LM); // If fixing the length modifier was enough, we might be done. - if (hasValidLengthModifier(Ctx.getTargetInfo())) { + if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { // If we're going to offer a fix anyway, make sure the sign matches. switch (CS.getKind()) { case ConversionSpecifier::uArg: diff --git a/lib/AST/QualTypeNames.cpp b/lib/AST/QualTypeNames.cpp index 8b605ef295..f28f00171c 100644 --- a/lib/AST/QualTypeNames.cpp +++ b/lib/AST/QualTypeNames.cpp @@ -1,11 +1,8 @@ //===------- QualTypeNames.cpp - Generate Complete QualType Names ---------===// // -// The LLVM Compiler Infrastructure -// -//===----------------------------------------------------------------------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -382,6 +379,19 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, return QT; } + if (auto *MPT = dyn_cast<MemberPointerType>(QT.getTypePtr())) { + // Get the qualifiers. + Qualifiers Quals = QT.getQualifiers(); + // Fully qualify the pointee and class types. + QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); + QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx, + WithGlobalNsPrefix); + QT = Ctx.getMemberPointerType(QT, Class.getTypePtr()); + // Add back the qualifiers. + QT = Ctx.getQualifiedType(QT, Quals); + return QT; + } + // In case of myType& we need to strip the reference first, fully // qualify and attach the reference once again. if (isa<ReferenceType>(QT.getTypePtr())) { diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp index ab873a3964..df53b7fa10 100644 --- a/lib/AST/RawCommentList.cpp +++ b/lib/AST/RawCommentList.cpp @@ -1,9 +1,8 @@ //===--- RawCommentList.cpp - Processing raw comments -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp index 9db23d50d0..e7b500e190 100644 --- a/lib/AST/RecordLayout.cpp +++ b/lib/AST/RecordLayout.cpp @@ -1,9 +1,8 @@ //===- RecordLayout.cpp - Layout information for a struct/union -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 62dc22c814..e83376f66e 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1,9 +1,8 @@ //=== RecordLayoutBuilder.cpp - Helper class for building record layouts ---==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -239,7 +238,7 @@ EmptySubobjectMap::CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD, return true; const ClassVectorTy &Classes = I->second; - if (std::find(Classes.begin(), Classes.end(), RD) == Classes.end()) + if (llvm::find(Classes, RD) == Classes.end()) return true; // There is already an empty class of the same type at this offset. @@ -255,7 +254,7 @@ void EmptySubobjectMap::AddSubobjectAtOffset(const CXXRecordDecl *RD, // If we have empty structures inside a union, we can assign both // the same offset. Just avoid pushing them twice in the list. ClassVectorTy &Classes = EmptyClassOffsets[Offset]; - if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end()) + if (llvm::is_contained(Classes, RD)) return; Classes.push_back(RD); @@ -2693,7 +2692,8 @@ void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { auto FieldBitOffset = External.getExternalFieldOffset(FD); placeFieldAtBitOffset(FieldBitOffset); auto NewSize = Context.toCharUnitsFromBits( - llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth())); + llvm::alignDown(FieldBitOffset, Context.toBits(Info.Alignment)) + + Context.toBits(Info.Size)); Size = std::max(Size, NewSize); Alignment = std::max(Alignment, Info.Alignment); } else if (IsUnion) { @@ -2742,12 +2742,17 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) { CharUnits InjectionSite = VBPtrOffset; // But before we do, make sure it's properly aligned. VBPtrOffset = VBPtrOffset.alignTo(PointerInfo.Alignment); + // Determine where the first field should be laid out after the vbptr. + CharUnits FieldStart = VBPtrOffset + PointerInfo.Size; // Shift everything after the vbptr down, unless we're using an external // layout. - if (UseExternalLayout) + if (UseExternalLayout) { + // It is possible that there were no fields or bases located after vbptr, + // so the size was not adjusted before. + if (Size < FieldStart) + Size = FieldStart; return; - // Determine where the first field should be laid out after the vbptr. - CharUnits FieldStart = VBPtrOffset + PointerInfo.Size; + } // Make sure that the amount we push the fields back by is a multiple of the // alignment. CharUnits Offset = (FieldStart - InjectionSite) @@ -2772,8 +2777,14 @@ void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) { if (HasVBPtr) VBPtrOffset += Offset; - if (UseExternalLayout) + if (UseExternalLayout) { + // The class may have no bases or fields, but still have a vfptr + // (e.g. it's an interface class). The size was not correctly set before + // in this case. + if (FieldOffsets.empty() && Bases.empty()) + Size += Offset; return; + } Size += Offset; @@ -3276,10 +3287,10 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, } // Sort nvbases by offset. - std::stable_sort(Bases.begin(), Bases.end(), - [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { - return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); - }); + llvm::stable_sort( + Bases, [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { + return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); + }); // Dump (non-virtual) bases for (const CXXRecordDecl *Base : Bases) { diff --git a/lib/AST/ScanfFormatString.cpp b/lib/AST/ScanfFormatString.cpp index 08ba7a7a4f..1a87de70f8 100644 --- a/lib/AST/ScanfFormatString.cpp +++ b/lib/AST/ScanfFormatString.cpp @@ -1,9 +1,8 @@ //= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -262,9 +261,10 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: return ArgType::Invalid(); } - llvm_unreachable("Unsupported LenghtModifier Type"); + llvm_unreachable("Unsupported LengthModifier Type"); // Unsigned int. case ConversionSpecifier::oArg: @@ -302,9 +302,10 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: return ArgType::Invalid(); } - llvm_unreachable("Unsupported LenghtModifier Type"); + llvm_unreachable("Unsupported LengthModifier Type"); // Float. case ConversionSpecifier::aArg: @@ -397,6 +398,7 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsInt32: case LengthModifier::AsInt3264: case LengthModifier::AsWide: + case LengthModifier::AsShortLong: return ArgType::Invalid(); } @@ -502,7 +504,7 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, namedTypeToLengthModifier(PT, LM); // If fixing the length modifier was enough, we are done. - if (hasValidLengthModifier(Ctx.getTargetInfo())) { + if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) { const analyze_scanf::ArgType &AT = getArgType(Ctx); if (AT.isValid() && AT.matchesType(Ctx, QT)) return true; diff --git a/lib/AST/SelectorLocationsKind.cpp b/lib/AST/SelectorLocationsKind.cpp index 8b72c85d7e..2c34c9c60c 100644 --- a/lib/AST/SelectorLocationsKind.cpp +++ b/lib/AST/SelectorLocationsKind.cpp @@ -1,9 +1,8 @@ //===--- SelectorLocationsKind.cpp - Kind of selector locations -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 116291bfa1..4796ee87f7 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -1,9 +1,8 @@ //===- Stmt.cpp - Statement AST Node Implementation -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -118,30 +117,6 @@ void Stmt::EnableStatistics() { StatisticsEnabled = true; } -Stmt *Stmt::IgnoreImplicit() { - Stmt *s = this; - - Stmt *lasts = nullptr; - - while (s != lasts) { - lasts = s; - - if (auto *fe = dyn_cast<FullExpr>(s)) - s = fe->getSubExpr(); - - if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) - s = mte->GetTemporaryExpr(); - - if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) - s = bte->getSubExpr(); - - if (auto *ice = dyn_cast<ImplicitCastExpr>(s)) - s = ice->getSubExpr(); - } - - return s; -} - /// Skip no-op (attributed, compound) container stmts and skip captured /// stmt at the top, if \a IgnoreCaptured is true. Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) { @@ -345,6 +320,23 @@ CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, return New; } +const Expr *ValueStmt::getExprStmt() const { + const Stmt *S = this; + do { + if (const auto *E = dyn_cast<Expr>(S)) + return E; + + if (const auto *LS = dyn_cast<LabelStmt>(S)) + S = LS->getSubStmt(); + else if (const auto *AS = dyn_cast<AttributedStmt>(S)) + S = AS->getSubStmt(); + else + llvm_unreachable("unknown kind of ValueStmt"); + } while (isa<ValueStmt>(S)); + + return nullptr; +} + const char *LabelStmt::getName() const { return getDecl()->getIdentifier()->getNameStart(); } @@ -1262,6 +1254,10 @@ Stmt::child_range CapturedStmt::children() { return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); } +Stmt::const_child_range CapturedStmt::children() const { + return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures); +} + CapturedDecl *CapturedStmt::getCapturedDecl() { return CapDeclAndKind.getPointer(); } diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp index 12367f8fd5..060d090fc0 100644 --- a/lib/AST/StmtCXX.cpp +++ b/lib/AST/StmtCXX.cpp @@ -1,9 +1,8 @@ //===--- StmtCXX.cpp - Classes for representing C++ statements ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp index 00056e83af..70c8dc94e2 100644 --- a/lib/AST/StmtIterator.cpp +++ b/lib/AST/StmtIterator.cpp @@ -1,9 +1,8 @@ //===- StmtIterator.cpp - Iterators for Statements ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/StmtObjC.cpp b/lib/AST/StmtObjC.cpp index ed21e2d0d2..3d58679551 100644 --- a/lib/AST/StmtObjC.cpp +++ b/lib/AST/StmtObjC.cpp @@ -1,9 +1,8 @@ //===--- StmtObjC.cpp - Classes for representing ObjC statements ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp index 85a2daa080..4e829897ce 100644 --- a/lib/AST/StmtOpenMP.cpp +++ b/lib/AST/StmtOpenMP.cpp @@ -1,9 +1,8 @@ //===--- StmtOpenMP.cpp - Classes for OpenMP directives -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -23,6 +22,25 @@ void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { std::copy(Clauses.begin(), Clauses.end(), getClauses().begin()); } +bool OMPExecutableDirective::isStandaloneDirective() const { + // Special case: 'omp target enter data', 'omp target exit data', + // 'omp target update' are stand-alone directives, but for implementation + // reasons they have empty synthetic structured block, to simplify codegen. + if (isa<OMPTargetEnterDataDirective>(this) || + isa<OMPTargetExitDataDirective>(this) || + isa<OMPTargetUpdateDirective>(this)) + return true; + return !hasAssociatedStmt() || !getAssociatedStmt(); +} + +const Stmt *OMPExecutableDirective::getStructuredBlock() const { + assert(!isStandaloneDirective() && + "Standalone Executable Directives don't have Structured Blocks."); + if (auto *LD = dyn_cast<OMPLoopDirective>(this)) + return LD->getBody(); + return getInnermostCapturedStmt()->getCapturedStmt(); +} + void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) { assert(A.size() == getCollapsedNumber() && "Number of loop counters is not the same as the collapsed number"); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index ae726e3871..012bd4a898 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1,9 +1,8 @@ //===- StmtPrinter.cpp - Printing implementation for Stmt ASTs ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -1262,15 +1261,15 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){ void StmtPrinter::VisitGenericSelectionExpr(GenericSelectionExpr *Node) { OS << "_Generic("; PrintExpr(Node->getControllingExpr()); - for (unsigned i = 0; i != Node->getNumAssocs(); ++i) { + for (const GenericSelectionExpr::Association &Assoc : Node->associations()) { OS << ", "; - QualType T = Node->getAssocType(i); + QualType T = Assoc.getType(); if (T.isNull()) OS << "default"; else T.print(OS, Policy); OS << ": "; - PrintExpr(Node->getAssocExpr(i)); + PrintExpr(Assoc.getAssociationExpr()); } OS << ")"; } @@ -1896,13 +1895,22 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { llvm_unreachable("VLA type in explicit captures."); } + if (C->isPackExpansion()) + OS << "..."; + if (Node->isInitCapture(C)) PrintExpr(C->getCapturedVar()->getInit()); } OS << ']'; + if (!Node->getExplicitTemplateParameters().empty()) { + Node->getTemplateParameterList()->print( + OS, Node->getLambdaClass()->getASTContext(), + /*OmitTemplateKW*/true); + } + if (Node->hasExplicitParameters()) { - OS << " ("; + OS << '('; CXXMethodDecl *Method = Node->getCallOperator(); NeedComma = false; for (const auto *P : Method->parameters()) { @@ -1937,9 +1945,8 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { } // Print the body. - CompoundStmt *Body = Node->getBody(); OS << ' '; - PrintStmt(Body); + PrintRawCompoundStmt(Node->getBody()); } void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { @@ -1969,10 +1976,11 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isParenTypeId()) OS << "("; std::string TypeS; - if (Expr *Size = E->getArraySize()) { + if (Optional<Expr *> Size = E->getArraySize()) { llvm::raw_string_ostream s(TypeS); s << '['; - Size->printPretty(s, Helper, Policy); + if (*Size) + (*Size)->printPretty(s, Helper, Policy); s << ']'; } E->getAllocatedType().print(OS, Policy, TypeS); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index ec4dac03d4..da80322a70 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -1,9 +1,8 @@ //===---- StmtProfile.cpp - Profile implementation for Stmt ASTs ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -458,6 +457,11 @@ void OMPClauseProfiler::VisitOMPSimdlenClause(const OMPSimdlenClause *C) { Profiler->VisitStmt(C->getSimdlen()); } +void OMPClauseProfiler::VisitOMPAllocatorClause(const OMPAllocatorClause *C) { + if (C->getAllocator()) + Profiler->VisitStmt(C->getAllocator()); +} + void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) { if (C->getNumForLoops()) Profiler->VisitStmt(C->getNumForLoops()); @@ -712,6 +716,11 @@ void OMPClauseProfiler::VisitOMPDeviceClause(const OMPDeviceClause *C) { void OMPClauseProfiler::VisitOMPMapClause(const OMPMapClause *C) { VisitOMPClauseList(C); } +void OMPClauseProfiler::VisitOMPAllocateClause(const OMPAllocateClause *C) { + if (Expr *Allocator = C->getAllocator()) + Profiler->VisitStmt(Allocator); + VisitOMPClauseList(C); +} void OMPClauseProfiler::VisitOMPNumTeamsClause(const OMPNumTeamsClause *C) { VistOMPClauseWithPreInit(C); if (C->getNumTeams()) @@ -1260,13 +1269,14 @@ void StmtProfiler::VisitBlockExpr(const BlockExpr *S) { void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { VisitExpr(S); - for (unsigned i = 0; i != S->getNumAssocs(); ++i) { - QualType T = S->getAssocType(i); + for (const GenericSelectionExpr::ConstAssociation &Assoc : + S->associations()) { + QualType T = Assoc.getType(); if (T.isNull()) ID.AddPointer(nullptr); else VisitType(T); - VisitExpr(S->getAssocExpr(i)); + VisitExpr(Assoc.getAssociationExpr()); } } diff --git a/lib/AST/StmtViz.cpp b/lib/AST/StmtViz.cpp index 8be287e7cb..4eb0da8a0e 100644 --- a/lib/AST/StmtViz.cpp +++ b/lib/AST/StmtViz.cpp @@ -1,9 +1,8 @@ //===--- StmtViz.cpp - Graphviz visualization for Stmt ASTs -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index a78927d229..cb4cbd2f76 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -1,9 +1,8 @@ //===- TemplateBase.cpp - Common template AST class implementation --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index 0a7a6bc3c6..2474d6278b 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -1,9 +1,8 @@ //===- TemplateName.cpp - C++ Template Name Representation ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -251,6 +250,20 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB << NameStr; } +const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD, + TemplateName N) { + std::string NameStr; + llvm::raw_string_ostream OS(NameStr); + LangOptions LO; + LO.CPlusPlus = true; + LO.Bool = true; + OS << '\''; + N.print(OS, PrintingPolicy(LO)); + OS << '\''; + OS.flush(); + return PD << NameStr; +} + void TemplateName::dump(raw_ostream &OS) const { LangOptions LO; // FIXME! LO.CPlusPlus = true; diff --git a/lib/AST/TextNodeDumper.cpp b/lib/AST/TextNodeDumper.cpp index b51a900622..f287e961b6 100644 --- a/lib/AST/TextNodeDumper.cpp +++ b/lib/AST/TextNodeDumper.cpp @@ -1,9 +1,8 @@ //===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -122,6 +121,9 @@ void TextNodeDumper::Visit(const Stmt *Node) { dumpPointer(Node); dumpSourceRange(Node->getSourceRange()); + if (Node->isOMPStructuredBlock()) + OS << " openmp_structured_block"; + if (const auto *E = dyn_cast<Expr>(Node)) { dumpType(E->getType()); @@ -256,6 +258,19 @@ void TextNodeDumper::Visit(const Decl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) if (FD->isConstexpr()) OS << " constexpr"; + + if (!isa<FunctionDecl>(*D)) { + const auto *MD = dyn_cast<ObjCMethodDecl>(D); + if (!MD || !MD->isThisDeclarationADefinition()) { + const auto *DC = dyn_cast<DeclContext>(D); + if (DC && DC->hasExternalLexicalStorage()) { + ColorScope Color(OS, ShowColors, UndeserializedColor); + OS << " <undeserialized declarations>"; + } + } + } + + ConstDeclVisitor<TextNodeDumper>::Visit(D); } void TextNodeDumper::Visit(const CXXCtorInitializer *Init) { @@ -302,6 +317,19 @@ void TextNodeDumper::Visit(const OMPClause *C) { OS << " <implicit>"; } +void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { + const TypeSourceInfo *TSI = A.getTypeSourceInfo(); + if (TSI) { + OS << "case "; + dumpType(TSI->getType()); + } else { + OS << "default"; + } + + if (A.isSelected()) + OS << " selected"; +} + void TextNodeDumper::dumpPointer(const void *Ptr) { ColorScope Color(OS, ShowColors, AddressColor); OS << ' ' << Ptr; @@ -753,6 +781,11 @@ void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) { } } +void TextNodeDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) { + if (E->isResultDependent()) + OS << " result_dependent"; +} + void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) { OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; @@ -824,6 +857,8 @@ void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) { } void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) { + if (Node->isImplicit()) + OS << " implicit"; OS << " this"; } @@ -1096,6 +1131,8 @@ void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) { OS << " volatile"; if (T->isRestrict()) OS << " restrict"; + if (T->getExtProtoInfo().Variadic) + OS << " variadic"; switch (EPI.RefQualifier) { case RQ_None: break; @@ -1166,3 +1203,715 @@ void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) { if (auto N = T->getNumExpansions()) OS << " expansions " << *N; } + +void TextNodeDumper::VisitLabelDecl(const LabelDecl *D) { dumpName(D); } + +void TextNodeDumper::VisitTypedefDecl(const TypedefDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) { + if (D->isScoped()) { + if (D->isScopedUsingClassTag()) + OS << " class"; + else + OS << " struct"; + } + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isFixed()) + dumpType(D->getIntegerType()); +} + +void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) { + OS << ' ' << D->getKindName(); + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isCompleteDefinition()) + OS << " definition"; +} + +void TextNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { + dumpName(D); + dumpType(D->getType()); +} + +void TextNodeDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + + for (const auto *Child : D->chain()) + dumpDeclRef(Child); +} + +void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { + dumpName(D); + dumpType(D->getType()); + + StorageClass SC = D->getStorageClass(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isInlineSpecified()) + OS << " inline"; + if (D->isVirtualAsWritten()) + OS << " virtual"; + if (D->isModulePrivate()) + OS << " __module_private__"; + + if (D->isPure()) + OS << " pure"; + if (D->isDefaulted()) { + OS << " default"; + if (D->isDeleted()) + OS << "_delete"; + } + if (D->isDeletedAsWritten()) + OS << " delete"; + if (D->isTrivial()) + OS << " trivial"; + + if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) { + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + switch (EPI.ExceptionSpec.Type) { + default: + break; + case EST_Unevaluated: + OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl; + break; + case EST_Uninstantiated: + OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate; + break; + } + } + + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { + if (MD->size_overridden_methods() != 0) { + auto dumpOverride = [=](const CXXMethodDecl *D) { + SplitQualType T_split = D->getType().split(); + OS << D << " " << D->getParent()->getName() + << "::" << D->getNameAsString() << " '" + << QualType::getAsString(T_split, PrintPolicy) << "'"; + }; + + AddChild([=] { + auto Overrides = MD->overridden_methods(); + OS << "Overrides: [ "; + dumpOverride(*Overrides.begin()); + for (const auto *Override : + llvm::make_range(Overrides.begin() + 1, Overrides.end())) { + OS << ", "; + dumpOverride(Override); + } + OS << " ]"; + }); + } + } + + // Since NumParams comes from the FunctionProtoType of the FunctionDecl and + // the Params are set later, it is possible for a dump during debugging to + // encounter a FunctionDecl that has been created but hasn't been assigned + // ParmVarDecls yet. + if (!D->param_empty() && !D->param_begin()) + OS << " <<<NULL params x " << D->getNumParams() << ">>>"; +} + +void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->isMutable()) + OS << " mutable"; + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void TextNodeDumper::VisitVarDecl(const VarDecl *D) { + dumpName(D); + dumpType(D->getType()); + StorageClass SC = D->getStorageClass(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + switch (D->getTLSKind()) { + case VarDecl::TLS_None: + break; + case VarDecl::TLS_Static: + OS << " tls"; + break; + case VarDecl::TLS_Dynamic: + OS << " tls_dynamic"; + break; + } + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isNRVOVariable()) + OS << " nrvo"; + if (D->isInline()) + OS << " inline"; + if (D->isConstexpr()) + OS << " constexpr"; + if (D->hasInit()) { + switch (D->getInitStyle()) { + case VarDecl::CInit: + OS << " cinit"; + break; + case VarDecl::CallInit: + OS << " callinit"; + break; + case VarDecl::ListInit: + OS << " listinit"; + break; + } + } +} + +void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) { + dumpName(D); + dumpType(D->getType()); +} + +void TextNodeDumper::VisitCapturedDecl(const CapturedDecl *D) { + if (D->isNothrow()) + OS << " nothrow"; +} + +void TextNodeDumper::VisitImportDecl(const ImportDecl *D) { + OS << ' ' << D->getImportedModule()->getFullModuleName(); + + for (Decl *InitD : + D->getASTContext().getModuleInitializers(D->getImportedModule())) + dumpDeclRef(InitD, "initializer"); +} + +void TextNodeDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) { + OS << ' '; + switch (D->getCommentKind()) { + case PCK_Unknown: + llvm_unreachable("unexpected pragma comment kind"); + case PCK_Compiler: + OS << "compiler"; + break; + case PCK_ExeStr: + OS << "exestr"; + break; + case PCK_Lib: + OS << "lib"; + break; + case PCK_Linker: + OS << "linker"; + break; + case PCK_User: + OS << "user"; + break; + } + StringRef Arg = D->getArg(); + if (!Arg.empty()) + OS << " \"" << Arg << "\""; +} + +void TextNodeDumper::VisitPragmaDetectMismatchDecl( + const PragmaDetectMismatchDecl *D) { + OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\""; +} + +void TextNodeDumper::VisitOMPExecutableDirective( + const OMPExecutableDirective *D) { + if (D->isStandaloneDirective()) + OS << " openmp_standalone_directive"; +} + +void TextNodeDumper::VisitOMPDeclareReductionDecl( + const OMPDeclareReductionDecl *D) { + dumpName(D); + dumpType(D->getType()); + OS << " combiner"; + dumpPointer(D->getCombiner()); + if (const auto *Initializer = D->getInitializer()) { + OS << " initializer"; + dumpPointer(Initializer); + switch (D->getInitializerKind()) { + case OMPDeclareReductionDecl::DirectInit: + OS << " omp_priv = "; + break; + case OMPDeclareReductionDecl::CopyInit: + OS << " omp_priv ()"; + break; + case OMPDeclareReductionDecl::CallInit: + break; + } + } +} + +void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) { + for (const auto *C : D->clauselists()) { + AddChild([=] { + if (!C) { + ColorScope Color(OS, ShowColors, NullColor); + OS << "<<<NULL>>> OMPClause"; + return; + } + { + ColorScope Color(OS, ShowColors, AttrColor); + StringRef ClauseName(getOpenMPClauseName(C->getClauseKind())); + OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper() + << ClauseName.drop_front() << "Clause"; + } + dumpPointer(C); + dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc())); + }); + } +} + +void TextNodeDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) { + dumpName(D); + dumpType(D->getType()); +} + +void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) { + dumpName(D); + if (D->isInline()) + OS << " inline"; + if (!D->isOriginalNamespace()) + dumpDeclRef(D->getOriginalNamespace(), "original"); +} + +void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getNominatedNamespace()); +} + +void TextNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { + dumpName(D); + dumpDeclRef(D->getAliasedNamespace()); +} + +void TextNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); +} + +void TextNodeDumper::VisitTypeAliasTemplateDecl( + const TypeAliasTemplateDecl *D) { + dumpName(D); +} + +void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { + VisitRecordDecl(D); + if (!D->isCompleteDefinition()) + return; + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "DefinitionData"; + } +#define FLAG(fn, name) \ + if (D->fn()) \ + OS << " " #name; + FLAG(isParsingBaseSpecifiers, parsing_base_specifiers); + + FLAG(isGenericLambda, generic); + FLAG(isLambda, lambda); + + FLAG(canPassInRegisters, pass_in_registers); + FLAG(isEmpty, empty); + FLAG(isAggregate, aggregate); + FLAG(isStandardLayout, standard_layout); + FLAG(isTriviallyCopyable, trivially_copyable); + FLAG(isPOD, pod); + FLAG(isTrivial, trivial); + FLAG(isPolymorphic, polymorphic); + FLAG(isAbstract, abstract); + FLAG(isLiteral, literal); + + FLAG(hasUserDeclaredConstructor, has_user_declared_ctor); + FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor); + FLAG(hasMutableFields, has_mutable_fields); + FLAG(hasVariantMembers, has_variant_members); + FLAG(allowConstDefaultInit, can_const_default_init); + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "DefaultConstructor"; + } + FLAG(hasDefaultConstructor, exists); + FLAG(hasTrivialDefaultConstructor, trivial); + FLAG(hasNonTrivialDefaultConstructor, non_trivial); + FLAG(hasUserProvidedDefaultConstructor, user_provided); + FLAG(hasConstexprDefaultConstructor, constexpr); + FLAG(needsImplicitDefaultConstructor, needs_implicit); + FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr); + }); + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "CopyConstructor"; + } + FLAG(hasSimpleCopyConstructor, simple); + FLAG(hasTrivialCopyConstructor, trivial); + FLAG(hasNonTrivialCopyConstructor, non_trivial); + FLAG(hasUserDeclaredCopyConstructor, user_declared); + FLAG(hasCopyConstructorWithConstParam, has_const_param); + FLAG(needsImplicitCopyConstructor, needs_implicit); + FLAG(needsOverloadResolutionForCopyConstructor, + needs_overload_resolution); + if (!D->needsOverloadResolutionForCopyConstructor()) + FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted); + FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param); + }); + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "MoveConstructor"; + } + FLAG(hasMoveConstructor, exists); + FLAG(hasSimpleMoveConstructor, simple); + FLAG(hasTrivialMoveConstructor, trivial); + FLAG(hasNonTrivialMoveConstructor, non_trivial); + FLAG(hasUserDeclaredMoveConstructor, user_declared); + FLAG(needsImplicitMoveConstructor, needs_implicit); + FLAG(needsOverloadResolutionForMoveConstructor, + needs_overload_resolution); + if (!D->needsOverloadResolutionForMoveConstructor()) + FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted); + }); + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "CopyAssignment"; + } + FLAG(hasTrivialCopyAssignment, trivial); + FLAG(hasNonTrivialCopyAssignment, non_trivial); + FLAG(hasCopyAssignmentWithConstParam, has_const_param); + FLAG(hasUserDeclaredCopyAssignment, user_declared); + FLAG(needsImplicitCopyAssignment, needs_implicit); + FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution); + FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param); + }); + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "MoveAssignment"; + } + FLAG(hasMoveAssignment, exists); + FLAG(hasSimpleMoveAssignment, simple); + FLAG(hasTrivialMoveAssignment, trivial); + FLAG(hasNonTrivialMoveAssignment, non_trivial); + FLAG(hasUserDeclaredMoveAssignment, user_declared); + FLAG(needsImplicitMoveAssignment, needs_implicit); + FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution); + }); + + AddChild([=] { + { + ColorScope Color(OS, ShowColors, DeclKindNameColor); + OS << "Destructor"; + } + FLAG(hasSimpleDestructor, simple); + FLAG(hasIrrelevantDestructor, irrelevant); + FLAG(hasTrivialDestructor, trivial); + FLAG(hasNonTrivialDestructor, non_trivial); + FLAG(hasUserDeclaredDestructor, user_declared); + FLAG(needsImplicitDestructor, needs_implicit); + FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution); + if (!D->needsOverloadResolutionForDestructor()) + FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted); + }); + }); + + for (const auto &I : D->bases()) { + AddChild([=] { + if (I.isVirtual()) + OS << "virtual "; + dumpAccessSpecifier(I.getAccessSpecifier()); + dumpType(I.getType()); + if (I.isPackExpansion()) + OS << "..."; + }); + } +} + +void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + dumpName(D); +} + +void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { + dumpName(D); +} + +void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { + dumpName(D); +} + +void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { + dumpName(D); +} + +void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + if (D->wasDeclaredWithTypename()) + OS << " typename"; + else + OS << " class"; + OS << " depth " << D->getDepth() << " index " << D->getIndex(); + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); +} + +void TextNodeDumper::VisitNonTypeTemplateParmDecl( + const NonTypeTemplateParmDecl *D) { + dumpType(D->getType()); + OS << " depth " << D->getDepth() << " index " << D->getIndex(); + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); +} + +void TextNodeDumper::VisitTemplateTemplateParmDecl( + const TemplateTemplateParmDecl *D) { + OS << " depth " << D->getDepth() << " index " << D->getIndex(); + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); +} + +void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) { + OS << ' '; + if (D->getQualifier()) + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void TextNodeDumper::VisitUnresolvedUsingTypenameDecl( + const UnresolvedUsingTypenameDecl *D) { + OS << ' '; + if (D->getQualifier()) + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void TextNodeDumper::VisitUnresolvedUsingValueDecl( + const UnresolvedUsingValueDecl *D) { + OS << ' '; + if (D->getQualifier()) + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); + dumpType(D->getType()); +} + +void TextNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getTargetDecl()); +} + +void TextNodeDumper::VisitConstructorUsingShadowDecl( + const ConstructorUsingShadowDecl *D) { + if (D->constructsVirtualBase()) + OS << " virtual"; + + AddChild([=] { + OS << "target "; + dumpBareDeclRef(D->getTargetDecl()); + }); + + AddChild([=] { + OS << "nominated "; + dumpBareDeclRef(D->getNominatedBaseClass()); + OS << ' '; + dumpBareDeclRef(D->getNominatedBaseClassShadowDecl()); + }); + + AddChild([=] { + OS << "constructed "; + dumpBareDeclRef(D->getConstructedBaseClass()); + OS << ' '; + dumpBareDeclRef(D->getConstructedBaseClassShadowDecl()); + }); +} + +void TextNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { + switch (D->getLanguage()) { + case LinkageSpecDecl::lang_c: + OS << " C"; + break; + case LinkageSpecDecl::lang_cxx: + OS << " C++"; + break; + } +} + +void TextNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { + OS << ' '; + dumpAccessSpecifier(D->getAccess()); +} + +void TextNodeDumper::VisitFriendDecl(const FriendDecl *D) { + if (TypeSourceInfo *T = D->getFriendType()) + dumpType(T->getType()); +} + +void TextNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->getSynthesize()) + OS << " synthesize"; + + switch (D->getAccessControl()) { + case ObjCIvarDecl::None: + OS << " none"; + break; + case ObjCIvarDecl::Private: + OS << " private"; + break; + case ObjCIvarDecl::Protected: + OS << " protected"; + break; + case ObjCIvarDecl::Public: + OS << " public"; + break; + case ObjCIvarDecl::Package: + OS << " package"; + break; + } +} + +void TextNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { + if (D->isInstanceMethod()) + OS << " -"; + else + OS << " +"; + dumpName(D); + dumpType(D->getReturnType()); + + if (D->isVariadic()) + OS << " variadic"; +} + +void TextNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) { + dumpName(D); + switch (D->getVariance()) { + case ObjCTypeParamVariance::Invariant: + break; + + case ObjCTypeParamVariance::Covariant: + OS << " covariant"; + break; + + case ObjCTypeParamVariance::Contravariant: + OS << " contravariant"; + break; + } + + if (D->hasExplicitBound()) + OS << " bounded"; + dumpType(D->getUnderlyingType()); +} + +void TextNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + dumpDeclRef(D->getImplementation()); + for (const auto *P : D->protocols()) + dumpDeclRef(P); +} + +void TextNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + dumpDeclRef(D->getCategoryDecl()); +} + +void TextNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { + dumpName(D); + + for (const auto *Child : D->protocols()) + dumpDeclRef(Child); +} + +void TextNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + + dumpDeclRef(D->getImplementation()); + for (const auto *Child : D->protocols()) + dumpDeclRef(Child); +} + +void TextNodeDumper::VisitObjCImplementationDecl( + const ObjCImplementationDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + dumpDeclRef(D->getClassInterface()); +} + +void TextNodeDumper::VisitObjCCompatibleAliasDecl( + const ObjCCompatibleAliasDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); +} + +void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { + dumpName(D); + dumpType(D->getType()); + + if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) + OS << " required"; + else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional) + OS << " optional"; + + ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); + if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { + if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly) + OS << " readonly"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) + OS << " assign"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite) + OS << " readwrite"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_retain) + OS << " retain"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_copy) + OS << " copy"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) + OS << " nonatomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic) + OS << " atomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_weak) + OS << " weak"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_strong) + OS << " strong"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) + OS << " unsafe_unretained"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_class) + OS << " class"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) + dumpDeclRef(D->getGetterMethodDecl(), "getter"); + if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) + dumpDeclRef(D->getSetterMethodDecl(), "setter"); + } +} + +void TextNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { + dumpName(D->getPropertyDecl()); + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) + OS << " synthesize"; + else + OS << " dynamic"; + dumpDeclRef(D->getPropertyDecl()); + dumpDeclRef(D->getPropertyIvarDecl()); +} + +void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) { + if (D->isVariadic()) + OS << " variadic"; + + if (D->capturesCXXThis()) + OS << " captures_this"; +} diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 0dbc88c045..adffe92f95 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1,9 +1,8 @@ //===- Type.cpp - Type representation and manipulation --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -23,6 +22,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" @@ -723,25 +723,30 @@ const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals( return ctx.getObjCObjectPointerType(obj)->castAs<ObjCObjectPointerType>(); } -template<typename F> -static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f); - namespace { -/// Visitor used by simpleTransform() to perform the transformation. -template<typename F> -struct SimpleTransformVisitor - : public TypeVisitor<SimpleTransformVisitor<F>, QualType> { +/// Visitor used to perform a simple type transformation that does not change +/// the semantics of the type. +template <typename Derived> +struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> { ASTContext &Ctx; - F &&TheFunc; QualType recurse(QualType type) { - return simpleTransform(Ctx, type, std::move(TheFunc)); + // Split out the qualifiers from the type. + SplitQualType splitType = type.split(); + + // Visit the type itself. + QualType result = static_cast<Derived *>(this)->Visit(splitType.Ty); + if (result.isNull()) + return result; + + // Reconstruct the transformed type by applying the local qualifiers + // from the split type. + return Ctx.getQualifiedType(result, splitType.Quals); } public: - SimpleTransformVisitor(ASTContext &ctx, F &&f) - : Ctx(ctx), TheFunc(std::move(f)) {} + explicit SimpleTransformVisitor(ASTContext &ctx) : Ctx(ctx) {} // None of the clients of this transformation can occur where // there are dependent types, so skip dependent types. @@ -752,6 +757,17 @@ public: #define TRIVIAL_TYPE_CLASS(Class) \ QualType Visit##Class##Type(const Class##Type *T) { return QualType(T, 0); } +#define SUGARED_TYPE_CLASS(Class) \ + QualType Visit##Class##Type(const Class##Type *T) { \ + if (!T->isSugared()) \ + return QualType(T, 0); \ + QualType desugaredType = recurse(T->desugar()); \ + if (desugaredType.isNull()) \ + return {}; \ + if (desugaredType.getAsOpaquePtr() == T->desugar().getAsOpaquePtr()) \ + return QualType(T, 0); \ + return desugaredType; \ + } TRIVIAL_TYPE_CLASS(Builtin) @@ -955,8 +971,8 @@ public: return Ctx.getParenType(innerType); } - TRIVIAL_TYPE_CLASS(Typedef) - TRIVIAL_TYPE_CLASS(ObjCTypeParam) + SUGARED_TYPE_CLASS(Typedef) + SUGARED_TYPE_CLASS(ObjCTypeParam) QualType VisitAdjustedType(const AdjustedType *T) { QualType originalType = recurse(T->getOriginalType()); @@ -987,15 +1003,15 @@ public: return Ctx.getDecayedType(originalType); } - TRIVIAL_TYPE_CLASS(TypeOfExpr) - TRIVIAL_TYPE_CLASS(TypeOf) - TRIVIAL_TYPE_CLASS(Decltype) - TRIVIAL_TYPE_CLASS(UnaryTransform) + SUGARED_TYPE_CLASS(TypeOfExpr) + SUGARED_TYPE_CLASS(TypeOf) + SUGARED_TYPE_CLASS(Decltype) + SUGARED_TYPE_CLASS(UnaryTransform) TRIVIAL_TYPE_CLASS(Record) TRIVIAL_TYPE_CLASS(Enum) // FIXME: Non-trivial to implement, but important for C++ - TRIVIAL_TYPE_CLASS(Elaborated) + SUGARED_TYPE_CLASS(Elaborated) QualType VisitAttributedType(const AttributedType *T) { QualType modifiedType = recurse(T->getModifiedType()); @@ -1030,7 +1046,7 @@ public: } // FIXME: Non-trivial to implement, but important for C++ - TRIVIAL_TYPE_CLASS(TemplateSpecialization) + SUGARED_TYPE_CLASS(TemplateSpecialization) QualType VisitAutoType(const AutoType *T) { if (!T->isDeduced()) @@ -1049,7 +1065,7 @@ public: } // FIXME: Non-trivial to implement, but important for C++ - TRIVIAL_TYPE_CLASS(PackExpansion) + SUGARED_TYPE_CLASS(PackExpansion) QualType VisitObjCObjectType(const ObjCObjectType *T) { QualType baseType = recurse(T->getBaseType()); @@ -1107,222 +1123,245 @@ public: } #undef TRIVIAL_TYPE_CLASS +#undef SUGARED_TYPE_CLASS }; -} // namespace - -/// Perform a simple type transformation that does not change the -/// semantics of the type. -template<typename F> -static QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) { - // Transform the type. If it changed, return the transformed result. - QualType transformed = f(type); - if (transformed.getAsOpaquePtr() != type.getAsOpaquePtr()) - return transformed; - - // Split out the qualifiers from the type. - SplitQualType splitType = type.split(); - - // Visit the type itself. - SimpleTransformVisitor<F> visitor(ctx, std::forward<F>(f)); - QualType result = visitor.Visit(splitType.Ty); - if (result.isNull()) - return result; +struct SubstObjCTypeArgsVisitor + : public SimpleTransformVisitor<SubstObjCTypeArgsVisitor> { + using BaseType = SimpleTransformVisitor<SubstObjCTypeArgsVisitor>; - // Reconstruct the transformed type by applying the local qualifiers - // from the split type. - return ctx.getQualifiedType(result, splitType.Quals); -} + ArrayRef<QualType> TypeArgs; + ObjCSubstitutionContext SubstContext; -/// Substitute the given type arguments for Objective-C type -/// parameters within the given type, recursively. -QualType QualType::substObjCTypeArgs( - ASTContext &ctx, - ArrayRef<QualType> typeArgs, - ObjCSubstitutionContext context) const { - return simpleTransform(ctx, *this, - [&](QualType type) -> QualType { - SplitQualType splitType = type.split(); + SubstObjCTypeArgsVisitor(ASTContext &ctx, ArrayRef<QualType> typeArgs, + ObjCSubstitutionContext context) + : BaseType(ctx), TypeArgs(typeArgs), SubstContext(context) {} + QualType VisitObjCTypeParamType(const ObjCTypeParamType *OTPTy) { // Replace an Objective-C type parameter reference with the corresponding // type argument. - if (const auto *OTPTy = dyn_cast<ObjCTypeParamType>(splitType.Ty)) { - ObjCTypeParamDecl *typeParam = OTPTy->getDecl(); - // If we have type arguments, use them. - if (!typeArgs.empty()) { - QualType argType = typeArgs[typeParam->getIndex()]; - if (OTPTy->qual_empty()) - return ctx.getQualifiedType(argType, splitType.Quals); - - // Apply protocol lists if exists. - bool hasError; - SmallVector<ObjCProtocolDecl*, 8> protocolsVec; - protocolsVec.append(OTPTy->qual_begin(), - OTPTy->qual_end()); - ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec; - QualType resultTy = ctx.applyObjCProtocolQualifiers(argType, - protocolsToApply, hasError, true/*allowOnPointerType*/); - - return ctx.getQualifiedType(resultTy, splitType.Quals); - } + ObjCTypeParamDecl *typeParam = OTPTy->getDecl(); + // If we have type arguments, use them. + if (!TypeArgs.empty()) { + QualType argType = TypeArgs[typeParam->getIndex()]; + if (OTPTy->qual_empty()) + return argType; + + // Apply protocol lists if exists. + bool hasError; + SmallVector<ObjCProtocolDecl *, 8> protocolsVec; + protocolsVec.append(OTPTy->qual_begin(), OTPTy->qual_end()); + ArrayRef<ObjCProtocolDecl *> protocolsToApply = protocolsVec; + return Ctx.applyObjCProtocolQualifiers( + argType, protocolsToApply, hasError, true/*allowOnPointerType*/); + } - switch (context) { - case ObjCSubstitutionContext::Ordinary: - case ObjCSubstitutionContext::Parameter: - case ObjCSubstitutionContext::Superclass: - // Substitute the bound. - return ctx.getQualifiedType(typeParam->getUnderlyingType(), - splitType.Quals); - - case ObjCSubstitutionContext::Result: - case ObjCSubstitutionContext::Property: { - // Substitute the __kindof form of the underlying type. - const auto *objPtr = typeParam->getUnderlyingType() - ->castAs<ObjCObjectPointerType>(); - - // __kindof types, id, and Class don't need an additional - // __kindof. - if (objPtr->isKindOfType() || objPtr->isObjCIdOrClassType()) - return ctx.getQualifiedType(typeParam->getUnderlyingType(), - splitType.Quals); - - // Add __kindof. - const auto *obj = objPtr->getObjectType(); - QualType resultTy = ctx.getObjCObjectType(obj->getBaseType(), - obj->getTypeArgsAsWritten(), - obj->getProtocols(), - /*isKindOf=*/true); - - // Rebuild object pointer type. - resultTy = ctx.getObjCObjectPointerType(resultTy); - return ctx.getQualifiedType(resultTy, splitType.Quals); - } - } + switch (SubstContext) { + case ObjCSubstitutionContext::Ordinary: + case ObjCSubstitutionContext::Parameter: + case ObjCSubstitutionContext::Superclass: + // Substitute the bound. + return typeParam->getUnderlyingType(); + + case ObjCSubstitutionContext::Result: + case ObjCSubstitutionContext::Property: { + // Substitute the __kindof form of the underlying type. + const auto *objPtr = + typeParam->getUnderlyingType()->castAs<ObjCObjectPointerType>(); + + // __kindof types, id, and Class don't need an additional + // __kindof. + if (objPtr->isKindOfType() || objPtr->isObjCIdOrClassType()) + return typeParam->getUnderlyingType(); + + // Add __kindof. + const auto *obj = objPtr->getObjectType(); + QualType resultTy = Ctx.getObjCObjectType( + obj->getBaseType(), obj->getTypeArgsAsWritten(), obj->getProtocols(), + /*isKindOf=*/true); + + // Rebuild object pointer type. + return Ctx.getObjCObjectPointerType(resultTy); + } + } + llvm_unreachable("Unexpected ObjCSubstitutionContext!"); + } + + QualType VisitFunctionType(const FunctionType *funcType) { + // If we have a function type, update the substitution context + // appropriately. + + //Substitute result type. + QualType returnType = funcType->getReturnType().substObjCTypeArgs( + Ctx, TypeArgs, ObjCSubstitutionContext::Result); + if (returnType.isNull()) + return {}; + + // Handle non-prototyped functions, which only substitute into the result + // type. + if (isa<FunctionNoProtoType>(funcType)) { + // If the return type was unchanged, do nothing. + if (returnType.getAsOpaquePtr() == + funcType->getReturnType().getAsOpaquePtr()) + return BaseType::VisitFunctionType(funcType); + + // Otherwise, build a new type. + return Ctx.getFunctionNoProtoType(returnType, funcType->getExtInfo()); } - // If we have a function type, update the context appropriately. - if (const auto *funcType = dyn_cast<FunctionType>(splitType.Ty)) { - // Substitute result type. - QualType returnType = funcType->getReturnType().substObjCTypeArgs( - ctx, - typeArgs, - ObjCSubstitutionContext::Result); - if (returnType.isNull()) + const auto *funcProtoType = cast<FunctionProtoType>(funcType); + + // Transform parameter types. + SmallVector<QualType, 4> paramTypes; + bool paramChanged = false; + for (auto paramType : funcProtoType->getParamTypes()) { + QualType newParamType = paramType.substObjCTypeArgs( + Ctx, TypeArgs, ObjCSubstitutionContext::Parameter); + if (newParamType.isNull()) return {}; - // Handle non-prototyped functions, which only substitute into the result - // type. - if (isa<FunctionNoProtoType>(funcType)) { - // If the return type was unchanged, do nothing. - if (returnType.getAsOpaquePtr() - == funcType->getReturnType().getAsOpaquePtr()) - return type; + if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr()) + paramChanged = true; - // Otherwise, build a new type. - return ctx.getFunctionNoProtoType(returnType, funcType->getExtInfo()); - } + paramTypes.push_back(newParamType); + } - const auto *funcProtoType = cast<FunctionProtoType>(funcType); - - // Transform parameter types. - SmallVector<QualType, 4> paramTypes; - bool paramChanged = false; - for (auto paramType : funcProtoType->getParamTypes()) { - QualType newParamType = paramType.substObjCTypeArgs( - ctx, - typeArgs, - ObjCSubstitutionContext::Parameter); - if (newParamType.isNull()) + // Transform extended info. + FunctionProtoType::ExtProtoInfo info = funcProtoType->getExtProtoInfo(); + bool exceptionChanged = false; + if (info.ExceptionSpec.Type == EST_Dynamic) { + SmallVector<QualType, 4> exceptionTypes; + for (auto exceptionType : info.ExceptionSpec.Exceptions) { + QualType newExceptionType = exceptionType.substObjCTypeArgs( + Ctx, TypeArgs, ObjCSubstitutionContext::Ordinary); + if (newExceptionType.isNull()) return {}; - if (newParamType.getAsOpaquePtr() != paramType.getAsOpaquePtr()) - paramChanged = true; + if (newExceptionType.getAsOpaquePtr() != exceptionType.getAsOpaquePtr()) + exceptionChanged = true; - paramTypes.push_back(newParamType); + exceptionTypes.push_back(newExceptionType); } - // Transform extended info. - FunctionProtoType::ExtProtoInfo info = funcProtoType->getExtProtoInfo(); - bool exceptionChanged = false; - if (info.ExceptionSpec.Type == EST_Dynamic) { - SmallVector<QualType, 4> exceptionTypes; - for (auto exceptionType : info.ExceptionSpec.Exceptions) { - QualType newExceptionType = exceptionType.substObjCTypeArgs( - ctx, - typeArgs, - ObjCSubstitutionContext::Ordinary); - if (newExceptionType.isNull()) - return {}; - - if (newExceptionType.getAsOpaquePtr() - != exceptionType.getAsOpaquePtr()) - exceptionChanged = true; - - exceptionTypes.push_back(newExceptionType); - } - - if (exceptionChanged) { - info.ExceptionSpec.Exceptions = - llvm::makeArrayRef(exceptionTypes).copy(ctx); - } + if (exceptionChanged) { + info.ExceptionSpec.Exceptions = + llvm::makeArrayRef(exceptionTypes).copy(Ctx); } + } - if (returnType.getAsOpaquePtr() - == funcProtoType->getReturnType().getAsOpaquePtr() && - !paramChanged && !exceptionChanged) - return type; + if (returnType.getAsOpaquePtr() == + funcProtoType->getReturnType().getAsOpaquePtr() && + !paramChanged && !exceptionChanged) + return BaseType::VisitFunctionType(funcType); - return ctx.getFunctionType(returnType, paramTypes, info); - } + return Ctx.getFunctionType(returnType, paramTypes, info); + } + QualType VisitObjCObjectType(const ObjCObjectType *objcObjectType) { // Substitute into the type arguments of a specialized Objective-C object // type. - if (const auto *objcObjectType = dyn_cast<ObjCObjectType>(splitType.Ty)) { - if (objcObjectType->isSpecializedAsWritten()) { - SmallVector<QualType, 4> newTypeArgs; - bool anyChanged = false; - for (auto typeArg : objcObjectType->getTypeArgsAsWritten()) { - QualType newTypeArg = typeArg.substObjCTypeArgs( - ctx, typeArgs, - ObjCSubstitutionContext::Ordinary); - if (newTypeArg.isNull()) - return {}; - - if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr()) { - // If we're substituting based on an unspecialized context type, - // produce an unspecialized type. - ArrayRef<ObjCProtocolDecl *> protocols( - objcObjectType->qual_begin(), - objcObjectType->getNumProtocols()); - if (typeArgs.empty() && - context != ObjCSubstitutionContext::Superclass) { - return ctx.getObjCObjectType( - objcObjectType->getBaseType(), {}, - protocols, - objcObjectType->isKindOfTypeAsWritten()); - } - - anyChanged = true; + if (objcObjectType->isSpecializedAsWritten()) { + SmallVector<QualType, 4> newTypeArgs; + bool anyChanged = false; + for (auto typeArg : objcObjectType->getTypeArgsAsWritten()) { + QualType newTypeArg = typeArg.substObjCTypeArgs( + Ctx, TypeArgs, ObjCSubstitutionContext::Ordinary); + if (newTypeArg.isNull()) + return {}; + + if (newTypeArg.getAsOpaquePtr() != typeArg.getAsOpaquePtr()) { + // If we're substituting based on an unspecialized context type, + // produce an unspecialized type. + ArrayRef<ObjCProtocolDecl *> protocols( + objcObjectType->qual_begin(), objcObjectType->getNumProtocols()); + if (TypeArgs.empty() && + SubstContext != ObjCSubstitutionContext::Superclass) { + return Ctx.getObjCObjectType( + objcObjectType->getBaseType(), {}, protocols, + objcObjectType->isKindOfTypeAsWritten()); } - newTypeArgs.push_back(newTypeArg); + anyChanged = true; } - if (anyChanged) { - ArrayRef<ObjCProtocolDecl *> protocols( - objcObjectType->qual_begin(), - objcObjectType->getNumProtocols()); - return ctx.getObjCObjectType(objcObjectType->getBaseType(), - newTypeArgs, protocols, - objcObjectType->isKindOfTypeAsWritten()); - } + newTypeArgs.push_back(newTypeArg); } - return type; + if (anyChanged) { + ArrayRef<ObjCProtocolDecl *> protocols( + objcObjectType->qual_begin(), objcObjectType->getNumProtocols()); + return Ctx.getObjCObjectType(objcObjectType->getBaseType(), newTypeArgs, + protocols, + objcObjectType->isKindOfTypeAsWritten()); + } } - return type; - }); + return BaseType::VisitObjCObjectType(objcObjectType); + } + + QualType VisitAttributedType(const AttributedType *attrType) { + QualType newType = BaseType::VisitAttributedType(attrType); + if (newType.isNull()) + return {}; + + const auto *newAttrType = dyn_cast<AttributedType>(newType.getTypePtr()); + if (!newAttrType || newAttrType->getAttrKind() != attr::ObjCKindOf) + return newType; + + // Find out if it's an Objective-C object or object pointer type; + QualType newEquivType = newAttrType->getEquivalentType(); + const ObjCObjectPointerType *ptrType = + newEquivType->getAs<ObjCObjectPointerType>(); + const ObjCObjectType *objType = ptrType + ? ptrType->getObjectType() + : newEquivType->getAs<ObjCObjectType>(); + if (!objType) + return newType; + + // Rebuild the "equivalent" type, which pushes __kindof down into + // the object type. + newEquivType = Ctx.getObjCObjectType( + objType->getBaseType(), objType->getTypeArgsAsWritten(), + objType->getProtocols(), + // There is no need to apply kindof on an unqualified id type. + /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true); + + // If we started with an object pointer type, rebuild it. + if (ptrType) + newEquivType = Ctx.getObjCObjectPointerType(newEquivType); + + // Rebuild the attributed type. + return Ctx.getAttributedType(newAttrType->getAttrKind(), + newAttrType->getModifiedType(), newEquivType); + } +}; + +struct StripObjCKindOfTypeVisitor + : public SimpleTransformVisitor<StripObjCKindOfTypeVisitor> { + using BaseType = SimpleTransformVisitor<StripObjCKindOfTypeVisitor>; + + explicit StripObjCKindOfTypeVisitor(ASTContext &ctx) : BaseType(ctx) {} + + QualType VisitObjCObjectType(const ObjCObjectType *objType) { + if (!objType->isKindOfType()) + return BaseType::VisitObjCObjectType(objType); + + QualType baseType = objType->getBaseType().stripObjCKindOfType(Ctx); + return Ctx.getObjCObjectType(baseType, objType->getTypeArgsAsWritten(), + objType->getProtocols(), + /*isKindOf=*/false); + } +}; + +} // namespace + +/// Substitute the given type arguments for Objective-C type +/// parameters within the given type, recursively. +QualType QualType::substObjCTypeArgs(ASTContext &ctx, + ArrayRef<QualType> typeArgs, + ObjCSubstitutionContext context) const { + SubstObjCTypeArgsVisitor visitor(ctx, typeArgs, context); + return visitor.recurse(*this); } QualType QualType::substObjCMemberType(QualType objectType, @@ -1337,25 +1376,8 @@ QualType QualType::substObjCMemberType(QualType objectType, QualType QualType::stripObjCKindOfType(const ASTContext &constCtx) const { // FIXME: Because ASTContext::getAttributedType() is non-const. auto &ctx = const_cast<ASTContext &>(constCtx); - return simpleTransform(ctx, *this, - [&](QualType type) -> QualType { - SplitQualType splitType = type.split(); - if (auto *objType = splitType.Ty->getAs<ObjCObjectType>()) { - if (!objType->isKindOfType()) - return type; - - QualType baseType - = objType->getBaseType().stripObjCKindOfType(ctx); - return ctx.getQualifiedType( - ctx.getObjCObjectType(baseType, - objType->getTypeArgsAsWritten(), - objType->getProtocols(), - /*isKindOf=*/false), - splitType.Quals); - } - - return type; - }); + StripObjCKindOfTypeVisitor visitor(ctx); + return visitor.recurse(*this); } QualType QualType::getAtomicUnqualifiedType() const { @@ -2245,6 +2267,62 @@ bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const { getObjCLifetime() != Qualifiers::OCL_Weak; } +namespace { +// Helper class that determines whether this is a type that is non-trivial to +// primitive copy or move, or is a struct type that has a field of such type. +template <bool IsMove> +struct IsNonTrivialCopyMoveVisitor + : CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool> { + using Super = + CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool>; + IsNonTrivialCopyMoveVisitor(const ASTContext &C) : Ctx(C) {} + void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT) {} + + bool visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT) { + if (const auto *AT = this->Ctx.getAsArrayType(QT)) + return this->asDerived().visit(Ctx.getBaseElementType(AT)); + return Super::visitWithKind(PCK, QT); + } + + bool visitARCStrong(QualType QT) { return true; } + bool visitARCWeak(QualType QT) { return true; } + bool visitTrivial(QualType QT) { return false; } + // Volatile fields are considered trivial. + bool visitVolatileTrivial(QualType QT) { return false; } + + bool visitStruct(QualType QT) { + const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); + // We don't want to apply the C restriction in C++ because C++ + // (1) can apply the restriction at a finer grain by banning copying or + // destroying the union, and + // (2) allows users to override these restrictions by declaring explicit + // constructors/etc, which we're not proposing to add to C. + if (isa<CXXRecordDecl>(RD)) + return false; + for (const FieldDecl *FD : RD->fields()) + if (this->asDerived().visit(FD->getType())) + return true; + return false; + } + + const ASTContext &Ctx; +}; + +} // namespace + +bool QualType::isNonTrivialPrimitiveCType(const ASTContext &Ctx) const { + if (isNonTrivialToPrimitiveDefaultInitialize()) + return true; + DestructionKind DK = isDestructedType(); + if (DK != DK_none && DK != DK_cxx_destructor) + return true; + if (IsNonTrivialCopyMoveVisitor<false>(Ctx).visit(*this)) + return true; + if (IsNonTrivialCopyMoveVisitor<true>(Ctx).visit(*this)) + return true; + return false; +} + QualType::PrimitiveDefaultInitializeKind QualType::isNonTrivialToPrimitiveDefaultInitialize() const { if (const auto *RT = @@ -3206,6 +3284,7 @@ bool AttributedType::isQualifier() const { case attr::TypeNullable: case attr::TypeNullUnspecified: case attr::LifetimeBound: + case attr::AddressSpace: return true; // All other type attributes aren't qualifiers; they rewrite the modified @@ -4016,25 +4095,8 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { void clang::FixedPointValueToString(SmallVectorImpl<char> &Str, llvm::APSInt Val, unsigned Scale) { - if (Val.isSigned() && Val.isNegative() && Val != -Val) { - Val = -Val; - Str.push_back('-'); - } - - llvm::APSInt IntPart = Val >> Scale; - - // Add 4 digits to hold the value after multiplying 10 (the radix) - unsigned Width = Val.getBitWidth() + 4; - llvm::APInt FractPart = Val.zextOrTrunc(Scale).zext(Width); - llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); - llvm::APInt RadixInt = llvm::APInt(Width, 10); - - IntPart.toString(Str, /*radix=*/10); - Str.push_back('.'); - do { - (FractPart * RadixInt) - .lshr(Scale) - .toString(Str, /*radix=*/10, Val.isSigned()); - FractPart = (FractPart * RadixInt) & FractPartMask; - } while (FractPart != 0); + FixedPointSemantics FXSema(Val.getBitWidth(), Scale, Val.isSigned(), + /*isSaturated=*/false, + /*hasUnsignedPadding=*/false); + APFixedPoint(Val, FXSema).toString(Str); } diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index b7b2f188d7..abe4c4eb25 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -1,9 +1,8 @@ //===- TypeLoc.cpp - Type Source Info Wrapper -----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 32c75afb43..8504532497 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -1,9 +1,8 @@ //===- TypePrinter.cpp - Pretty-Print Clang Types -------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -258,11 +257,17 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::FunctionProto: case Type::FunctionNoProto: case Type::Paren: - case Type::Attributed: case Type::PackExpansion: case Type::SubstTemplateTypeParm: CanPrefixQualifiers = false; break; + + case Type::Attributed: { + // We still want to print the address_space before the type if it is an + // address_space attribute. + const auto *AttrTy = cast<AttributedType>(T); + CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace; + } } return CanPrefixQualifiers; @@ -810,8 +815,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, printFunctionAfter(Info, OS); - if (!T->getTypeQuals().empty()) - OS << " " << T->getTypeQuals().getAsString(); + if (!T->getMethodQuals().empty()) + OS << " " << T->getMethodQuals().getAsString(); switch (T->getRefQualifier()) { case RQ_None: @@ -1212,8 +1217,18 @@ void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T, raw_ostream &OS) { if (IdentifierInfo *Id = T->getIdentifier()) OS << Id->getName(); - else - OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex(); + else { + bool IsLambdaAutoParam = false; + if (auto D = T->getDecl()) { + if (auto M = dyn_cast_or_null<CXXMethodDecl>(D->getDeclContext())) + IsLambdaAutoParam = D->isImplicit() && M->getParent()->isLambda(); + } + + if (IsLambdaAutoParam) + OS << "auto"; + else + OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex(); + } spaceBeforePlaceHolder(OS); } @@ -1378,7 +1393,10 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, if (T->getAttrKind() == attr::ObjCKindOf) OS << "__kindof "; - printBefore(T->getModifiedType(), OS); + if (T->getAttrKind() == attr::AddressSpace) + printBefore(T->getEquivalentType(), OS); + else + printBefore(T->getModifiedType(), OS); if (T->isMSTypeSpec()) { switch (T->getAttrKind()) { @@ -1624,6 +1642,19 @@ static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) { return A.getArgument(); } +static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP, + llvm::raw_ostream &OS) { + A.print(PP, OS); +} + +static void printArgument(const TemplateArgumentLoc &A, + const PrintingPolicy &PP, llvm::raw_ostream &OS) { + const TemplateArgument::ArgKind &Kind = A.getArgument().getKind(); + if (Kind == TemplateArgument::ArgKind::Type) + return A.getTypeSourceInfo()->getType().print(OS, PP); + return A.getArgument().print(PP, OS); +} + template<typename TA> static void printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy, bool SkipBrackets) { @@ -1645,7 +1676,8 @@ static void printTo(raw_ostream &OS, ArrayRef<TA> Args, } else { if (!FirstArg) OS << Comma; - Argument.print(Policy, ArgOS); + // Tries to print the argument with location info if exists. + printArgument(Arg, Policy, ArgOS); } StringRef ArgString = ArgOS.str(); diff --git a/lib/AST/VTTBuilder.cpp b/lib/AST/VTTBuilder.cpp index a3f3dbdfb4..53d0ef09f1 100644 --- a/lib/AST/VTTBuilder.cpp +++ b/lib/AST/VTTBuilder.cpp @@ -1,9 +1,8 @@ //===- VTTBuilder.cpp - C++ VTT layout builder ----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp index 846a608574..5c79ea37ab 100644 --- a/lib/AST/VTableBuilder.cpp +++ b/lib/AST/VTableBuilder.cpp @@ -1,9 +1,8 @@ //===--- VTableBuilder.cpp - C++ vtable layout builder --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -480,7 +479,7 @@ static bool HasSameVirtualSignature(const CXXMethodDecl *LHS, // Force the signatures to match. We can't rely on the overrides // list here because there isn't necessarily an inheritance // relationship between the two methods. - if (LT->getTypeQuals() != RT->getTypeQuals()) + if (LT->getMethodQuals() != RT->getMethodQuals()) return false; return LT->getParamTypes() == RT->getParamTypes(); } @@ -847,6 +846,8 @@ private: : BaseOffset(CharUnits::Zero()), BaseOffsetInLayoutClass(CharUnits::Zero()), VTableIndex(0) { } + + MethodInfo(MethodInfo const&) = default; }; typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy; @@ -1061,8 +1062,7 @@ void ItaniumVTableBuilder::AddThunk(const CXXMethodDecl *MD, SmallVectorImpl<ThunkInfo> &ThunksVector = Thunks[MD]; // Check if we have this thunk already. - if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) != - ThunksVector.end()) + if (llvm::find(ThunksVector, Thunk) != ThunksVector.end()) return; ThunksVector.push_back(Thunk); @@ -2451,8 +2451,7 @@ private: SmallVector<ThunkInfo, 1> &ThunksVector = Thunks[MD]; // Check if we have this thunk already. - if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) != - ThunksVector.end()) + if (llvm::find(ThunksVector, Thunk) != ThunksVector.end()) return; ThunksVector.push_back(Thunk); @@ -3189,8 +3188,8 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { const CXXMethodDecl *MD = MethodNameAndDecl.second; ThunkInfoVectorTy ThunksVector = Thunks[MD]; - std::stable_sort(ThunksVector.begin(), ThunksVector.end(), - [](const ThunkInfo &LHS, const ThunkInfo &RHS) { + llvm::stable_sort(ThunksVector, [](const ThunkInfo &LHS, + const ThunkInfo &RHS) { // Keep different thunks with the same adjustments in the order they // were put into the vector. return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return); |