diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST')
39 files changed, 11242 insertions, 3515 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/APValue.cpp b/contrib/llvm/tools/clang/lib/AST/APValue.cpp index 6f63a32..a31b3c5 100644 --- a/contrib/llvm/tools/clang/lib/AST/APValue.cpp +++ b/contrib/llvm/tools/clang/lib/AST/APValue.cpp @@ -12,7 +12,11 @@ //===----------------------------------------------------------------------===// #include "clang/AST/APValue.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" @@ -20,49 +24,169 @@ using namespace clang; namespace { - struct LV { - const Expr* Base; + struct LVBase { + llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd; CharUnits Offset; + unsigned PathLength; + unsigned CallIndex; }; } -APValue::APValue(const Expr* B) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, CharUnits::Zero()); -} - -const APValue &APValue::operator=(const APValue &RHS) { - if (Kind != RHS.Kind) { - MakeUninit(); - if (RHS.isInt()) - MakeInt(); - else if (RHS.isFloat()) - MakeFloat(); - else if (RHS.isVector()) - MakeVector(); - else if (RHS.isComplexInt()) - MakeComplexInt(); - else if (RHS.isComplexFloat()) - MakeComplexFloat(); - else if (RHS.isLValue()) - MakeLValue(); +struct APValue::LV : LVBase { + static const unsigned InlinePathSpace = + (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry); + + /// Path - The sequence of base classes, fields and array indices to follow to + /// walk from Base to the subobject. When performing GCC-style folding, there + /// may not be such a path. + union { + LValuePathEntry Path[InlinePathSpace]; + LValuePathEntry *PathPtr; + }; + + LV() { PathLength = (unsigned)-1; } + ~LV() { resizePath(0); } + + void resizePath(unsigned Length) { + if (Length == PathLength) + return; + if (hasPathPtr()) + delete [] PathPtr; + PathLength = Length; + if (hasPathPtr()) + PathPtr = new LValuePathEntry[Length]; + } + + bool hasPath() const { return PathLength != (unsigned)-1; } + bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } + + LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; } + const LValuePathEntry *getPath() const { + return hasPathPtr() ? PathPtr : Path; + } +}; + +namespace { + struct MemberPointerBase { + llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; + unsigned PathLength; + }; +} + +struct APValue::MemberPointerData : MemberPointerBase { + static const unsigned InlinePathSpace = + (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); + typedef const CXXRecordDecl *PathElem; + union { + PathElem Path[InlinePathSpace]; + PathElem *PathPtr; + }; + + MemberPointerData() { PathLength = 0; } + ~MemberPointerData() { resizePath(0); } + + void resizePath(unsigned Length) { + if (Length == PathLength) + return; + if (hasPathPtr()) + delete [] PathPtr; + PathLength = Length; + if (hasPathPtr()) + PathPtr = new PathElem[Length]; } - if (isInt()) + + bool hasPathPtr() const { return PathLength > InlinePathSpace; } + + PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } + const PathElem *getPath() const { + return hasPathPtr() ? PathPtr : Path; + } +}; + +// FIXME: Reduce the malloc traffic here. + +APValue::Arr::Arr(unsigned NumElts, unsigned Size) : + Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), + NumElts(NumElts), ArrSize(Size) {} +APValue::Arr::~Arr() { delete [] Elts; } + +APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) : + Elts(new APValue[NumBases+NumFields]), + NumBases(NumBases), NumFields(NumFields) {} +APValue::StructData::~StructData() { + delete [] Elts; +} + +APValue::UnionData::UnionData() : Field(0), Value(new APValue) {} +APValue::UnionData::~UnionData () { + delete Value; +} + +APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { + switch (RHS.getKind()) { + case Uninitialized: + break; + case Int: + MakeInt(); setInt(RHS.getInt()); - else if (isFloat()) + break; + case Float: + MakeFloat(); setFloat(RHS.getFloat()); - else if (isVector()) + break; + case Vector: + MakeVector(); setVector(((const Vec *)(const char *)RHS.Data)->Elts, RHS.getVectorLength()); - else if (isComplexInt()) + break; + case ComplexInt: + MakeComplexInt(); setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); - else if (isComplexFloat()) + break; + case ComplexFloat: + MakeComplexFloat(); setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); - else if (isLValue()) - setLValue(RHS.getLValueBase(), RHS.getLValueOffset()); - return *this; + break; + case LValue: + MakeLValue(); + if (RHS.hasLValuePath()) + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), + RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex()); + else + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), + RHS.getLValueCallIndex()); + break; + case Array: + MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); + for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) + getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); + if (RHS.hasArrayFiller()) + getArrayFiller() = RHS.getArrayFiller(); + break; + case Struct: + MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); + for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) + getStructBase(I) = RHS.getStructBase(I); + for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) + getStructField(I) = RHS.getStructField(I); + break; + case Union: + MakeUnion(); + setUnion(RHS.getUnionField(), RHS.getUnionValue()); + break; + case MemberPointer: + MakeMemberPointer(RHS.getMemberPointerDecl(), + RHS.isMemberPointerToDerivedMember(), + RHS.getMemberPointerPath()); + break; + case AddrLabelDiff: + MakeAddrLabelDiff(); + setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); + break; + } } -void APValue::MakeUninit() { +void APValue::DestroyDataAndMakeUninit() { if (Kind == Int) ((APSInt*)(char*)Data)->~APSInt(); else if (Kind == Float) @@ -73,14 +197,31 @@ void APValue::MakeUninit() { ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt(); else if (Kind == ComplexFloat) ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat(); - else if (Kind == LValue) { + else if (Kind == LValue) ((LV*)(char*)Data)->~LV(); - } + else if (Kind == Array) + ((Arr*)(char*)Data)->~Arr(); + else if (Kind == Struct) + ((StructData*)(char*)Data)->~StructData(); + else if (Kind == Union) + ((UnionData*)(char*)Data)->~UnionData(); + else if (Kind == MemberPointer) + ((MemberPointerData*)(char*)Data)->~MemberPointerData(); + else if (Kind == AddrLabelDiff) + ((AddrLabelDiffData*)(char*)Data)->~AddrLabelDiffData(); Kind = Uninitialized; } +void APValue::swap(APValue &RHS) { + std::swap(Kind, RHS.Kind); + char TmpData[MaxSize]; + memcpy(TmpData, Data, MaxSize); + memcpy(Data, RHS.Data, MaxSize); + memcpy(RHS.Data, TmpData, MaxSize); +} + void APValue::dump() const { - print(llvm::errs()); + dump(llvm::errs()); llvm::errs() << '\n'; } @@ -92,9 +233,8 @@ static double GetApproxValue(const llvm::APFloat &F) { return V.convertToDouble(); } -void APValue::print(raw_ostream &OS) const { +void APValue::dump(raw_ostream &OS) const { switch (getKind()) { - default: llvm_unreachable("Unknown APValue kind!"); case Uninitialized: OS << "Uninitialized"; return; @@ -105,9 +245,12 @@ void APValue::print(raw_ostream &OS) const { OS << "Float: " << GetApproxValue(getFloat()); return; case Vector: - OS << "Vector: " << getVectorElt(0); - for (unsigned i = 1; i != getVectorLength(); ++i) - OS << ", " << getVectorElt(i); + OS << "Vector: "; + getVectorElt(0).dump(OS); + for (unsigned i = 1; i != getVectorLength(); ++i) { + OS << ", "; + getVectorElt(i).dump(OS); + } return; case ComplexInt: OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); @@ -115,74 +258,350 @@ void APValue::print(raw_ostream &OS) const { case ComplexFloat: OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) << ", " << GetApproxValue(getComplexFloatImag()); + return; case LValue: OS << "LValue: <todo>"; return; + case Array: + OS << "Array: "; + for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { + getArrayInitializedElt(I).dump(OS); + if (I != getArraySize() - 1) OS << ", "; + } + if (hasArrayFiller()) { + OS << getArraySize() - getArrayInitializedElts() << " x "; + getArrayFiller().dump(OS); + } + return; + case Struct: + OS << "Struct "; + if (unsigned N = getStructNumBases()) { + OS << " bases: "; + getStructBase(0).dump(OS); + for (unsigned I = 1; I != N; ++I) { + OS << ", "; + getStructBase(I).dump(OS); + } + } + if (unsigned N = getStructNumFields()) { + OS << " fields: "; + getStructField(0).dump(OS); + for (unsigned I = 1; I != N; ++I) { + OS << ", "; + getStructField(I).dump(OS); + } + } + return; + case Union: + OS << "Union: "; + getUnionValue().dump(OS); + return; + case MemberPointer: + OS << "MemberPointer: <todo>"; + return; + case AddrLabelDiff: + OS << "AddrLabelDiff: <todo>"; + return; } + llvm_unreachable("Unknown APValue kind!"); } -static void WriteShortAPValueToStream(raw_ostream& Out, - const APValue& V) { - switch (V.getKind()) { - default: llvm_unreachable("Unknown APValue kind!"); +void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ + switch (getKind()) { case APValue::Uninitialized: - Out << "Uninitialized"; - break; + Out << "<uninitialized>"; + return; case APValue::Int: - Out << V.getInt(); - break; + if (Ty->isBooleanType()) + Out << (getInt().getBoolValue() ? "true" : "false"); + else + Out << getInt(); + return; case APValue::Float: - Out << GetApproxValue(V.getFloat()); - break; - case APValue::Vector: - Out << '['; - WriteShortAPValueToStream(Out, V.getVectorElt(0)); - for (unsigned i = 1; i != V.getVectorLength(); ++i) { + Out << GetApproxValue(getFloat()); + return; + case APValue::Vector: { + Out << '{'; + QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); + getVectorElt(0).printPretty(Out, Ctx, ElemTy); + for (unsigned i = 1; i != getVectorLength(); ++i) { Out << ", "; - WriteShortAPValueToStream(Out, V.getVectorElt(i)); + getVectorElt(i).printPretty(Out, Ctx, ElemTy); } - Out << ']'; - break; + Out << '}'; + return; + } case APValue::ComplexInt: - Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i"; - break; + Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; + return; case APValue::ComplexFloat: - Out << GetApproxValue(V.getComplexFloatReal()) << "+" - << GetApproxValue(V.getComplexFloatImag()) << "i"; - break; - case APValue::LValue: - Out << "LValue: <todo>"; - break; + Out << GetApproxValue(getComplexFloatReal()) << "+" + << GetApproxValue(getComplexFloatImag()) << "i"; + return; + case APValue::LValue: { + LValueBase Base = getLValueBase(); + if (!Base) { + Out << "0"; + return; + } + + bool IsReference = Ty->isReferenceType(); + QualType InnerTy + = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); + + if (!hasLValuePath()) { + // No lvalue path: just print the offset. + CharUnits O = getLValueOffset(); + CharUnits S = Ctx.getTypeSizeInChars(InnerTy); + if (!O.isZero()) { + if (IsReference) + Out << "*("; + if (O % S) { + Out << "(char*)"; + S = CharUnits::One(); + } + Out << '&'; + } else if (!IsReference) + Out << '&'; + + if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) + Out << *VD; + else + Base.get<const Expr*>()->printPretty(Out, Ctx, 0, + Ctx.getPrintingPolicy()); + if (!O.isZero()) { + Out << " + " << (O / S); + if (IsReference) + Out << ')'; + } + return; + } + + // We have an lvalue path. Print it out nicely. + if (!IsReference) + Out << '&'; + else if (isLValueOnePastTheEnd()) + Out << "*(&"; + + QualType ElemTy; + if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { + Out << *VD; + ElemTy = VD->getType(); + } else { + const Expr *E = Base.get<const Expr*>(); + E->printPretty(Out, Ctx, 0,Ctx.getPrintingPolicy()); + ElemTy = E->getType(); + } + + ArrayRef<LValuePathEntry> Path = getLValuePath(); + const CXXRecordDecl *CastToBase = 0; + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + if (ElemTy->getAs<RecordType>()) { + // The lvalue refers to a class type, so the next path entry is a base + // or member. + const Decl *BaseOrMember = + BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer(); + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { + CastToBase = RD; + ElemTy = Ctx.getRecordType(RD); + } else { + const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); + Out << "."; + if (CastToBase) + Out << *CastToBase << "::"; + Out << *VD; + ElemTy = VD->getType(); + } + } else { + // The lvalue must refer to an array. + Out << '[' << Path[I].ArrayIndex << ']'; + ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); + } + } + + // Handle formatting of one-past-the-end lvalues. + if (isLValueOnePastTheEnd()) { + // FIXME: If CastToBase is non-0, we should prefix the output with + // "(CastToBase*)". + Out << " + 1"; + if (IsReference) + Out << ')'; + } + return; } + case APValue::Array: { + const ArrayType *AT = Ctx.getAsArrayType(Ty); + QualType ElemTy = AT->getElementType(); + Out << '{'; + if (unsigned N = getArrayInitializedElts()) { + getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); + for (unsigned I = 1; I != N; ++I) { + Out << ", "; + if (I == 10) { + // Avoid printing out the entire contents of large arrays. + Out << "..."; + break; + } + getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); + } + } + Out << '}'; + return; + } + case APValue::Struct: { + Out << '{'; + const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); + bool First = true; + if (unsigned N = getStructNumBases()) { + const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); + CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); + for (unsigned I = 0; I != N; ++I, ++BI) { + assert(BI != CD->bases_end()); + if (!First) + Out << ", "; + getStructBase(I).printPretty(Out, Ctx, BI->getType()); + First = false; + } + } + for (RecordDecl::field_iterator FI = RD->field_begin(); + FI != RD->field_end(); ++FI) { + if (!First) + Out << ", "; + if ((*FI)->isUnnamedBitfield()) continue; + getStructField((*FI)->getFieldIndex()). + printPretty(Out, Ctx, (*FI)->getType()); + First = false; + } + Out << '}'; + return; + } + case APValue::Union: + Out << '{'; + if (const FieldDecl *FD = getUnionField()) { + Out << "." << *FD << " = "; + getUnionValue().printPretty(Out, Ctx, FD->getType()); + } + Out << '}'; + return; + case APValue::MemberPointer: + // FIXME: This is not enough to unambiguously identify the member in a + // multiple-inheritance scenario. + if (const ValueDecl *VD = getMemberPointerDecl()) { + Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; + return; + } + Out << "0"; + return; + case APValue::AddrLabelDiff: + Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); + Out << " - "; + Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); + return; + } + llvm_unreachable("Unknown APValue kind!"); +} + +std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { + std::string Result; + llvm::raw_string_ostream Out(Result); + printPretty(Out, Ctx, Ty); + Out.flush(); + return Result; +} + +const APValue::LValueBase APValue::getLValueBase() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer(); +} + +bool APValue::isLValueOnePastTheEnd() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt(); } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - const APValue &V) { - llvm::SmallString<64> Buffer; - llvm::raw_svector_ostream Out(Buffer); - WriteShortAPValueToStream(Out, V); - return DB << Out.str(); +CharUnits &APValue::getLValueOffset() { + assert(isLValue() && "Invalid accessor"); + return ((LV*)(void*)Data)->Offset; } -const Expr* APValue::getLValueBase() const { +bool APValue::hasLValuePath() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->Base; + return ((const LV*)(const char*)Data)->hasPath(); } -CharUnits APValue::getLValueOffset() const { - assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->Offset; +ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { + assert(isLValue() && hasLValuePath() && "Invalid accessor"); + const LV &LVal = *((const LV*)(const char*)Data); + return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength); } -void APValue::setLValue(const Expr *B, const CharUnits &O) { +unsigned APValue::getLValueCallIndex() const { assert(isLValue() && "Invalid accessor"); - ((LV*)(char*)Data)->Base = B; - ((LV*)(char*)Data)->Offset = O; + return ((const LV*)(const char*)Data)->CallIndex; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, + unsigned CallIndex) { + assert(isLValue() && "Invalid accessor"); + LV &LVal = *((LV*)(char*)Data); + LVal.BaseAndIsOnePastTheEnd.setPointer(B); + LVal.BaseAndIsOnePastTheEnd.setInt(false); + LVal.Offset = O; + LVal.CallIndex = CallIndex; + LVal.resizePath((unsigned)-1); +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, + unsigned CallIndex) { + assert(isLValue() && "Invalid accessor"); + LV &LVal = *((LV*)(char*)Data); + LVal.BaseAndIsOnePastTheEnd.setPointer(B); + LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd); + LVal.Offset = O; + LVal.CallIndex = CallIndex; + LVal.resizePath(Path.size()); + memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); +} + +const ValueDecl *APValue::getMemberPointerDecl() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + return MPD.MemberAndIsDerivedMember.getPointer(); +} + +bool APValue::isMemberPointerToDerivedMember() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + return MPD.MemberAndIsDerivedMember.getInt(); +} + +ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength); } void APValue::MakeLValue() { assert(isUninit() && "Bad state change"); + assert(sizeof(LV) <= MaxSize && "LV too big"); new ((void*)(char*)Data) LV(); Kind = LValue; } +void APValue::MakeArray(unsigned InitElts, unsigned Size) { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) Arr(InitElts, Size); + Kind = Array; +} + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path) { + assert(isUninit() && "Bad state change"); + MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData; + Kind = MemberPointer; + MPD->MemberAndIsDerivedMember.setPointer(Member); + MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); + MPD->resizePath(Path.size()); + memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp index 04a084a..1672bc8 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTConsumer.cpp @@ -15,8 +15,12 @@ #include "clang/AST/DeclGroup.h" using namespace clang; -void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {} +bool ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) { + return true; +} void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) { HandleTopLevelDecl(D); } + +void ASTConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {} diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 0833286..acf5e0b 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -74,12 +74,14 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { ID.AddInteger(1); ID.AddBoolean(NTTP->isParameterPack()); - ID.AddPointer(NTTP->getType().getAsOpaquePtr()); + ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr()); if (NTTP->isExpandedParameterPack()) { ID.AddBoolean(true); ID.AddInteger(NTTP->getNumExpansionTypes()); - for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) - ID.AddPointer(NTTP->getExpansionType(I).getAsOpaquePtr()); + for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { + QualType T = NTTP->getExpansionType(I); + ID.AddPointer(T.getCanonicalType().getAsOpaquePtr()); + } } else ID.AddBoolean(false); continue; @@ -193,7 +195,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { case CXXABI_Microsoft: return CreateMicrosoftCXXABI(*this); } - return 0; + llvm_unreachable("Invalid CXXABI type!"); } static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T, @@ -224,13 +226,14 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, SubstTemplateTemplateParmPacks(this_()), GlobalNestedNameSpecifier(0), Int128Decl(0), UInt128Decl(0), - ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), + ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0), CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0), - NullTypeSourceInfo(QualType()), + NullTypeSourceInfo(QualType()), + FirstLocalImport(), LastLocalImport(), SourceMgr(SM), LangOpts(LOpts), AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), @@ -258,12 +261,6 @@ ASTContext::~ASTContext() { for (unsigned I = 0, N = Deallocations.size(); I != N; ++I) Deallocations[I].first(Deallocations[I].second); - // Release all of the memory associated with overridden C++ methods. - for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator - OM = OverriddenMethods.begin(), OMEnd = OverriddenMethods.end(); - OM != OMEnd; ++OM) - OM->second.Destroy(); - // ASTRecordLayout objects in ASTRecordLayouts must always be destroyed // because they can contain DenseMaps. for (llvm::DenseMap<const ObjCContainerDecl*, @@ -291,7 +288,7 @@ void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { } void -ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) { +ASTContext::setExternalSource(OwningPtr<ExternalASTSource> &Source) { ExternalSource.reset(Source.take()); } @@ -331,14 +328,14 @@ void ASTContext::PrintStats() const { llvm::errs() << NumImplicitCopyConstructorsDeclared << "/" << NumImplicitCopyConstructors << " implicit copy constructors created\n"; - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) llvm::errs() << NumImplicitMoveConstructorsDeclared << "/" << NumImplicitMoveConstructors << " implicit move constructors created\n"; llvm::errs() << NumImplicitCopyAssignmentOperatorsDeclared << "/" << NumImplicitCopyAssignmentOperators << " implicit copy assignment operators created\n"; - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) llvm::errs() << NumImplicitMoveAssignmentOperatorsDeclared << "/" << NumImplicitMoveAssignmentOperators << " implicit move assignment operators created\n"; @@ -462,9 +459,15 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { // Placeholder type for bound members. InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember); + // Placeholder type for pseudo-objects. + InitBuiltinType(PseudoObjectTy, BuiltinType::PseudoObject); + // "any" type; useful for debugger-like clients. InitBuiltinType(UnknownAnyTy, BuiltinType::UnknownAny); + // Placeholder type for unbridged ARC casts. + InitBuiltinType(ARCUnbridgedCastTy, BuiltinType::ARCUnbridgedCast); + // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); @@ -476,7 +479,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass); InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel); - + + // Builtin type for __objc_yes and __objc_no + ObjCBuiltinBoolTy = SignedCharTy; + ObjCConstantStringType = QualType(); // void * type @@ -676,6 +682,19 @@ void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method, OverriddenMethods[Method].push_back(Overridden); } +void ASTContext::addedLocalImportDecl(ImportDecl *Import) { + assert(!Import->NextLocalImport && "Import declaration already in the chain"); + assert(!Import->isFromASTFile() && "Non-local import declaration"); + if (!FirstLocalImport) { + FirstLocalImport = Import; + LastLocalImport = Import; + return; + } + + LastLocalImport->NextLocalImport = Import; + LastLocalImport = Import; +} + //===----------------------------------------------------------------------===// // Type Sizing and Analysis //===----------------------------------------------------------------------===// @@ -796,14 +815,24 @@ ASTContext::getTypeInfoInChars(QualType T) const { return getTypeInfoInChars(T.getTypePtr()); } -/// getTypeSize - Return the size of the specified type, in bits. This method -/// does not work on incomplete types. +std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const { + TypeInfoMap::iterator it = MemoizedTypeInfo.find(T); + if (it != MemoizedTypeInfo.end()) + return it->second; + + std::pair<uint64_t, unsigned> Info = getTypeInfoImpl(T); + MemoizedTypeInfo.insert(std::make_pair(T, Info)); + return Info; +} + +/// getTypeInfoImpl - Return the size of the specified type, in bits. This +/// method does not work on incomplete types. /// /// FIXME: Pointers into different addr spaces could have different sizes and /// alignment requirements: getPointerInfo should take an AddrSpace, this /// should take a QualType, &c. std::pair<uint64_t, unsigned> -ASTContext::getTypeInfo(const Type *T) const { +ASTContext::getTypeInfoImpl(const Type *T) const { uint64_t Width=0; unsigned Align=8; switch (T->getTypeClass()) { @@ -813,7 +842,6 @@ ASTContext::getTypeInfo(const Type *T) const { #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" llvm_unreachable("Should not see dependent types"); - break; case Type::FunctionNoProto: case Type::FunctionProto: @@ -832,7 +860,10 @@ ASTContext::getTypeInfo(const Type *T) const { const ConstantArrayType *CAT = cast<ConstantArrayType>(T); std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType()); - Width = EltInfo.first*CAT->getSize().getZExtValue(); + uint64_t Size = CAT->getSize().getZExtValue(); + assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) && + "Overflow in array type bit size evaluation"); + Width = EltInfo.first*Size; Align = EltInfo.second; Width = llvm::RoundUpToAlignment(Width, Align); break; @@ -1134,7 +1165,8 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { if (const ComplexType* CT = T->getAs<ComplexType>()) T = CT->getElementType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || - T->isSpecificBuiltinType(BuiltinType::LongLong)) + T->isSpecificBuiltinType(BuiltinType::LongLong) || + T->isSpecificBuiltinType(BuiltinType::ULongLong)) return std::max(ABIAlign, (unsigned)getTypeSize(T)); return ABIAlign; @@ -1173,10 +1205,10 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(), PE = OI->all_referenced_protocol_end(); P != PE; ++P) { ObjCProtocolDecl *Proto = (*P); - Protocols.insert(Proto); + Protocols.insert(Proto->getCanonicalDecl()); for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), PE = Proto->protocol_end(); P != PE; ++P) { - Protocols.insert(*P); + Protocols.insert((*P)->getCanonicalDecl()); CollectInheritedProtocols(*P, Protocols); } } @@ -1194,7 +1226,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(), PE = OC->protocol_end(); P != PE; ++P) { ObjCProtocolDecl *Proto = (*P); - Protocols.insert(Proto); + Protocols.insert(Proto->getCanonicalDecl()); for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), PE = Proto->protocol_end(); P != PE; ++P) CollectInheritedProtocols(*P, Protocols); @@ -1203,7 +1235,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(), PE = OP->protocol_end(); P != PE; ++P) { ObjCProtocolDecl *Proto = (*P); - Protocols.insert(Proto); + Protocols.insert(Proto->getCanonicalDecl()); for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), PE = Proto->protocol_end(); P != PE; ++P) CollectInheritedProtocols(*P, Protocols); @@ -1226,6 +1258,24 @@ unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { return count; } +bool ASTContext::isSentinelNullExpr(const Expr *E) { + if (!E) + return false; + + // nullptr_t is always treated as null. + if (E->getType()->isNullPtrType()) return true; + + if (E->getType()->isAnyPointerType() && + E->IgnoreParenCasts()->isNullPointerConstant(*this, + Expr::NPC_ValueDependentIsNull)) + return true; + + // Unfortunately, __null has type 'int'. + if (isa<GNUNullExpr>(E)) return true; + + return false; +} + /// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists. ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) { llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator @@ -1256,6 +1306,17 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCImpls[CatD] = ImplD; } +ObjCInterfaceDecl *ASTContext::getObjContainingInterface(NamedDecl *ND) const { + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) + return ID; + if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) + return CD->getClassInterface(); + if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext())) + return IMD->getClassInterface(); + + return 0; +} + /// \brief Get the copy initialization expression of VarDecl,or NULL if /// none exists. Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { @@ -1337,8 +1398,8 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const { QualType canon; if (!baseType->isCanonicalUnqualified()) { SplitQualType canonSplit = baseType->getCanonicalTypeInternal().split(); - canonSplit.second.addConsistentQualifiers(quals); - canon = getExtQualType(canonSplit.first, canonSplit.second); + canonSplit.Quals.addConsistentQualifiers(quals); + canon = getExtQualType(canonSplit.Ty, canonSplit.Quals); // Re-find the insert position. (void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos); @@ -1640,9 +1701,9 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, QualType Canon; if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) { SplitQualType canonSplit = getCanonicalType(EltTy).split(); - Canon = getConstantArrayType(QualType(canonSplit.first, 0), ArySize, + Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize, ASM, IndexTypeQuals); - Canon = getQualifiedType(Canon, canonSplit.second); + Canon = getQualifiedType(Canon, canonSplit.Quals); // Get the new insert position for the node we care about. ConstantArrayType *NewIP = @@ -1667,7 +1728,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { QualType result; SplitQualType split = type.getSplitDesugaredType(); - const Type *ty = split.first; + const Type *ty = split.Ty; switch (ty->getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) @@ -1786,7 +1847,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { } // Apply the top-level qualifiers from the original. - return getQualifiedType(result, split.second); + return getQualifiedType(result, split.Quals); } /// getVariableArrayType - Returns a non-unique reference to the type for a @@ -1803,9 +1864,9 @@ QualType ASTContext::getVariableArrayType(QualType EltTy, // Be sure to pull qualifiers off the element type. if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) { SplitQualType canonSplit = getCanonicalType(EltTy).split(); - Canon = getVariableArrayType(QualType(canonSplit.first, 0), NumElts, ASM, + Canon = getVariableArrayType(QualType(canonSplit.Ty, 0), NumElts, ASM, IndexTypeQuals, Brackets); - Canon = getQualifiedType(Canon, canonSplit.second); + Canon = getQualifiedType(Canon, canonSplit.Quals); } VariableArrayType *New = new(*this, TypeAlignment) @@ -1850,7 +1911,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, void *insertPos = 0; llvm::FoldingSetNodeID ID; DependentSizedArrayType::Profile(ID, *this, - QualType(canonElementType.first, 0), + QualType(canonElementType.Ty, 0), ASM, elementTypeQuals, numElements); // Look for an existing type with these properties. @@ -1860,7 +1921,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // If we don't have one, build one. if (!canonTy) { canonTy = new (*this, TypeAlignment) - DependentSizedArrayType(*this, QualType(canonElementType.first, 0), + DependentSizedArrayType(*this, QualType(canonElementType.Ty, 0), QualType(), numElements, ASM, elementTypeQuals, brackets); DependentSizedArrayTypes.InsertNode(canonTy, insertPos); @@ -1869,11 +1930,11 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // Apply qualifiers from the element type to the array. QualType canon = getQualifiedType(QualType(canonTy,0), - canonElementType.second); + canonElementType.Quals); // If we didn't need extra canonicalization for the element type, // then just use that as our result. - if (QualType(canonElementType.first, 0) == elementType) + if (QualType(canonElementType.Ty, 0) == elementType) return canon; // Otherwise, we need to build a type which follows the spelling @@ -1904,9 +1965,9 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType, if (!elementType.isCanonical() || elementType.hasLocalQualifiers()) { SplitQualType canonSplit = getCanonicalType(elementType).split(); - canon = getIncompleteArrayType(QualType(canonSplit.first, 0), + canon = getIncompleteArrayType(QualType(canonSplit.Ty, 0), ASM, elementTypeQuals); - canon = getQualifiedType(canon, canonSplit.second); + canon = getQualifiedType(canon, canonSplit.Quals); // Get the new insert position for the node we care about. IncompleteArrayType *existing = @@ -2082,7 +2143,9 @@ ASTContext::getFunctionType(QualType ResultTy, return QualType(FTP, 0); // Determine whether the type being created is already canonical or not. - bool isCanonical= EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical(); + bool isCanonical = + EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() && + !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; @@ -2101,6 +2164,7 @@ ASTContext::getFunctionType(QualType ResultTy, CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; + CanonicalEPI.HasTrailingReturn = false; CanonicalEPI.ExceptionSpecType = EST_None; CanonicalEPI.NumExceptions = 0; CanonicalEPI.ExtInfo @@ -2162,7 +2226,7 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl, assert(NeedsInjectedClassNameType(Decl)); if (Decl->TypeForDecl) { assert(isa<InjectedClassNameType>(Decl->TypeForDecl)); - } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDeclaration()) { + } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDecl()) { assert(PrevDecl->TypeForDecl && "previous declaration has no type"); Decl->TypeForDecl = PrevDecl->TypeForDecl; assert(isa<InjectedClassNameType>(Decl->TypeForDecl)); @@ -2188,12 +2252,12 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { "Template type parameter types are always available."); if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) { - assert(!Record->getPreviousDeclaration() && + assert(!Record->getPreviousDecl() && "struct/union has previous declaration"); assert(!NeedsInjectedClassNameType(Record)); return getRecordType(Record); } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) { - assert(!Enum->getPreviousDeclaration() && + assert(!Enum->getPreviousDecl() && "enum has previous declaration"); return getEnumType(Enum); } else if (const UnresolvedUsingTypenameDecl *Using = @@ -2226,7 +2290,7 @@ ASTContext::getTypedefType(const TypedefNameDecl *Decl, QualType ASTContext::getRecordType(const RecordDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - if (const RecordDecl *PrevDecl = Decl->getPreviousDeclaration()) + if (const RecordDecl *PrevDecl = Decl->getPreviousDecl()) if (PrevDecl->TypeForDecl) return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); @@ -2239,7 +2303,7 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const { QualType ASTContext::getEnumType(const EnumDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - if (const EnumDecl *PrevDecl = Decl->getPreviousDeclaration()) + if (const EnumDecl *PrevDecl = Decl->getPreviousDecl()) if (PrevDecl->TypeForDecl) return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); @@ -2374,6 +2438,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, TypeSourceInfo *DI = CreateTypeSourceInfo(TST); TemplateSpecializationTypeLoc TL = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc()); + TL.setTemplateKeywordLoc(SourceLocation()); TL.setTemplateNameLoc(NameLoc); TL.setLAngleLoc(Args.getLAngleLoc()); TL.setRAngleLoc(Args.getRAngleLoc()); @@ -2400,6 +2465,17 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, Underlying); } +#ifndef NDEBUG +static bool hasAnyPackExpansions(const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) + if (Args[I].isPackExpansion()) + return true; + + return true; +} +#endif + QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, @@ -2411,16 +2487,18 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Template = TemplateName(QTN->getTemplateDecl()); - bool isTypeAlias = + bool IsTypeAlias = Template.getAsTemplateDecl() && isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); - QualType CanonType; if (!Underlying.isNull()) CanonType = getCanonicalType(Underlying); else { - assert(!isTypeAlias && - "Underlying type for template alias must be computed by caller"); + // We can get here with an alias template when the specialization contains + // a pack expansion that does not match up with a parameter pack. + assert((!IsTypeAlias || hasAnyPackExpansions(Args, NumArgs)) && + "Caller must compute aliased type"); + IsTypeAlias = false; CanonType = getCanonicalTemplateSpecializationType(Template, Args, NumArgs); } @@ -2430,13 +2508,11 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, // we don't unique and don't want to lose. void *Mem = Allocate(sizeof(TemplateSpecializationType) + sizeof(TemplateArgument) * NumArgs + - (isTypeAlias ? sizeof(QualType) : 0), + (IsTypeAlias? sizeof(QualType) : 0), TypeAlignment); TemplateSpecializationType *Spec - = new (Mem) TemplateSpecializationType(Template, - Args, NumArgs, - CanonType, - isTypeAlias ? Underlying : QualType()); + = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, CanonType, + IsTypeAlias ? Underlying : QualType()); Types.push_back(Spec); return QualType(Spec, 0); @@ -2448,9 +2524,6 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, unsigned NumArgs) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); - assert((!Template.getAsTemplateDecl() || - !isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) && - "Underlying type for template alias must be computed by caller"); // Look through qualified template names. if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) @@ -2677,8 +2750,12 @@ static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols, unsigned NumProtocols) { if (NumProtocols == 0) return true; + if (Protocols[0]->getCanonicalDecl() != Protocols[0]) + return false; + for (unsigned i = 1; i != NumProtocols; ++i) - if (!CmpProtocolNames(Protocols[i-1], Protocols[i])) + if (!CmpProtocolNames(Protocols[i-1], Protocols[i]) || + Protocols[i]->getCanonicalDecl() != Protocols[i]) return false; return true; } @@ -2690,6 +2767,10 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, // Sort protocols, keyed by name. std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames); + // Canonicalize. + for (unsigned I = 0, N = NumProtocols; I != N; ++I) + Protocols[I] = Protocols[I]->getCanonicalDecl(); + // Remove duplicates. ProtocolsEnd = std::unique(Protocols, ProtocolsEnd); NumProtocols = ProtocolsEnd-Protocols; @@ -2775,11 +2856,21 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const { /// getObjCInterfaceType - Return the unique reference to the type for the /// specified ObjC interface decl. The list of protocols is optional. -QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const { +QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + ObjCInterfaceDecl *PrevDecl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); - // FIXME: redeclarations? + if (PrevDecl) { + assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); + Decl->TypeForDecl = PrevDecl->TypeForDecl; + return QualType(PrevDecl->TypeForDecl, 0); + } + + // Prefer the definition, if there is one. + if (const ObjCInterfaceDecl *Def = Decl->getDefinition()) + Decl = Def; + void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment); ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl); Decl->TypeForDecl = T; @@ -2833,44 +2924,13 @@ QualType ASTContext::getTypeOfType(QualType tofType) const { return QualType(tot, 0); } -/// getDecltypeForExpr - Given an expr, will return the decltype for that -/// expression, according to the rules in C++0x [dcl.type.simple]p4 -static QualType getDecltypeForExpr(const Expr *e, const ASTContext &Context) { - if (e->isTypeDependent()) - return Context.DependentTy; - - // If e is an id expression or a class member access, decltype(e) is defined - // as the type of the entity named by e. - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(e)) { - if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) - return VD->getType(); - } - if (const MemberExpr *ME = dyn_cast<MemberExpr>(e)) { - if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) - return FD->getType(); - } - // If e is a function call or an invocation of an overloaded operator, - // (parentheses around e are ignored), decltype(e) is defined as the - // return type of that function. - if (const CallExpr *CE = dyn_cast<CallExpr>(e->IgnoreParens())) - return CE->getCallReturnType(); - - QualType T = e->getType(); - - // Otherwise, where T is the type of e, if e is an lvalue, decltype(e) is - // defined as T&, otherwise decltype(e) is defined as T. - if (e->isLValue()) - T = Context.getLValueReferenceType(T); - - return T; -} /// getDecltypeType - Unlike many "get<Type>" functions, we don't unique /// DecltypeType AST's. The only motivation to unique these nodes would be /// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be /// an issue. This doesn't effect the type checker, since it operates -/// on canonical type's (which are always unique). -QualType ASTContext::getDecltypeType(Expr *e) const { +/// on canonical types (which are always unique). +QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { DecltypeType *dt; // C++0x [temp.type]p2: @@ -2896,8 +2956,8 @@ QualType ASTContext::getDecltypeType(Expr *e) const { dt = Canon; } } else { - QualType T = getDecltypeForExpr(e, *this); - dt = new (*this, TypeAlignment) DecltypeType(e, T, getCanonicalType(T)); + dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType, + getCanonicalType(UnderlyingType)); } Types.push_back(dt); return QualType(dt, 0); @@ -2913,7 +2973,7 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType, new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType, Kind, UnderlyingType->isDependentType() ? - QualType() : UnderlyingType); + QualType() : getCanonicalType(UnderlyingType)); Types.push_back(Ty); return QualType(Ty, 0); } @@ -2996,6 +3056,16 @@ CanQualType ASTContext::getSizeType() const { return getFromTargetType(Target->getSizeType()); } +/// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5). +CanQualType ASTContext::getIntMaxType() const { + return getFromTargetType(Target->getIntMaxType()); +} + +/// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5). +CanQualType ASTContext::getUIntMaxType() const { + return getFromTargetType(Target->getUIntMaxType()); +} + /// getSignedWCharType - Return the type of "signed wchar_t". /// Used when in C++, as a GCC extension. QualType ASTContext::getSignedWCharType() const { @@ -3010,7 +3080,7 @@ QualType ASTContext::getUnsignedWCharType() const { return UnsignedIntTy; } -/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?) +/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType ASTContext::getPointerDiffType() const { return getFromTargetType(Target->getPtrDiffType(0)); @@ -3047,12 +3117,12 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, // We then have to strip that sugar back off with // getUnqualifiedDesugaredType(), which is silly. const ArrayType *AT = - dyn_cast<ArrayType>(splitType.first->getUnqualifiedDesugaredType()); + dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType()); // If we don't have an array, just use the results in splitType. if (!AT) { - quals = splitType.second; - return QualType(splitType.first, 0); + quals = splitType.Quals; + return QualType(splitType.Ty, 0); } // Otherwise, recurse on the array's element type. @@ -3063,13 +3133,13 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, // can just use the results in splitType. if (elementType == unqualElementType) { assert(quals.empty()); // from the recursive call - quals = splitType.second; - return QualType(splitType.first, 0); + quals = splitType.Quals; + return QualType(splitType.Ty, 0); } // Otherwise, add in the qualifiers from the outermost type, then // build the type back up. - quals.addConsistentQualifiers(splitType.second); + quals.addConsistentQualifiers(splitType.Quals); if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { return getConstantArrayType(unqualElementType, CAT->getSize(), @@ -3121,7 +3191,7 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { return true; } - if (getLangOptions().ObjC1) { + if (getLangOpts().ObjC1) { const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(), *T2OPType = T2->getAs<ObjCObjectPointerType>(); if (T1OPType && T2OPType) { @@ -3243,8 +3313,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { case TemplateArgument::Expression: return Arg; - case TemplateArgument::Declaration: - return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl()); + case TemplateArgument::Declaration: { + if (Decl *D = Arg.getAsDecl()) + return TemplateArgument(D->getCanonicalDecl()); + return TemplateArgument((Decl*)0); + } case TemplateArgument::Template: return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); @@ -3317,26 +3390,13 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { // types, e.g., // typedef typename T::type T1; // typedef typename T1::type T2; - if (const DependentNameType *DNT = T->getAs<DependentNameType>()) { - NestedNameSpecifier *Prefix - = getCanonicalNestedNameSpecifier(DNT->getQualifier()); - return NestedNameSpecifier::Create(*this, Prefix, + if (const DependentNameType *DNT = T->getAs<DependentNameType>()) + return NestedNameSpecifier::Create(*this, DNT->getQualifier(), const_cast<IdentifierInfo *>(DNT->getIdentifier())); - } - // Do the same thing as above, but with dependent-named specializations. - if (const DependentTemplateSpecializationType *DTST - = T->getAs<DependentTemplateSpecializationType>()) { - NestedNameSpecifier *Prefix - = getCanonicalNestedNameSpecifier(DTST->getQualifier()); - - T = getDependentTemplateSpecializationType(DTST->getKeyword(), - Prefix, DTST->getIdentifier(), - DTST->getNumArgs(), - DTST->getArgs()); - T = getCanonicalType(T); - } - + // Otherwise, just canonicalize the type, and force it to be a TypeSpec. + // FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the + // first place? return NestedNameSpecifier::Create(*this, 0, false, const_cast<Type*>(T.getTypePtr())); } @@ -3346,8 +3406,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { return NNS; } - // Required to silence a GCC warning - return 0; + llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } @@ -3372,10 +3431,10 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // we must propagate them down into the element type. SplitQualType split = T.getSplitDesugaredType(); - Qualifiers qs = split.second; + Qualifiers qs = split.Quals; // If we have a simple case, just return now. - const ArrayType *ATy = dyn_cast<ArrayType>(split.first); + const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty); if (ATy == 0 || qs.empty()) return ATy; @@ -3462,11 +3521,11 @@ QualType ASTContext::getBaseElementType(QualType type) const { Qualifiers qs; while (true) { SplitQualType split = type.getSplitDesugaredType(); - const ArrayType *array = split.first->getAsArrayTypeUnsafe(); + const ArrayType *array = split.Ty->getAsArrayTypeUnsafe(); if (!array) break; type = array->getElementType(); - qs.addConsistentQualifiers(split.second); + qs.addConsistentQualifiers(split.Quals); } return getQualifiedType(type, qs); @@ -3508,7 +3567,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, FloatingRank EltRank = getFloatingRank(Size); if (Domain->isComplexType()) { switch (EltRank) { - default: llvm_unreachable("getFloatingRank(): illegal value for rank"); + case HalfRank: llvm_unreachable("Complex half is not supported"); case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; case LongDoubleRank: return LongDoubleComplexTy; @@ -3517,11 +3576,12 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { - default: llvm_unreachable("getFloatingRank(): illegal value for rank"); + case HalfRank: llvm_unreachable("Half ranks are not valid here"); case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; } + llvm_unreachable("getFloatingRank(): illegal value for rank"); } /// getFloatingTypeOrder - Compare the rank of the two specified floating @@ -3544,18 +3604,6 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const { /// or if it is not canonicalized. unsigned ASTContext::getIntegerRank(const Type *T) const { assert(T->isCanonicalUnqualified() && "T should be canonicalized"); - if (const EnumType* ET = dyn_cast<EnumType>(T)) - T = ET->getDecl()->getPromotionType().getTypePtr(); - - if (T->isSpecificBuiltinType(BuiltinType::WChar_S) || - T->isSpecificBuiltinType(BuiltinType::WChar_U)) - T = getFromTargetType(Target->getWCharType()).getTypePtr(); - - if (T->isSpecificBuiltinType(BuiltinType::Char16)) - T = getFromTargetType(Target->getChar16Type()).getTypePtr(); - - if (T->isSpecificBuiltinType(BuiltinType::Char32)) - T = getFromTargetType(Target->getChar32Type()).getTypePtr(); switch (cast<BuiltinType>(T)->getKind()) { default: llvm_unreachable("getIntegerRank(): not a built-in integer"); @@ -3625,6 +3673,34 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { assert(Promotable->isPromotableIntegerType()); if (const EnumType *ET = Promotable->getAs<EnumType>()) return ET->getDecl()->getPromotionType(); + + if (const BuiltinType *BT = Promotable->getAs<BuiltinType>()) { + // C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t + // (3.9.1) can be converted to a prvalue of the first of the following + // types that can represent all the values of its underlying type: + // int, unsigned int, long int, unsigned long int, long long int, or + // unsigned long long int [...] + // FIXME: Is there some better way to compute this? + if (BT->getKind() == BuiltinType::WChar_S || + BT->getKind() == BuiltinType::WChar_U || + BT->getKind() == BuiltinType::Char16 || + BT->getKind() == BuiltinType::Char32) { + bool FromIsSigned = BT->getKind() == BuiltinType::WChar_S; + uint64_t FromSize = getTypeSize(BT); + QualType PromoteTypes[] = { IntTy, UnsignedIntTy, LongTy, UnsignedLongTy, + LongLongTy, UnsignedLongLongTy }; + for (size_t Idx = 0; Idx < llvm::array_lengthof(PromoteTypes); ++Idx) { + uint64_t ToSize = getTypeSize(PromoteTypes[Idx]); + if (FromSize < ToSize || + (FromSize == ToSize && + FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) + return PromoteTypes[Idx]; + } + llvm_unreachable("char type should fit into long long"); + } + } + + // At this point, we should have a signed or unsigned integer type. if (Promotable->isSignedIntegerType()) return IntTy; uint64_t PromotableSize = getTypeSize(Promotable); @@ -3697,7 +3773,7 @@ static RecordDecl * CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, IdentifierInfo *Id) { SourceLocation Loc; - if (Ctx.getLangOptions().CPlusPlus) + if (Ctx.getLangOpts().CPlusPlus) return CXXRecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); else return RecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); @@ -3832,7 +3908,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { bool ASTContext::BlockRequiresCopying(QualType Ty) const { if (Ty->isObjCRetainableType()) return true; - if (getLangOptions().CPlusPlus) { + if (getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); return RD->hasConstCopyConstructor(); @@ -3857,7 +3933,7 @@ ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const { bool HasCopyAndDispose = BlockRequiresCopying(Ty); // FIXME: Move up - llvm::SmallString<36> Name; + SmallString<36> Name; llvm::raw_svector_ostream(Name) << "__Block_byref_" << ++UniqueBlockByRefTypeID << '_' << DeclName; RecordDecl *T; @@ -4037,15 +4113,32 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, return false; } +/// getObjCEncodingForMethodParameter - Return the encoded type for a single +/// method parameter or return type. If Extended, include class names and +/// block object types. +void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, + QualType T, std::string& S, + bool Extended) const { + // Encode type qualifer, 'in', 'inout', etc. for the parameter. + getObjCEncodingForTypeQualifier(QT, S); + // Encode parameter type. + getObjCEncodingForTypeImpl(T, S, true, true, 0, + true /*OutermostType*/, + false /*EncodingProperty*/, + false /*StructField*/, + Extended /*EncodeBlockParameters*/, + Extended /*EncodeClassNames*/); +} + /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, - std::string& S) const { + std::string& S, + bool Extended) const { // FIXME: This is not very efficient. - // Encode type qualifer, 'in', 'inout', etc. for the return type. - getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S); - // Encode result type. - getObjCEncodingForType(Decl->getResultType(), S); + // Encode return type. + getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), + Decl->getResultType(), S, Extended); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! @@ -4083,10 +4176,8 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, PType = PVDecl->getType(); } else if (PType->isFunctionType()) PType = PVDecl->getType(); - // Process argument qualifiers for user supplied arguments; such as, - // 'in', 'inout', etc. - getObjCEncodingForTypeQualifier(PVDecl->getObjCDeclQualifier(), S); - getObjCEncodingForType(PType, S); + getObjCEncodingForMethodParameter(PVDecl->getObjCDeclQualifier(), + PType, S, Extended); S += charUnitsToString(ParmOffset); ParmOffset += getObjCEncodingTypeSize(PType); } @@ -4113,7 +4204,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, /// kPropertyGetter = 'G', // followed by getter selector name /// kPropertySetter = 'S', // followed by setter selector name /// kPropertyInstanceVariable = 'V' // followed by instance variable name -/// kPropertyType = 't' // followed by old-style type encoding. +/// kPropertyType = 'T' // followed by old-style type encoding. /// kPropertyWeak = 'W' // 'weak' property /// kPropertyStrong = 'P' // property GC'able /// kPropertyNonAtomic = 'N' // property non-atomic @@ -4293,7 +4384,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, // information is not especially sensible, but we're stuck with it for // compatibility with GCC, although providing it breaks anything that // actually uses runtime introspection and wants to work on both runtimes... - if (!Ctx->getLangOptions().NeXTRuntime) { + if (!Ctx->getLangOpts().NeXTRuntime) { const RecordDecl *RD = FD->getParent(); const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD); S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); @@ -4312,7 +4403,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, const FieldDecl *FD, bool OutermostType, bool EncodingProperty, - bool StructField) const { + bool StructField, + bool EncodeBlockParameters, + bool EncodeClassNames) const { if (T->getAs<BuiltinType>()) { if (FD && FD->isBitField()) return EncodeBitField(this, S, T, FD); @@ -4491,8 +4584,40 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - if (T->isBlockPointerType()) { + if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { S += "@?"; // Unlike a pointer-to-function, which is "^?". + if (EncodeBlockParameters) { + const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>(); + + S += '<'; + // Block return type + getObjCEncodingForTypeImpl(FT->getResultType(), S, + ExpandPointedToStructures, ExpandStructures, + FD, + false /* OutermostType */, + EncodingProperty, + false /* StructField */, + EncodeBlockParameters, + EncodeClassNames); + // Block self + S += "@?"; + // Block parameters + if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { + for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(), + E = FPT->arg_type_end(); I && (I != E); ++I) { + getObjCEncodingForTypeImpl(*I, S, + ExpandPointedToStructures, + ExpandStructures, + FD, + false /* OutermostType */, + EncodingProperty, + false /* StructField */, + EncodeBlockParameters, + EncodeClassNames); + } + } + S += '>'; + } return; } @@ -4538,7 +4663,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getObjCEncodingForTypeImpl(getObjCIdType(), S, ExpandPointedToStructures, ExpandStructures, FD); - if (FD || EncodingProperty) { + if (FD || EncodingProperty || EncodeClassNames) { // Note that we do extended encoding of protocol qualifer list // Only when doing ivar or property encoding. S += '"'; @@ -4567,7 +4692,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } S += '@'; - if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) { + if (OPT->getInterfaceDecl() && + (FD || EncodingProperty || EncodeClassNames)) { S += '"'; S += OPT->getInterfaceDecl()->getIdentifier()->getName(); for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), @@ -4780,10 +4906,6 @@ TypedefDecl *ASTContext::getObjCSelDecl() const { return ObjCSelDecl; } -void ASTContext::setObjCProtoType(QualType QT) { - ObjCProtoType = QT; -} - TypedefDecl *ASTContext::getObjCClassDecl() const { if (!ObjCClassDecl) { QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0); @@ -4798,6 +4920,19 @@ TypedefDecl *ASTContext::getObjCClassDecl() const { return ObjCClassDecl; } +ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const { + if (!ObjCProtocolClassDecl) { + ObjCProtocolClassDecl + = ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(), + SourceLocation(), + &Idents.get("Protocol"), + /*PrevDecl=*/0, + SourceLocation(), true); + } + + return ObjCProtocolClassDecl; +} + void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { assert(ObjCConstantStringType.isNull() && "'NSConstantString' type already set!"); @@ -4987,10 +5122,10 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { /// garbage collection attribute. /// Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const { - if (getLangOptions().getGC() == LangOptions::NonGC) + if (getLangOpts().getGC() == LangOptions::NonGC) return Qualifiers::GCNone; - assert(getLangOptions().ObjC1); + assert(getLangOpts().ObjC1); Qualifiers::GC GCAttrs = Ty.getObjCGCAttr(); // Default behaviour under objective-C's gc is for ObjC pointers @@ -5059,7 +5194,7 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, bool ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, ObjCProtocolDecl *rProto) const { - if (lProto == rProto) + if (declaresSameEntity(lProto, rProto)) return true; for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), E = rProto->protocol_end(); PI != E; ++PI) @@ -5360,7 +5495,7 @@ QualType ASTContext::areCommonBaseCompatible( const ObjCObjectType *RHS = Rptr->getObjectType(); const ObjCInterfaceDecl* LDecl = LHS->getInterface(); const ObjCInterfaceDecl* RDecl = RHS->getInterface(); - if (!LDecl || !RDecl || (LDecl == RDecl)) + if (!LDecl || !RDecl || (declaresSameEntity(LDecl, RDecl))) return QualType(); do { @@ -5484,7 +5619,7 @@ bool ASTContext::canBindObjCObjectType(QualType To, QualType From) { /// same. See 6.7.[2,3,5] for additional rules. bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS, bool CompareUnqualified) { - if (getLangOptions().CPlusPlus) + if (getLangOpts().CPlusPlus) return hasSameType(LHS, RHS); return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull(); @@ -5791,14 +5926,23 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, // Compatibility is based on the underlying type, not the promotion // type. if (const EnumType* ETy = LHS->getAs<EnumType>()) { - if (ETy->getDecl()->getIntegerType() == RHSCan.getUnqualifiedType()) + QualType TINT = ETy->getDecl()->getIntegerType(); + if (!TINT.isNull() && hasSameType(TINT, RHSCan.getUnqualifiedType())) return RHS; } if (const EnumType* ETy = RHS->getAs<EnumType>()) { - if (ETy->getDecl()->getIntegerType() == LHSCan.getUnqualifiedType()) + QualType TINT = ETy->getDecl()->getIntegerType(); + if (!TINT.isNull() && hasSameType(TINT, LHSCan.getUnqualifiedType())) return LHS; } - + // allow block pointer type to match an 'id' type. + if (OfBlockPointer && !BlockReturnType) { + if (LHS->isObjCIdType() && RHS->isBlockPointerType()) + return LHS; + if (RHS->isObjCIdType() && LHS->isBlockPointerType()) + return RHS; + } + return QualType(); } @@ -5959,7 +6103,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, LHS->getAs<ObjCObjectPointerType>(), RHS->getAs<ObjCObjectPointerType>(), BlockReturnType)) - return LHS; + return LHS; return QualType(); } if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(), @@ -5967,10 +6111,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return LHS; return QualType(); - } + } } - return QualType(); + llvm_unreachable("Invalid Type::Class!"); } bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs( @@ -6333,6 +6477,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, case 'D': Type = Context.getVolatileType(Type); break; + case 'R': + Type = Type.withRestrict(); + break; } } @@ -6425,7 +6572,7 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { if (!FD->isInlined()) return External; - if (!getLangOptions().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) { + if (!getLangOpts().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) { // GNU or C99 inline semantics. Determine whether this symbol should be // externally visible. if (FD->isInlineDefinitionExternallyVisible()) @@ -6457,7 +6604,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { TSK = VD->getTemplateSpecializationKind(); Linkage L = VD->getLinkage(); - if (L == ExternalLinkage && getLangOptions().CPlusPlus && + if (L == ExternalLinkage && getLangOpts().CPlusPlus && VD->getType()->getLinkage() == UniqueExternalLinkage) L = UniqueExternalLinkage; @@ -6485,7 +6632,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { } } - return GVA_StrongExternal; + llvm_unreachable("Invalid Linkage!"); } bool ASTContext::DeclMustBeEmitted(const Decl *D) { @@ -6602,6 +6749,13 @@ size_t ASTContext::getSideTableAllocatedMemory() const { + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); } +unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) { + CXXRecordDecl *Lambda = CallOperator->getParent(); + return LambdaMangleContexts[Lambda->getDeclContext()] + .getManglingNumber(CallOperator); +} + + void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) { ParamIndices[D] = index; } diff --git a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp index 07820dc..ca4fe26 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp @@ -154,26 +154,34 @@ static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, - SmallVectorImpl<intptr_t> &QualTypeVals) { + ArrayRef<intptr_t> QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); std::string S = Ty.getAsString(Context.getPrintingPolicy()); std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); - for (SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(), - E = QualTypeVals.end(); I != E; ++I) { + for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { QualType CompareTy = - QualType::getFromOpaquePtr(reinterpret_cast<void*>(*I)); + QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); + if (CompareTy.isNull()) + continue; if (CompareTy == Ty) continue; // Same types QualType CompareCanTy = CompareTy.getCanonicalType(); if (CompareCanTy == CanTy) continue; // Same canonical types std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); - if (CompareS != S) - continue; // Original strings are different - std::string CompareCanS = CompareCanTy.getAsString(Context.getPrintingPolicy()); + bool aka; + QualType CompareDesugar = Desugar(Context, CompareTy, aka); + std::string CompareDesugarStr = + CompareDesugar.getAsString(Context.getPrintingPolicy()); + if (CompareS != S && CompareDesugarStr != S) + continue; // The type string is different than the comparison string + // and the desugared comparison string. + std::string CompareCanS = + CompareCanTy.getAsString(Context.getPrintingPolicy()); + if (CompareCanS == CanS) continue; // No new info from canonical type @@ -228,7 +236,7 @@ void clang::FormatASTNodeDiagnosticArgument( unsigned NumPrevArgs, SmallVectorImpl<char> &Output, void *Cookie, - SmallVectorImpl<intptr_t> &QualTypeVals) { + ArrayRef<intptr_t> QualTypeVals) { ASTContext &Context = *static_cast<ASTContext*>(Cookie); std::string S; @@ -286,7 +294,7 @@ void clang::FormatASTNodeDiagnosticArgument( if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place - if (Context.getLangOptions().CPlusPlus) + if (Context.getLangOpts().CPlusPlus) S = "the global namespace"; else S = "the global scope"; diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index af66b04..3879907 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -25,9 +25,7 @@ #include "llvm/Support/MemoryBuffer.h" #include <deque> -using namespace clang; - -namespace { +namespace clang { class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>, public DeclVisitor<ASTNodeImporter, Decl *>, public StmtVisitor<ASTNodeImporter, Stmt *> { @@ -80,7 +78,7 @@ namespace { QualType VisitObjCObjectType(const ObjCObjectType *T); QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); - // Importing declarations + // Importing declarations bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, SourceLocation &Loc); @@ -88,10 +86,33 @@ namespace { void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + + /// \brief What we should import from the definition. + enum ImportDefinitionKind { + /// \brief Import the default subset of the definition, which might be + /// nothing (if minimal import is set) or might be everything (if minimal + /// import is not set). + IDK_Default, + /// \brief Import everything. + IDK_Everything, + /// \brief Import only the bare bones needed to establish a valid + /// DeclContext. + IDK_Basic + }; + + bool shouldForceImportDeclContext(ImportDefinitionKind IDK) { + return IDK == IDK_Everything || + (IDK == IDK_Default && !Importer.isMinimalImport()); + } + bool ImportDefinition(RecordDecl *From, RecordDecl *To, - bool ForceImport = false); + ImportDefinitionKind Kind = IDK_Default); bool ImportDefinition(EnumDecl *From, EnumDecl *To, - bool ForceImport = false); + ImportDefinitionKind Kind = IDK_Default); + bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, + ImportDefinitionKind Kind = IDK_Default); + bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To, + ImportDefinitionKind Kind = IDK_Default); TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); @@ -102,6 +123,7 @@ namespace { bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); + Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); @@ -128,8 +150,6 @@ namespace { Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D); Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D); Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); - Decl *VisitObjCClassDecl(ObjCClassDecl *D); Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); @@ -154,6 +174,7 @@ namespace { Expr *VisitCStyleCastExpr(CStyleCastExpr *E); }; } +using namespace clang; //---------------------------------------------------------------------------- // Structural Equivalence @@ -304,6 +325,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return IsSameValue(*Arg1.getAsIntegral(), *Arg2.getAsIntegral()); case TemplateArgument::Declaration: + if (!Arg1.getAsDecl() || !Arg2.getAsDecl()) + return !Arg1.getAsDecl() && !Arg2.getAsDecl(); return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl()); case TemplateArgument::Template: @@ -334,7 +357,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } llvm_unreachable("Invalid template argument kind"); - return true; } /// \brief Determine structural equivalence for the common part of array @@ -945,10 +967,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Base1->getType(), Base2->getType())) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.C2.getTypeDeclType(D2); - Context.Diag2(Base2->getSourceRange().getBegin(), diag::note_odr_base) + Context.Diag2(Base2->getLocStart(), diag::note_odr_base) << Base2->getType() << Base2->getSourceRange(); - Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base) + Context.Diag1(Base1->getLocStart(), diag::note_odr_base) << Base1->getType() << Base1->getSourceRange(); return false; @@ -958,10 +980,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (Base1->isVirtual() != Base2->isVirtual()) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.C2.getTypeDeclType(D2); - Context.Diag2(Base2->getSourceRange().getBegin(), + Context.Diag2(Base2->getLocStart(), diag::note_odr_virtual_base) << Base2->isVirtual() << Base2->getSourceRange(); - Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base) + Context.Diag1(Base1->getLocStart(), diag::note_odr_base) << Base1->isVirtual() << Base1->getSourceRange(); return false; @@ -971,7 +993,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) << Context.C2.getTypeDeclType(D2); const CXXBaseSpecifier *Base1 = D1CXX->bases_begin(); - Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base) + Context.Diag1(Base1->getLocStart(), diag::note_odr_base) << Base1->getType() << Base1->getSourceRange(); Context.Diag2(D2->getLocation(), diag::note_odr_missing_base); @@ -1324,82 +1346,43 @@ QualType ASTNodeImporter::VisitType(const Type *T) { QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { - case BuiltinType::Void: return Importer.getToContext().VoidTy; - case BuiltinType::Bool: return Importer.getToContext().BoolTy; - +#define SHARED_SINGLETON_TYPE(Expansion) +#define BUILTIN_TYPE(Id, SingletonId) \ + case BuiltinType::Id: return Importer.getToContext().SingletonId; +#include "clang/AST/BuiltinTypes.def" + + // FIXME: for Char16, Char32, and NullPtr, make sure that the "to" + // context supports C++. + + // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to" + // context supports ObjC. + case BuiltinType::Char_U: // The context we're importing from has an unsigned 'char'. If we're // importing into a context with a signed 'char', translate to // 'unsigned char' instead. - if (Importer.getToContext().getLangOptions().CharIsSigned) + if (Importer.getToContext().getLangOpts().CharIsSigned) return Importer.getToContext().UnsignedCharTy; return Importer.getToContext().CharTy; - case BuiltinType::UChar: return Importer.getToContext().UnsignedCharTy; - - case BuiltinType::Char16: - // FIXME: Make sure that the "to" context supports C++! - return Importer.getToContext().Char16Ty; - - case BuiltinType::Char32: - // FIXME: Make sure that the "to" context supports C++! - return Importer.getToContext().Char32Ty; - - case BuiltinType::UShort: return Importer.getToContext().UnsignedShortTy; - case BuiltinType::UInt: return Importer.getToContext().UnsignedIntTy; - case BuiltinType::ULong: return Importer.getToContext().UnsignedLongTy; - case BuiltinType::ULongLong: - return Importer.getToContext().UnsignedLongLongTy; - case BuiltinType::UInt128: return Importer.getToContext().UnsignedInt128Ty; - case BuiltinType::Char_S: // The context we're importing from has an unsigned 'char'. If we're // importing into a context with a signed 'char', translate to // 'unsigned char' instead. - if (!Importer.getToContext().getLangOptions().CharIsSigned) + if (!Importer.getToContext().getLangOpts().CharIsSigned) return Importer.getToContext().SignedCharTy; return Importer.getToContext().CharTy; - case BuiltinType::SChar: return Importer.getToContext().SignedCharTy; case BuiltinType::WChar_S: case BuiltinType::WChar_U: // FIXME: If not in C++, shall we translate to the C equivalent of // wchar_t? return Importer.getToContext().WCharTy; - - case BuiltinType::Short : return Importer.getToContext().ShortTy; - case BuiltinType::Int : return Importer.getToContext().IntTy; - case BuiltinType::Long : return Importer.getToContext().LongTy; - case BuiltinType::LongLong : return Importer.getToContext().LongLongTy; - case BuiltinType::Int128 : return Importer.getToContext().Int128Ty; - case BuiltinType::Half: return Importer.getToContext().HalfTy; - case BuiltinType::Float: return Importer.getToContext().FloatTy; - case BuiltinType::Double: return Importer.getToContext().DoubleTy; - case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy; - - case BuiltinType::NullPtr: - // FIXME: Make sure that the "to" context supports C++0x! - return Importer.getToContext().NullPtrTy; - - case BuiltinType::Overload: return Importer.getToContext().OverloadTy; - case BuiltinType::Dependent: return Importer.getToContext().DependentTy; - case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy; - case BuiltinType::BoundMember: return Importer.getToContext().BoundMemberTy; - - case BuiltinType::ObjCId: - // FIXME: Make sure that the "to" context supports Objective-C! - return Importer.getToContext().ObjCBuiltinIdTy; - - case BuiltinType::ObjCClass: - return Importer.getToContext().ObjCBuiltinClassTy; - - case BuiltinType::ObjCSel: - return Importer.getToContext().ObjCBuiltinSelTy; } - - return QualType(); + + llvm_unreachable("Invalid BuiltinType Kind!"); } QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { @@ -1600,7 +1583,11 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { if (!ToExpr) return QualType(); - return Importer.getToContext().getDecltypeType(ToExpr); + QualType UnderlyingType = Importer.Import(T->getUnderlyingType()); + if (UnderlyingType.isNull()) + return QualType(); + + return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType); } QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { @@ -1813,11 +1800,11 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, To.setNamedTypeInfo(Importer.Import(FromTInfo)); return; } - llvm_unreachable("Unknown name kind."); } + llvm_unreachable("Unknown name kind."); } -void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { +void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { if (Importer.isMinimalImport() && !ForceImport) { Importer.ImportContext(FromDC); return; @@ -1831,16 +1818,75 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { } bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, - bool ForceImport) { - if (To->getDefinition() || To->isBeingDefined()) + ImportDefinitionKind Kind) { + if (To->getDefinition() || To->isBeingDefined()) { + if (Kind == IDK_Everything) + ImportDeclContext(From, /*ForceImport=*/true); + return false; + } To->startDefinition(); // Add base classes. if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(To)) { CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From); - + + struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); + struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); + ToData.UserDeclaredConstructor = FromData.UserDeclaredConstructor; + ToData.UserDeclaredCopyConstructor = FromData.UserDeclaredCopyConstructor; + ToData.UserDeclaredMoveConstructor = FromData.UserDeclaredMoveConstructor; + ToData.UserDeclaredCopyAssignment = FromData.UserDeclaredCopyAssignment; + ToData.UserDeclaredMoveAssignment = FromData.UserDeclaredMoveAssignment; + ToData.UserDeclaredDestructor = FromData.UserDeclaredDestructor; + ToData.Aggregate = FromData.Aggregate; + ToData.PlainOldData = FromData.PlainOldData; + ToData.Empty = FromData.Empty; + ToData.Polymorphic = FromData.Polymorphic; + ToData.Abstract = FromData.Abstract; + ToData.IsStandardLayout = FromData.IsStandardLayout; + ToData.HasNoNonEmptyBases = FromData.HasNoNonEmptyBases; + ToData.HasPrivateFields = FromData.HasPrivateFields; + ToData.HasProtectedFields = FromData.HasProtectedFields; + ToData.HasPublicFields = FromData.HasPublicFields; + ToData.HasMutableFields = FromData.HasMutableFields; + ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; + ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor; + ToData.HasConstexprNonCopyMoveConstructor + = FromData.HasConstexprNonCopyMoveConstructor; + ToData.DefaultedDefaultConstructorIsConstexpr + = FromData.DefaultedDefaultConstructorIsConstexpr; + ToData.DefaultedCopyConstructorIsConstexpr + = FromData.DefaultedCopyConstructorIsConstexpr; + ToData.DefaultedMoveConstructorIsConstexpr + = FromData.DefaultedMoveConstructorIsConstexpr; + ToData.HasConstexprDefaultConstructor + = FromData.HasConstexprDefaultConstructor; + ToData.HasConstexprCopyConstructor = FromData.HasConstexprCopyConstructor; + ToData.HasConstexprMoveConstructor = FromData.HasConstexprMoveConstructor; + ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor; + ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor; + ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment; + ToData.HasTrivialMoveAssignment = FromData.HasTrivialMoveAssignment; + ToData.HasTrivialDestructor = FromData.HasTrivialDestructor; + ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; + ToData.HasNonLiteralTypeFieldsOrBases + = FromData.HasNonLiteralTypeFieldsOrBases; + // ComputedVisibleConversions not imported. + ToData.UserProvidedDefaultConstructor + = FromData.UserProvidedDefaultConstructor; + ToData.DeclaredDefaultConstructor = FromData.DeclaredDefaultConstructor; + ToData.DeclaredCopyConstructor = FromData.DeclaredCopyConstructor; + ToData.DeclaredMoveConstructor = FromData.DeclaredMoveConstructor; + ToData.DeclaredCopyAssignment = FromData.DeclaredCopyAssignment; + ToData.DeclaredMoveAssignment = FromData.DeclaredMoveAssignment; + ToData.DeclaredDestructor = FromData.DeclaredDestructor; + ToData.FailedImplicitMoveConstructor + = FromData.FailedImplicitMoveConstructor; + ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment; + ToData.IsLambda = FromData.IsLambda; + SmallVector<CXXBaseSpecifier *, 4> Bases; for (CXXRecordDecl::base_class_iterator Base1 = FromCXX->bases_begin(), @@ -1871,15 +1917,20 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToCXX->setBases(Bases.data(), Bases.size()); } - ImportDeclContext(From, ForceImport); + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From, /*ForceImport=*/true); + To->completeDefinition(); return false; } bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, - bool ForceImport) { - if (To->getDefinition() || To->isBeingDefined()) + ImportDefinitionKind Kind) { + if (To->getDefinition() || To->isBeingDefined()) { + if (Kind == IDK_Everything) + ImportDeclContext(From, /*ForceImport=*/true); return false; + } To->startDefinition(); @@ -1890,8 +1941,9 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, QualType ToPromotionType = Importer.Import(From->getPromotionType()); if (ToPromotionType.isNull()) return true; - - ImportDeclContext(From, ForceImport); + + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From, /*ForceImport=*/true); // FIXME: we might need to merge the number of positive or negative bits // if the enumerator lists don't match. @@ -1983,7 +2035,6 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { } llvm_unreachable("Invalid template argument kind"); - return TemplateArgument(); } bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, @@ -2029,6 +2080,15 @@ Decl *ASTNodeImporter::VisitDecl(Decl *D) { return 0; } +Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { + TranslationUnitDecl *ToD = + Importer.getToContext().getTranslationUnitDecl(); + + Importer.Imported(D, ToD); + + return ToD; +} + Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; @@ -2074,10 +2134,12 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, + D->isInline(), Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo()); + Loc, Name.getAsIdentifierInfo(), + /*PrevDecl=*/0); ToNamespace->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToNamespace); + LexicalDC->addDeclInternal(ToNamespace); // If this is an anonymous namespace, register it as the anonymous // namespace within its context. @@ -2156,7 +2218,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToTypedef); - LexicalDC->addDecl(ToTypedef); + LexicalDC->addDeclInternal(ToTypedef); return ToTypedef; } @@ -2183,7 +2245,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (!SearchName && D->getTypedefNameForAnonDecl()) { SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); IDNS = Decl::IDNS_Ordinary; - } else if (Importer.getToContext().getLangOptions().CPlusPlus) + } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; // We may already have an enum of the same name; try to find and match it. @@ -2227,7 +2289,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); Importer.Imported(D, D2); - LexicalDC->addDecl(D2); + LexicalDC->addDeclInternal(D2); // Import the integer type. QualType ToIntegerType = Importer.Import(D->getIntegerType()); @@ -2268,7 +2330,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (!SearchName && D->getTypedefNameForAnonDecl()) { SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); IDNS = Decl::IDNS_Ordinary; - } else if (Importer.getToContext().getLangOptions().CPlusPlus) + } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; // We may already have a record of the same name; try to find and match it. @@ -2332,12 +2394,12 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(D2); + LexicalDC->addDeclInternal(D2); } Importer.Imported(D, D2); - if (D->isCompleteDefinition() && ImportDefinition(D, D2)) + if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) return 0; return D2; @@ -2389,7 +2451,7 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { ToEnumerator->setAccess(D->getAccess()); ToEnumerator->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToEnumerator); - LexicalDC->addDecl(ToEnumerator); + LexicalDC->addDeclInternal(ToEnumerator); return ToEnumerator; } @@ -2425,7 +2487,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Sema::IsOverload out to the AST library. // Function overloading is okay in C++. - if (Importer.getToContext().getLangOptions().CPlusPlus) + if (Importer.getToContext().getLangOpts().CPlusPlus) continue; // Complain about inconsistent function types. @@ -2530,14 +2592,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Set the parameters. for (unsigned I = 0, N = Parameters.size(); I != N; ++I) { Parameters[I]->setOwningFunction(ToFunction); - ToFunction->addDecl(Parameters[I]); + ToFunction->addDeclInternal(Parameters[I]); } ToFunction->setParams(Parameters); // FIXME: Other bits to merge? // Add this function to the lexical context. - LexicalDC->addDecl(ToFunction); + LexicalDC->addDeclInternal(ToFunction); return ToFunction; } @@ -2605,7 +2667,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (ToField->hasInClassInitializer()) ToField->setInClassInitializer(D->getInClassInitializer()); Importer.Imported(D, ToField); - LexicalDC->addDecl(ToField); + LexicalDC->addDeclInternal(ToField); return ToField; } @@ -2661,7 +2723,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIndirectField); - LexicalDC->addDecl(ToIndirectField); + LexicalDC->addDeclInternal(ToIndirectField); return ToIndirectField; } @@ -2710,7 +2772,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { BitWidth, D->getSynthesize()); ToIvar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIvar); - LexicalDC->addDecl(ToIvar); + LexicalDC->addDeclInternal(ToIvar); return ToIvar; } @@ -2791,6 +2853,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { } else { Expr *Init = Importer.Import(DDef->getInit()); MergeWithVar->setInit(Init); + if (DDef->isInitKnownICE()) { + EvaluatedStmt *Eval = MergeWithVar->ensureEvaluatedStmt(); + Eval->CheckedICE = true; + Eval->IsICE = DDef->isInitICE(); + } } } @@ -2823,7 +2890,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToVar); - LexicalDC->addDecl(ToVar); + LexicalDC->addDeclInternal(ToVar); // Merge the initializer. // FIXME: Can we really import any initializer? Alternatively, we could force @@ -3002,7 +3069,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Set the parameters. for (unsigned I = 0, N = ToParams.size(); I != N; ++I) { ToParams[I]->setOwningFunction(ToMethod); - ToMethod->addDecl(ToParams[I]); + ToMethod->addDeclInternal(ToParams[I]); } SmallVector<SourceLocation, 12> SelLocs; D->getSelectorLocs(SelLocs); @@ -3010,7 +3077,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { ToMethod->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToMethod); - LexicalDC->addDecl(ToMethod); + LexicalDC->addDeclInternal(ToMethod); return ToMethod; } @@ -3037,9 +3104,11 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { Loc, Importer.Import(D->getCategoryNameLoc()), Name.getAsIdentifierInfo(), - ToInterface); + ToInterface, + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc())); ToCategory->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToCategory); + LexicalDC->addDeclInternal(ToCategory); Importer.Imported(D, ToCategory); // Import protocols @@ -3084,7 +3153,59 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { return ToCategory; } +bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, + ObjCProtocolDecl *To, + ImportDefinitionKind Kind) { + if (To->getDefinition()) { + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From); + return false; + } + + // Start the protocol definition + To->startDefinition(); + + // Import protocols + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> ProtocolLocs; + ObjCProtocolDecl::protocol_loc_iterator + FromProtoLoc = From->protocol_loc_begin(); + for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(), + FromProtoEnd = From->protocol_end(); + FromProto != FromProtoEnd; + ++FromProto, ++FromProtoLoc) { + ObjCProtocolDecl *ToProto + = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); + if (!ToProto) + return true; + Protocols.push_back(ToProto); + ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + } + + // FIXME: If we're merging, make sure that the protocol list is the same. + To->setProtocolList(Protocols.data(), Protocols.size(), + ProtocolLocs.data(), Importer.getToContext()); + + if (shouldForceImportDeclContext(Kind)) { + // Import all of the members of this protocol. + ImportDeclContext(From, /*ForceImport=*/true); + } + return false; +} + Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + // If this protocol 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. + ObjCProtocolDecl *Definition = D->getDefinition(); + if (Definition && Definition != D) { + Decl *ImportedDef = Importer.Import(Definition); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + // Import the major distinguishing characteristics of a protocol. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -3104,48 +3225,133 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { } ObjCProtocolDecl *ToProto = MergeWithProtocol; - if (!ToProto || ToProto->isForwardDecl()) { - if (!ToProto) { - ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, - Name.getAsIdentifierInfo(), Loc, - Importer.Import(D->getAtStartLoc())); - ToProto->setForwardDecl(D->isForwardDecl()); - ToProto->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToProto); - } - Importer.Imported(D, ToProto); + if (!ToProto) { + ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, + Name.getAsIdentifierInfo(), Loc, + Importer.Import(D->getAtStartLoc()), + /*PrevDecl=*/0); + ToProto->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToProto); + } + + Importer.Imported(D, ToProto); - // Import protocols - SmallVector<ObjCProtocolDecl *, 4> Protocols; - SmallVector<SourceLocation, 4> ProtocolLocs; - ObjCProtocolDecl::protocol_loc_iterator - FromProtoLoc = D->protocol_loc_begin(); - for (ObjCProtocolDecl::protocol_iterator FromProto = D->protocol_begin(), - FromProtoEnd = D->protocol_end(); - FromProto != FromProtoEnd; - ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - return 0; - Protocols.push_back(ToProto); - ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) + return 0; + + return ToProto; +} + +bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, + ObjCInterfaceDecl *To, + ImportDefinitionKind Kind) { + if (To->getDefinition()) { + // Check consistency of superclass. + ObjCInterfaceDecl *FromSuper = From->getSuperClass(); + if (FromSuper) { + FromSuper = cast_or_null<ObjCInterfaceDecl>(Importer.Import(FromSuper)); + if (!FromSuper) + return true; } - // FIXME: If we're merging, make sure that the protocol list is the same. - ToProto->setProtocolList(Protocols.data(), Protocols.size(), - ProtocolLocs.data(), Importer.getToContext()); - } else { - Importer.Imported(D, ToProto); + ObjCInterfaceDecl *ToSuper = To->getSuperClass(); + if ((bool)FromSuper != (bool)ToSuper || + (FromSuper && !declaresSameEntity(FromSuper, ToSuper))) { + Importer.ToDiag(To->getLocation(), + diag::err_odr_objc_superclass_inconsistent) + << To->getDeclName(); + if (ToSuper) + Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass) + << To->getSuperClass()->getDeclName(); + else + Importer.ToDiag(To->getLocation(), + diag::note_odr_objc_missing_superclass); + if (From->getSuperClass()) + Importer.FromDiag(From->getSuperClassLoc(), + diag::note_odr_objc_superclass) + << From->getSuperClass()->getDeclName(); + else + Importer.FromDiag(From->getLocation(), + diag::note_odr_objc_missing_superclass); + } + + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From); + return false; } + + // Start the definition. + To->startDefinition(); + + // If this class has a superclass, import it. + if (From->getSuperClass()) { + ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>( + Importer.Import(From->getSuperClass())); + if (!Super) + return true; + + To->setSuperClass(Super); + To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc())); + } + + // Import protocols + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> ProtocolLocs; + ObjCInterfaceDecl::protocol_loc_iterator + FromProtoLoc = From->protocol_loc_begin(); + + for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(), + FromProtoEnd = From->protocol_end(); + FromProto != FromProtoEnd; + ++FromProto, ++FromProtoLoc) { + ObjCProtocolDecl *ToProto + = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); + if (!ToProto) + return true; + Protocols.push_back(ToProto); + ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + } + + // FIXME: If we're merging, make sure that the protocol list is the same. + To->setProtocolList(Protocols.data(), Protocols.size(), + ProtocolLocs.data(), Importer.getToContext()); + + // Import categories. When the categories themselves are imported, they'll + // hook themselves into this interface. + for (ObjCCategoryDecl *FromCat = From->getCategoryList(); FromCat; + FromCat = FromCat->getNextClassCategory()) + Importer.Import(FromCat); - // Import all of the members of this protocol. - ImportDeclContext(D); + // If we have an @implementation, import it as well. + if (From->getImplementation()) { + ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( + Importer.Import(From->getImplementation())); + if (!Impl) + return true; + + To->setImplementation(Impl); + } - return ToProto; + if (shouldForceImportDeclContext(Kind)) { + // Import all of the members of this class. + ImportDeclContext(From, /*ForceImport=*/true); + } + return false; } Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + // If this class 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. + ObjCInterfaceDecl *Definition = D->getDefinition(); + if (Definition && Definition != D) { + Decl *ImportedDef = Importer.Import(Definition); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + // Import the major distinguishing characteristics of an @interface. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -3153,6 +3359,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; + // Look for an existing interface with the same name. ObjCInterfaceDecl *MergeWithIface = 0; llvm::SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); @@ -3164,105 +3371,22 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { break; } + // Create an interface declaration, if one does not already exist. ObjCInterfaceDecl *ToIface = MergeWithIface; - if (!ToIface || ToIface->isForwardDecl()) { - if (!ToIface) { - ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Name.getAsIdentifierInfo(), Loc, - D->isForwardDecl(), - D->isImplicitInterfaceDecl()); - ToIface->setForwardDecl(D->isForwardDecl()); - ToIface->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToIface); - } - Importer.Imported(D, ToIface); - - if (D->getSuperClass()) { - ObjCInterfaceDecl *Super - = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass())); - if (!Super) - return 0; - - ToIface->setSuperClass(Super); - ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc())); - } - - // Import protocols - SmallVector<ObjCProtocolDecl *, 4> Protocols; - SmallVector<SourceLocation, 4> ProtocolLocs; - ObjCInterfaceDecl::protocol_loc_iterator - FromProtoLoc = D->protocol_loc_begin(); - - // FIXME: Should we be usng all_referenced_protocol_begin() here? - for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(), - FromProtoEnd = D->protocol_end(); - FromProto != FromProtoEnd; - ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - return 0; - Protocols.push_back(ToProto); - ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); - } - - // FIXME: If we're merging, make sure that the protocol list is the same. - ToIface->setProtocolList(Protocols.data(), Protocols.size(), - ProtocolLocs.data(), Importer.getToContext()); - - // Import @end range - ToIface->setAtEndRange(Importer.Import(D->getAtEndRange())); - } else { - Importer.Imported(D, ToIface); - - // Check for consistency of superclasses. - DeclarationName FromSuperName, ToSuperName; - if (D->getSuperClass()) - FromSuperName = Importer.Import(D->getSuperClass()->getDeclName()); - if (ToIface->getSuperClass()) - ToSuperName = ToIface->getSuperClass()->getDeclName(); - if (FromSuperName != ToSuperName) { - Importer.ToDiag(ToIface->getLocation(), - diag::err_odr_objc_superclass_inconsistent) - << ToIface->getDeclName(); - if (ToIface->getSuperClass()) - Importer.ToDiag(ToIface->getSuperClassLoc(), - diag::note_odr_objc_superclass) - << ToIface->getSuperClass()->getDeclName(); - else - Importer.ToDiag(ToIface->getLocation(), - diag::note_odr_objc_missing_superclass); - if (D->getSuperClass()) - Importer.FromDiag(D->getSuperClassLoc(), - diag::note_odr_objc_superclass) - << D->getSuperClass()->getDeclName(); - else - Importer.FromDiag(D->getLocation(), - diag::note_odr_objc_missing_superclass); - return 0; - } + if (!ToIface) { + ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), + Name.getAsIdentifierInfo(), + /*PrevDecl=*/0,Loc, + D->isImplicitInterfaceDecl()); + ToIface->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToIface); } + Importer.Imported(D, ToIface); - // Import categories. When the categories themselves are imported, they'll - // hook themselves into this interface. - for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat; - FromCat = FromCat->getNextClassCategory()) - Importer.Import(FromCat); - - // Import all of the members of this class. - ImportDeclContext(D); - - // If we have an @implementation, import it as well. - if (D->getImplementation()) { - ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( - Importer.Import(D->getImplementation())); - if (!Impl) - return 0; + if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface)) + return 0; - ToIface->setImplementation(Impl); - } - return ToIface; } @@ -3278,11 +3402,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { if (!DC) return 0; + SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getIdentifier()), Category->getClassInterface(), Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc())); + Importer.Import(D->getAtStartLoc()), + CategoryNameLoc); DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { @@ -3293,7 +3419,7 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { ToImpl->setLexicalDeclContext(LexicalDC); } - LexicalDC->addDecl(ToImpl); + LexicalDC->addDeclInternal(ToImpl); Category->setImplementation(ToImpl); } @@ -3326,7 +3452,9 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Importer.ImportContext(D->getDeclContext()), Iface, Super, Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc())); + Importer.Import(D->getAtStartLoc()), + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc())); if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC @@ -3346,7 +3474,7 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { if ((Super && !Impl->getSuperClass()) || (!Super && Impl->getSuperClass()) || (Super && Impl->getSuperClass() && - Super->getCanonicalDecl() != Impl->getSuperClass())) { + !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) { Importer.ToDiag(Impl->getLocation(), diag::err_odr_objc_superclass_inconsistent) << Iface->getDeclName(); @@ -3418,11 +3546,12 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()), + Importer.Import(D->getLParenLoc()), T, D->getPropertyImplementation()); Importer.Imported(D, ToProperty); ToProperty->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToProperty); + LexicalDC->addDeclInternal(ToProperty); ToProperty->setPropertyAttributes(D->getPropertyAttributes()); ToProperty->setPropertyAttributesAsWritten( @@ -3481,7 +3610,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { Importer.Import(D->getPropertyIvarDeclLoc())); ToImpl->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToImpl); - LexicalDC->addDecl(ToImpl); + LexicalDC->addDeclInternal(ToImpl); } else { // Check that we have the same kind of property implementation (@synthesize // vs. @dynamic). @@ -3519,79 +3648,6 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { return ToImpl; } -Decl * -ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { - // Import the context of this declaration. - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return 0; - - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return 0; - } - - // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); - - SmallVector<ObjCProtocolDecl *, 4> Protocols; - SmallVector<SourceLocation, 4> Locations; - ObjCForwardProtocolDecl::protocol_loc_iterator FromProtoLoc - = D->protocol_loc_begin(); - for (ObjCForwardProtocolDecl::protocol_iterator FromProto - = D->protocol_begin(), FromProtoEnd = D->protocol_end(); - FromProto != FromProtoEnd; - ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - continue; - - Protocols.push_back(ToProto); - Locations.push_back(Importer.Import(*FromProtoLoc)); - } - - ObjCForwardProtocolDecl *ToForward - = ObjCForwardProtocolDecl::Create(Importer.getToContext(), DC, Loc, - Protocols.data(), Protocols.size(), - Locations.data()); - ToForward->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToForward); - Importer.Imported(D, ToForward); - return ToForward; -} - -Decl *ASTNodeImporter::VisitObjCClassDecl(ObjCClassDecl *D) { - // Import the context of this declaration. - DeclContext *DC = Importer.ImportContext(D->getDeclContext()); - if (!DC) - return 0; - - DeclContext *LexicalDC = DC; - if (D->getDeclContext() != D->getLexicalDeclContext()) { - LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); - if (!LexicalDC) - return 0; - } - - // Import the location of this declaration. - SourceLocation Loc = Importer.Import(D->getLocation()); - ObjCClassDecl::ObjCClassRef *From = D->getForwardDecl(); - ObjCInterfaceDecl *ToIface - = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface())); - ObjCClassDecl *ToClass = ObjCClassDecl::Create(Importer.getToContext(), DC, - Loc, - ToIface, - Importer.Import(From->getLocation())); - - ToClass->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(ToClass); - Importer.Imported(D, ToClass); - return ToClass; -} - Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // For template arguments, we adopt the translation unit as our declaration // context. This context will be fixed when the actual template declaration @@ -3749,7 +3805,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(D2); + LexicalDC->addDeclInternal(D2); // Note the relationship between the class templates. Importer.Imported(D, D2); @@ -3844,7 +3900,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Add the specialization to this context. D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDecl(D2); + LexicalDC->addDeclInternal(D2); } Importer.Imported(D, D2); @@ -3891,7 +3947,9 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), ToD, + E->refersToEnclosingLocal(), Importer.Import(E->getLocation()), T, E->getValueKind(), FoundD, @@ -4116,7 +4174,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { return 0; return ToContext.getTrivialTypeSourceInfo(T, - FromTSI->getTypeLoc().getSourceRange().getBegin()); + FromTSI->getTypeLoc().getLocStart()); } Decl *ASTImporter::Import(Decl *FromD) { @@ -4170,7 +4228,55 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; - return cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); + DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); + if (!ToDC) + return 0; + + // When we're using a record/enum/Objective-C class/protocol as a context, we + // need it to have a definition. + if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) { + RecordDecl *FromRecord = cast<RecordDecl>(FromDC); + if (ToRecord->isCompleteDefinition()) { + // Do nothing. + } else if (FromRecord->isCompleteDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromRecord, ToRecord, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToRecord); + } + } else if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(ToDC)) { + EnumDecl *FromEnum = cast<EnumDecl>(FromDC); + if (ToEnum->isCompleteDefinition()) { + // Do nothing. + } else if (FromEnum->isCompleteDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromEnum, ToEnum, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToEnum); + } + } else if (ObjCInterfaceDecl *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) { + ObjCInterfaceDecl *FromClass = cast<ObjCInterfaceDecl>(FromDC); + if (ToClass->getDefinition()) { + // Do nothing. + } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromDef, ToClass, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToClass); + } + } else if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) { + ObjCProtocolDecl *FromProto = cast<ObjCProtocolDecl>(FromDC); + if (ToProto->getDefinition()) { + // Do nothing. + } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromDef, ToProto, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToProto); + } + } + + return ToDC; } Expr *ASTImporter::Import(Expr *FromE) { @@ -4244,7 +4350,6 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { } llvm_unreachable("Invalid nested name specifier kind"); - return 0; } NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { @@ -4339,7 +4444,6 @@ TemplateName ASTImporter::Import(TemplateName From) { } llvm_unreachable("Invalid template name kind"); - return TemplateName(); } SourceLocation ASTImporter::Import(SourceLocation FromLoc) { @@ -4413,7 +4517,7 @@ void ASTImporter::ImportDefinition(Decl *From) { if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(To)) { if (!ToRecord->getDefinition()) { Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord, - /*ForceImport=*/true); + ASTNodeImporter::IDK_Everything); return; } } @@ -4421,11 +4525,27 @@ void ASTImporter::ImportDefinition(Decl *From) { if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) { if (!ToEnum->getDefinition()) { Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum, - /*ForceImport=*/true); + ASTNodeImporter::IDK_Everything); return; } } + + if (ObjCInterfaceDecl *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { + if (!ToIFace->getDefinition()) { + Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace, + ASTNodeImporter::IDK_Everything); + return; + } + } + if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { + if (!ToProto->getDefinition()) { + Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto, + ASTNodeImporter::IDK_Everything); + return; + } + } + Importer.ImportDeclContext(FromDC, true); } } @@ -4483,8 +4603,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { return DeclarationName::getUsingDirectiveName(); } - // Silence bogus GCC warning - return DeclarationName(); + llvm_unreachable("Invalid DeclarationName Kind!"); } IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { @@ -4521,6 +4640,26 @@ DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { return FromContext.getDiagnostics().Report(Loc, DiagID); } +void ASTImporter::CompleteDecl (Decl *D) { + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + if (!ID->getDefinition()) + ID->startDefinition(); + } + else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + if (!PD->getDefinition()) + PD->startDefinition(); + } + else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (!TD->getDefinition() && !TD->isBeingDefined()) { + TD->startDefinition(); + TD->setCompleteDefinition(true); + } + } + else { + assert (0 && "CompleteDecl called on a Decl that can't be completed"); + } +} + Decl *ASTImporter::Imported(Decl *From, Decl *To) { ImportedDecls[From] = To; return To; diff --git a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp index 3ca7d4d..cffcc65 100644 --- a/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp @@ -19,4 +19,8 @@ using namespace clang; Attr::~Attr() { } +void InheritableAttr::anchor() { } + +void InheritableParamAttr::anchor() { } + #include "clang/AST/AttrImpl.inc" diff --git a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp index f29bfd1..2186730 100644 --- a/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp +++ b/contrib/llvm/tools/clang/lib/AST/CXXInheritance.cpp @@ -23,12 +23,15 @@ using namespace clang; void CXXBasePaths::ComputeDeclsFound() { assert(NumDeclsFound == 0 && !DeclsFound && "Already computed the set of declarations"); - - std::set<NamedDecl *> Decls; - for (CXXBasePaths::paths_iterator Path = begin(), PathEnd = end(); - Path != PathEnd; ++Path) - Decls.insert(*Path->Decls.first); - + + SmallVector<NamedDecl *, 8> Decls; + for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) + Decls.push_back(*Path->Decls.first); + + // Eliminate duplicated decls. + llvm::array_pod_sort(Decls.begin(), Decls.end()); + Decls.erase(std::unique(Decls.begin(), Decls.end()), Decls.end()); + NumDeclsFound = Decls.size(); DeclsFound = new NamedDecl * [NumDeclsFound]; std::copy(Decls.begin(), Decls.end(), DeclsFound); diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 95d52cb..399f2e4 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -24,6 +24,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/Module.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" @@ -47,8 +48,6 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { case VisibilityAttr::Protected: return ProtectedVisibility; } - - return DefaultVisibility; } // If we're on Mac OS X, an 'availability' for Mac OS X attribute @@ -66,17 +65,6 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) { } typedef NamedDecl::LinkageInfo LinkageInfo; -typedef std::pair<Linkage,Visibility> LVPair; - -static LVPair merge(LVPair L, LVPair R) { - return LVPair(minLinkage(L.first, R.first), - minVisibility(L.second, R.second)); -} - -static LVPair merge(LVPair L, LinkageInfo R) { - return LVPair(minLinkage(L.first, R.linkage()), - minVisibility(L.second, R.visibility())); -} namespace { /// Flags controlling the computation of linkage and visibility. @@ -112,11 +100,16 @@ struct LVFlags { }; } // end anonymous namespace +static LinkageInfo getLVForType(QualType T) { + std::pair<Linkage,Visibility> P = T->getLinkageAndVisibility(); + return LinkageInfo(P.first, P.second, T->isVisibilityExplicit()); +} + /// \brief Get the most restrictive linkage for the types in the given /// template parameter list. -static LVPair +static LinkageInfo getLVForTemplateParameterList(const TemplateParameterList *Params) { - LVPair LV(ExternalLinkage, DefaultVisibility); + LinkageInfo LV(ExternalLinkage, DefaultVisibility, false); for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { @@ -125,20 +118,20 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) { for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { QualType T = NTTP->getExpansionType(I); if (!T->isDependentType()) - LV = merge(LV, T->getLinkageAndVisibility()); + LV.merge(getLVForType(T)); } continue; } - + if (!NTTP->getType()->isDependentType()) { - LV = merge(LV, NTTP->getType()->getLinkageAndVisibility()); + LV.merge(getLVForType(NTTP->getType())); continue; } } if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*P)) { - LV = merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters())); + LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters())); } } @@ -150,10 +143,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F); /// \brief Get the most restrictive linkage for the types and /// declarations in the given template argument list. -static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args, - unsigned NumArgs, - LVFlags &F) { - LVPair LV(ExternalLinkage, DefaultVisibility); +static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args, + unsigned NumArgs, + LVFlags &F) { + LinkageInfo LV(ExternalLinkage, DefaultVisibility, false); for (unsigned I = 0; I != NumArgs; ++I) { switch (Args[I].getKind()) { @@ -161,9 +154,9 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args, case TemplateArgument::Integral: case TemplateArgument::Expression: break; - + case TemplateArgument::Type: - LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility()); + LV.merge(getLVForType(Args[I].getAsType())); break; case TemplateArgument::Declaration: @@ -177,15 +170,15 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args, case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (TemplateDecl *Template + if (TemplateDecl *Template = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl()) - LV = merge(LV, getLVForDecl(Template, F)); + LV.merge(getLVForDecl(Template, F)); break; case TemplateArgument::Pack: - LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(), - Args[I].pack_size(), - F)); + LV.mergeWithMin(getLVForTemplateArgumentList(Args[I].pack_begin(), + Args[I].pack_size(), + F)); break; } } @@ -193,7 +186,7 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args, return LV; } -static LVPair +static LinkageInfo getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, LVFlags &F) { return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F); @@ -229,14 +222,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // and neither explicitly declared extern nor previously // declared to have external linkage; or // (there is no equivalent in C99) - if (Context.getLangOptions().CPlusPlus && + if (Context.getLangOpts().CPlusPlus && Var->getType().isConstant(Context) && Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern) { bool FoundExtern = false; - for (const VarDecl *PrevVar = Var->getPreviousDeclaration(); + for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar && !FoundExtern; - PrevVar = PrevVar->getPreviousDeclaration()) + PrevVar = PrevVar->getPreviousDecl()) if (isExternalLinkage(PrevVar->getLinkage())) FoundExtern = true; @@ -244,8 +237,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { return LinkageInfo::internal(); } if (Var->getStorageClass() == SC_None) { - const VarDecl *PrevVar = Var->getPreviousDeclaration(); - for (; PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) + const VarDecl *PrevVar = Var->getPreviousDecl(); + for (; PrevVar; PrevVar = PrevVar->getPreviousDecl()) if (PrevVar->getStorageClass() == SC_PrivateExtern) break; if (PrevVar) @@ -274,7 +267,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast<VarDecl>(D); const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); - if ((!Var || !Var->isExternC()) && (!Func || !Func->isExternC())) + if ((!Var || !Var->getDeclContext()->isExternCContext()) && + (!Func || !Func->getDeclContext()->isExternCContext())) return LinkageInfo::uniqueExternal(); } @@ -285,6 +279,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // scope and no storage-class specifier, its linkage is // external. LinkageInfo LV; + LV.mergeVisibility(Context.getLangOpts().getVisibilityMode()); if (F.ConsiderVisibilityAttributes) { if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) { @@ -296,10 +291,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { for (const DeclContext *DC = D->getDeclContext(); !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) { - if (!isa<NamespaceDecl>(DC)) continue; - if (llvm::Optional<Visibility> Vis - = cast<NamespaceDecl>(DC)->getExplicitVisibility()) { - LV.setVisibility(*Vis, false); + const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); + if (!ND) continue; + if (llvm::Optional<Visibility> Vis = ND->getExplicitVisibility()) { + LV.setVisibility(*Vis, true); F.ConsiderGlobalVisibility = false; break; } @@ -335,18 +330,19 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) { - LVPair TypeLV = Var->getType()->getLinkageAndVisibility(); - if (TypeLV.first != ExternalLinkage) + if (Context.getLangOpts().CPlusPlus && + !Var->getDeclContext()->isExternCContext()) { + LinkageInfo TypeLV = getLVForType(Var->getType()); + if (TypeLV.linkage() != ExternalLinkage) return LinkageInfo::uniqueExternal(); - if (!LV.visibilityExplicit()) - LV.mergeVisibility(TypeLV.second); + LV.mergeVisibilityWithMin(TypeLV.visibility(), + TypeLV.visibilityExplicit()); } if (Var->getStorageClass() == SC_PrivateExtern) LV.setVisibility(HiddenVisibility, true); - if (!Context.getLangOptions().CPlusPlus && + if (!Context.getLangOpts().CPlusPlus && (Var->getStorageClass() == SC_Extern || Var->getStorageClass() == SC_PrivateExtern)) { @@ -359,7 +355,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // specified at the prior declaration. If no prior declaration // is visible, or if the prior declaration specifies no // linkage, then the identifier has external linkage. - if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) { + if (const VarDecl *PrevVar = Var->getPreviousDecl()) { LinkageInfo PrevLV = getLVForDecl(PrevVar, F); if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); LV.mergeVisibility(PrevLV); @@ -381,7 +377,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // storage-class specifier, its linkage is determined exactly // as if it were declared with the storage-class specifier // extern. - if (!Context.getLangOptions().CPlusPlus && + if (!Context.getLangOpts().CPlusPlus && (Function->getStorageClass() == SC_Extern || Function->getStorageClass() == SC_PrivateExtern || Function->getStorageClass() == SC_None)) { @@ -394,7 +390,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // specified at the prior declaration. If no prior declaration // is visible, or if the prior declaration specifies no // linkage, then the identifier has external linkage. - if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) { + if (const FunctionDecl *PrevFunc = Function->getPreviousDecl()) { LinkageInfo PrevLV = getLVForDecl(PrevFunc, F); if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); LV.mergeVisibility(PrevLV); @@ -405,7 +401,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // unique-external linkage, it's not legally usable from outside // this translation unit. However, we should use the C linkage // rules instead for extern "C" declarations. - if (Context.getLangOptions().CPlusPlus && !Function->isExternC() && + if (Context.getLangOpts().CPlusPlus && + !Function->getDeclContext()->isExternCContext() && Function->getType()->getLinkage() == UniqueExternalLinkage) return LinkageInfo::uniqueExternal(); @@ -417,7 +414,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { LV.merge(getLVForDecl(specInfo->getTemplate(), F.onlyTemplateVisibility())); const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; - LV.merge(getLVForTemplateArgumentList(templateArgs, F)); + LV.mergeWithMin(getLVForTemplateArgumentList(templateArgs, F)); } } @@ -443,14 +440,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // The arguments at which the template was instantiated. const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs(); - LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); + LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, F)); } } // Consider -fvisibility unless the type has C linkage. if (F.ConsiderGlobalVisibility) F.ConsiderGlobalVisibility = - (Context.getLangOptions().CPlusPlus && + (Context.getLangOpts().CPlusPlus && !Tag->getDeclContext()->isExternCContext()); // - an enumerator belonging to an enumeration with external linkage; @@ -486,11 +483,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { if (LV.linkage() != ExternalLinkage) return LinkageInfo(LV.linkage(), DefaultVisibility, false); - // If we didn't end up with hidden visibility, consider attributes - // and -fvisibility. - if (F.ConsiderGlobalVisibility) - LV.mergeVisibility(Context.getLangOptions().getVisibilityMode()); - return LV; } @@ -507,6 +499,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { return LinkageInfo::none(); LinkageInfo LV; + LV.mergeVisibility(D->getASTContext().getLangOpts().getVisibilityMode()); // The flags we're going to use to compute the class's visibility. LVFlags ClassF = F; @@ -548,7 +541,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { if (FunctionTemplateSpecializationInfo *spec = MD->getTemplateSpecializationInfo()) { if (shouldConsiderTemplateLV(MD, spec)) { - LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F)); + LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments, + F)); if (F.ConsiderTemplateParameterTypes) LV.merge(getLVForTemplateParameterList( spec->getTemplate()->getTemplateParameters())); @@ -567,8 +561,9 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { // about whether containing classes have visibility attributes, // and that's intentional. if (TSK != TSK_ExplicitInstantiationDeclaration && + TSK != TSK_ExplicitInstantiationDefinition && F.ConsiderGlobalVisibility && - MD->getASTContext().getLangOptions().InlineVisibilityHidden) { + MD->getASTContext().getLangOpts().InlineVisibilityHidden) { // InlineVisibilityHidden only applies to definitions, and // isInlined() only gives meaningful answers on definitions // anyway. @@ -586,7 +581,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { if (shouldConsiderTemplateLV(spec)) { // Merge template argument/parameter information for member // class template specializations. - LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F)); + LV.mergeWithMin(getLVForTemplateArgumentList(spec->getTemplateArgs(), + F)); if (F.ConsiderTemplateParameterTypes) LV.merge(getLVForTemplateParameterList( spec->getSpecializedTemplate()->getTemplateParameters())); @@ -597,18 +593,11 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. - LVPair TypeLV = VD->getType()->getLinkageAndVisibility(); - if (TypeLV.first != ExternalLinkage) + LinkageInfo TypeLV = getLVForType(VD->getType()); + if (TypeLV.linkage() != ExternalLinkage) LV.mergeLinkage(UniqueExternalLinkage); if (!LV.visibilityExplicit()) - LV.mergeVisibility(TypeLV.second); - } - - F.ConsiderGlobalVisibility &= !LV.visibilityExplicit(); - - // Apply -fvisibility if desired. - if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) { - LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode()); + LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit()); } return LV; @@ -623,6 +612,8 @@ static void clearLinkageForClass(const CXXRecordDecl *record) { } } +void NamedDecl::anchor() { } + void NamedDecl::ClearLinkageCache() { // Note that we can't skip clearing the linkage of children just // because the parent doesn't have cached linkage: we don't cache @@ -683,13 +674,13 @@ LinkageInfo NamedDecl::getLinkageAndVisibility() const { llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { // Use the most recent declaration of a variable. if (const VarDecl *var = dyn_cast<VarDecl>(this)) - return getVisibilityOf(var->getMostRecentDeclaration()); + return getVisibilityOf(var->getMostRecentDecl()); // Use the most recent declaration of a function, and also handle // function template specializations. if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) { if (llvm::Optional<Visibility> V - = getVisibilityOf(fn->getMostRecentDeclaration())) + = getVisibilityOf(fn->getMostRecentDecl())) return V; // If the function is a specialization of a template with an @@ -698,6 +689,12 @@ llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { = fn->getTemplateSpecializationInfo()) return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl()); + // If the function is a member of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom); + return llvm::Optional<Visibility>(); } @@ -712,6 +709,14 @@ llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const { = dyn_cast<ClassTemplateSpecializationDecl>(this)) return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl()); + // If this is a member class of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) { + CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom); + } + return llvm::Optional<Visibility>(); } @@ -721,19 +726,46 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { switch (D->getKind()) { default: break; + case Decl::ParmVar: + return LinkageInfo::none(); case Decl::TemplateTemplateParm: // count these as external case Decl::NonTypeTemplateParm: case Decl::ObjCAtDefsField: case Decl::ObjCCategory: case Decl::ObjCCategoryImpl: case Decl::ObjCCompatibleAlias: - case Decl::ObjCForwardProtocol: case Decl::ObjCImplementation: case Decl::ObjCMethod: case Decl::ObjCProperty: case Decl::ObjCPropertyImpl: case Decl::ObjCProtocol: return LinkageInfo::external(); + + case Decl::CXXRecord: { + const CXXRecordDecl *Record = cast<CXXRecordDecl>(D); + if (Record->isLambda()) { + if (!Record->getLambdaManglingNumber()) { + // This lambda has no mangling number, so it's internal. + return LinkageInfo::internal(); + } + + // This lambda has its linkage/visibility determined by its owner. + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); + if (Decl *ContextDecl = Record->getLambdaContextDecl()) { + if (isa<ParmVarDecl>(ContextDecl)) + DC = ContextDecl->getDeclContext()->getRedeclContext(); + else + return getLVForDecl(cast<NamedDecl>(ContextDecl), Flags); + } + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) + return getLVForDecl(ND, Flags); + + return LinkageInfo::external(); + } + + break; + } } // Handle linkage for namespace-scope names. @@ -763,7 +795,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { // external linkage. if (D->getLexicalDeclContext()->isFunctionOrMethod()) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - if (Function->isInAnonymousNamespace() && !Function->isExternC()) + if (Function->isInAnonymousNamespace() && + !Function->getDeclContext()->isExternCContext()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -772,7 +805,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { LV.setVisibility(*Vis); } - if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) { + if (const FunctionDecl *Prev = Function->getPreviousDecl()) { LinkageInfo PrevLV = getLVForDecl(Prev, Flags); if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); LV.mergeVisibility(PrevLV); @@ -784,7 +817,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { if (const VarDecl *Var = dyn_cast<VarDecl>(D)) if (Var->getStorageClass() == SC_Extern || Var->getStorageClass() == SC_PrivateExtern) { - if (Var->isInAnonymousNamespace() && !Var->isExternC()) + if (Var->isInAnonymousNamespace() && + !Var->getDeclContext()->isExternCContext()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -795,7 +829,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { LV.setVisibility(*Vis); } - if (const VarDecl *Prev = Var->getPreviousDeclaration()) { + if (const VarDecl *Prev = Var->getPreviousDecl()) { LinkageInfo PrevLV = getLVForDecl(Prev, Flags); if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); LV.mergeVisibility(PrevLV); @@ -811,7 +845,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { } std::string NamedDecl::getQualifiedNameAsString() const { - return getQualifiedNameAsString(getASTContext().getLangOptions()); + return getQualifiedNameAsString(getASTContext().getPrintingPolicy()); } std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { @@ -904,7 +938,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) // For function declarations, we keep track of redeclarations. - return FD->getPreviousDeclaration() == OldD; + return FD->getPreviousDecl() == OldD; // For function templates, the underlying function declarations are linked. if (const FunctionTemplateDecl *FunctionTemplate @@ -933,6 +967,12 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { cast<UsingDecl>(OldD)->getQualifier()); } + // A typedef of an Objective-C class type can replace an Objective-C class + // declaration or definition, and vice versa. + if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) || + (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD))) + return true; + // For non-function declarations, if the declarations are of the // same kind then this must be a redeclaration, or semantic analysis // would not have given us the new declaration. @@ -943,23 +983,21 @@ bool NamedDecl::hasLinkage() const { return getLinkage() != NoLinkage; } -NamedDecl *NamedDecl::getUnderlyingDecl() { +NamedDecl *NamedDecl::getUnderlyingDeclImpl() { NamedDecl *ND = this; - while (true) { - if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND)) - ND = UD->getTargetDecl(); - else if (ObjCCompatibleAliasDecl *AD - = dyn_cast<ObjCCompatibleAliasDecl>(ND)) - return AD->getClassInterface(); - else - return ND; - } + while (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND)) + ND = UD->getTargetDecl(); + + if (ObjCCompatibleAliasDecl *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) + return AD->getClassInterface(); + + return ND; } bool NamedDecl::isCXXInstanceMember() const { - assert(isCXXClassMember() && - "checking whether non-member is instance member"); - + if (!isCXXClassMember()) + return false; + const NamedDecl *D = this; if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -1131,7 +1169,6 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { } llvm_unreachable("Invalid storage class"); - return 0; } VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, @@ -1141,6 +1178,12 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten); } +VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl)); + return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0, + QualType(), 0, SC_None, SC_None); +} + void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); if (getStorageClass() != SC) @@ -1156,34 +1199,26 @@ SourceRange VarDecl::getSourceRange() const { } bool VarDecl::isExternC() const { - ASTContext &Context = getASTContext(); - if (!Context.getLangOptions().CPlusPlus) - return (getDeclContext()->isTranslationUnit() && - getStorageClass() != SC_Static) || - (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); + if (getLinkage() != ExternalLinkage) + return false; const DeclContext *DC = getDeclContext(); - if (DC->isFunctionOrMethod()) + if (DC->isRecord()) return false; - for (; !DC->isTranslationUnit(); DC = DC->getParent()) { - if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { - if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) - return getStorageClass() != SC_Static; - - break; - } - - } - - return false; + ASTContext &Context = getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return true; + return DC->isExternCContext(); } VarDecl *VarDecl::getCanonicalDecl() { return getFirstDeclaration(); } -VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const { +VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( + ASTContext &C) const +{ // C++ [basic.def]p2: // A declaration is a definition unless [...] it contains the 'extern' // specifier or a linkage-specification and neither an initializer [...], @@ -1214,8 +1249,8 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const { if (getStorageClassAsWritten() == SC_Extern || getStorageClassAsWritten() == SC_PrivateExtern) { - for (const VarDecl *PrevVar = getPreviousDeclaration(); - PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) { + for (const VarDecl *PrevVar = getPreviousDecl(); + PrevVar; PrevVar = PrevVar->getPreviousDecl()) { if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit()) return DeclarationOnly; } @@ -1225,7 +1260,7 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const { // and without a storage class specifier or the scs 'static', constitutes // a tentative definition. // No such thing in C++. - if (!getASTContext().getLangOptions().CPlusPlus && isFileVarDecl()) + if (!C.getLangOpts().CPlusPlus && isFileVarDecl()) return TentativeDefinition; // What's left is (in C, block-scope) declarations without initializers or @@ -1263,23 +1298,26 @@ bool VarDecl::isTentativeDefinitionNow() const { return true; } -VarDecl *VarDecl::getDefinition() { +VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl *First = getFirstDeclaration(); for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); I != E; ++I) { - if ((*I)->isThisDeclarationADefinition() == Definition) + if ((*I)->isThisDeclarationADefinition(C) == Definition) return *I; } return 0; } -VarDecl::DefinitionKind VarDecl::hasDefinition() const { +VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; const VarDecl *First = getFirstDeclaration(); for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) - Kind = std::max(Kind, (*I)->isThisDeclarationADefinition()); + I != E; ++I) { + Kind = std::max(Kind, (*I)->isThisDeclarationADefinition(C)); + if (Kind == Definition) + break; + } return Kind; } @@ -1334,6 +1372,130 @@ void VarDecl::setInit(Expr *I) { Init = I; } +bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const { + const LangOptions &Lang = C.getLangOpts(); + + if (!Lang.CPlusPlus) + return false; + + // In C++11, any variable of reference type can be used in a constant + // expression if it is initialized by a constant expression. + if (Lang.CPlusPlus0x && getType()->isReferenceType()) + return true; + + // Only const objects can be used in constant expressions in C++. C++98 does + // not require the variable to be non-volatile, but we consider this to be a + // defect. + if (!getType().isConstQualified() || getType().isVolatileQualified()) + return false; + + // In C++, const, non-volatile variables of integral or enumeration types + // can be used in constant expressions. + if (getType()->isIntegralOrEnumerationType()) + return true; + + // Additionally, in C++11, non-volatile constexpr variables can be used in + // constant expressions. + return Lang.CPlusPlus0x && isConstexpr(); +} + +/// Convert the initializer for this declaration to the elaborated EvaluatedStmt +/// form, which contains extra information on the evaluated value of the +/// initializer. +EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { + EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); + if (!Eval) { + Stmt *S = Init.get<Stmt *>(); + Eval = new (getASTContext()) EvaluatedStmt; + Eval->Value = S; + Init = Eval; + } + return Eval; +} + +APValue *VarDecl::evaluateValue() const { + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + return evaluateValue(Notes); +} + +APValue *VarDecl::evaluateValue( + llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + + // We only produce notes indicating why an initializer is non-constant the + // first time it is evaluated. FIXME: The notes won't always be emitted the + // first time we try evaluation, so might not be produced at all. + if (Eval->WasEvaluated) + return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated; + + const Expr *Init = cast<Expr>(Eval->Value); + assert(!Init->isValueDependent()); + + if (Eval->IsEvaluating) { + // FIXME: Produce a diagnostic for self-initialization. + Eval->CheckedICE = true; + Eval->IsICE = false; + return 0; + } + + Eval->IsEvaluating = true; + + bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(), + this, Notes); + + // Ensure the result is an uninitialized APValue if evaluation fails. + if (!Result) + Eval->Evaluated = APValue(); + + Eval->IsEvaluating = false; + Eval->WasEvaluated = true; + + // In C++11, we have determined whether the initializer was a constant + // expression as a side-effect. + if (getASTContext().getLangOpts().CPlusPlus0x && !Eval->CheckedICE) { + Eval->CheckedICE = true; + Eval->IsICE = Result && Notes.empty(); + } + + return Result ? &Eval->Evaluated : 0; +} + +bool VarDecl::checkInitIsICE() const { + // Initializers of weak variables are never ICEs. + if (isWeak()) + return false; + + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + if (Eval->CheckedICE) + // We have already checked whether this subexpression is an + // integral constant expression. + return Eval->IsICE; + + const Expr *Init = cast<Expr>(Eval->Value); + assert(!Init->isValueDependent()); + + // In C++11, evaluate the initializer to check whether it's a constant + // expression. + if (getASTContext().getLangOpts().CPlusPlus0x) { + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + evaluateValue(Notes); + return Eval->IsICE; + } + + // It's an ICE whether or not the definition we found is + // out-of-line. See DR 721 and the discussion in Clang PR + // 6206 for details. + + if (Eval->CheckingICE) + return false; + Eval->CheckingICE = true; + + Eval->IsICE = Init->isIntegerConstantExpr(getASTContext()); + Eval->CheckingICE = false; + Eval->CheckedICE = true; + return Eval->IsICE; +} + bool VarDecl::extendsLifetimeOfTemporary() const { assert(getType()->isReferenceType() &&"Non-references never extend lifetime"); @@ -1390,6 +1552,12 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, S, SCAsWritten, DefArg); } +ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); + return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(), + 0, QualType(), 0, SC_None, SC_None, 0); +} + SourceRange ParmVarDecl::getSourceRange() const { if (!hasInheritedDefaultArg()) { SourceRange ArgRange = getDefaultArgRange(); @@ -1412,21 +1580,6 @@ Expr *ParmVarDecl::getDefaultArg() { return Arg; } -unsigned ParmVarDecl::getNumDefaultArgTemporaries() const { - if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(getInit())) - return E->getNumTemporaries(); - - return 0; -} - -CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) { - assert(getNumDefaultArgTemporaries() && - "Default arguments does not have any temporaries!"); - - ExprWithCleanups *E = cast<ExprWithCleanups>(getInit()); - return E->getTemporary(i); -} - SourceRange ParmVarDecl::getDefaultArgRange() const { if (const Expr *E = getInit()) return E->getSourceRange(); @@ -1540,7 +1693,7 @@ bool FunctionDecl::isMain() const { const TranslationUnitDecl *tunit = dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); return tunit && - !tunit->getASTContext().getLangOptions().Freestanding && + !tunit->getASTContext().getLangOpts().Freestanding && getIdentifier() && getIdentifier()->isStr("main"); } @@ -1568,27 +1721,21 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { } bool FunctionDecl::isExternC() const { - ASTContext &Context = getASTContext(); - // In C, any non-static, non-overloadable function has external - // linkage. - if (!Context.getLangOptions().CPlusPlus) - return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>(); + if (getLinkage() != ExternalLinkage) + return false; + + if (getAttr<OverloadableAttr>()) + return false; const DeclContext *DC = getDeclContext(); if (DC->isRecord()) return false; - for (; !DC->isTranslationUnit(); DC = DC->getParent()) { - if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { - if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) - return getStorageClass() != SC_Static && - !getAttr<OverloadableAttr>(); - - break; - } - } + ASTContext &Context = getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return true; - return isMain(); + return isMain() || DC->isExternCContext(); } bool FunctionDecl::isGlobal() const { @@ -1622,7 +1769,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { FunTmpl->setPreviousDeclaration(PrevFunTmpl); } - if (PrevDecl->IsInline) + if (PrevDecl && PrevDecl->IsInline) IsInline = true; } @@ -1652,11 +1799,14 @@ void FunctionDecl::setStorageClass(StorageClass SC) { /// 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 { - ASTContext &Context = getASTContext(); - if (!getIdentifier() || !getIdentifier()->getBuiltinID()) + if (!getIdentifier()) return 0; unsigned BuiltinID = getIdentifier()->getBuiltinID(); + if (!BuiltinID) + return 0; + + ASTContext &Context = getASTContext(); if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return BuiltinID; @@ -1670,7 +1820,7 @@ unsigned FunctionDecl::getBuiltinID() const { // If this function is at translation-unit scope and we're not in // C++, it refers to the C library function. - if (!Context.getLangOptions().CPlusPlus && + if (!Context.getLangOpts().CPlusPlus && getDeclContext()->isTranslationUnit()) return BuiltinID; @@ -1710,12 +1860,22 @@ void FunctionDecl::setParams(ASTContext &C, } } +void FunctionDecl::setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls) { + assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!"); + + if (!NewDecls.empty()) { + NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; + std::copy(NewDecls.begin(), NewDecls.end(), A); + DeclsInPrototypeScope = llvm::ArrayRef<NamedDecl*>(A, NewDecls.size()); + } +} + /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default /// arguments (in C++) or the last parameter is a parameter pack. unsigned FunctionDecl::getMinRequiredArguments() const { - if (!getASTContext().getLangOptions().CPlusPlus) + if (!getASTContext().getLangOpts().CPlusPlus) return getNumParams(); unsigned NumRequiredArgs = getNumParams(); @@ -1777,31 +1937,79 @@ bool FunctionDecl::isInlined() const { return false; } +static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { + // Only consider file-scope declarations in this test. + if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) + return false; + + // Only consider explicit declarations; the presence of a builtin for a + // libcall shouldn't affect whether a definition is externally visible. + if (Redecl->isImplicit()) + return false; + + if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern) + return true; // Not an inline definition + + return false; +} + /// \brief For a function declaration in C or C++, determine whether this /// declaration causes the definition to be externally visible. /// -/// Determines whether this is the first non-inline redeclaration of an inline -/// function in a language where "inline" does not normally require an -/// externally visible definition. +/// Specifically, this determines if adding the current declaration to the set +/// of redeclarations of the given functions causes +/// isInlineDefinitionExternallyVisible to change from false to true. bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { assert(!doesThisDeclarationHaveABody() && "Must have a declaration without a body."); ASTContext &Context = getASTContext(); - // In C99 mode, a function may have an inline definition (causing it to - // be deferred) then redeclared later. As a special case, "extern inline" - // is not required to produce an external symbol. - if (Context.getLangOptions().GNUInline || !Context.getLangOptions().C99 || - Context.getLangOptions().CPlusPlus) + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { + // With GNU inlining, a declaration with 'inline' but not 'extern', forces + // an externally visible definition. + // + // FIXME: What happens if gnu_inline gets added on after the first + // declaration? + if (!isInlineSpecified() || getStorageClassAsWritten() == SC_Extern) + return false; + + const FunctionDecl *Prev = this; + bool FoundBody = false; + while ((Prev = Prev->getPreviousDecl())) { + FoundBody |= Prev->Body; + + if (Prev->Body) { + // If it's not the case that both 'inline' and 'extern' are + // specified on the definition, then it is always externally visible. + if (!Prev->isInlineSpecified() || + Prev->getStorageClassAsWritten() != SC_Extern) + return false; + } else if (Prev->isInlineSpecified() && + Prev->getStorageClassAsWritten() != SC_Extern) { + return false; + } + } + return FoundBody; + } + + if (Context.getLangOpts().CPlusPlus) return false; - if (getLinkage() != ExternalLinkage || isInlineSpecified()) + + // C99 6.7.4p6: + // [...] If all of the file scope declarations for a function in a + // translation unit include the inline function specifier without extern, + // then the definition in that translation unit is an inline definition. + if (isInlineSpecified() && getStorageClass() != SC_Extern) return false; - const FunctionDecl *Definition = 0; - if (hasBody(Definition)) - return Definition->isInlined() && - Definition->isInlineDefinitionExternallyVisible(); - return false; + const FunctionDecl *Prev = this; + bool FoundBody = false; + while ((Prev = Prev->getPreviousDecl())) { + FoundBody |= Prev->Body; + if (RedeclForcesDefC99(Prev)) + return false; + } + return FoundBody; } /// \brief For an inline function definition in C or C++, determine whether the @@ -1826,7 +2034,10 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { assert(isInlined() && "Function must be inline"); ASTContext &Context = getASTContext(); - if (Context.getLangOptions().GNUInline || hasAttr<GNUInlineAttr>()) { + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { + // Note: If you change the logic here, please change + // doesDeclarationForceExternallyVisibleDefinition as well. + // // If it's not the case that both 'inline' and 'extern' are // specified on the definition, then this inline definition is // externally visible. @@ -1845,7 +2056,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { return false; } - + // C99 6.7.4p6: // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, @@ -1853,17 +2064,8 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); Redecl != RedeclEnd; ++Redecl) { - // Only consider file-scope declarations in this test. - if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) - continue; - - // Only consider explicit declarations; the presence of a builtin for a - // libcall shouldn't affect whether a definition is externally visible. - if (Redecl->isImplicit()) - continue; - - if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern) - return true; // Not an inline definition + if (RedeclForcesDefC99(*Redecl)) + return true; } // C99 6.7.4p6: @@ -1966,7 +2168,20 @@ bool FunctionDecl::isImplicitlyInstantiable() const { return true; return PatternDecl->isInlined(); -} +} + +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."); +} FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. @@ -2040,22 +2255,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, TemplateArgsAsWritten, PointOfInstantiation); TemplateOrSpecialization = Info; - - // Insert this function template specialization into the set of known - // function template specializations. - if (InsertPos) - Template->addSpecialization(Info, InsertPos); - else { - // Try to insert the new node. If there is an existing node, leave it, the - // set will contain the canonical decls while - // FunctionTemplateDecl::findSpecialization will return - // the most recent redeclarations. - FunctionTemplateSpecializationInfo *Existing - = Template->getSpecializations().GetOrInsertNode(Info); - (void)Existing; - assert((!Existing || Existing->Function->isCanonicalDecl()) && - "Set is supposed to only contain canonical decls"); - } + Template->addSpecialization(Info, InsertPos); } void @@ -2169,6 +2369,92 @@ SourceRange FunctionDecl::getSourceRange() const { return SourceRange(getOuterLocStart(), EndRangeLoc); } +unsigned FunctionDecl::getMemoryFunctionKind() const { + IdentifierInfo *FnInfo = getIdentifier(); + + if (!FnInfo) + return 0; + + // Builtin handling. + switch (getBuiltinID()) { + case Builtin::BI__builtin_memset: + case Builtin::BI__builtin___memset_chk: + case Builtin::BImemset: + return Builtin::BImemset; + + case Builtin::BI__builtin_memcpy: + case Builtin::BI__builtin___memcpy_chk: + case Builtin::BImemcpy: + return Builtin::BImemcpy; + + case Builtin::BI__builtin_memmove: + case Builtin::BI__builtin___memmove_chk: + case Builtin::BImemmove: + return Builtin::BImemmove; + + case Builtin::BIstrlcpy: + return Builtin::BIstrlcpy; + case Builtin::BIstrlcat: + return Builtin::BIstrlcat; + + case Builtin::BI__builtin_memcmp: + case Builtin::BImemcmp: + return Builtin::BImemcmp; + + case Builtin::BI__builtin_strncpy: + case Builtin::BI__builtin___strncpy_chk: + case Builtin::BIstrncpy: + return Builtin::BIstrncpy; + + case Builtin::BI__builtin_strncmp: + case Builtin::BIstrncmp: + return Builtin::BIstrncmp; + + case Builtin::BI__builtin_strncasecmp: + case Builtin::BIstrncasecmp: + return Builtin::BIstrncasecmp; + + case Builtin::BI__builtin_strncat: + case Builtin::BI__builtin___strncat_chk: + case Builtin::BIstrncat: + return Builtin::BIstrncat; + + case Builtin::BI__builtin_strndup: + case Builtin::BIstrndup: + return Builtin::BIstrndup; + + case Builtin::BI__builtin_strlen: + case Builtin::BIstrlen: + return Builtin::BIstrlen; + + default: + if (isExternC()) { + if (FnInfo->isStr("memset")) + return Builtin::BImemset; + else if (FnInfo->isStr("memcpy")) + return Builtin::BImemcpy; + else if (FnInfo->isStr("memmove")) + return Builtin::BImemmove; + else if (FnInfo->isStr("memcmp")) + return Builtin::BImemcmp; + else if (FnInfo->isStr("strncpy")) + return Builtin::BIstrncpy; + else if (FnInfo->isStr("strncmp")) + return Builtin::BIstrncmp; + else if (FnInfo->isStr("strncasecmp")) + return Builtin::BIstrncasecmp; + else if (FnInfo->isStr("strncat")) + return Builtin::BIstrncat; + else if (FnInfo->isStr("strndup")) + return Builtin::BIstrndup; + else if (FnInfo->isStr("strlen")) + return Builtin::BIstrlen; + } + break; + } + return 0; +} + //===----------------------------------------------------------------------===// // FieldDecl Implementation //===----------------------------------------------------------------------===// @@ -2182,6 +2468,12 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, BW, Mutable, HasInit); } +FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FieldDecl)); + return new (Mem) FieldDecl(Field, 0, SourceLocation(), SourceLocation(), + 0, QualType(), 0, 0, false, false); +} + bool FieldDecl::isAnonymousStructOrUnion() const { if (!isImplicit() || getDeclName()) return false; @@ -2201,31 +2493,27 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; - unsigned index = 0; + unsigned Index = 0; const RecordDecl *RD = getParent(); const FieldDecl *LastFD = 0; bool IsMsStruct = RD->hasAttr<MsStructAttr>(); - - RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); - while (true) { - assert(i != e && "failed to find field in parent!"); - if (*i == this) - break; + + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I, ++Index) { + (*I)->CachedFieldIndex = Index + 1; if (IsMsStruct) { // Zero-length bitfields following non-bitfield members are ignored. - if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD)) { - ++i; + if (getASTContext().ZeroBitfieldFollowsNonBitfield((*I), LastFD)) { + --Index; continue; } - LastFD = (*i); + LastFD = (*I); } - ++i; - ++index; } - CachedFieldIndex = index + 1; - return index; + assert(CachedFieldIndex && "failed to find field in parent"); + return CachedFieldIndex - 1; } SourceRange FieldDecl::getSourceRange() const { @@ -2339,6 +2627,8 @@ void TagDecl::setTemplateParameterListsInfo(ASTContext &Context, // EnumDecl Implementation //===----------------------------------------------------------------------===// +void EnumDecl::anchor() { } + EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -2350,9 +2640,10 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, return Enum; } -EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0, - false, false, false); +EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl)); + return new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0, + false, false, false); } void EnumDecl::completeDefinition(QualType NewType, @@ -2368,6 +2659,37 @@ void EnumDecl::completeDefinition(QualType NewType, TagDecl::completeDefinition(); } +TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const { + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation) { + MemberSpecializationInfo *MSI = getMemberSpecializationInfo(); + assert(MSI && "Not an instantiated member enumeration?"); + MSI->setTemplateSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && + MSI->getPointOfInstantiation().isInvalid()) + MSI->setPointOfInstantiation(PointOfInstantiation); +} + +EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const { + if (SpecializationInfo) + return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom()); + + return 0; +} + +void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, + TemplateSpecializationKind TSK) { + assert(!SpecializationInfo && "Member enum is already a specialization"); + SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK); +} + //===----------------------------------------------------------------------===// // RecordDecl Implementation //===----------------------------------------------------------------------===// @@ -2392,9 +2714,10 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, return R; } -RecordDecl *RecordDecl::Create(const ASTContext &C, EmptyShell Empty) { - return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); +RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl)); + return new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), + SourceLocation(), 0, 0); } bool RecordDecl::isInjectedClassName() const { @@ -2502,10 +2825,14 @@ SourceRange BlockDecl::getSourceRange() const { // Other Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// +void TranslationUnitDecl::anchor() { } + TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C) TranslationUnitDecl(C); } +void LabelDecl::anchor() { } + LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II) { return new (C) LabelDecl(DC, IdentL, II, 0, IdentL); @@ -2518,17 +2845,14 @@ LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, return new (C) LabelDecl(DC, IdentL, II, 0, GnuLabelL); } - -NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id) { - return new (C) NamespaceDecl(DC, StartLoc, IdLoc, Id); +LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LabelDecl)); + return new (Mem) LabelDecl(0, SourceLocation(), 0, 0, SourceLocation()); } -NamespaceDecl *NamespaceDecl::getNextNamespace() { - return dyn_cast_or_null<NamespaceDecl>( - NextNamespace.get(getASTContext().getExternalSource())); -} +void ValueDecl::anchor() { } + +void ImplicitParamDecl::anchor() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, @@ -2537,6 +2861,12 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, return new (C) ImplicitParamDecl(DC, IdLoc, Id, Type); } +ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ImplicitParamDecl)); + return new (Mem) ImplicitParamDecl(0, SourceLocation(), 0, QualType()); +} + FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -2553,10 +2883,22 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, return New; } +FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl)); + return new (Mem) FunctionDecl(Function, 0, SourceLocation(), + DeclarationNameInfo(), QualType(), 0, + SC_None, SC_None, false, false); +} + BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { return new (C) BlockDecl(DC, L); } +BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(BlockDecl)); + return new (Mem) BlockDecl(0, SourceLocation()); +} + EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, @@ -2564,6 +2906,15 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, return new (C) EnumConstantDecl(CD, L, Id, T, E, V); } +EnumConstantDecl * +EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumConstantDecl)); + return new (Mem) EnumConstantDecl(0, SourceLocation(), 0, QualType(), 0, + llvm::APSInt()); +} + +void IndirectFieldDecl::anchor() { } + IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, @@ -2571,6 +2922,13 @@ IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); } +IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(IndirectFieldDecl)); + return new (Mem) IndirectFieldDecl(0, SourceLocation(), DeclarationName(), + QualType(), 0, 0); +} + SourceRange EnumConstantDecl::getSourceRange() const { SourceLocation End = getLocation(); if (Init) @@ -2578,12 +2936,21 @@ SourceRange EnumConstantDecl::getSourceRange() const { return SourceRange(getLocation(), End); } +void TypeDecl::anchor() { } + TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) { return new (C) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo); } +void TypedefNameDecl::anchor() { } + +TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypedefDecl)); + return new (Mem) TypedefDecl(0, SourceLocation(), SourceLocation(), 0, 0); +} + TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -2591,6 +2958,11 @@ TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, return new (C) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo); } +TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasDecl)); + return new (Mem) TypeAliasDecl(0, SourceLocation(), SourceLocation(), 0, 0); +} + SourceRange TypedefDecl::getSourceRange() const { SourceLocation RangeEnd = getLocation(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { @@ -2607,9 +2979,96 @@ SourceRange TypeAliasDecl::getSourceRange() const { return SourceRange(getLocStart(), RangeEnd); } +void FileScopeAsmDecl::anchor() { } + FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc) { return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); } + +FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FileScopeAsmDecl)); + return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation()); +} + +//===----------------------------------------------------------------------===// +// ImportDecl Implementation +//===----------------------------------------------------------------------===// + +/// \brief Retrieve the number of module identifiers needed to name the given +/// module. +static unsigned getNumModuleIdentifiers(Module *Mod) { + unsigned Result = 1; + while (Mod->Parent) { + Mod = Mod->Parent; + ++Result; + } + return Result; +} + +ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, + Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs) + : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true), + NextLocalImport() +{ + assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size()); + SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(this + 1); + memcpy(StoredLocs, IdentifierLocs.data(), + IdentifierLocs.size() * sizeof(SourceLocation)); +} + +ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, + Module *Imported, SourceLocation EndLoc) + : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false), + NextLocalImport() +{ + *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc; +} + +ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs) { + void *Mem = C.Allocate(sizeof(ImportDecl) + + IdentifierLocs.size() * sizeof(SourceLocation)); + return new (Mem) ImportDecl(DC, StartLoc, Imported, IdentifierLocs); +} + +ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + Module *Imported, + SourceLocation EndLoc) { + void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation)); + ImportDecl *Import = new (Mem) ImportDecl(DC, StartLoc, Imported, EndLoc); + Import->setImplicit(); + return Import; +} + +ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumLocations) { + void *Mem = AllocateDeserializedDecl(C, ID, + (sizeof(ImportDecl) + + NumLocations * sizeof(SourceLocation))); + return new (Mem) ImportDecl(EmptyShell()); +} + +ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { + if (!ImportedAndComplete.getInt()) + return ArrayRef<SourceLocation>(); + + const SourceLocation *StoredLocs + = reinterpret_cast<const SourceLocation *>(this + 1); + return ArrayRef<SourceLocation>(StoredLocs, + getNumModuleIdentifiers(getImportedModule())); +} + +SourceRange ImportDecl::getSourceRange() const { + if (!ImportedAndComplete.getInt()) + return SourceRange(getLocation(), + *reinterpret_cast<const SourceLocation *>(this + 1)); + + return SourceRange(getLocation(), getIdentifierLocs().back()); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index 321e40b..47a0d25 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -39,7 +39,24 @@ using namespace clang; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" -static bool StatSwitch = false; +void *Decl::AllocateDeserializedDecl(const ASTContext &Context, + unsigned ID, + unsigned Size) { + // Allocate an extra 8 bytes worth of storage, which ensures that the + // resulting pointer will still be 8-byte aligned. + void *Start = Context.Allocate(Size + 8); + void *Result = (char*)Start + 8; + + unsigned *PrefixPtr = (unsigned *)Result - 2; + + // Zero out the first 4 bytes; this is used to store the owning module ID. + PrefixPtr[0] = 0; + + // Store the global declaration ID in the second 4 bytes. + PrefixPtr[1] = ID; + + return Result; +} const char *Decl::getDeclKindName() const { switch (DeclKind) { @@ -52,7 +69,7 @@ const char *Decl::getDeclKindName() const { void Decl::setInvalidDecl(bool Invalid) { InvalidDecl = Invalid; - if (Invalid) { + if (Invalid && !isa<ParmVarDecl>(this)) { // Defensive maneuver for ill-formed code: we're likely not to make it to // a point where we set the access specifier, so default it to "public" // to avoid triggering asserts elsewhere in the front end. @@ -69,9 +86,9 @@ const char *DeclContext::getDeclKindName() const { } } -bool Decl::CollectingStats(bool Enable) { - if (Enable) StatSwitch = true; - return StatSwitch; +bool Decl::StatisticsEnabled = false; +void Decl::EnableStatistics() { + StatisticsEnabled = true; } void Decl::PrintStats() { @@ -100,7 +117,6 @@ void Decl::PrintStats() { void Decl::add(Kind k) { switch (k) { - default: llvm_unreachable("Declaration not in DeclNodes.inc!"); #define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break; #define ABSTRACT_DECL(DECL) #include "clang/AST/DeclNodes.inc" @@ -185,15 +201,24 @@ void Decl::setLexicalDeclContext(DeclContext *DC) { return; if (isInSemaDC()) { - MultipleDC *MDC = new (getASTContext()) MultipleDC(); - MDC->SemanticDC = getDeclContext(); - MDC->LexicalDC = DC; - DeclCtx = MDC; + setDeclContextsImpl(getDeclContext(), DC, getASTContext()); } else { getMultipleDC()->LexicalDC = DC; } } +void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, + ASTContext &Ctx) { + if (SemaDC == LexicalDC) { + DeclCtx = SemaDC; + } else { + Decl::MultipleDC *MDC = new (Ctx) Decl::MultipleDC(); + MDC->SemanticDC = SemaDC; + MDC->LexicalDC = LexicalDC; + DeclCtx = MDC; + } +} + bool Decl::isInAnonymousNamespace() const { const DeclContext *DC = getDeclContext(); do { @@ -282,13 +307,20 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, // Match the platform name. if (A->getPlatform()->getName() != TargetPlatform) return AR_Available; - + + std::string HintMessage; + if (!A->getMessage().empty()) { + HintMessage = " - "; + HintMessage += A->getMessage(); + } + // Make sure that this declaration has not been marked 'unavailable'. if (A->getUnavailable()) { if (Message) { Message->clear(); llvm::raw_string_ostream Out(*Message); - Out << "not available on " << PrettyPlatformName; + Out << "not available on " << PrettyPlatformName + << HintMessage; } return AR_Unavailable; @@ -301,7 +333,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "introduced in " << PrettyPlatformName << ' ' - << A->getIntroduced(); + << A->getIntroduced() << HintMessage; } return AR_NotYetIntroduced; @@ -313,7 +345,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "obsoleted in " << PrettyPlatformName << ' ' - << A->getObsoleted(); + << A->getObsoleted() << HintMessage; } return AR_Unavailable; @@ -325,7 +357,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, Message->clear(); llvm::raw_string_ostream Out(*Message); Out << "first deprecated in " << PrettyPlatformName << ' ' - << A->getDeprecated(); + << A->getDeprecated() << HintMessage; } return AR_Deprecated; @@ -391,7 +423,7 @@ bool Decl::canBeWeakImported(bool &IsDefinition) const { } } else if (isa<ObjCPropertyDecl>(this) || isa<ObjCMethodDecl>(this)) return false; - else if (!(getASTContext().getLangOptions().ObjCNonFragileABI && + else if (!(getASTContext().getLangOpts().ObjCNonFragileABI && isa<ObjCInterfaceDecl>(this))) return false; @@ -488,9 +520,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case LinkageSpec: case FileScopeAsm: case StaticAssert: - case ObjCClass: case ObjCPropertyImpl: - case ObjCForwardProtocol: case Block: case TranslationUnit: @@ -501,17 +531,18 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCImplementation: case ObjCCategory: case ObjCCategoryImpl: + case Import: // Never looked up by name. return 0; } - return 0; + llvm_unreachable("Invalid DeclKind!"); } -void Decl::setAttrs(const AttrVec &attrs) { +void Decl::setAttrsImpl(const AttrVec &attrs, ASTContext &Ctx) { assert(!HasAttrs && "Decl already contains attrs."); - AttrVec &AttrBlank = getASTContext().getDeclAttrs(this); + AttrVec &AttrBlank = Ctx.getDeclAttrs(this); assert(AttrBlank.empty() && "HasAttrs was wrong?"); AttrBlank = attrs; @@ -640,7 +671,11 @@ void Decl::CheckAccessDeclContext() const { } DeclContext *Decl::getNonClosureContext() { - DeclContext *DC = getDeclContext(); + return getDeclContext()->getNonClosureAncestor(); +} + +DeclContext *DeclContext::getNonClosureAncestor() { + DeclContext *DC = this; // This is basically "while (DC->isClosure()) DC = DC->getParent();" // except that it's significantly more efficient to cast to a known @@ -704,10 +739,14 @@ bool DeclContext::isDependentContext() const { if (isa<ClassTemplatePartialSpecializationDecl>(this)) return true; - if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) { if (Record->getDescribedClassTemplate()) return true; - + + if (Record->isDependentLambda()) + return true; + } + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) { if (Function->getDescribedFunctionTemplate()) return true; @@ -767,9 +806,18 @@ DeclContext *DeclContext::getPrimaryContext() { return this; case Decl::ObjCInterface: + if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition()) + return Def; + + return this; + case Decl::ObjCProtocol: + if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(this)->getDefinition()) + return Def; + + return this; + case Decl::ObjCCategory: - // FIXME: Can Objective-C interfaces be forward-declared? return this; case Decl::ObjCImplementation: @@ -804,21 +852,27 @@ DeclContext *DeclContext::getPrimaryContext() { } } -DeclContext *DeclContext::getNextContext() { - switch (DeclKind) { - case Decl::Namespace: - // Return the next namespace - return static_cast<NamespaceDecl*>(this)->getNextNamespace(); - - default: - return 0; +void +DeclContext::collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts){ + Contexts.clear(); + + if (DeclKind != Decl::Namespace) { + Contexts.push_back(this); + return; } + + NamespaceDecl *Self = static_cast<NamespaceDecl *>(this); + for (NamespaceDecl *N = Self->getMostRecentDecl(); N; + N = N->getPreviousDecl()) + Contexts.push_back(N); + + std::reverse(Contexts.begin(), Contexts.end()); } std::pair<Decl *, Decl *> -DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, +DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded) { - // Build up a chain of declarations via the Decl::NextDeclInContext field. + // Build up a chain of declarations via the Decl::NextInContextAndBits field. Decl *FirstNewDecl = 0; Decl *PrevDecl = 0; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { @@ -827,7 +881,7 @@ DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, Decl *D = Decls[I]; if (PrevDecl) - PrevDecl->NextDeclInContext = D; + PrevDecl->NextInContextAndBits.setPointer(D); else FirstNewDecl = D; @@ -873,7 +927,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { Decl *ExternalFirst, *ExternalLast; llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls, FieldsAlreadyLoaded); - ExternalLast->NextDeclInContext = FirstDecl; + ExternalLast->NextInContextAndBits.setPointer(FirstDecl); FirstDecl = ExternalFirst; if (!LastDecl) LastDecl = ExternalLast; @@ -884,7 +938,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name) { ASTContext &Context = DC->getParentASTContext(); StoredDeclsMap *Map; - if (!(Map = DC->LookupPtr)) + if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); StoredDeclsList &List = (*Map)[Name]; @@ -901,7 +955,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, ASTContext &Context = DC->getParentASTContext();; StoredDeclsMap *Map; - if (!(Map = DC->LookupPtr)) + if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); StoredDeclsList &List = (*Map)[Name]; @@ -948,7 +1002,7 @@ bool DeclContext::decls_empty() const { void DeclContext::removeDecl(Decl *D) { assert(D->getLexicalDeclContext() == this && "decl being removed from non-lexical context"); - assert((D->NextDeclInContext || D == LastDecl) && + assert((D->NextInContextAndBits.getPointer() || D == LastDecl) && "decl is not in decls list"); // Remove D from the decl chain. This is O(n) but hopefully rare. @@ -956,12 +1010,12 @@ void DeclContext::removeDecl(Decl *D) { if (D == LastDecl) FirstDecl = LastDecl = 0; else - FirstDecl = D->NextDeclInContext; + FirstDecl = D->NextInContextAndBits.getPointer(); } else { - for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) { + for (Decl *I = FirstDecl; true; I = I->NextInContextAndBits.getPointer()) { assert(I && "decl not found in linked list"); - if (I->NextDeclInContext == D) { - I->NextDeclInContext = D->NextDeclInContext; + if (I->NextInContextAndBits.getPointer() == D) { + I->NextInContextAndBits.setPointer(D->NextInContextAndBits.getPointer()); if (D == LastDecl) LastDecl = I; break; } @@ -969,7 +1023,7 @@ void DeclContext::removeDecl(Decl *D) { } // Mark that D is no longer in the decl chain. - D->NextDeclInContext = 0; + D->NextInContextAndBits.setPointer(0); // Remove D from the lookup table if necessary. if (isa<NamedDecl>(D)) { @@ -978,12 +1032,13 @@ void DeclContext::removeDecl(Decl *D) { // Remove only decls that have a name if (!ND->getDeclName()) return; - StoredDeclsMap *Map = getPrimaryContext()->LookupPtr; + StoredDeclsMap *Map = getPrimaryContext()->LookupPtr.getPointer(); if (!Map) return; StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName()); assert(Pos != Map->end() && "no lookup entry for decl"); - Pos->second.remove(ND); + if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND) + Pos->second.remove(ND); } } @@ -994,7 +1049,7 @@ void DeclContext::addHiddenDecl(Decl *D) { "Decl already inserted into a DeclContext"); if (FirstDecl) { - LastDecl->NextDeclInContext = D; + LastDecl->NextInContextAndBits.setPointer(D); LastDecl = D; } else { FirstDecl = LastDecl = D; @@ -1004,55 +1059,118 @@ void DeclContext::addHiddenDecl(Decl *D) { // update it's class-specific state. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) Record->addedMember(D); + + // If this is a newly-created (not de-serialized) import declaration, wire + // it in to the list of local import declarations. + if (!D->isFromASTFile()) { + if (ImportDecl *Import = dyn_cast<ImportDecl>(D)) + D->getASTContext().addedLocalImportDecl(Import); + } } void DeclContext::addDecl(Decl *D) { addHiddenDecl(D); if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) - ND->getDeclContext()->makeDeclVisibleInContext(ND); + ND->getDeclContext()->getPrimaryContext()-> + makeDeclVisibleInContextWithFlags(ND, false, true); +} + +void DeclContext::addDeclInternal(Decl *D) { + addHiddenDecl(D); + + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) + ND->getDeclContext()->getPrimaryContext()-> + makeDeclVisibleInContextWithFlags(ND, true, true); +} + +/// shouldBeHidden - Determine whether a declaration which was declared +/// within its semantic context should be invisible to qualified name lookup. +static bool shouldBeHidden(NamedDecl *D) { + // Skip unnamed declarations. + if (!D->getDeclName()) + return true; + + // Skip entities that can't be found by name lookup into a particular + // context. + if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) || + D->isTemplateParameter()) + return true; + + // Skip template specializations. + // FIXME: This feels like a hack. Should DeclarationName support + // template-ids, or is there a better way to keep specializations + // from being visible? + if (isa<ClassTemplateSpecializationDecl>(D)) + return true; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isFunctionTemplateSpecialization()) + return true; + + return false; } /// buildLookup - Build the lookup data structure with all of the -/// declarations in DCtx (and any other contexts linked to it or -/// transparent contexts nested within it). -void DeclContext::buildLookup(DeclContext *DCtx) { - for (; DCtx; DCtx = DCtx->getNextContext()) { - for (decl_iterator D = DCtx->decls_begin(), - DEnd = DCtx->decls_end(); - D != DEnd; ++D) { - // Insert this declaration into the lookup structure, but only - // if it's semantically in its decl context. During non-lazy - // lookup building, this is implicitly enforced by addDecl. - if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) - if (D->getDeclContext() == DCtx) - makeDeclVisibleInContextImpl(ND); - - // Insert any forward-declared Objective-C interface into the lookup - // data structure. - if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) - makeDeclVisibleInContextImpl(Class->getForwardInterfaceDecl()); - - // If this declaration is itself a transparent declaration context or - // inline namespace, add its members (recursively). - if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) - if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) - buildLookup(InnerCtx->getPrimaryContext()); - } +/// declarations in this DeclContext (and any other contexts linked +/// to it or transparent contexts nested within it) and return it. +StoredDeclsMap *DeclContext::buildLookup() { + assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); + + if (!LookupPtr.getInt()) + return LookupPtr.getPointer(); + + llvm::SmallVector<DeclContext *, 2> Contexts; + collectAllContexts(Contexts); + for (unsigned I = 0, N = Contexts.size(); I != N; ++I) + buildLookupImpl(Contexts[I]); + + // We no longer have any lazy decls. + LookupPtr.setInt(false); + return LookupPtr.getPointer(); +} + +/// buildLookupImpl - Build part of the lookup data structure for the +/// declarations contained within DCtx, which will either be this +/// DeclContext, a DeclContext linked to it, or a transparent context +/// nested within it. +void DeclContext::buildLookupImpl(DeclContext *DCtx) { + for (decl_iterator I = DCtx->decls_begin(), E = DCtx->decls_end(); + I != E; ++I) { + Decl *D = *I; + + // Insert this declaration into the lookup structure, but only if + // it's semantically within its decl context. Any other decls which + // should be found in this context are added eagerly. + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND)) + makeDeclVisibleInContextImpl(ND, false); + + // If this declaration is itself a transparent declaration context + // or inline namespace, add the members of this declaration of that + // context (recursively). + if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D)) + if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) + buildLookupImpl(InnerCtx); } } DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) { + assert(DeclKind != Decl::LinkageSpec && + "Should not perform lookups into linkage specs!"); + DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { - // Check to see if we've already cached the lookup results. - if (LookupPtr) { - StoredDeclsMap::iterator I = LookupPtr->find(Name); - if (I != LookupPtr->end()) + // If a PCH has a result for this name, and we have a local declaration, we + // will have imported the PCH result when adding the local declaration. + // FIXME: For modules, we could have had more declarations added by module + // imoprts since we saw the declaration of the local name. + if (StoredDeclsMap *Map = LookupPtr.getPointer()) { + StoredDeclsMap::iterator I = Map->find(Name); + if (I != Map->end()) return I->second.getLookupResult(); } @@ -1060,20 +1178,18 @@ DeclContext::lookup(DeclarationName Name) { return Source->FindExternalVisibleDeclsByName(this, Name); } - /// If there is no lookup data structure, build one now by walking - /// all of the linked DeclContexts (in declaration order!) and - /// inserting their values. - if (!LookupPtr) { - buildLookup(this); + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (LookupPtr.getInt()) + Map = buildLookup(); - if (!LookupPtr) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); - } + if (!Map) + return lookup_result(lookup_iterator(0), lookup_iterator(0)); - StoredDeclsMap::iterator Pos = LookupPtr->find(Name); - if (Pos == LookupPtr->end()) + StoredDeclsMap::iterator I = Map->find(Name); + if (I == Map->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); - return Pos->second.getLookupResult(); + + return I->second.getLookupResult(); } DeclContext::lookup_const_result @@ -1094,10 +1210,10 @@ void DeclContext::localUncachedLookup(DeclarationName Name, } // If we have a lookup table, check there first. Maybe we'll get lucky. - if (LookupPtr) { - StoredDeclsMap::iterator Pos = LookupPtr->find(Name); - if (Pos != LookupPtr->end()) { - Results.insert(Results.end(), + if (StoredDeclsMap *Map = LookupPtr.getPointer()) { + StoredDeclsMap::iterator Pos = Map->find(Name); + if (Pos != Map->end()) { + Results.insert(Results.end(), Pos->second.getLookupResult().first, Pos->second.getLookupResult().second); return; @@ -1147,79 +1263,97 @@ bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const { return false; } -void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) { - // FIXME: This feels like a hack. Should DeclarationName support - // template-ids, or is there a better way to keep specializations - // from being visible? - if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter()) +void DeclContext::makeDeclVisibleInContext(NamedDecl *D) { + DeclContext *PrimaryDC = this->getPrimaryContext(); + DeclContext *DeclDC = D->getDeclContext()->getPrimaryContext(); + // If the decl is being added outside of its semantic decl context, we + // need to ensure that we eagerly build the lookup information for it. + PrimaryDC->makeDeclVisibleInContextWithFlags(D, false, PrimaryDC == DeclDC); +} + +void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, + bool Recoverable) { + assert(this == getPrimaryContext() && "expected a primary DC"); + + // Skip declarations within functions. + // FIXME: We shouldn't need to build lookup tables for function declarations + // ever, and we can't do so correctly because we can't model the nesting of + // scopes which occurs within functions. We use "qualified" lookup into + // function declarations when handling friend declarations inside nested + // classes, and consequently accept the following invalid code: + // + // void f() { void g(); { int g; struct S { friend void g(); }; } } + if (isFunctionOrMethod() && !isa<FunctionDecl>(D)) return; - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - if (FD->isFunctionTemplateSpecialization()) - return; - DeclContext *PrimaryContext = getPrimaryContext(); - if (PrimaryContext != this) { - PrimaryContext->makeDeclVisibleInContext(D, Recoverable); + // Skip declarations which should be invisible to name lookup. + if (shouldBeHidden(D)) return; - } - // If we already have a lookup data structure, perform the insertion - // into it. If we haven't deserialized externally stored decls, deserialize - // them so we can add the decl. Otherwise, be lazy and don't build that - // structure until someone asks for it. - if (LookupPtr || !Recoverable || hasExternalVisibleStorage()) - makeDeclVisibleInContextImpl(D); + // If we already have a lookup data structure, perform the insertion into + // it. If we might have externally-stored decls with this name, look them + // up and perform the insertion. If this decl was declared outside its + // semantic context, buildLookup won't add it, so add it now. + // + // FIXME: As a performance hack, don't add such decls into the translation + // unit unless we're in C++, since qualified lookup into the TU is never + // performed. + if (LookupPtr.getPointer() || hasExternalVisibleStorage() || + ((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) && + (getParentASTContext().getLangOpts().CPlusPlus || + !isTranslationUnit()))) { + // If we have lazily omitted any decls, they might have the same name as + // the decl which we are adding, so build a full lookup table before adding + // this decl. + buildLookup(); + makeDeclVisibleInContextImpl(D, Internal); + } else { + LookupPtr.setInt(true); + } // If we are a transparent context or inline namespace, insert into our // parent context, too. This operation is recursive. if (isTransparentContext() || isInlineNamespace()) - getParent()->makeDeclVisibleInContext(D, Recoverable); + getParent()->getPrimaryContext()-> + makeDeclVisibleInContextWithFlags(D, Internal, Recoverable); Decl *DCAsDecl = cast<Decl>(this); - // Notify that a decl was made visible unless it's a Tag being defined. + // Notify that a decl was made visible unless we are a Tag being defined. if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined())) if (ASTMutationListener *L = DCAsDecl->getASTMutationListener()) L->AddedVisibleDecl(this, D); } -void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { - // Skip unnamed declarations. - if (!D->getDeclName()) - return; - - // Skip entities that can't be found by name lookup into a particular - // context. - if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) || - D->isTemplateParameter()) - return; - - ASTContext *C = 0; - if (!LookupPtr) { - C = &getParentASTContext(); - CreateStoredDeclsMap(*C); +void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { + // Find or create the stored declaration map. + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (!Map) { + ASTContext *C = &getParentASTContext(); + Map = CreateStoredDeclsMap(*C); } // If there is an external AST source, load any declarations it knows about // with this declaration's name. // If the lookup table contains an entry about this name it means that we // have already checked the external source. - if (ExternalASTSource *Source = getParentASTContext().getExternalSource()) - if (hasExternalVisibleStorage() && - LookupPtr->find(D->getDeclName()) == LookupPtr->end()) - Source->FindExternalVisibleDeclsByName(this, D->getDeclName()); + if (!Internal) + if (ExternalASTSource *Source = getParentASTContext().getExternalSource()) + if (hasExternalVisibleStorage() && + Map->find(D->getDeclName()) == Map->end()) + Source->FindExternalVisibleDeclsByName(this, D->getDeclName()); // Insert this declaration into the map. - StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()]; + StoredDeclsList &DeclNameEntries = (*Map)[D->getDeclName()]; if (DeclNameEntries.isNull()) { DeclNameEntries.setOnlyValue(D); return; } - // If it is possible that this is a redeclaration, check to see if there is - // already a decl for which declarationReplaces returns true. If there is - // one, just replace it and return. - if (DeclNameEntries.HandleRedeclaration(D)) + if (DeclNameEntries.HandleRedeclaration(D)) { + // This declaration has replaced an existing one for which + // declarationReplaces returns true. return; + } // Put this declaration into the appropriate slot. DeclNameEntries.AddSubsequentDecl(D); @@ -1229,6 +1363,8 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { /// this context. DeclContext::udir_iterator_range DeclContext::getUsingDirectives() const { + // FIXME: Use something more efficient than normal lookup for using + // directives. In C++, using directives are looked up more than anything else. lookup_const_result Result = lookup(UsingDirectiveDecl::getName()); return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first), reinterpret_cast<udir_iterator>(Result.second)); @@ -1239,7 +1375,7 @@ DeclContext::getUsingDirectives() const { //===----------------------------------------------------------------------===// StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const { - assert(!LookupPtr && "context already has a decls map"); + assert(!LookupPtr.getPointer() && "context already has a decls map"); assert(getPrimaryContext() == this && "creating decls map on non-primary context"); @@ -1251,7 +1387,7 @@ StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const { M = new StoredDeclsMap(); M->Previous = C.LastSDM; C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent); - LookupPtr = M; + LookupPtr.setPointer(M); return M; } @@ -1283,11 +1419,11 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C, assert(Parent->isDependentContext() && "cannot iterate dependent diagnostics of non-dependent context"); Parent = Parent->getPrimaryContext(); - if (!Parent->LookupPtr) + if (!Parent->LookupPtr.getPointer()) Parent->CreateStoredDeclsMap(C); DependentStoredDeclsMap *Map - = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr); + = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr.getPointer()); // Allocate the copy of the PartialDiagnostic via the ASTContext's // BumpPtrAllocator, rather than the ASTContext itself. diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index f3da67c..114322b 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" @@ -27,6 +28,13 @@ using namespace clang; // Decl Allocation/Deallocation Method Implementations //===----------------------------------------------------------------------===// +void AccessSpecDecl::anchor() { } + +AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(AccessSpecDecl)); + return new (Mem) AccessSpecDecl(EmptyShell()); +} + CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false), @@ -34,17 +42,24 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), - HasMutableFields(false), HasTrivialDefaultConstructor(true), - HasConstexprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true), + HasMutableFields(false), HasOnlyCMembers(true), + HasTrivialDefaultConstructor(true), + HasConstexprNonCopyMoveConstructor(false), + DefaultedDefaultConstructorIsConstexpr(true), + DefaultedCopyConstructorIsConstexpr(true), + DefaultedMoveConstructorIsConstexpr(true), + HasConstexprDefaultConstructor(false), HasConstexprCopyConstructor(false), + HasConstexprMoveConstructor(false), HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true), HasTrivialDestructor(true), + HasIrrelevantDestructor(true), HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), DeclaredMoveConstructor(false), DeclaredCopyAssignment(false), DeclaredMoveAssignment(false), DeclaredDestructor(false), FailedImplicitMoveConstructor(false), - FailedImplicitMoveAssignment(false), NumBases(0), NumVBases(0), Bases(), - VBases(), Definition(D), FirstFriend(0) { + FailedImplicitMoveAssignment(false), IsLambda(false), NumBases(0), + NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend(0) { } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -68,24 +83,41 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } -CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, EmptyShell Empty) { - return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); +CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, + SourceLocation Loc, bool Dependent) { + CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, + 0, 0); + R->IsBeingDefined = true; + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Dependent); + C.getTypeDeclType(R, /*PrevDecl=*/0); + return R; +} + +CXXRecordDecl * +CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl)); + return new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), + SourceLocation(), 0, 0); } void CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases) { ASTContext &C = getASTContext(); - - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class (clause 9) with [...] - // no base classes [...]. - data().Aggregate = false; if (!data().Bases.isOffset() && data().NumBases > 0) C.Deallocate(data().getBases()); + if (NumBases) { + // C++ [dcl.init.aggr]p1: + // An aggregate is [...] a class with [...] no base classes [...]. + data().Aggregate = false; + + // C++ [class]p4: + // A POD-struct is an aggregate class... + data().PlainOldData = false; + } + // The set of seen virtual base types. llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes; @@ -105,14 +137,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); - // C++ [dcl.init.aggr]p1: - // An aggregate is [...] a class with [...] no base classes [...]. - data().Aggregate = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class... - data().PlainOldData = false; - // A class with a non-empty base class is not empty. // FIXME: Standard ref? if (!BaseClassDecl->isEmpty()) { @@ -190,6 +214,13 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // A standard-layout class is a class that: [...] // -- has [...] no virtual base classes data().IsStandardLayout = false; + + // C++11 [dcl.constexpr]p4: + // In the definition of a constexpr constructor [...] + // -- the class shall not have any virtual base classes + data().DefaultedDefaultConstructorIsConstexpr = false; + data().DefaultedCopyConstructorIsConstexpr = false; + data().DefaultedMoveConstructorIsConstexpr = false; } else { // C++ [class.ctor]p5: // A default constructor is trivial [...] if: @@ -221,6 +252,32 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().HasTrivialCopyAssignment = false; if (!BaseClassDecl->hasTrivialMoveAssignment()) data().HasTrivialMoveAssignment = false; + + // C++11 [class.ctor]p6: + // If that user-written default constructor would satisfy the + // requirements of a constexpr constructor, the implicitly-defined + // default constructor is constexpr. + if (!BaseClassDecl->hasConstexprDefaultConstructor()) + data().DefaultedDefaultConstructorIsConstexpr = false; + + // C++11 [class.copy]p13: + // If the implicitly-defined constructor would satisfy the requirements + // of a constexpr constructor, the implicitly-defined constructor is + // constexpr. + // C++11 [dcl.constexpr]p4: + // -- every constructor involved in initializing [...] base class + // sub-objects shall be a constexpr constructor + if (!BaseClassDecl->hasConstexprCopyConstructor()) + data().DefaultedCopyConstructorIsConstexpr = false; + if (BaseClassDecl->hasDeclaredMoveConstructor() || + BaseClassDecl->needsImplicitMoveConstructor()) + // FIXME: If the implicit move constructor generated for the base class + // would be ill-formed, the implicit move constructor generated for the + // derived class calls the base class' copy constructor. + data().DefaultedMoveConstructorIsConstexpr &= + BaseClassDecl->hasConstexprMoveConstructor(); + else if (!BaseClassDecl->hasConstexprCopyConstructor()) + data().DefaultedMoveConstructorIsConstexpr = false; } // C++ [class.ctor]p3: @@ -228,7 +285,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // have trivial destructors. if (!BaseClassDecl->hasTrivialDestructor()) data().HasTrivialDestructor = false; - + + if (!BaseClassDecl->hasIrrelevantDestructor()) + data().HasIrrelevantDestructor = false; + // A class has an Objective-C object member if... or any of its bases // has an Objective-C object member. if (BaseClassDecl->hasObjectMember()) @@ -410,6 +470,12 @@ void CXXRecordDecl::markedVirtualFunctionPure() { } void CXXRecordDecl::addedMember(Decl *D) { + if (!D->isImplicit() && + !isa<FieldDecl>(D) && + !isa<IndirectFieldDecl>(D) && + (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class)) + data().HasOnlyCMembers = false; + // Ignore friends and invalid declarations. if (D->getFriendObjectKind() || D->isInvalidDecl()) return; @@ -453,8 +519,7 @@ void CXXRecordDecl::addedMember(Decl *D) { // -- class X has no virtual functions [...] data().HasTrivialCopyAssignment = false; data().HasTrivialMoveAssignment = false; - // FIXME: Destructor? - + // C++0x [class]p7: // A standard-layout class is a class that: [...] // -- has no virtual functions @@ -472,13 +537,21 @@ void CXXRecordDecl::addedMember(Decl *D) { // If this is a special member function, note that it was added and then // return early. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - if (Constructor->isDefaultConstructor()) + if (Constructor->isDefaultConstructor()) { data().DeclaredDefaultConstructor = true; - else if (Constructor->isCopyConstructor()) + if (Constructor->isConstexpr()) { + data().HasConstexprDefaultConstructor = true; + data().HasConstexprNonCopyMoveConstructor = true; + } + } else if (Constructor->isCopyConstructor()) { data().DeclaredCopyConstructor = true; - else if (Constructor->isMoveConstructor()) + if (Constructor->isConstexpr()) + data().HasConstexprCopyConstructor = true; + } else if (Constructor->isMoveConstructor()) { data().DeclaredMoveConstructor = true; - else + if (Constructor->isConstexpr()) + data().HasConstexprMoveConstructor = true; + } else goto NotASpecialMember; return; } else if (isa<CXXDestructorDecl>(D)) { @@ -508,14 +581,18 @@ NotASpecialMember:; // to all functions. bool UserProvided = Constructor->isUserProvided(); - // C++0x [class.ctor]p5: - // A default constructor is trivial if it is not user-provided [...] if (Constructor->isDefaultConstructor()) { data().DeclaredDefaultConstructor = true; if (UserProvided) { + // C++0x [class.ctor]p5: + // A default constructor is trivial if it is not user-provided [...] data().HasTrivialDefaultConstructor = false; data().UserProvidedDefaultConstructor = true; } + if (Constructor->isConstexpr()) { + data().HasConstexprDefaultConstructor = true; + data().HasConstexprNonCopyMoveConstructor = true; + } } // Note when we have a user-declared copy or move constructor, which will @@ -530,6 +607,9 @@ NotASpecialMember:; // user-provided [...] if (UserProvided) data().HasTrivialCopyConstructor = false; + + if (Constructor->isConstexpr()) + data().HasConstexprCopyConstructor = true; } else if (Constructor->isMoveConstructor()) { data().UserDeclaredMoveConstructor = true; data().DeclaredMoveConstructor = true; @@ -539,6 +619,9 @@ NotASpecialMember:; // user-provided [...] if (UserProvided) data().HasTrivialMoveConstructor = false; + + if (Constructor->isConstexpr()) + data().HasConstexprMoveConstructor = true; } } if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) { @@ -553,7 +636,7 @@ NotASpecialMember:; // C++0x [dcl.init.aggr]p1: // An aggregate is an array or a class with no user-provided // constructors [...]. - if (!getASTContext().getLangOptions().CPlusPlus0x || UserProvided) + if (!getASTContext().getLangOpts().CPlusPlus0x || UserProvided) data().Aggregate = false; // C++ [class]p4: @@ -569,17 +652,29 @@ NotASpecialMember:; if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) { data().DeclaredDestructor = true; data().UserDeclaredDestructor = true; - + data().HasIrrelevantDestructor = false; + // C++ [class]p4: // A POD-struct is an aggregate class that has [...] no user-defined // destructor. // This bit is the C++03 POD bit, not the 0x one. data().PlainOldData = false; - // C++0x [class.dtor]p5: - // A destructor is trivial if it is not user-provided and [...] - if (DD->isUserProvided()) + // C++11 [class.dtor]p5: + // A destructor is trivial if it is not user-provided and if + // -- the destructor is not virtual. + if (DD->isUserProvided() || DD->isVirtual()) { data().HasTrivialDestructor = false; + // C++11 [dcl.constexpr]p1: + // The constexpr specifier shall be applied only to [...] the + // declaration of a static data member of a literal type. + // C++11 [basic.types]p10: + // A type is a literal type if it is [...] a class type that [...] has + // a trivial destructor. + data().DefaultedDefaultConstructorIsConstexpr = false; + data().DefaultedCopyConstructorIsConstexpr = false; + data().DefaultedMoveConstructorIsConstexpr = false; + } return; } @@ -634,14 +729,14 @@ NotASpecialMember:; // hasn't been set yet. That's really just a misdesign in Sema. if (FunTmpl) { - if (FunTmpl->getPreviousDeclaration()) - data().Conversions.replace(FunTmpl->getPreviousDeclaration(), + if (FunTmpl->getPreviousDecl()) + data().Conversions.replace(FunTmpl->getPreviousDecl(), FunTmpl); else data().Conversions.addDecl(FunTmpl); } else { - if (Conversion->getPreviousDeclaration()) - data().Conversions.replace(Conversion->getPreviousDeclaration(), + if (Conversion->getPreviousDecl()) + data().Conversions.replace(Conversion->getPreviousDecl(), Conversion); else data().Conversions.addDecl(Conversion); @@ -703,7 +798,7 @@ NotASpecialMember:; ASTContext &Context = getASTContext(); QualType T = Context.getBaseElementType(Field->getType()); if (T->isObjCRetainableType() || T.isObjCGCStrong()) { - if (!Context.getLangOptions().ObjCAutoRefCount || + if (!Context.getLangOpts().ObjCAutoRefCount || T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) setHasObjectMember(true); } else if (!T.isPODType(Context)) @@ -718,12 +813,8 @@ NotASpecialMember:; data().IsStandardLayout = false; } - // Record if this field is the first non-literal field or base. - // As a slight variation on the standard, we regard mutable members as being - // non-literal, since mutating a constexpr variable would break C++11 - // constant expression semantics. - if ((!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) || - Field->isMutable()) + // Record if this field is the first non-literal or volatile field or base. + if (!T->isLiteralType() || T.isVolatileQualified()) data().HasNonLiteralTypeFieldsOrBases = true; if (Field->hasInClassInitializer()) { @@ -746,7 +837,7 @@ NotASpecialMember:; CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl()); if (FieldRec->getDefinition()) { // C++0x [class.ctor]p5: - // A defulat constructor is trivial [...] if: + // A default constructor is trivial [...] if: // -- for all the non-static data members of its class that are of // class type (or array thereof), each such class has a trivial // default constructor. @@ -779,6 +870,8 @@ NotASpecialMember:; if (!FieldRec->hasTrivialDestructor()) data().HasTrivialDestructor = false; + if (!FieldRec->hasIrrelevantDestructor()) + data().HasIrrelevantDestructor = false; if (FieldRec->hasObjectMember()) setHasObjectMember(true); @@ -818,7 +911,41 @@ NotASpecialMember:; // Keep track of the presence of mutable fields. if (FieldRec->hasMutableFields()) data().HasMutableFields = true; + + // C++11 [class.copy]p13: + // If the implicitly-defined constructor would satisfy the + // requirements of a constexpr constructor, the implicitly-defined + // constructor is constexpr. + // C++11 [dcl.constexpr]p4: + // -- every constructor involved in initializing non-static data + // members [...] shall be a constexpr constructor + if (!Field->hasInClassInitializer() && + !FieldRec->hasConstexprDefaultConstructor()) + // The standard requires any in-class initializer to be a constant + // expression. We consider this to be a defect. + data().DefaultedDefaultConstructorIsConstexpr = false; + + if (!FieldRec->hasConstexprCopyConstructor()) + data().DefaultedCopyConstructorIsConstexpr = false; + + if (FieldRec->hasDeclaredMoveConstructor() || + FieldRec->needsImplicitMoveConstructor()) + // FIXME: If the implicit move constructor generated for the member's + // class would be ill-formed, the implicit move constructor generated + // for this class calls the member's copy constructor. + data().DefaultedMoveConstructorIsConstexpr &= + FieldRec->hasConstexprMoveConstructor(); + else if (!FieldRec->hasConstexprCopyConstructor()) + data().DefaultedMoveConstructorIsConstexpr = false; } + } else { + // Base element type of field is a non-class type. + if (!T->isLiteralType()) { + data().DefaultedDefaultConstructorIsConstexpr = false; + data().DefaultedCopyConstructorIsConstexpr = false; + data().DefaultedMoveConstructorIsConstexpr = false; + } else if (!Field->hasInClassInitializer()) + data().DefaultedDefaultConstructorIsConstexpr = false; } // C++0x [class]p7: @@ -849,6 +976,35 @@ NotASpecialMember:; data().Conversions.addDecl(Shadow, Shadow->getAccess()); } +bool CXXRecordDecl::isCLike() const { + if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull()) + return false; + if (!hasDefinition()) + return true; + + return isPOD() && data().HasOnlyCMembers; +} + +void CXXRecordDecl::getCaptureFields( + llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures, + FieldDecl *&ThisCapture) const { + Captures.clear(); + ThisCapture = 0; + + LambdaDefinitionData &Lambda = getLambdaData(); + RecordDecl::field_iterator Field = field_begin(); + for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures; + C != CEnd; ++C, ++Field) { + if (C->capturesThis()) { + ThisCapture = *Field; + continue; + } + + Captures[C->getCapturedVar()] = *Field; + } +} + + static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T; if (isa<UsingShadowDecl>(Conv)) @@ -1087,7 +1243,7 @@ void CXXRecordDecl::completeDefinition() { void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { RecordDecl::completeDefinition(); - if (hasObjectMember() && getASTContext().getLangOptions().ObjCAutoRefCount) { + if (hasObjectMember() && getASTContext().getLangOpts().ObjCAutoRefCount) { // Objective-C Automatic Reference Counting: // If a class has a non-static data member of Objective-C pointer // type (or array thereof), it is a non-POD type and its @@ -1099,6 +1255,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { Data.HasTrivialCopyConstructor = false; Data.HasTrivialCopyAssignment = false; Data.HasTrivialDestructor = false; + Data.HasIrrelevantDestructor = false; } // If the class may be abstract (but hasn't been marked as such), check for @@ -1157,6 +1314,8 @@ bool CXXRecordDecl::mayBeAbstract() const { return false; } +void CXXMethodDecl::anchor() { } + CXXMethodDecl * CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, @@ -1169,6 +1328,14 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, EndLocation); } +CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl)); + return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(), + DeclarationNameInfo(), QualType(), + 0, false, SC_None, false, false, + SourceLocation()); +} + bool CXXMethodDecl::isUsualDeallocationFunction() const { if (getOverloadedOperator() != OO_Delete && getOverloadedOperator() != OO_Array_Delete) @@ -1254,19 +1421,23 @@ void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) { assert(MD->isCanonicalDecl() && "Method is not canonical!"); assert(!MD->getParent()->isDependentContext() && "Can't add an overridden method to a class template!"); + assert(MD->isVirtual() && "Method is not virtual!"); getASTContext().addOverriddenMethod(this, MD); } CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const { + if (isa<CXXConstructorDecl>(this)) return 0; return getASTContext().overridden_methods_begin(this); } CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const { + if (isa<CXXConstructorDecl>(this)) return 0; return getASTContext().overridden_methods_end(this); } unsigned CXXMethodDecl::size_overridden_methods() const { + if (isa<CXXConstructorDecl>(this)) return 0; return getASTContext().overridden_methods_size(this); } @@ -1296,14 +1467,20 @@ bool CXXMethodDecl::hasInlineBody() const { return CheckFn->hasBody(fn) && !fn->isOutOfLine(); } +bool CXXMethodDecl::isLambdaStaticInvoker() const { + return getParent()->isLambda() && + getIdentifier() && getIdentifier()->getName() == "__invoke"; +} + + CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R, SourceLocation EllipsisLoc) : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false), - SourceOrderOrNumArrayIndices(0) + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), + IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1313,7 +1490,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1324,17 +1501,17 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R) : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, - SourceLocation D, SourceLocation L, - CXXConstructorDecl *Target, Expr *Init, + TypeSourceInfo *TInfo, + SourceLocation L, Expr *Init, SourceLocation R) - : Initializee(Target), MemberOrEllipsisLocation(D), Init(Init), - LParenLoc(L), RParenLoc(R), IsVirtual(false), + : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init), + LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } @@ -1383,13 +1560,16 @@ const Type *CXXCtorInitializer::getBaseClass() const { } SourceLocation CXXCtorInitializer::getSourceLocation() const { - if (isAnyMemberInitializer() || isDelegatingInitializer()) + if (isAnyMemberInitializer()) return getMemberLocation(); if (isInClassMemberInitializer()) return getAnyMember()->getLocation(); - return getBaseClassLoc().getLocalSourceRange().getBegin(); + if (TypeSourceInfo *TSInfo = Initializee.get<TypeSourceInfo*>()) + return TSInfo->getTypeLoc().getLocalSourceRange().getBegin(); + + return SourceLocation(); } SourceRange CXXCtorInitializer::getSourceRange() const { @@ -1403,10 +1583,13 @@ SourceRange CXXCtorInitializer::getSourceRange() const { return SourceRange(getSourceLocation(), getRParenLoc()); } +void CXXConstructorDecl::anchor() { } + CXXConstructorDecl * -CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(), - QualType(), 0, false, false, false, false); +CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConstructorDecl)); + return new (Mem) CXXConstructorDecl(0, SourceLocation(),DeclarationNameInfo(), + QualType(), 0, false, false, false,false); } CXXConstructorDecl * @@ -1424,6 +1607,15 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isConstexpr); } +CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { + assert(isDelegatingConstructor() && "Not a delegating constructor!"); + Expr *E = (*init_begin())->getInit()->IgnoreImplicit(); + if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E)) + return Construct->getConstructor(); + + return 0; +} + bool CXXConstructorDecl::isDefaultConstructor() const { // C++ [class.ctor]p5: // A default constructor for a class X is a constructor of class @@ -1524,8 +1716,8 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const { const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const { // Hack: we store the inherited constructor in the overridden method table - method_iterator It = begin_overridden_methods(); - if (It == end_overridden_methods()) + method_iterator It = getASTContext().overridden_methods_begin(this); + if (It == getASTContext().overridden_methods_end(this)) return 0; return cast<CXXConstructorDecl>(*It); @@ -1534,13 +1726,17 @@ const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const { void CXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl *BaseCtor){ // Hack: we store the inherited constructor in the overridden method table - assert(size_overridden_methods() == 0 && "Base ctor already set."); - addOverriddenMethod(BaseCtor); + assert(getASTContext().overridden_methods_size(this) == 0 && + "Base ctor already set."); + getASTContext().addOverriddenMethod(this, BaseCtor); } +void CXXDestructorDecl::anchor() { } + CXXDestructorDecl * -CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(), +CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXDestructorDecl)); + return new (Mem) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(), QualType(), 0, false, false); } @@ -1557,11 +1753,14 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isImplicitlyDeclared); } +void CXXConversionDecl::anchor() { } + CXXConversionDecl * -CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(), - QualType(), 0, false, false, false, - SourceLocation()); +CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConversionDecl)); + return new (Mem) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(), + QualType(), 0, false, false, false, + SourceLocation()); } CXXConversionDecl * @@ -1579,6 +1778,13 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, EndLocation); } +bool CXXConversionDecl::isLambdaToBlockPointerConversion() const { + return isImplicit() && getParent()->isLambda() && + getConversionType()->isBlockPointerType(); +} + +void LinkageSpecDecl::anchor() { } + LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation ExternLoc, @@ -1588,6 +1794,14 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, RBraceLoc); } +LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LinkageSpecDecl)); + return new (Mem) LinkageSpecDecl(0, SourceLocation(), SourceLocation(), + lang_c, SourceLocation()); +} + +void UsingDirectiveDecl::anchor() { } + UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation NamespaceLoc, @@ -1601,6 +1815,14 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, IdentLoc, Used, CommonAncestor); } +UsingDirectiveDecl * +UsingDirectiveDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDirectiveDecl)); + return new (Mem) UsingDirectiveDecl(0, SourceLocation(), SourceLocation(), + NestedNameSpecifierLoc(), + SourceLocation(), 0, 0); +} + NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { if (NamespaceAliasDecl *NA = dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace)) @@ -1608,6 +1830,36 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { return cast_or_null<NamespaceDecl>(NominatedNamespace); } +void NamespaceDecl::anchor() { } + +NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl) + : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline) +{ + setPreviousDeclaration(PrevDecl); + + if (PrevDecl) + AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace()); +} + +NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, + bool Inline, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl) { + return new (C) NamespaceDecl(DC, Inline, StartLoc, IdLoc, Id, PrevDecl); +} + +NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceDecl)); + return new (Mem) NamespaceDecl(0, false, SourceLocation(), SourceLocation(), + 0, 0); +} + +void NamespaceAliasDecl::anchor() { } + NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation AliasLoc, @@ -1621,6 +1873,22 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, QualifierLoc, IdentLoc, Namespace); } +NamespaceAliasDecl * +NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceAliasDecl)); + return new (Mem) NamespaceAliasDecl(0, SourceLocation(), SourceLocation(), 0, + NestedNameSpecifierLoc(), + SourceLocation(), 0); +} + +void UsingShadowDecl::anchor() { } + +UsingShadowDecl * +UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingShadowDecl)); + return new (Mem) UsingShadowDecl(0, SourceLocation(), 0, 0); +} + UsingDecl *UsingShadowDecl::getUsingDecl() const { const UsingShadowDecl *Shadow = this; while (const UsingShadowDecl *NextShadow = @@ -1629,14 +1897,16 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const { return cast<UsingDecl>(Shadow->UsingOrNextShadow); } +void UsingDecl::anchor() { } + void UsingDecl::addShadowDecl(UsingShadowDecl *S) { assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() && "declaration already in set"); assert(S->getUsingDecl() == this); - if (FirstUsingShadow) - S->UsingOrNextShadow = FirstUsingShadow; - FirstUsingShadow = S; + if (FirstUsingShadow.getPointer()) + S->UsingOrNextShadow = FirstUsingShadow.getPointer(); + FirstUsingShadow.setPointer(S); } void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { @@ -1646,13 +1916,14 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { // Remove S from the shadow decl chain. This is O(n) but hopefully rare. - if (FirstUsingShadow == S) { - FirstUsingShadow = dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow); + if (FirstUsingShadow.getPointer() == S) { + FirstUsingShadow.setPointer( + dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow)); S->UsingOrNextShadow = this; return; } - UsingShadowDecl *Prev = FirstUsingShadow; + UsingShadowDecl *Prev = FirstUsingShadow.getPointer(); while (Prev->UsingOrNextShadow != S) Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow); Prev->UsingOrNextShadow = S->UsingOrNextShadow; @@ -1666,6 +1937,14 @@ UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg); } +UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDecl)); + return new (Mem) UsingDecl(0, SourceLocation(), NestedNameSpecifierLoc(), + DeclarationNameInfo(), false); +} + +void UnresolvedUsingValueDecl::anchor() { } + UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, @@ -1675,6 +1954,16 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, QualifierLoc, NameInfo); } +UnresolvedUsingValueDecl * +UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UnresolvedUsingValueDecl)); + return new (Mem) UnresolvedUsingValueDecl(0, QualType(), SourceLocation(), + NestedNameSpecifierLoc(), + DeclarationNameInfo()); +} + +void UnresolvedUsingTypenameDecl::anchor() { } + UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, @@ -1687,6 +1976,19 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, TargetName.getAsIdentifierInfo()); } +UnresolvedUsingTypenameDecl * +UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, + sizeof(UnresolvedUsingTypenameDecl)); + return new (Mem) UnresolvedUsingTypenameDecl(0, SourceLocation(), + SourceLocation(), + NestedNameSpecifierLoc(), + SourceLocation(), + 0); +} + +void StaticAssertDecl::anchor() { } + StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, Expr *AssertExpr, @@ -1696,9 +1998,14 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, RParenLoc); } +StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(StaticAssertDecl)); + return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0,SourceLocation()); +} + static const char *getAccessName(AccessSpecifier AS) { switch (AS) { - default: case AS_none: llvm_unreachable("Invalid access specifier!"); case AS_public: @@ -1708,9 +2015,15 @@ static const char *getAccessName(AccessSpecifier AS) { case AS_protected: return "protected"; } + llvm_unreachable("Invalid access specifier!"); } const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, AccessSpecifier AS) { return DB << getAccessName(AS); } + +const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB, + AccessSpecifier AS) { + return DB << getAccessName(AS); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp index 99bfe40..6e3bd8d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclFriend.cpp @@ -16,6 +16,8 @@ #include "clang/AST/DeclTemplate.h" using namespace clang; +void FriendDecl::anchor() { } + FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend, @@ -40,6 +42,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC, return FD; } -FriendDecl *FriendDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) FriendDecl(Empty); +FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendDecl)); + return new (Mem) FriendDecl(EmptyShell()); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp index a589b7f..2370d3c 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp @@ -46,6 +46,8 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, // ObjCInterfaceDecl //===----------------------------------------------------------------------===// +void ObjCContainerDecl::anchor() { } + /// getIvarDecl - This method looks up an ivar in this ContextDecl. /// ObjCIvarDecl * @@ -147,6 +149,8 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { return 0; } +void ObjCInterfaceDecl::anchor() { } + /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property /// with name 'PropertyId' in the primary class; including those in protocols /// (direct or indirect) used by the primary class. @@ -154,7 +158,11 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( IdentifierInfo *PropertyId) const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); if (ObjCPropertyDecl *PD = @@ -175,11 +183,12 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ObjCProtocolDecl *const* ExtList, unsigned ExtNum, ASTContext &C) { - if (ExternallyCompleted) + if (data().ExternallyCompleted) LoadExternalDefinition(); - if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) { - AllReferencedProtocols.set(ExtList, ExtNum, C); + if (data().AllReferencedProtocols.empty() && + data().ReferencedProtocols.empty()) { + data().AllReferencedProtocols.set(ExtList, ExtNum, C); return; } @@ -214,7 +223,28 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ProtocolRefs.push_back(*p); } - AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C); + data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C); +} + +void ObjCInterfaceDecl::allocateDefinitionData() { + assert(!hasDefinition() && "ObjC class already has a definition"); + Data = new (getASTContext()) DefinitionData(); + Data->Definition = this; + + // Make the type point at the definition, now that we have one. + if (TypeForDecl) + cast<ObjCInterfaceType>(TypeForDecl)->Decl = this; +} + +void ObjCInterfaceDecl::startDefinition() { + allocateDefinitionData(); + + // Update all of the declarations with a pointer to the definition. + for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); + RD != RDEnd; ++RD) { + if (*RD != this) + RD->Data = Data; + } } /// getFirstClassExtension - Find first class extension of the given class. @@ -237,6 +267,13 @@ const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const { ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) + LoadExternalDefinition(); + ObjCInterfaceDecl* ClassDecl = this; while (ClassDecl != NULL) { if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { @@ -261,6 +298,13 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, /// the it returns NULL. ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( const IdentifierInfo*ICName) { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) + LoadExternalDefinition(); + ObjCInterfaceDecl* ClassDecl = this; while (ClassDecl != NULL) { if (ClassDecl->getIdentifier() == ICName) @@ -272,12 +316,17 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( /// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). -ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, - bool isInstance) const { +ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, + bool isInstance, + bool shallowCategoryLookup) const { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + const ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; - if (ExternallyCompleted) + if (data().ExternallyCompleted) LoadExternalDefinition(); while (ClassDecl != NULL) { @@ -285,28 +334,30 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, return MethodDecl; // Didn't find one yet - look through protocols. - const ObjCList<ObjCProtocolDecl> &Protocols = - ClassDecl->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); I != E; ++I) + for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(), + E = ClassDecl->protocol_end(); + I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; - + // Didn't find one yet - now look through categories. ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); while (CatDecl) { if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) return MethodDecl; - // Didn't find one yet - look through protocols. - const ObjCList<ObjCProtocolDecl> &Protocols = - CatDecl->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) - return MethodDecl; + if (!shallowCategoryLookup) { + // Didn't find one yet - look through protocols. + const ObjCList<ObjCProtocolDecl> &Protocols = + CatDecl->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); I != E; ++I) + if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) + return MethodDecl; + } CatDecl = CatDecl->getNextClassCategory(); } + ClassDecl = ClassDecl->getSuperClass(); } return NULL; @@ -315,6 +366,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( const Selector &Sel, bool Instance) { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) + LoadExternalDefinition(); + ObjCMethodDecl *Method = 0; if (ObjCImplementationDecl *ImpDecl = getImplementation()) Method = Instance ? ImpDecl->getInstanceMethod(Sel) @@ -351,6 +409,12 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C, HasRelatedResultType); } +ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCMethodDecl)); + return new (Mem) ObjCMethodDecl(SourceLocation(), SourceLocation(), + Selector(), QualType(), 0, 0); +} + void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) { assert(PrevMethod); getASTContext().setObjCMethodRedeclaration(PrevMethod, this); @@ -452,6 +516,10 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() { return MD; } + if (isRedeclaration()) + return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), + isInstanceMethod()); + return this; } @@ -560,17 +628,26 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, bool selfIsPseudoStrong = false; bool selfIsConsumed = false; - if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) { - selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); - - // 'self' is always __strong. It's actually pseudo-strong except - // in init methods, though. - Qualifiers qs; - qs.setObjCLifetime(Qualifiers::OCL_Strong); - selfTy = Context.getQualifiedType(selfTy, qs); - - // In addition, 'self' is const unless this is an init method. - if (getMethodFamily() != OMF_init) { + + if (Context.getLangOpts().ObjCAutoRefCount) { + if (isInstanceMethod()) { + selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); + + // 'self' is always __strong. It's actually pseudo-strong except + // in init methods (or methods labeled ns_consumes_self), though. + Qualifiers qs; + qs.setObjCLifetime(Qualifiers::OCL_Strong); + selfTy = Context.getQualifiedType(selfTy, qs); + + // In addition, 'self' is const unless this is an init method. + if (getMethodFamily() != OMF_init && !selfIsConsumed) { + selfTy = selfTy.withConst(); + selfIsPseudoStrong = true; + } + } + else { + assert(isClassMethod()); + // 'self' is always const in class methods. selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } @@ -608,28 +685,45 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() { // ObjCInterfaceDecl //===----------------------------------------------------------------------===// -ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, +ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, + ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc, - bool ForwardDecl, bool isInternal){ - return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl, - isInternal); + bool isInternal){ + ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, + PrevDecl, isInternal); + C.getObjCInterfaceType(Result, PrevDecl); + return Result; +} + +ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCInterfaceDecl)); + return new (Mem) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(), + 0, false); } ObjCInterfaceDecl:: ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal) + SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, + bool isInternal) : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), - TypeForDecl(0), SuperClass(0), - CategoryList(0), IvarList(0), - ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false) { + TypeForDecl(0), Data() +{ + setPreviousDeclaration(PrevDecl); + + // Copy the 'data' pointer over. + if (PrevDecl) + Data = PrevDecl->Data; + + setImplicit(isInternal); } void ObjCInterfaceDecl::LoadExternalDefinition() const { - assert(ExternallyCompleted && "Class is not externally completed"); - ExternallyCompleted = false; + assert(data().ExternallyCompleted && "Class is not externally completed"); + data().ExternallyCompleted = false; getASTContext().getExternalSource()->CompleteType( const_cast<ObjCInterfaceDecl *>(this)); } @@ -637,35 +731,44 @@ void ObjCInterfaceDecl::LoadExternalDefinition() const { void ObjCInterfaceDecl::setExternallyCompleted() { assert(getASTContext().getExternalSource() && "Class can't be externally completed without an external source"); - assert(!ForwardDecl && + assert(hasDefinition() && "Forward declarations can't be externally completed"); - ExternallyCompleted = true; + data().ExternallyCompleted = true; } ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { - if (ExternallyCompleted) - LoadExternalDefinition(); - - return getASTContext().getObjCImplementation( - const_cast<ObjCInterfaceDecl*>(this)); + if (const ObjCInterfaceDecl *Def = getDefinition()) { + if (data().ExternallyCompleted) + LoadExternalDefinition(); + + return getASTContext().getObjCImplementation( + const_cast<ObjCInterfaceDecl*>(Def)); + } + + // FIXME: Should make sure no callers ever do this. + return 0; } void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { - getASTContext().setObjCImplementation(this, ImplD); + getASTContext().setObjCImplementation(getDefinition(), ImplD); } /// all_declared_ivar_begin - return first ivar declared in this class, /// its extensions and its implementation. Lazily build the list on first /// access. ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { - if (IvarList) - return IvarList; + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().IvarList) + return data().IvarList; ObjCIvarDecl *curIvar = 0; if (!ivar_empty()) { ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); - IvarList = (*I); ++I; - for (curIvar = IvarList; I != E; curIvar = *I, ++I) + data().IvarList = (*I); ++I; + for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); } @@ -674,9 +777,9 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { if (!CDecl->ivar_empty()) { ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), E = CDecl->ivar_end(); - if (!IvarList) { - IvarList = (*I); ++I; - curIvar = IvarList; + if (!data().IvarList) { + data().IvarList = (*I); ++I; + curIvar = data().IvarList; } for ( ;I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); @@ -687,15 +790,15 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { if (!ImplDecl->ivar_empty()) { ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), E = ImplDecl->ivar_end(); - if (!IvarList) { - IvarList = (*I); ++I; - curIvar = IvarList; + if (!data().IvarList) { + data().IvarList = (*I); ++I; + curIvar = data().IvarList; } for ( ;I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); } } - return IvarList; + return data().IvarList; } /// FindCategoryDeclaration - Finds category declaration in the list of @@ -704,7 +807,11 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { /// ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); for (ObjCCategoryDecl *Category = getCategoryList(); @@ -739,13 +846,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, bool lookupCategory, bool RHSIsQualifiedID) { + if (!hasDefinition()) + return false; + ObjCInterfaceDecl *IDecl = this; // 1st, look up the class. - const ObjCList<ObjCProtocolDecl> &Protocols = - IDecl->getReferencedProtocols(); - - for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(), - E = Protocols.end(); PI != E; ++PI) { + for (ObjCInterfaceDecl::protocol_iterator + PI = IDecl->protocol_begin(), E = IDecl->protocol_end(); PI != E; ++PI){ if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI)) return true; // This is dubious and is added to be compatible with gcc. In gcc, it is @@ -782,6 +889,8 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, // ObjCIvarDecl //===----------------------------------------------------------------------===// +void ObjCIvarDecl::anchor() { } + ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -824,6 +933,12 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC, ac, BW, synthesized); } +ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCIvarDecl)); + return new (Mem) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0, + QualType(), 0, ObjCIvarDecl::None, 0, false); +} + const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext()); @@ -852,6 +967,8 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const { // ObjCAtDefsFieldDecl //===----------------------------------------------------------------------===// +void ObjCAtDefsFieldDecl::anchor() { } + ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -859,15 +976,46 @@ ObjCAtDefsFieldDecl return new (C) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW); } +ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCAtDefsFieldDecl)); + return new (Mem) ObjCAtDefsFieldDecl(0, SourceLocation(), SourceLocation(), + 0, QualType(), 0); +} + //===----------------------------------------------------------------------===// // ObjCProtocolDecl //===----------------------------------------------------------------------===// +void ObjCProtocolDecl::anchor() { } + +ObjCProtocolDecl::ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, + SourceLocation nameLoc, + SourceLocation atStartLoc, + ObjCProtocolDecl *PrevDecl) + : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), Data() +{ + setPreviousDeclaration(PrevDecl); + if (PrevDecl) + Data = PrevDecl->Data; +} + ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, - SourceLocation atStartLoc) { - return new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc); + SourceLocation atStartLoc, + ObjCProtocolDecl *PrevDecl) { + ObjCProtocolDecl *Result + = new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl); + + return Result; +} + +ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCProtocolDecl)); + return new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(), SourceLocation(), + 0); } ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { @@ -898,87 +1046,57 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, return NULL; } -//===----------------------------------------------------------------------===// -// ObjCClassDecl -//===----------------------------------------------------------------------===// - -ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const Elt, - const SourceLocation Loc, - ASTContext &C) - : Decl(ObjCClass, DC, L) { - setClass(C, Elt, Loc); +void ObjCProtocolDecl::allocateDefinitionData() { + assert(!Data && "Protocol already has a definition!"); + Data = new (getASTContext()) DefinitionData; + Data->Definition = this; } -ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - ObjCInterfaceDecl *const Elt, - const SourceLocation Loc) { - return new (C) ObjCClassDecl(DC, L, Elt, Loc, C); -} - -void ObjCClassDecl::setClass(ASTContext &C, ObjCInterfaceDecl*const Cls, - const SourceLocation Loc) { - - ForwardDecl = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef), - llvm::alignOf<ObjCClassRef>()); - new (ForwardDecl) ObjCClassRef(Cls, Loc); -} - -SourceRange ObjCClassDecl::getSourceRange() const { - // FIXME: We should include the semicolon - return SourceRange(getLocation(), ForwardDecl->getLocation()); -} - -//===----------------------------------------------------------------------===// -// ObjCForwardProtocolDecl -//===----------------------------------------------------------------------===// - -ObjCForwardProtocolDecl:: -ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L, - ObjCProtocolDecl *const *Elts, unsigned nElts, - const SourceLocation *Locs, ASTContext &C) -: Decl(ObjCForwardProtocol, DC, L) { - ReferencedProtocols.set(Elts, nElts, Locs, C); -} - - -ObjCForwardProtocolDecl * -ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - ObjCProtocolDecl *const *Elts, - unsigned NumElts, - const SourceLocation *Locs) { - return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C); +void ObjCProtocolDecl::startDefinition() { + allocateDefinitionData(); + + // Update all of the declarations with a pointer to the definition. + for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); + RD != RDEnd; ++RD) + RD->Data = this->Data; } //===----------------------------------------------------------------------===// // ObjCCategoryDecl //===----------------------------------------------------------------------===// +void ObjCCategoryDecl::anchor() { } + ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, IdentifierInfo *Id, - ObjCInterfaceDecl *IDecl) { + ObjCInterfaceDecl *IDecl, + SourceLocation IvarLBraceLoc, + SourceLocation IvarRBraceLoc) { ObjCCategoryDecl *CatDecl = new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id, - IDecl); + IDecl, + IvarLBraceLoc, IvarRBraceLoc); if (IDecl) { // Link this category into its class's category list. CatDecl->NextClassCategory = IDecl->getCategoryList(); - IDecl->setCategoryList(CatDecl); - if (ASTMutationListener *L = C.getASTMutationListener()) - L->AddedObjCCategoryToInterface(CatDecl, IDecl); + if (IDecl->hasDefinition()) { + IDecl->setCategoryList(CatDecl); + if (ASTMutationListener *L = C.getASTMutationListener()) + L->AddedObjCCategoryToInterface(CatDecl, IDecl); + } } return CatDecl; } -ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(), - SourceLocation(), 0, 0); +ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCategoryDecl)); + return new (Mem) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(), + SourceLocation(), 0, 0); } ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const { @@ -995,14 +1113,26 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) { // ObjCCategoryImplDecl //===----------------------------------------------------------------------===// +void ObjCCategoryImplDecl::anchor() { } + ObjCCategoryImplDecl * ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, ObjCInterfaceDecl *ClassInterface, SourceLocation nameLoc, - SourceLocation atStartLoc) { + SourceLocation atStartLoc, + SourceLocation CategoryNameLoc) { + if (ClassInterface && ClassInterface->hasDefinition()) + ClassInterface = ClassInterface->getDefinition(); return new (C) ObjCCategoryImplDecl(DC, Id, ClassInterface, - nameLoc, atStartLoc); + nameLoc, atStartLoc, CategoryNameLoc); +} + +ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCategoryImplDecl)); + return new (Mem) ObjCCategoryImplDecl(0, 0, 0, SourceLocation(), + SourceLocation(), SourceLocation()); } ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { @@ -1013,6 +1143,8 @@ ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const { } +void ObjCImplDecl::anchor() { } + void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) { // FIXME: The context should be correct before we get here. property->setLexicalDeclContext(this); @@ -1066,8 +1198,8 @@ FindPropertyImplDecl(IdentifierInfo *Id) const { } raw_ostream &clang::operator<<(raw_ostream &OS, - const ObjCCategoryImplDecl *CID) { - OS << CID->getName(); + const ObjCCategoryImplDecl &CID) { + OS << CID.getName(); return OS; } @@ -1075,14 +1207,28 @@ raw_ostream &clang::operator<<(raw_ostream &OS, // ObjCImplementationDecl //===----------------------------------------------------------------------===// +void ObjCImplementationDecl::anchor() { } + ObjCImplementationDecl * ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *ClassInterface, ObjCInterfaceDecl *SuperDecl, SourceLocation nameLoc, - SourceLocation atStartLoc) { + SourceLocation atStartLoc, + SourceLocation IvarLBraceLoc, + SourceLocation IvarRBraceLoc) { + if (ClassInterface && ClassInterface->hasDefinition()) + ClassInterface = ClassInterface->getDefinition(); return new (C) ObjCImplementationDecl(DC, ClassInterface, SuperDecl, - nameLoc, atStartLoc); + nameLoc, atStartLoc, + IvarLBraceLoc, IvarRBraceLoc); +} + +ObjCImplementationDecl * +ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCImplementationDecl)); + return new (Mem) ObjCImplementationDecl(0, 0, 0, SourceLocation(), + SourceLocation()); } void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, @@ -1099,8 +1245,8 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, } raw_ostream &clang::operator<<(raw_ostream &OS, - const ObjCImplementationDecl *ID) { - OS << ID->getName(); + const ObjCImplementationDecl &ID) { + OS << ID.getName(); return OS; } @@ -1108,6 +1254,8 @@ raw_ostream &clang::operator<<(raw_ostream &OS, // ObjCCompatibleAliasDecl //===----------------------------------------------------------------------===// +void ObjCCompatibleAliasDecl::anchor() { } + ObjCCompatibleAliasDecl * ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1116,17 +1264,34 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC, return new (C) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass); } +ObjCCompatibleAliasDecl * +ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCompatibleAliasDecl)); + return new (Mem) ObjCCompatibleAliasDecl(0, SourceLocation(), 0, 0); +} + //===----------------------------------------------------------------------===// // ObjCPropertyDecl //===----------------------------------------------------------------------===// +void ObjCPropertyDecl::anchor() { } + ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation AtLoc, + SourceLocation LParenLoc, TypeSourceInfo *T, PropertyControl propControl) { - return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T); + return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T); +} + +ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void * Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCPropertyDecl)); + return new (Mem) ObjCPropertyDecl(0, SourceLocation(), 0, SourceLocation(), + SourceLocation(), + 0); } //===----------------------------------------------------------------------===// @@ -1145,6 +1310,13 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, ivarLoc); } +ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCPropertyImplDecl)); + return new (Mem) ObjCPropertyImplDecl(0, SourceLocation(), SourceLocation(), + 0, Dynamic, 0, SourceLocation()); +} + SourceRange ObjCPropertyImplDecl::getSourceRange() const { SourceLocation EndLoc = getLocation(); if (IvarLoc.isValid()) diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 08a1ab5..74e1c1b 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/Basic/Module.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -58,6 +59,7 @@ namespace { void VisitLabelDecl(LabelDecl *D); void VisitParmVarDecl(ParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); + void VisitImportDecl(ImportDecl *D); void VisitStaticAssertDecl(StaticAssertDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); @@ -68,10 +70,8 @@ namespace { void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitObjCMethodDecl(ObjCMethodDecl *D); - void VisitObjCClassDecl(ObjCClassDecl *D); void VisitObjCImplementationDecl(ObjCImplementationDecl *D); void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); - void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); void VisitObjCProtocolDecl(ObjCProtocolDecl *D); void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); void VisitObjCCategoryDecl(ObjCCategoryDecl *D); @@ -85,6 +85,7 @@ namespace { void PrintTemplateParameters(const TemplateParameterList *Params, const TemplateArgumentList *Args); + void prettyPrintAttributes(Decl *D); }; } @@ -182,6 +183,16 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) { return Out; } +void DeclPrinter::prettyPrintAttributes(Decl *D) { + if (D->hasAttrs()) { + AttrVec &Attrs = D->getAttrs(); + for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) { + Attr *A = *i; + A->printPretty(Out, Context); + } + } +} + void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) { this->Indent(); Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); @@ -320,11 +331,11 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { Out << "__module_private__ "; } Out << S; + prettyPrintAttributes(D); } void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { - Out << "using " << D->getNameAsString() << " = " - << D->getUnderlyingType().getAsString(Policy); + Out << "using " << *D << " = " << D->getUnderlyingType().getAsString(Policy); } void DeclPrinter::VisitEnumDecl(EnumDecl *D) { @@ -350,6 +361,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { VisitDeclContext(D); Indent() << "}"; } + prettyPrintAttributes(D); } void DeclPrinter::VisitRecordDecl(RecordDecl *D) { @@ -376,7 +388,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (!Policy.SuppressSpecifiers) { - switch (D->getStorageClass()) { + switch (D->getStorageClassAsWritten()) { case SC_None: break; case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; @@ -466,12 +478,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } } - if (D->hasAttr<NoReturnAttr>()) - Proto += " __attribute((noreturn))"; - - if (D->hasAttr<ReturnsTwiceAttr>()) - Proto += " __attribute((returns_twice))"; - if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { bool HasInitializerList = false; for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), @@ -542,6 +548,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } Out << Proto; + prettyPrintAttributes(D); if (D->isPure()) Out << " = 0"; @@ -588,16 +595,18 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { Out << " = "; Init->printPretty(Out, Context, 0, Policy, Indentation); } + prettyPrintAttributes(D); } void DeclPrinter::VisitLabelDecl(LabelDecl *D) { - Out << D->getNameAsString() << ":"; + Out << *D << ":"; } void DeclPrinter::VisitVarDecl(VarDecl *D) { - if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None) - Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; + StorageClass SCAsWritten = D->getStorageClassAsWritten(); + if (!Policy.SuppressSpecifiers && SCAsWritten != SC_None) + Out << VarDecl::getStorageClassSpecifierString(SCAsWritten) << " "; if (!Policy.SuppressSpecifiers && D->isThreadSpecified()) Out << "__thread "; @@ -612,17 +621,22 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { Out << Name; Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { - if (D->hasCXXDirectInitializer()) - Out << "("; - else { - CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init); - if (!CCE || CCE->getConstructor()->isCopyConstructor()) - Out << " = "; + bool ImplicitInit = false; + if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) + ImplicitInit = D->getInitStyle() == VarDecl::CallInit && + Construct->getNumArgs() == 0 && !Construct->isListInitialization(); + if (!ImplicitInit) { + if (D->getInitStyle() == VarDecl::CallInit) + Out << "("; + else if (D->getInitStyle() == VarDecl::CInit) { + Out << " = "; + } + Init->printPretty(Out, Context, 0, Policy, Indentation); + if (D->getInitStyle() == VarDecl::CallInit) + Out << ")"; } - Init->printPretty(Out, Context, 0, Policy, Indentation); - if (D->hasCXXDirectInitializer()) - Out << ")"; } + prettyPrintAttributes(D); } void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { @@ -635,6 +649,11 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { Out << ")"; } +void DeclPrinter::VisitImportDecl(ImportDecl *D) { + Out << "@__experimental_modules_import " << D->getImportedModule()->getFullModuleName() + << ";\n"; +} + void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { Out << "static_assert("; D->getAssertExpr()->printPretty(Out, Context, 0, Policy, Indentation); @@ -745,7 +764,7 @@ void DeclPrinter::PrintTemplateParameters( if (TTP->isParameterPack()) Out << "... "; - Out << TTP->getNameAsString(); + Out << *TTP; if (Args) { Out << " = "; @@ -829,10 +848,6 @@ void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // Objective-C declarations //---------------------------------------------------------------------------- -void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { - Out << "@class " << *D->getForwardInterfaceDecl(); -} - void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) { if (OMD->isInstanceMethod()) Out << "- "; @@ -882,6 +897,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { std::string I = OID->getNameAsString(); ObjCInterfaceDecl *SID = OID->getSuperClass(); + if (!OID->isThisDeclarationADefinition()) { + Out << "@class " << I << ";"; + return; + } + if (SID) Out << "@interface " << I << " : " << *SID; else @@ -914,17 +934,12 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { // FIXME: implement the rest... } -void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { - Out << "@protocol "; - for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(), - E = D->protocol_end(); - I != E; ++I) { - if (I != D->protocol_begin()) Out << ", "; - Out << **I; - } -} - void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { + if (!PID->isThisDeclarationADefinition()) { + Out << "@protocol " << PID->getIdentifier() << ";\n"; + return; + } + Out << "@protocol " << *PID << '\n'; VisitDeclContext(PID, false); Out << "@end"; diff --git a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp index 558a4cc..4590195 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclTemplate.cpp @@ -112,42 +112,34 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params, //===----------------------------------------------------------------------===// RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() { - // Find the first declaration of this function template. - RedeclarableTemplateDecl *First = getCanonicalDecl(); + if (!Common) { + // Walk the previous-declaration chain until we either find a declaration + // with a common pointer or we run out of previous declarations. + llvm::SmallVector<RedeclarableTemplateDecl *, 2> PrevDecls; + for (RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; + Prev = Prev->getPreviousDecl()) { + if (Prev->Common) { + Common = Prev->Common; + break; + } + + PrevDecls.push_back(Prev); + } - if (First->CommonOrPrev.isNull()) { - CommonBase *CommonPtr = First->newCommon(getASTContext()); - First->CommonOrPrev = CommonPtr; - CommonPtr->Latest = First; + // If we never found a common pointer, allocate one now. + if (!Common) { + // FIXME: If any of the declarations is from an AST file, we probably + // need an update record to add the common data. + + Common = newCommon(getASTContext()); + } + + // Update any previous declarations we saw with the common pointer. + for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I) + PrevDecls[I]->Common = Common; } - return First->CommonOrPrev.get<CommonBase*>(); -} - - -RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() { - RedeclarableTemplateDecl *Tmpl = this; - while (Tmpl->getPreviousDeclaration()) - Tmpl = Tmpl->getPreviousDeclaration(); - return Tmpl; -} -void RedeclarableTemplateDecl::setPreviousDeclarationImpl( - RedeclarableTemplateDecl *Prev) { - if (Prev) { - CommonBase *Common = Prev->getCommonPtr(); - Prev = Common->Latest; - Common->Latest = this; - CommonOrPrev = Prev; - } else { - assert(CommonOrPrev.is<CommonBase*>() && "Cannot reset TemplateDecl Prev"); - } -} - -RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() { - if (CommonOrPrev.is<RedeclarableTemplateDecl*>()) - return CommonOrPrev.get<RedeclarableTemplateDecl*>(); - CommonBase *Common = CommonOrPrev.get<CommonBase*>(); - return Common ? Common->Latest : this; + return Common; } template <class EntryType> @@ -160,7 +152,7 @@ RedeclarableTemplateDecl::findSpecializationImpl( llvm::FoldingSetNodeID ID; EntryType::Profile(ID,Args,NumArgs, getASTContext()); EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos); - return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0; + return Entry ? SETraits::getMostRecentDecl(Entry) : 0; } /// \brief Generate the injected template arguments for the given template @@ -181,7 +173,7 @@ static void GenerateInjectedTemplateArgs(ASTContext &Context, Arg = TemplateArgument(ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - Expr *E = new (Context) DeclRefExpr(NTTP, + Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false, NTTP->getType().getNonLValueExprType(Context), Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); @@ -224,9 +216,11 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); } -FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, EmptyShell) { - return new (C) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(), - 0, 0); +FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionTemplateDecl)); + return new (Mem) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(), + 0, 0); } RedeclarableTemplateDecl::CommonBase * @@ -244,7 +238,10 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args, void FunctionTemplateDecl::addSpecialization( FunctionTemplateSpecializationInfo *Info, void *InsertPos) { - getSpecializations().InsertNode(Info, InsertPos); + if (InsertPos) + getSpecializations().InsertNode(Info, InsertPos); + else + getSpecializations().GetOrInsertNode(Info); if (ASTMutationListener *L = getASTMutationListener()) L->AddedCXXTemplateSpecialization(this, Info->Function); } @@ -284,8 +281,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, return New; } -ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) ClassTemplateDecl(Empty); +ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplateDecl)); + return new (Mem) ClassTemplateDecl(EmptyShell()); } void ClassTemplateDecl::LoadLazySpecializations() { @@ -326,7 +325,14 @@ ClassTemplateDecl::findSpecialization(const TemplateArgument *Args, void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) { - getSpecializations().InsertNode(D, InsertPos); + if (InsertPos) + getSpecializations().InsertNode(D, InsertPos); + else { + ClassTemplateSpecializationDecl *Existing + = getSpecializations().GetOrInsertNode(D); + (void)Existing; + assert(Existing->isCanonicalDecl() && "Non-canonical specialization?"); + } if (ASTMutationListener *L = getASTMutationListener()) L->AddedCXXTemplateSpecialization(this, D); } @@ -342,7 +348,15 @@ ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, void ClassTemplateDecl::AddPartialSpecialization( ClassTemplatePartialSpecializationDecl *D, void *InsertPos) { - getPartialSpecializations().InsertNode(D, InsertPos); + if (InsertPos) + getPartialSpecializations().InsertNode(D, InsertPos); + else { + ClassTemplatePartialSpecializationDecl *Existing + = getPartialSpecializations().GetOrInsertNode(D); + (void)Existing; + assert(Existing->isCanonicalDecl() && "Non-canonical specialization?"); + } + if (ASTMutationListener *L = getASTMutationListener()) L->AddedCXXTemplateSpecialization(this, D); } @@ -357,7 +371,7 @@ void ClassTemplateDecl::getPartialSpecializations( P = PartialSpecs.begin(), PEnd = PartialSpecs.end(); P != PEnd; ++P) { assert(!PS[P->getSequenceNumber()]); - PS[P->getSequenceNumber()] = P->getMostRecentDeclaration(); + PS[P->getSequenceNumber()] = P->getMostRecentDecl(); } } @@ -370,7 +384,7 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) { PEnd = getPartialSpecializations().end(); P != PEnd; ++P) { if (Context.hasSameType(P->getInjectedSpecializationType(), T)) - return P->getMostRecentDeclaration(); + return P->getMostRecentDecl(); } return 0; @@ -385,7 +399,7 @@ ClassTemplateDecl::findPartialSpecInstantiatedFromMember( PEnd = getPartialSpecializations().end(); P != PEnd; ++P) { if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) - return P->getMostRecentDeclaration(); + return P->getMostRecentDecl(); } return 0; @@ -433,9 +447,10 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, } TemplateTypeParmDecl * -TemplateTypeParmDecl::Create(const ASTContext &C, EmptyShell Empty) { - return new (C) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(), - 0, false); +TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTypeParmDecl)); + return new (Mem) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(), + 0, false); } SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { @@ -520,6 +535,27 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, ExpandedTInfos); } +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NonTypeTemplateParmDecl)); + return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(), + SourceLocation(), 0, 0, 0, + QualType(), false, 0); +} + +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumExpandedTypes) { + unsigned Size = sizeof(NonTypeTemplateParmDecl) + + NumExpandedTypes * 2 * sizeof(void*); + + void *Mem = AllocateDeserializedDecl(C, ID, Size); + return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(), + SourceLocation(), 0, 0, 0, + QualType(), 0, 0, NumExpandedTypes, + 0); +} + SourceRange NonTypeTemplateParmDecl::getSourceRange() const { if (hasDefaultArgument() && !defaultArgumentWasInherited()) return SourceRange(getOuterLocStart(), @@ -537,6 +573,8 @@ SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { // TemplateTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// +void TemplateTemplateParmDecl::anchor() { } + TemplateTemplateParmDecl * TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, @@ -546,6 +584,13 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, Params); } +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl)); + return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false, + 0, 0); +} + //===----------------------------------------------------------------------===// // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// @@ -582,6 +627,12 @@ FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD, } //===----------------------------------------------------------------------===// +// TemplateDecl Implementation +//===----------------------------------------------------------------------===// + +void TemplateDecl::anchor() { } + +//===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// ClassTemplateSpecializationDecl:: @@ -628,9 +679,11 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, } ClassTemplateSpecializationDecl * -ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) { - return - new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization); +ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, + sizeof(ClassTemplateSpecializationDecl)); + return new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization); } void @@ -682,6 +735,8 @@ ClassTemplateSpecializationDecl::getSourceRange() const { //===----------------------------------------------------------------------===// // ClassTemplatePartialSpecializationDecl Implementation //===----------------------------------------------------------------------===// +void ClassTemplatePartialSpecializationDecl::anchor() { } + ClassTemplatePartialSpecializationDecl:: ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, DeclContext *DC, @@ -740,15 +795,19 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, } ClassTemplatePartialSpecializationDecl * -ClassTemplatePartialSpecializationDecl::Create(ASTContext &Context, - EmptyShell Empty) { - return new (Context)ClassTemplatePartialSpecializationDecl(); +ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, + sizeof(ClassTemplatePartialSpecializationDecl)); + return new (Mem) ClassTemplatePartialSpecializationDecl(); } //===----------------------------------------------------------------------===// // FriendTemplateDecl Implementation //===----------------------------------------------------------------------===// +void FriendTemplateDecl::anchor() { } + FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, SourceLocation L, @@ -761,9 +820,10 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, return Result; } -FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context, - EmptyShell Empty) { - return new (Context) FriendTemplateDecl(Empty); +FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendTemplateDecl)); + return new (Mem) FriendTemplateDecl(EmptyShell()); } //===----------------------------------------------------------------------===// @@ -780,10 +840,11 @@ TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C, return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl); } -TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C, - EmptyShell) { - return new (C) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(), - 0, 0); +TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasTemplateDecl)); + return new (Mem) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(), + 0, 0); } void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) { @@ -796,3 +857,16 @@ TypeAliasTemplateDecl::newCommon(ASTContext &C) { return CommonPtr; } +//===----------------------------------------------------------------------===// +// ClassScopeFunctionSpecializationDecl Implementation +//===----------------------------------------------------------------------===// + +void ClassScopeFunctionSpecializationDecl::anchor() { } + +ClassScopeFunctionSpecializationDecl * +ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + void *Mem = AllocateDeserializedDecl(C, ID, + sizeof(ClassScopeFunctionSpecializationDecl)); + return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0); +} diff --git a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp index bf647ed..64924ad 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclarationName.cpp @@ -53,7 +53,7 @@ public: void *FETokenInfo; }; -/// CXXLiberalOperatorName - Contains the actual identifier that makes up the +/// CXXLiteralOperatorName - Contains the actual identifier that makes up the /// name. /// /// This identifier is stored here rather than directly in DeclarationName so as @@ -64,6 +64,10 @@ class CXXLiteralOperatorIdName public: IdentifierInfo *ID; + /// FETokenInfo - Extra information associated with this operator + /// name that can be used by the front end. + void *FETokenInfo; + void Profile(llvm::FoldingSetNodeID &FSID) { FSID.AddPointer(ID); } @@ -125,8 +129,8 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { case DeclarationName::CXXUsingDirective: return 0; } - - return 0; + + llvm_unreachable("Invalid DeclarationName Kind!"); } } // end namespace clang @@ -189,7 +193,6 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { return ObjCMultiArgSelector; } - break; } // Can't actually get here. @@ -334,7 +337,7 @@ void *DeclarationName::getFETokenInfoAsVoid() const { return getAsCXXOperatorIdName()->FETokenInfo; case CXXLiteralOperatorName: - return getCXXLiteralIdentifier()->getFETokenInfo<void>(); + return getAsCXXLiteralOperatorIdName()->FETokenInfo; default: llvm_unreachable("Declaration name has no FETokenInfo"); @@ -358,7 +361,7 @@ void DeclarationName::setFETokenInfo(void *T) { break; case CXXLiteralOperatorName: - getCXXLiteralIdentifier()->setFETokenInfo(T); + getAsCXXLiteralOperatorIdName()->FETokenInfo = T; break; default: @@ -472,6 +475,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName; LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; LiteralName->ID = II; + LiteralName->FETokenInfo = 0; LiteralNames->InsertNode(LiteralName, InsertPos); return DeclarationName(LiteralName); diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp index 2568ada..4c7cd8a 100644 --- a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp @@ -39,8 +39,7 @@ #include "clang/AST/TypeVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" using namespace clang; @@ -66,7 +65,6 @@ template <class Impl> struct XMLDeclVisitor { void dispatch(Decl *D) { switch (D->getKind()) { - default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); #define DECL(DERIVED, BASE) \ case Decl::DERIVED: \ DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \ @@ -121,7 +119,6 @@ template <class Impl> struct XMLTypeVisitor { void dispatch(Type *T) { switch (T->getTypeClass()) { - default: llvm_unreachable("Type that isn't part of TypeNodes.inc!"); #define TYPE(DERIVED, BASE) \ case Type::DERIVED: \ DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \ @@ -167,7 +164,6 @@ static StringRef getTypeKindName(Type *T) { } llvm_unreachable("unknown type kind!"); - return "unknown_type"; } struct XMLDumper : public XMLDeclVisitor<XMLDumper>, @@ -227,7 +223,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, //---- General utilities -------------------------------------------// void setPointer(StringRef prop, const void *p) { - llvm::SmallString<10> buffer; + SmallString<10> buffer; llvm::raw_svector_ostream os(buffer); os << p; os.flush(); @@ -243,7 +239,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } void setInteger(StringRef prop, unsigned n) { - llvm::SmallString<10> buffer; + SmallString<10> buffer; llvm::raw_svector_ostream os(buffer); os << n; os.flush(); @@ -324,7 +320,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, break; case TemplateArgument::Declaration: { - visitDeclRef(A.getAsDecl()); + if (Decl *D = A.getAsDecl()) + visitDeclRef(D); break; } case TemplateArgument::Integral: { @@ -411,7 +408,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } template <class T> void visitRedeclarableAttrs(T *D) { - if (T *Prev = D->getPreviousDeclaration()) + if (T *Prev = D->getPreviousDecl()) setPointer("previous", Prev); } @@ -465,7 +462,13 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, if (D->getStorageClass() != SC_None) set("storage", VarDecl::getStorageClassSpecifierString(D->getStorageClass())); - setFlag("directinit", D->hasCXXDirectInitializer()); + StringRef initStyle = ""; + switch (D->getInitStyle()) { + case VarDecl::CInit: initStyle = "c"; break; + case VarDecl::CallInit: initStyle = "call"; break; + case VarDecl::ListInit: initStyle = "list"; break; + } + set("initstyle", initStyle); setFlag("nrvo", D->isNRVOVariable()); // TODO: instantiation, etc. } @@ -495,6 +498,10 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) dispatch(*I); + for (llvm::ArrayRef<NamedDecl*>::iterator + I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end(); + I != E; ++I) + dispatch(*I); if (D->doesThisDeclarationHaveABody()) dispatch(D->getBody()); } @@ -740,11 +747,6 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, visitDeclContext(D); } - // ObjCClassDecl - void visitObjCClassDeclChildren(ObjCClassDecl *D) { - visitDeclRef(D->getForwardInterfaceDecl()); - } - // ObjCInterfaceDecl void visitCategoryList(ObjCCategoryDecl *D) { if (!D) return; @@ -755,7 +757,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { setPointer("typeptr", D->getTypeForDecl()); - setFlag("forward_decl", D->isForwardDecl()); + setFlag("forward_decl", !D->isThisDeclarationADefinition()); setFlag("implicit_interface", D->isImplicitInterfaceDecl()); } void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { @@ -815,18 +817,11 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } } - // ObjCForwardProtocolDecl - void visitObjCForwardProtocolDeclChildren(ObjCForwardProtocolDecl *D) { - for (ObjCForwardProtocolDecl::protocol_iterator - I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) - visitDeclRef(*I); - } - // ObjCProtocolDecl - void visitObjCProtocolDeclAttrs(ObjCProtocolDecl *D) { - setFlag("forward_decl", D->isForwardDecl()); - } void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) { + if (!D->isThisDeclarationADefinition()) + return; + if (D->protocol_begin() != D->protocol_end()) { TemporaryContainer C(*this, "protocols"); for (ObjCInterfaceDecl::protocol_iterator @@ -835,6 +830,9 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } } void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) { + if (!D->isThisDeclarationADefinition()) + return; + visitDeclContext(D); } diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index b0bcfe0..868109e 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/LiteralSupport.h" @@ -29,6 +30,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cstring> using namespace clang; /// isKnownToHaveBooleanValue - Return true if this is an integer expression @@ -92,6 +94,8 @@ bool Expr::isKnownToHaveBooleanValue() const { // Amusing macro metaprogramming hack: check whether a class provides // a more specific implementation of getExprLoc(). +// +// See also Stmt.cpp:{getLocStart(),getLocEnd()}. namespace { /// This implementation is used when a class provides a custom /// implementation of getExprLoc. @@ -108,7 +112,7 @@ namespace { template <class E> SourceLocation getExprLocImpl(const Expr *expr, SourceLocation (Expr::*v)() const) { - return static_cast<const E*>(expr)->getSourceRange().getBegin(); + return static_cast<const E*>(expr)->getLocStart(); } } @@ -123,7 +127,6 @@ SourceLocation Expr::getExprLoc() const { #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); - return SourceLocation(); } //===----------------------------------------------------------------------===// @@ -133,7 +136,7 @@ SourceLocation Expr::getExprLoc() const { /// \brief Compute the type-, value-, and instantiation-dependence of a /// declaration reference /// based on the declaration being referenced. -static void computeDeclRefDependence(NamedDecl *D, QualType T, +static void computeDeclRefDependence(ASTContext &Ctx, NamedDecl *D, QualType T, bool &TypeDependent, bool &ValueDependent, bool &InstantiationDependent) { @@ -184,21 +187,29 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T, // (VD) - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent. + // (VD) - a constant with literal type and is initialized with an + // expression that is value-dependent [C++11]. + // (VD) - FIXME: Missing from the standard: + // - an entity with reference type and is initialized with an + // expression that is value-dependent [C++11] if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - if (Var->getType()->isIntegralOrEnumerationType() && - Var->getType().getCVRQualifiers() == Qualifiers::Const) { + if ((Ctx.getLangOpts().CPlusPlus0x ? + Var->getType()->isLiteralType() : + Var->getType()->isIntegralOrEnumerationType()) && + (Var->getType().getCVRQualifiers() == Qualifiers::Const || + Var->getType()->isReferenceType())) { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) { ValueDependent = true; InstantiationDependent = true; } - } - + } + // (VD) - FIXME: Missing from the standard: // - a member function or a static data member of the current // instantiation - else if (Var->isStaticDataMember() && - Var->getDeclContext()->isDependentContext()) { + if (Var->isStaticDataMember() && + Var->getDeclContext()->isDependentContext()) { ValueDependent = true; InstantiationDependent = true; } @@ -212,16 +223,15 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T, if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) { ValueDependent = true; InstantiationDependent = true; - return; - } + } } -void DeclRefExpr::computeDependence() { +void DeclRefExpr::computeDependence(ASTContext &Ctx) { bool TypeDependent = false; bool ValueDependent = false; bool InstantiationDependent = false; - computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent, - InstantiationDependent); + computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent, + ValueDependent, InstantiationDependent); // (TD) C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: @@ -250,8 +260,11 @@ void DeclRefExpr::computeDependence() { ExprBits.ContainsUnexpandedParameterPack = true; } -DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, - ValueDecl *D, const DeclarationNameInfo &NameInfo, +DeclRefExpr::DeclRefExpr(ASTContext &Ctx, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + ValueDecl *D, bool RefersToEnclosingLocal, + const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK) @@ -263,38 +276,48 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0; if (FoundD) getInternalFoundDecl() = FoundD; - DeclRefExprBits.HasExplicitTemplateArgs = TemplateArgs ? 1 : 0; + DeclRefExprBits.HasTemplateKWAndArgsInfo + = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0; + DeclRefExprBits.RefersToEnclosingLocal = RefersToEnclosingLocal; if (TemplateArgs) { bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs, + Dependent, + InstantiationDependent, + ContainsUnexpandedParameterPack); if (InstantiationDependent) setInstantiationDependent(true); + } else if (TemplateKWLoc.isValid()) { + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } DeclRefExprBits.HadMultipleCandidates = 0; - computeDependence(); + computeDependence(Ctx); } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingLocal, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs) { - return Create(Context, QualifierLoc, D, + return Create(Context, QualifierLoc, TemplateKWLoc, D, + RefersToEnclosingLocal, DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, FoundD, TemplateArgs); } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingLocal, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, @@ -310,25 +333,28 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, if (FoundD) Size += sizeof(NamedDecl *); if (TemplateArgs) - Size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs); + Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size()); + else if (TemplateKWLoc.isValid()) + Size += ASTTemplateKWAndArgsInfo::sizeFor(0); void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); - return new (Mem) DeclRefExpr(QualifierLoc, D, NameInfo, FoundD, TemplateArgs, - T, VK); + return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D, + RefersToEnclosingLocal, + NameInfo, FoundD, TemplateArgs, T, VK); } DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier, bool HasFoundDecl, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (HasQualifier) Size += sizeof(NestedNameSpecifierLoc); if (HasFoundDecl) Size += sizeof(NamedDecl *); - if (HasExplicitTemplateArgs) - Size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); + if (HasTemplateKWAndArgsInfo) + Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(EmptyShell()); @@ -342,6 +368,16 @@ SourceRange DeclRefExpr::getSourceRange() const { R.setEnd(getRAngleLoc()); return R; } +SourceLocation DeclRefExpr::getLocStart() const { + if (hasQualifier()) + return getQualifierLoc().getBeginLoc(); + return getNameInfo().getLocStart(); +} +SourceLocation DeclRefExpr::getLocEnd() const { + if (hasExplicitTemplateArgs()) + return getRAngleLoc(); + return getNameInfo().getLocEnd(); +} // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. @@ -352,7 +388,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual) return FD->getNameAsString(); - llvm::SmallString<256> Name; + SmallString<256> Name; llvm::raw_svector_ostream Out(Name); if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { @@ -362,22 +398,24 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { Out << "static "; } - PrintingPolicy Policy(Context.getLangOptions()); - + PrintingPolicy Policy(Context.getLangOpts()); std::string Proto = FD->getQualifiedNameAsString(Policy); + llvm::raw_string_ostream POut(Proto); - const FunctionType *AFT = FD->getType()->getAs<FunctionType>(); + const FunctionDecl *Decl = FD; + if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern()) + Decl = Pattern; + const FunctionType *AFT = Decl->getType()->getAs<FunctionType>(); const FunctionProtoType *FT = 0; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); - Proto += "("; + POut << "("; if (FT) { - llvm::raw_string_ostream POut(Proto); - for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { + for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) { if (i) POut << ", "; std::string Param; - FD->getParamDecl(i)->getType().getAsStringInternal(Param, Policy); + Decl->getParamDecl(i)->getType().getAsStringInternal(Param, Policy); POut << Param; } @@ -386,16 +424,74 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { POut << "..."; } } - Proto += ")"; + POut << ")"; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { Qualifiers ThisQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers()); if (ThisQuals.hasConst()) - Proto += " const"; + POut << " const"; if (ThisQuals.hasVolatile()) - Proto += " volatile"; + POut << " volatile"; + RefQualifierKind Ref = MD->getRefQualifier(); + if (Ref == RQ_LValue) + POut << " &"; + else if (Ref == RQ_RValue) + POut << " &&"; + } + + typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy; + SpecsTy Specs; + const DeclContext *Ctx = FD->getDeclContext(); + while (Ctx && isa<NamedDecl>(Ctx)) { + const ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Ctx); + if (Spec && !Spec->isExplicitSpecialization()) + Specs.push_back(Spec); + Ctx = Ctx->getParent(); } + std::string TemplateParams; + llvm::raw_string_ostream TOut(TemplateParams); + for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend(); + I != E; ++I) { + const TemplateParameterList *Params + = (*I)->getSpecializedTemplate()->getTemplateParameters(); + const TemplateArgumentList &Args = (*I)->getTemplateArgs(); + assert(Params->size() == Args.size()); + for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) { + StringRef Param = Params->getParam(i)->getName(); + if (Param.empty()) continue; + TOut << Param << " = "; + Args.get(i).print(Policy, TOut); + TOut << ", "; + } + } + + FunctionTemplateSpecializationInfo *FSI + = FD->getTemplateSpecializationInfo(); + if (FSI && !FSI->isExplicitSpecialization()) { + const TemplateParameterList* Params + = FSI->getTemplate()->getTemplateParameters(); + const TemplateArgumentList* Args = FSI->TemplateArguments; + assert(Params->size() == Args->size()); + for (unsigned i = 0, e = Params->size(); i != e; ++i) { + StringRef Param = Params->getParam(i)->getName(); + if (Param.empty()) continue; + TOut << Param << " = "; + Args->get(i).print(Policy, TOut); + TOut << ", "; + } + } + + TOut.flush(); + if (!TemplateParams.empty()) { + // remove the trailing comma and space + TemplateParams.resize(TemplateParams.size() - 2); + POut << " [" << TemplateParams << "]"; + } + + POut.flush(); + if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD)) AFT->getResultType().getAsStringInternal(Proto, Policy); @@ -405,7 +501,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { return Name.str().str(); } if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) { - llvm::SmallString<256> Name; + SmallString<256> Name; llvm::raw_svector_ostream Out(Name); Out << (MD->isInstanceMethod() ? '-' : '+'); Out << '['; @@ -417,7 +513,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext())) - Out << '(' << CID << ')'; + Out << '(' << *CID << ')'; Out << ' '; Out << MD->getSelector().getAsString(); @@ -468,7 +564,7 @@ FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V, FloatingLiteral * FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) { - return new (C) FloatingLiteral(Empty); + return new (C) FloatingLiteral(C, Empty); } /// getValueAsApproximateDouble - This returns the value as an inaccurate @@ -482,6 +578,30 @@ double FloatingLiteral::getValueAsApproximateDouble() const { return V.convertToDouble(); } +int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) { + int CharByteWidth = 0; + switch(k) { + case Ascii: + case UTF8: + CharByteWidth = target.getCharWidth(); + break; + case Wide: + CharByteWidth = target.getWCharWidth(); + break; + case UTF16: + CharByteWidth = target.getChar16Width(); + break; + case UTF32: + CharByteWidth = target.getChar32Width(); + break; + } + assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple"); + CharByteWidth /= 8; + assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4) + && "character byte widths supported are 1, 2, and 4 only"); + return CharByteWidth; +} + StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, @@ -494,12 +614,8 @@ StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str, StringLiteral *SL = new (Mem) StringLiteral(Ty); // OPTIMIZE: could allocate this appended to the StringLiteral. - char *AStrData = new (C, 1) char[Str.size()]; - memcpy(AStrData, Str.data(), Str.size()); - SL->StrData = AStrData; - SL->ByteLength = Str.size(); - SL->Kind = Kind; - SL->IsPascal = Pascal; + SL->setString(C,Str,Kind,Pascal); + SL->TokLocs[0] = Loc[0]; SL->NumConcatenated = NumStrs; @@ -513,17 +629,46 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) { sizeof(SourceLocation)*(NumStrs-1), llvm::alignOf<StringLiteral>()); StringLiteral *SL = new (Mem) StringLiteral(QualType()); - SL->StrData = 0; - SL->ByteLength = 0; + SL->CharByteWidth = 0; + SL->Length = 0; SL->NumConcatenated = NumStrs; return SL; } -void StringLiteral::setString(ASTContext &C, StringRef Str) { - char *AStrData = new (C, 1) char[Str.size()]; - memcpy(AStrData, Str.data(), Str.size()); - StrData = AStrData; - ByteLength = Str.size(); +void StringLiteral::setString(ASTContext &C, StringRef Str, + StringKind Kind, bool IsPascal) { + //FIXME: we assume that the string data comes from a target that uses the same + // code unit size and endianess for the type of string. + this->Kind = Kind; + this->IsPascal = IsPascal; + + CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind); + assert((Str.size()%CharByteWidth == 0) + && "size of data must be multiple of CharByteWidth"); + Length = Str.size()/CharByteWidth; + + switch(CharByteWidth) { + case 1: { + char *AStrData = new (C) char[Length]; + std::memcpy(AStrData,Str.data(),Str.size()); + StrData.asChar = AStrData; + break; + } + case 2: { + uint16_t *AStrData = new (C) uint16_t[Length]; + std::memcpy(AStrData,Str.data(),Str.size()); + StrData.asUInt16 = AStrData; + break; + } + case 4: { + uint32_t *AStrData = new (C) uint32_t[Length]; + std::memcpy(AStrData,Str.data(),Str.size()); + StrData.asUInt32 = AStrData; + break; + } + default: + assert(false && "unsupported CharByteWidth"); + } } /// getLocationOfByte - Return a source location that points to the specified @@ -596,7 +741,6 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM, /// corresponds to, e.g. "sizeof" or "[pre]++". const char *UnaryOperator::getOpcodeStr(Opcode Op) { switch (Op) { - default: llvm_unreachable("Unknown unary operator"); case UO_PostInc: return "++"; case UO_PostDec: return "--"; case UO_PreInc: return "++"; @@ -611,6 +755,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) { case UO_Imag: return "__imag"; case UO_Extension: return "__extension__"; } + llvm_unreachable("Unknown unary operator"); } UnaryOperatorKind @@ -778,7 +923,7 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) { /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If /// not, return 0. -unsigned CallExpr::isBuiltinCall(const ASTContext &Context) const { +unsigned CallExpr::isBuiltinCall() const { // All simple function calls (e.g. func()) are implicitly cast to pointer to // function. As a result, we try and obtain the DeclRefExpr from the // ImplicitCastExpr. @@ -826,6 +971,24 @@ SourceRange CallExpr::getSourceRange() const { end = getArg(getNumArgs() - 1)->getLocEnd(); return SourceRange(begin, end); } +SourceLocation CallExpr::getLocStart() const { + if (isa<CXXOperatorCallExpr>(this)) + return cast<CXXOperatorCallExpr>(this)->getSourceRange().getBegin(); + + SourceLocation begin = getCallee()->getLocStart(); + if (begin.isInvalid() && getNumArgs() > 0) + begin = getArg(0)->getLocStart(); + return begin; +} +SourceLocation CallExpr::getLocEnd() const { + if (isa<CXXOperatorCallExpr>(this)) + return cast<CXXOperatorCallExpr>(this)->getSourceRange().getEnd(); + + SourceLocation end = getRParenLoc(); + if (end.isInvalid() && getNumArgs() > 0) + end = getArg(getNumArgs() - 1)->getLocEnd(); + return end; +} OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type, SourceLocation OperatorLoc, @@ -886,6 +1049,7 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const { MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo nameinfo, @@ -902,7 +1066,9 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, Size += sizeof(MemberNameQualifier); if (targs) - Size += ASTTemplateArgumentListInfo::sizeFor(*targs); + Size += ASTTemplateKWAndArgsInfo::sizeFor(targs->size()); + else if (TemplateKWLoc.isValid()) + Size += ASTTemplateKWAndArgsInfo::sizeFor(0); void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, @@ -926,41 +1092,46 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, NQ->FoundDecl = founddecl; } + E->HasTemplateKWAndArgsInfo = (targs || TemplateKWLoc.isValid()); + if (targs) { bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - E->HasExplicitTemplateArgumentList = true; - E->getExplicitTemplateArgs().initializeFrom(*targs, Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *targs, + Dependent, + InstantiationDependent, + ContainsUnexpandedParameterPack); if (InstantiationDependent) E->setInstantiationDependent(true); + } else if (TemplateKWLoc.isValid()) { + E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } return E; } SourceRange MemberExpr::getSourceRange() const { - SourceLocation StartLoc; + return SourceRange(getLocStart(), getLocEnd()); +} +SourceLocation MemberExpr::getLocStart() const { if (isImplicitAccess()) { if (hasQualifier()) - StartLoc = getQualifierLoc().getBeginLoc(); - else - StartLoc = MemberLoc; - } else { - // FIXME: We don't want this to happen. Rather, we should be able to - // detect all kinds of implicit accesses more cleanly. - StartLoc = getBase()->getLocStart(); - if (StartLoc.isInvalid()) - StartLoc = MemberLoc; + return getQualifierLoc().getBeginLoc(); + return MemberLoc; } - - SourceLocation EndLoc = - HasExplicitTemplateArgumentList? getRAngleLoc() - : getMemberNameInfo().getEndLoc(); - - return SourceRange(StartLoc, EndLoc); + + // FIXME: We don't want this to happen. Rather, we should be able to + // detect all kinds of implicit accesses more cleanly. + SourceLocation BaseStartLoc = getBase()->getLocStart(); + if (BaseStartLoc.isValid()) + return BaseStartLoc; + return MemberLoc; +} +SourceLocation MemberExpr::getLocEnd() const { + if (hasExplicitTemplateArgs()) + return getRAngleLoc(); + return getMemberNameInfo().getEndLoc(); } void CastExpr::CheckCastConsistency() const { @@ -983,6 +1154,11 @@ void CastExpr::CheckCastConsistency() const { assert(getSubExpr()->getType()->isBlockPointerType()); goto CheckNoBasePath; + case CK_ReinterpretMemberPointer: + assert(getType()->isMemberPointerType()); + assert(getSubExpr()->getType()->isMemberPointerType()); + goto CheckNoBasePath; + case CK_BitCast: // Arbitrary casts to C pointer types count as bitcasts. // Otherwise, we should only have block and ObjC pointer casts @@ -1001,6 +1177,11 @@ void CastExpr::CheckCastConsistency() const { !getSubExpr()->getType()->isBlockPointerType()); goto CheckNoBasePath; + case CK_CopyAndAutoreleaseBlockObject: + assert(getType()->isBlockPointerType()); + assert(getSubExpr()->getType()->isBlockPointerType()); + goto CheckNoBasePath; + // These should not have an inheritance path. case CK_Dynamic: case CK_ToUnion: @@ -1035,8 +1216,9 @@ void CastExpr::CheckCastConsistency() const { case CK_Dependent: case CK_LValueToRValue: - case CK_GetObjCProperty: case CK_NoOp: + case CK_AtomicToNonAtomic: + case CK_NonAtomicToAtomic: case CK_PointerToBoolean: case CK_IntegralToBoolean: case CK_FloatingToBoolean: @@ -1061,8 +1243,6 @@ const char *CastExpr::getCastKindName() const { return "LValueBitCast"; case CK_LValueToRValue: return "LValueToRValue"; - case CK_GetObjCProperty: - return "GetObjCProperty"; case CK_NoOp: return "NoOp"; case CK_BaseToDerived: @@ -1087,6 +1267,8 @@ const char *CastExpr::getCastKindName() const { return "BaseToDerivedMemberPointer"; case CK_DerivedToBaseMemberPointer: return "DerivedToBaseMemberPointer"; + case CK_ReinterpretMemberPointer: + return "ReinterpretMemberPointer"; case CK_UserDefinedConversion: return "UserDefinedConversion"; case CK_ConstructorConversion: @@ -1151,10 +1333,15 @@ const char *CastExpr::getCastKindName() const { return "ARCReclaimReturnedObject"; case CK_ARCExtendBlockObject: return "ARCCExtendBlockObject"; + case CK_AtomicToNonAtomic: + return "AtomicToNonAtomic"; + case CK_NonAtomicToAtomic: + return "NonAtomicToAtomic"; + case CK_CopyAndAutoreleaseBlockObject: + return "CopyAndAutoreleaseBlockObject"; } llvm_unreachable("Unhandled cast kind!"); - return 0; } Expr *CastExpr::getSubExprAsWritten() { @@ -1196,7 +1383,6 @@ CXXBaseSpecifier **CastExpr::path_buffer() { #include "clang/AST/StmtNodes.inc" default: llvm_unreachable("non-cast expressions not possible here"); - return 0; } } @@ -1284,7 +1470,7 @@ const char *BinaryOperator::getOpcodeStr(Opcode Op) { case BO_Comma: return ","; } - return ""; + llvm_unreachable("Invalid OpCode!"); } BinaryOperatorKind @@ -1355,9 +1541,10 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, false, false), InitExprs(C, numInits), - LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), - HadArrayRangeDesignator(false) -{ + LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0) +{ + sawArrayRangeDesignator(false); + setInitializesStdInitializerList(false); for (unsigned I = 0; I != numInits; ++I) { if (initExprs[I]->isTypeDependent()) ExprBits.TypeDependent = true; @@ -1394,6 +1581,7 @@ Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) { } void InitListExpr::setArrayFiller(Expr *filler) { + assert(!hasArrayFiller() && "Filler already set!"); ArrayFillerOrUnionFieldInit = filler; // Fill out any "holes" in the array due to designated initializers. Expr **inits = getInits(); @@ -1433,9 +1621,10 @@ SourceRange InitListExpr::getSourceRange() const { /// getFunctionType - Return the underlying function type for this block. /// -const FunctionType *BlockExpr::getFunctionType() const { - return getType()->getAs<BlockPointerType>()-> - getPointeeType()->getAs<FunctionType>(); +const FunctionProtoType *BlockExpr::getFunctionType() const { + // The block pointer is never sugared, but the function type might be. + return cast<BlockPointerType>(getType()) + ->getPointeeType()->castAs<FunctionProtoType>(); } SourceLocation BlockExpr::getCaretLocation() const { @@ -1591,7 +1780,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // Fallthrough for generic call handling. } case CallExprClass: - case CXXMemberCallExprClass: { + case CXXMemberCallExprClass: + case UserDefinedLiteralClass: { // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); if (const Decl *FD = CE->getCalleeDecl()) { @@ -1620,7 +1810,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case ObjCMessageExprClass: { const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this); - if (Ctx.getLangOptions().ObjCAutoRefCount && + if (Ctx.getLangOpts().ObjCAutoRefCount && ME->isInstanceMessage() && !ME->getType()->isVoidType() && ME->getSelector().getIdentifierInfoForSlot(0) && @@ -1644,6 +1834,19 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, R1 = getSourceRange(); return true; + case PseudoObjectExprClass: { + const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this); + + // Only complain about things that have the form of a getter. + if (isa<UnaryOperator>(PO->getSyntacticForm()) || + isa<BinaryOperator>(PO->getSyntacticForm())) + return false; + + Loc = getExprLoc(); + R1 = getSourceRange(); + return true; + } + case StmtExprClass: { // Statement exprs don't logically have side effects themselves, but are // sometimes used in macros in ways that give them a type that is unused. @@ -1730,14 +1933,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { ->isOBJCGCCandidate(Ctx); case CStyleCastExprClass: return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx); - case BlockDeclRefExprClass: case DeclRefExprClass: { - - const Decl *D; - if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) - D = BDRE->getDecl(); - else - D = cast<DeclRefExpr>(E)->getDecl(); + const Decl *D = cast<DeclRefExpr>(E)->getDecl(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage()) @@ -1766,7 +1963,7 @@ bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { } QualType Expr::findBoundMemberType(const Expr *expr) { - assert(expr->getType()->isSpecificPlaceholderType(BuiltinType::BoundMember)); + assert(expr->hasPlaceholderType(BuiltinType::BoundMember)); // Bound member expressions are always one of these possibilities: // x->m x.m x->*y x.*y @@ -1910,8 +2107,9 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { // pointer, or member function pointer that does not have a non-throwing // exception-specification case CallExprClass: + case CXXMemberCallExprClass: case CXXOperatorCallExprClass: - case CXXMemberCallExprClass: { + case UserDefinedLiteralClass: { const CallExpr *CE = cast<CallExpr>(this); CanThrowResult CT; if (isTypeDependent()) @@ -1934,15 +2132,22 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { return MergeCanThrow(CT, CanSubExprsThrow(C, this)); } + case LambdaExprClass: { + const LambdaExpr *Lambda = cast<LambdaExpr>(this); + CanThrowResult CT = Expr::CT_Cannot; + for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(), + CapEnd = Lambda->capture_init_end(); + Cap != CapEnd; ++Cap) + CT = MergeCanThrow(CT, (*Cap)->CanThrow(C)); + return CT; + } + case CXXNewExprClass: { CanThrowResult CT; if (isTypeDependent()) CT = CT_Dependent; else - CT = MergeCanThrow( - CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()), - CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(), - /*NullThrows*/false)); + CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); @@ -1979,38 +2184,47 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { // specs. case ObjCMessageExprClass: case ObjCPropertyRefExprClass: + case ObjCSubscriptRefExprClass: + return CT_Can; + + // All the ObjC literals that are implemented as calls are + // potentially throwing unless we decide to close off that + // possibility. + case ObjCArrayLiteralClass: + case ObjCDictionaryLiteralClass: + case ObjCNumericLiteralClass: return CT_Can; // Many other things have subexpressions, so we have to test those. // Some are simple: - case ParenExprClass: - case MemberExprClass: - case CXXReinterpretCastExprClass: - case CXXConstCastExprClass: case ConditionalOperatorClass: case CompoundLiteralExprClass: - case ExtVectorElementExprClass: - case InitListExprClass: - case DesignatedInitExprClass: - case ParenListExprClass: - case VAArgExprClass: + case CXXConstCastExprClass: case CXXDefaultArgExprClass: + case CXXReinterpretCastExprClass: + case DesignatedInitExprClass: case ExprWithCleanupsClass: - case ObjCIvarRefExprClass: + case ExtVectorElementExprClass: + case InitListExprClass: + case MemberExprClass: case ObjCIsaExprClass: + case ObjCIvarRefExprClass: + case ParenExprClass: + case ParenListExprClass: case ShuffleVectorExprClass: + case VAArgExprClass: return CanSubExprsThrow(C, this); // Some might be dependent for other reasons. - case UnaryOperatorClass: case ArraySubscriptExprClass: - case ImplicitCastExprClass: + case BinaryOperatorClass: + case CompoundAssignOperatorClass: case CStyleCastExprClass: case CXXStaticCastExprClass: case CXXFunctionalCastExprClass: - case BinaryOperatorClass: - case CompoundAssignOperatorClass: - case MaterializeTemporaryExprClass: { + case ImplicitCastExprClass: + case MaterializeTemporaryExprClass: + case UnaryOperatorClass: { CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); } @@ -2030,16 +2244,71 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { return cast<GenericSelectionExpr>(this)->getResultExpr()->CanThrow(C); // Some expressions are always dependent. - case DependentScopeDeclRefExprClass: - case CXXUnresolvedConstructExprClass: case CXXDependentScopeMemberExprClass: + case CXXUnresolvedConstructExprClass: + case DependentScopeDeclRefExprClass: return CT_Dependent; - default: - // All other expressions don't have subexpressions, or else they are - // unevaluated. + case AtomicExprClass: + case AsTypeExprClass: + case BinaryConditionalOperatorClass: + case BlockExprClass: + case CUDAKernelCallExprClass: + case DeclRefExprClass: + case ObjCBridgedCastExprClass: + case ObjCIndirectCopyRestoreExprClass: + case ObjCProtocolExprClass: + case ObjCSelectorExprClass: + case OffsetOfExprClass: + case PackExpansionExprClass: + case PseudoObjectExprClass: + case SubstNonTypeTemplateParmExprClass: + case SubstNonTypeTemplateParmPackExprClass: + case UnaryExprOrTypeTraitExprClass: + case UnresolvedLookupExprClass: + case UnresolvedMemberExprClass: + // FIXME: Can any of the above throw? If so, when? return CT_Cannot; + + case AddrLabelExprClass: + case ArrayTypeTraitExprClass: + case BinaryTypeTraitExprClass: + case TypeTraitExprClass: + case CXXBoolLiteralExprClass: + case CXXNoexceptExprClass: + case CXXNullPtrLiteralExprClass: + case CXXPseudoDestructorExprClass: + case CXXScalarValueInitExprClass: + case CXXThisExprClass: + case CXXUuidofExprClass: + case CharacterLiteralClass: + case ExpressionTraitExprClass: + case FloatingLiteralClass: + case GNUNullExprClass: + case ImaginaryLiteralClass: + case ImplicitValueInitExprClass: + case IntegerLiteralClass: + case ObjCEncodeExprClass: + case ObjCStringLiteralClass: + case ObjCBoolLiteralExprClass: + case OpaqueValueExprClass: + case PredefinedExprClass: + case SizeOfPackExprClass: + case StringLiteralClass: + case UnaryTypeTraitExprClass: + // These expressions can never throw. + return CT_Cannot; + +#define STMT(CLASS, PARENT) case CLASS##Class: +#define STMT_RANGE(Base, First, Last) +#define LAST_STMT_RANGE(BASE, FIRST, LAST) +#define EXPR(CLASS, PARENT) +#define ABSTRACT_STMT(STMT) +#include "clang/AST/StmtNodes.inc" + case NoStmtClass: + llvm_unreachable("Invalid class for expression"); } + llvm_unreachable("Bogus StmtClass"); } Expr* Expr::IgnoreParens() { @@ -2364,24 +2633,14 @@ bool Expr::isImplicitCXXThis() const { /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. -bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) { - for (unsigned I = 0; I < NumExprs; ++I) +bool Expr::hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs) { + for (unsigned I = 0; I < Exprs.size(); ++I) if (Exprs[I]->isTypeDependent()) return true; return false; } -/// hasAnyValueDependentArguments - Determines if any of the expressions -/// in Exprs is value-dependent. -bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) { - for (unsigned I = 0; I < NumExprs; ++I) - if (Exprs[I]->isValueDependent()) - return true; - - return false; -} - bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { // This function is attempting whether an expression is an initializer // which can be evaluated at compile-time. isEvaluatable handles most @@ -2399,6 +2658,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { switch (getStmtClass()) { default: break; + case IntegerLiteralClass: + case FloatingLiteralClass: case StringLiteralClass: case ObjCStringLiteralClass: case ObjCEncodeExprClass: @@ -2408,15 +2669,20 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { const CXXConstructExpr *CE = cast<CXXConstructExpr>(this); // Only if it's - // 1) an application of the trivial default constructor or - if (!CE->getConstructor()->isTrivial()) return false; - if (!CE->getNumArgs()) return true; + if (CE->getConstructor()->isTrivial()) { + // 1) an application of the trivial default constructor or + if (!CE->getNumArgs()) return true; + + // 2) an elidable trivial copy construction of an operand which is + // itself a constant initializer. Note that we consider the + // operand on its own, *not* as a reference binding. + if (CE->isElidable() && + CE->getArg(0)->isConstantInitializer(Ctx, false)) + return true; + } - // 2) an elidable trivial copy construction of an operand which is - // itself a constant initializer. Note that we consider the - // operand on its own, *not* as a reference binding. - return CE->isElidable() && - CE->getArg(0)->isConstantInitializer(Ctx, false); + // 3) a foldable constexpr constructor. + break; } case CompoundLiteralExprClass: { // This handles gcc's extension that allows global initializers like @@ -2456,36 +2722,38 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return Exp->getSubExpr()->isConstantInitializer(Ctx, false); break; } - case BinaryOperatorClass: { - // Special case &&foo - &&bar. It would be nice to generalize this somehow - // but this handles the common case. - const BinaryOperator *Exp = cast<BinaryOperator>(this); - if (Exp->getOpcode() == BO_Sub && - isa<AddrLabelExpr>(Exp->getLHS()->IgnoreParenNoopCasts(Ctx)) && - isa<AddrLabelExpr>(Exp->getRHS()->IgnoreParenNoopCasts(Ctx))) - return true; - break; - } case CXXFunctionalCastExprClass: case CXXStaticCastExprClass: case ImplicitCastExprClass: - case CStyleCastExprClass: - // Handle casts with a destination that's a struct or union; this - // deals with both the gcc no-op struct cast extension and the - // cast-to-union extension. - if (getType()->isRecordType()) - return cast<CastExpr>(this)->getSubExpr() - ->isConstantInitializer(Ctx, false); - - // Integer->integer casts can be handled here, which is important for - // things like (int)(&&x-&&y). Scary but true. - if (getType()->isIntegerType() && - cast<CastExpr>(this)->getSubExpr()->getType()->isIntegerType()) - return cast<CastExpr>(this)->getSubExpr() - ->isConstantInitializer(Ctx, false); - + case CStyleCastExprClass: { + const CastExpr *CE = cast<CastExpr>(this); + + // If we're promoting an integer to an _Atomic type then this is constant + // if the integer is constant. We also need to check the converse in case + // someone does something like: + // + // int a = (_Atomic(int))42; + // + // I doubt anyone would write code like this directly, but it's quite + // possible as the result of macro expansions. + if (CE->getCastKind() == CK_NonAtomicToAtomic || + CE->getCastKind() == CK_AtomicToNonAtomic) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + + // Handle bitcasts of vector constants. + if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + + // Handle misc casts we want to ignore. + // FIXME: Is it really safe to ignore all these? + if (CE->getCastKind() == CK_NoOp || + CE->getCastKind() == CK_LValueToRValue || + CE->getCastKind() == CK_ToUnion || + CE->getCastKind() == CK_ConstructorConversion) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + break; - + } case MaterializeTemporaryExprClass: return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr() ->isConstantInitializer(Ctx, false); @@ -2493,6 +2761,60 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return isEvaluatable(Ctx); } +namespace { + /// \brief Look for a call to a non-trivial function within an expression. + class NonTrivialCallFinder : public EvaluatedExprVisitor<NonTrivialCallFinder> + { + typedef EvaluatedExprVisitor<NonTrivialCallFinder> Inherited; + + bool NonTrivial; + + public: + explicit NonTrivialCallFinder(ASTContext &Context) + : Inherited(Context), NonTrivial(false) { } + + bool hasNonTrivialCall() const { return NonTrivial; } + + void VisitCallExpr(CallExpr *E) { + if (CXXMethodDecl *Method + = dyn_cast_or_null<CXXMethodDecl>(E->getCalleeDecl())) { + if (Method->isTrivial()) { + // Recurse to children of the call. + Inherited::VisitStmt(E); + return; + } + } + + NonTrivial = true; + } + + void VisitCXXConstructExpr(CXXConstructExpr *E) { + if (E->getConstructor()->isTrivial()) { + // Recurse to children of the call. + Inherited::VisitStmt(E); + return; + } + + NonTrivial = true; + } + + void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + if (E->getTemporary()->getDestructor()->isTrivial()) { + Inherited::VisitStmt(E); + return; + } + + NonTrivial = true; + } + }; +} + +bool Expr::hasNonTrivialCall(ASTContext &Ctx) { + NonTrivialCallFinder Finder(Ctx); + Finder.Visit(this); + return Finder.hasNonTrivialCall(); +} + /// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null /// pointer constant or not, as well as the specific kind of constant detected. /// Null pointer constants can be integer constant expressions with the @@ -2518,7 +2840,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx, // Strip off a cast to void*, if it exists. Except in C++. if (const ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(this)) { - if (!Ctx.getLangOptions().CPlusPlus) { + if (!Ctx.getLangOpts().CPlusPlus) { // Check that it is a cast to void*. if (const PointerType *PT = CE->getType()->getAs<PointerType>()) { QualType Pointee = PT->getPointeeType(); @@ -2548,6 +2870,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx, } else if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(this)) { return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC); + } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) { + if (const Expr *Source = OVE->getSourceExpr()) + return Source->isNullPointerConstant(Ctx, NPC); } // C++0x nullptr_t is always a null pointer constant. @@ -2563,15 +2888,22 @@ Expr::isNullPointerConstant(ASTContext &Ctx, } // This expression must be an integer type. if (!getType()->isIntegerType() || - (Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType())) + (Ctx.getLangOpts().CPlusPlus && getType()->isEnumeralType())) return NPCK_NotNull; // If we have an integer constant expression, we need to *evaluate* it and - // test for the value 0. - llvm::APSInt Result; - bool IsNull = isIntegerConstantExpr(Result, Ctx) && Result == 0; + // test for the value 0. Don't use the C++11 constant expression semantics + // for this, for now; once the dust settles on core issue 903, we might only + // allow a literal 0 here in C++11 mode. + if (Ctx.getLangOpts().CPlusPlus0x) { + if (!isCXX98IntegralConstantExpr(Ctx)) + return NPCK_NotNull; + } else { + if (!isIntegerConstantExpr(Ctx)) + return NPCK_NotNull; + } - return (IsNull ? NPCK_ZeroInteger : NPCK_NotNull); + return (EvaluateKnownConstInt(Ctx) == 0) ? NPCK_ZeroInteger : NPCK_NotNull; } /// \brief If this expression is an l-value for an Objective C @@ -2722,7 +3054,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc) + SourceLocation RBracLoc, + bool isImplicit) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, /*TypeDependent=*/false, /*ValueDependent=*/false, /*InstantiationDependent=*/false, @@ -2730,8 +3063,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), Kind(IsInstanceSuper? SuperInstance : SuperClass), - HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit), + SuperLoc(SuperLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { initArgsAndSelLocs(Args, SelLocs, SelLocsK); setReceiverPointer(SuperType.getAsOpaquePtr()); @@ -2746,14 +3079,15 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc) + SourceLocation RBracLoc, + bool isImplicit) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isInstantiationDependentType(), T->containsUnexpandedParameterPack()), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), Kind(Class), - HasMethod(Method != 0), IsDelegateInitCall(false), + HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { initArgsAndSelLocs(Args, SelLocs, SelLocsK); @@ -2769,7 +3103,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc) + SourceLocation RBracLoc, + bool isImplicit) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(), Receiver->isTypeDependent(), Receiver->isInstantiationDependent(), @@ -2777,7 +3112,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), Kind(Instance), - HasMethod(Method != 0), IsDelegateInitCall(false), + HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { initArgsAndSelLocs(Args, SelLocs, SelLocsK); @@ -2803,8 +3138,10 @@ void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args, } SelLocsKind = SelLocsK; - if (SelLocsK == SelLoc_NonStandard) - std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); + if (!isImplicit()) { + if (SelLocsK == SelLoc_NonStandard) + std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs()); + } } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, @@ -2817,12 +3154,19 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc) { - SelectorLocationsKind SelLocsK; - ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + SourceLocation RBracLoc, + bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, SuperType, Sel, SelLocs, SelLocsK, - Method, Args, RBracLoc); + Method, Args, RBracLoc, isImplicit); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, @@ -2833,11 +3177,19 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc) { - SelectorLocationsKind SelLocsK; - ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + SourceLocation RBracLoc, + bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, - SelLocs, SelLocsK, Method, Args, RBracLoc); + SelLocs, SelLocsK, Method, Args, RBracLoc, + isImplicit); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, @@ -2848,11 +3200,19 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, ArrayRef<SourceLocation> SelLocs, ObjCMethodDecl *Method, ArrayRef<Expr *> Args, - SourceLocation RBracLoc) { - SelectorLocationsKind SelLocsK; - ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); + SourceLocation RBracLoc, + bool isImplicit) { + assert((!SelLocs.empty() || isImplicit) && + "No selector locs for non-implicit message"); + ObjCMessageExpr *Mem; + SelectorLocationsKind SelLocsK = SelectorLocationsKind(); + if (isImplicit) + Mem = alloc(Context, Args.size(), 0); + else + Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK); return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, - SelLocs, SelLocsK, Method, Args, RBracLoc); + SelLocs, SelLocsK, Method, Args, RBracLoc, + isImplicit); } ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, @@ -2902,7 +3262,7 @@ SourceRange ObjCMessageExpr::getReceiverRange() const { return getSuperLoc(); } - return SourceLocation(); + llvm_unreachable("Invalid ReceiverKind!"); } Selector ObjCMessageExpr::getSelector() const { @@ -2951,8 +3311,8 @@ StringRef ObjCBridgedCastExpr::getBridgeKindName() const { case OBC_BridgeRetained: return "__bridge_retained"; } - - return "__bridge"; + + llvm_unreachable("Invalid BridgeKind!"); } bool ChooseExpr::isConditionTrue(const ASTContext &C) const { @@ -3225,11 +3585,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx, ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, unsigned nexprs, - SourceLocation rparenloc, QualType T) - : Expr(ParenListExprClass, T, VK_RValue, OK_Ordinary, + SourceLocation rparenloc) + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, false, false), NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { - assert(!T.isNull() && "ParenListExpr must have a valid type"); Exprs = new (C) Stmt*[nexprs]; for (unsigned i = 0; i != nexprs; ++i) { if (exprs[i]->isTypeDependent()) @@ -3256,6 +3615,72 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { return cast<OpaqueValueExpr>(e); } +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context, EmptyShell sh, + unsigned numSemanticExprs) { + void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) + + (1 + numSemanticExprs) * sizeof(Expr*), + llvm::alignOf<PseudoObjectExpr>()); + return new(buffer) PseudoObjectExpr(sh, numSemanticExprs); +} + +PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs) + : Expr(PseudoObjectExprClass, shell) { + PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1; +} + +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax, + ArrayRef<Expr*> semantics, + unsigned resultIndex) { + assert(syntax && "no syntactic expression!"); + assert(semantics.size() && "no semantic expressions!"); + + QualType type; + ExprValueKind VK; + if (resultIndex == NoResult) { + type = C.VoidTy; + VK = VK_RValue; + } else { + assert(resultIndex < semantics.size()); + type = semantics[resultIndex]->getType(); + VK = semantics[resultIndex]->getValueKind(); + assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary); + } + + void *buffer = C.Allocate(sizeof(PseudoObjectExpr) + + (1 + semantics.size()) * sizeof(Expr*), + llvm::alignOf<PseudoObjectExpr>()); + return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics, + resultIndex); +} + +PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, + Expr *syntax, ArrayRef<Expr*> semantics, + unsigned resultIndex) + : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary, + /*filled in at end of ctor*/ false, false, false, false) { + PseudoObjectExprBits.NumSubExprs = semantics.size() + 1; + PseudoObjectExprBits.ResultIndex = resultIndex + 1; + + for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) { + Expr *E = (i == 0 ? syntax : semantics[i-1]); + getSubExprsBuffer()[i] = E; + + if (E->isTypeDependent()) + ExprBits.TypeDependent = true; + if (E->isValueDependent()) + ExprBits.ValueDependent = true; + if (E->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (E->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + if (isa<OpaqueValueExpr>(E)) + assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 && + "opaque-value semantic expressions for pseudo-object " + "operations must have sources"); + } +} + //===----------------------------------------------------------------------===// // ExprIterator. //===----------------------------------------------------------------------===// @@ -3298,24 +3723,117 @@ Stmt::child_range ObjCMessageExpr::children() { reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); } -// Blocks -BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, - SourceLocation l, bool ByRef, - bool constAdded) - : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false, false, - d->isParameterPack()), - D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded) +ObjCArrayLiteral::ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl *Method, + SourceRange SR) + : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary, + false, false, false, false), + NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) { - bool TypeDependent = false; - bool ValueDependent = false; - bool InstantiationDependent = false; - computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent, - InstantiationDependent); - ExprBits.TypeDependent = TypeDependent; - ExprBits.ValueDependent = ValueDependent; - ExprBits.InstantiationDependent = InstantiationDependent; + Expr **SaveElements = getElements(); + for (unsigned I = 0, N = Elements.size(); I != N; ++I) { + if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Elements[I]->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (Elements[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SaveElements[I] = Elements[I]; + } } +ObjCArrayLiteral *ObjCArrayLiteral::Create(ASTContext &C, + llvm::ArrayRef<Expr *> Elements, + QualType T, ObjCMethodDecl * Method, + SourceRange SR) { + void *Mem = C.Allocate(sizeof(ObjCArrayLiteral) + + Elements.size() * sizeof(Expr *)); + return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR); +} + +ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(ASTContext &C, + unsigned NumElements) { + + void *Mem = C.Allocate(sizeof(ObjCArrayLiteral) + + NumElements * sizeof(Expr *)); + return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements); +} + +ObjCDictionaryLiteral::ObjCDictionaryLiteral( + ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, + QualType T, ObjCMethodDecl *method, + SourceRange SR) + : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false, + false, false), + NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR), + DictWithObjectsMethod(method) +{ + KeyValuePair *KeyValues = getKeyValues(); + ExpansionData *Expansions = getExpansionData(); + for (unsigned I = 0; I < NumElements; I++) { + if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() || + VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent()) + ExprBits.ValueDependent = true; + if (VK[I].Key->isInstantiationDependent() || + VK[I].Value->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (VK[I].EllipsisLoc.isInvalid() && + (VK[I].Key->containsUnexpandedParameterPack() || + VK[I].Value->containsUnexpandedParameterPack())) + ExprBits.ContainsUnexpandedParameterPack = true; + + KeyValues[I].Key = VK[I].Key; + KeyValues[I].Value = VK[I].Value; + if (Expansions) { + Expansions[I].EllipsisLoc = VK[I].EllipsisLoc; + if (VK[I].NumExpansions) + Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1; + else + Expansions[I].NumExpansionsPlusOne = 0; + } + } +} + +ObjCDictionaryLiteral * +ObjCDictionaryLiteral::Create(ASTContext &C, + ArrayRef<ObjCDictionaryElement> VK, + bool HasPackExpansions, + QualType T, ObjCMethodDecl *method, + SourceRange SR) { + unsigned ExpansionsSize = 0; + if (HasPackExpansions) + ExpansionsSize = sizeof(ExpansionData) * VK.size(); + + void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) + + sizeof(KeyValuePair) * VK.size() + ExpansionsSize); + return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR); +} + +ObjCDictionaryLiteral * +ObjCDictionaryLiteral::CreateEmpty(ASTContext &C, unsigned NumElements, + bool HasPackExpansions) { + unsigned ExpansionsSize = 0; + if (HasPackExpansions) + ExpansionsSize = sizeof(ExpansionData) * NumElements; + void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) + + sizeof(KeyValuePair) * NumElements + ExpansionsSize); + return new (Mem) ObjCDictionaryLiteral(EmptyShell(), NumElements, + HasPackExpansions); +} + +ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(ASTContext &C, + Expr *base, + Expr *key, QualType T, + ObjCMethodDecl *getMethod, + ObjCMethodDecl *setMethod, + SourceLocation RB) { + void *Mem = C.Allocate(sizeof(ObjCSubscriptRefExpr)); + return new (Mem) ObjCSubscriptRefExpr(base, key, T, VK_LValue, + OK_ObjCSubscript, + getMethod, setMethod, RB); +} AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t, AtomicOp op, SourceLocation RP) @@ -3323,6 +3841,7 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, false, false, false, false), NumSubExprs(nexpr), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) { + assert(nexpr == getNumSubExprs(op) && "wrong number of subexpressions"); for (unsigned i = 0; i < nexpr; i++) { if (args[i]->isTypeDependent()) ExprBits.TypeDependent = true; @@ -3336,3 +3855,49 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, SubExprs[i] = args[i]; } } + +unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) { + switch (Op) { + case AO__c11_atomic_init: + case AO__c11_atomic_load: + case AO__atomic_load_n: + return 2; + + case AO__c11_atomic_store: + case AO__c11_atomic_exchange: + case AO__atomic_load: + case AO__atomic_store: + case AO__atomic_store_n: + case AO__atomic_exchange_n: + case AO__c11_atomic_fetch_add: + case AO__c11_atomic_fetch_sub: + case AO__c11_atomic_fetch_and: + case AO__c11_atomic_fetch_or: + case AO__c11_atomic_fetch_xor: + case AO__atomic_fetch_add: + case AO__atomic_fetch_sub: + case AO__atomic_fetch_and: + case AO__atomic_fetch_or: + case AO__atomic_fetch_xor: + case AO__atomic_fetch_nand: + case AO__atomic_add_fetch: + case AO__atomic_sub_fetch: + case AO__atomic_and_fetch: + case AO__atomic_or_fetch: + case AO__atomic_xor_fetch: + case AO__atomic_nand_fetch: + return 3; + + case AO__atomic_exchange: + return 4; + + case AO__c11_atomic_compare_exchange_strong: + case AO__c11_atomic_compare_exchange_weak: + return 5; + + case AO__atomic_compare_exchange: + case AO__atomic_compare_exchange_n: + return 6; + } + llvm_unreachable("unknown atomic op"); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index ad5ec8b..8cf519c 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -45,30 +45,26 @@ SourceRange CXXScalarValueInitExpr::getSourceRange() const { // CXXNewExpr CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - Expr **placementArgs, unsigned numPlaceArgs, - SourceRange TypeIdParens, Expr *arraySize, - CXXConstructorDecl *constructor, bool initializer, - Expr **constructorArgs, unsigned numConsArgs, - bool HadMultipleCandidates, FunctionDecl *operatorDelete, - bool usualArrayDeleteWantsSize, QualType ty, - TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceLocation endLoc, - SourceLocation constructorLParen, - SourceLocation constructorRParen) + bool usualArrayDeleteWantsSize, + Expr **placementArgs, unsigned numPlaceArgs, + SourceRange typeIdParens, Expr *arraySize, + InitializationStyle initializationStyle, + Expr *initializer, QualType ty, + TypeSourceInfo *allocatedTypeInfo, + SourceLocation startLoc, SourceRange directInitRange) : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(), ty->isDependentType(), ty->isInstantiationDependentType(), ty->containsUnexpandedParameterPack()), - GlobalNew(globalNew), Initializer(initializer), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), - HadMultipleCandidates(HadMultipleCandidates), - SubExprs(0), OperatorNew(operatorNew), - OperatorDelete(operatorDelete), Constructor(constructor), - AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), - StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen), - ConstructorRParen(constructorRParen) { - AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); + SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), + AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), + StartLoc(startLoc), DirectInitRange(directInitRange), + GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { + assert((initializer != 0 || initializationStyle == NoInit) && + "Only NoInit can have no initializer."); + StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; + AllocateArgsArray(C, arraySize != 0, numPlaceArgs, initializer != 0); unsigned i = 0; if (Array) { if (arraySize->isInstantiationDependent()) @@ -80,33 +76,33 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SubExprs[i++] = arraySize; } - for (unsigned j = 0; j < NumPlacementArgs; ++j) { - if (placementArgs[j]->isInstantiationDependent()) + if (initializer) { + if (initializer->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (placementArgs[j]->containsUnexpandedParameterPack()) + + if (initializer->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = placementArgs[j]; + SubExprs[i++] = initializer; } - for (unsigned j = 0; j < NumConstructorArgs; ++j) { - if (constructorArgs[j]->isInstantiationDependent()) + for (unsigned j = 0; j < NumPlacementArgs; ++j) { + if (placementArgs[j]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (constructorArgs[j]->containsUnexpandedParameterPack()) + if (placementArgs[j]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = constructorArgs[j]; + SubExprs[i++] = placementArgs[j]; } } void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, - unsigned numPlaceArgs, unsigned numConsArgs){ + unsigned numPlaceArgs, bool hasInitializer){ assert(SubExprs == 0 && "SubExprs already allocated"); Array = isArray; NumPlacementArgs = numPlaceArgs; - NumConstructorArgs = numConsArgs; - - unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; + + unsigned TotalSize = Array + hasInitializer + NumPlacementArgs; SubExprs = new (C) Stmt*[TotalSize]; } @@ -115,6 +111,18 @@ bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const { castAs<FunctionProtoType>()->isNothrow(Ctx); } +SourceLocation CXXNewExpr::getEndLoc() const { + switch (getInitializationStyle()) { + case NoInit: + return AllocatedTypeInfo->getTypeLoc().getEndLoc(); + case CallInit: + return DirectInitRange.getEnd(); + case ListInit: + return getInitializer()->getSourceRange().getEnd(); + } + llvm_unreachable("bogus initialization style"); +} + // CXXDeleteExpr QualType CXXDeleteExpr::getDestroyedType() const { const Expr *Arg = getArgument(); @@ -191,40 +199,45 @@ SourceRange CXXPseudoDestructorExpr::getSourceRange() const { return SourceRange(Base->getLocStart(), End); } - // UnresolvedLookupExpr UnresolvedLookupExpr * UnresolvedLookupExpr::Create(ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool ADL, - const TemplateArgumentListInfo &Args, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) + const TemplateArgumentListInfo *Args, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { - void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + - ASTTemplateArgumentListInfo::sizeFor(Args)); - return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, - ADL, /*Overload*/ true, &Args, + assert(Args || TemplateKWLoc.isValid()); + unsigned num_args = Args ? Args->size() : 0; + void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + + ASTTemplateKWAndArgsInfo::sizeFor(num_args)); + return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, + TemplateKWLoc, NameInfo, + ADL, /*Overload*/ true, Args, Begin, End, /*StdIsAssociated=*/false); } UnresolvedLookupExpr * -UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, +UnresolvedLookupExpr::CreateEmpty(ASTContext &C, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedLookupExpr); - if (HasExplicitTemplateArgs) - size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); + if (HasTemplateKWAndArgsInfo) + size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>()); UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); - E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; + E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; } OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, @@ -243,8 +256,9 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, (QualifierLoc && QualifierLoc.getNestedNameSpecifier() ->containsUnexpandedParameterPack()))), - Results(0), NumResults(End - Begin), NameInfo(NameInfo), - QualifierLoc(QualifierLoc), HasExplicitTemplateArgs(TemplateArgs != 0) + NameInfo(NameInfo), QualifierLoc(QualifierLoc), + Results(0), NumResults(End - Begin), + HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid()) { NumResults = End - Begin; if (NumResults) { @@ -271,9 +285,10 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, bool Dependent = false; bool InstantiationDependent = false; bool ContainsUnexpandedParameterPack = false; - getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs, + Dependent, + InstantiationDependent, + ContainsUnexpandedParameterPack); if (Dependent) { ExprBits.TypeDependent = true; @@ -283,6 +298,8 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, ExprBits.InstantiationDependent = true; if (ContainsUnexpandedParameterPack) ExprBits.ContainsUnexpandedParameterPack = true; + } else if (TemplateKWLoc.isValid()) { + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } if (isTypeDependent()) @@ -314,6 +331,7 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const { // DependentScopeDeclRefExpr DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) : Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary, @@ -326,47 +344,52 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, QualifierLoc.getNestedNameSpecifier() ->containsUnexpandedParameterPack()))), QualifierLoc(QualifierLoc), NameInfo(NameInfo), - HasExplicitTemplateArgs(Args != 0) + HasTemplateKWAndArgsInfo(Args != 0 || TemplateKWLoc.isValid()) { if (Args) { bool Dependent = true; bool InstantiationDependent = true; bool ContainsUnexpandedParameterPack = ExprBits.ContainsUnexpandedParameterPack; - - reinterpret_cast<ASTTemplateArgumentListInfo*>(this+1) - ->initializeFrom(*Args, Dependent, InstantiationDependent, - ContainsUnexpandedParameterPack); - + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *Args, + Dependent, + InstantiationDependent, + ContainsUnexpandedParameterPack); ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; + } else if (TemplateKWLoc.isValid()) { + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } } DependentScopeDeclRefExpr * DependentScopeDeclRefExpr::Create(ASTContext &C, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) { std::size_t size = sizeof(DependentScopeDeclRefExpr); if (Args) - size += ASTTemplateArgumentListInfo::sizeFor(*Args); + size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size()); + else if (TemplateKWLoc.isValid()) + size += ASTTemplateKWAndArgsInfo::sizeFor(0); void *Mem = C.Allocate(size); - return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, - NameInfo, Args); + return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, + TemplateKWLoc, NameInfo, Args); } DependentScopeDeclRefExpr * DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t size = sizeof(DependentScopeDeclRefExpr); - if (HasExplicitTemplateArgs) - size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); + if (HasTemplateKWAndArgsInfo) + size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size); - DependentScopeDeclRefExpr *E + DependentScopeDeclRefExpr *E = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), + SourceLocation(), DeclarationNameInfo(), 0); - E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; + E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; } @@ -601,6 +624,39 @@ CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); } +UserDefinedLiteral::LiteralOperatorKind +UserDefinedLiteral::getLiteralOperatorKind() const { + if (getNumArgs() == 0) + return LOK_Template; + if (getNumArgs() == 2) + return LOK_String; + + assert(getNumArgs() == 1 && "unexpected #args in literal operator call"); + QualType ParamTy = + cast<FunctionDecl>(getCalleeDecl())->getParamDecl(0)->getType(); + if (ParamTy->isPointerType()) + return LOK_Raw; + if (ParamTy->isAnyCharacterType()) + return LOK_Character; + if (ParamTy->isIntegerType()) + return LOK_Integer; + if (ParamTy->isFloatingType()) + return LOK_Floating; + + llvm_unreachable("unknown kind of literal operator"); +} + +Expr *UserDefinedLiteral::getCookedLiteral() { +#ifndef NDEBUG + LiteralOperatorKind LOK = getLiteralOperatorKind(); + assert(LOK != LOK_Template && LOK != LOK_Raw && "not a cooked literal"); +#endif + return getArg(0); +} + +const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { + return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier(); +} CXXDefaultArgExpr * CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, @@ -618,8 +674,9 @@ CXXTemporary *CXXTemporary::Create(ASTContext &C, CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C, CXXTemporary *Temp, Expr* SubExpr) { - assert(SubExpr->getType()->isRecordType() && - "Expression bound to a temporary must have record type!"); + assert((SubExpr->getType()->isRecordType() || + SubExpr->getType()->isArrayType()) && + "Expression bound to a temporary must have record or array type!"); return new (C) CXXBindTemporaryExpr(Temp, SubExpr); } @@ -636,7 +693,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), Cons, false, Args, NumArgs, - HadMultipleCandidates, ZeroInitialization, + HadMultipleCandidates, /*FIXME*/false, ZeroInitialization, CXXConstructExpr::CK_Complete, parenRange), Type(Type) { } @@ -651,13 +708,15 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool HadMultipleCandidates, + bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, NumArgs, - HadMultipleCandidates, ZeroInitialization, - ConstructKind, ParenRange); + HadMultipleCandidates, ListInitialization, + ZeroInitialization, ConstructKind, + ParenRange); } CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, @@ -665,6 +724,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, CXXConstructorDecl *D, bool elidable, Expr **args, unsigned numargs, bool HadMultipleCandidates, + bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) @@ -674,6 +734,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, T->containsUnexpandedParameterPack()), Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs), Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), + ListInitialization(ListInitialization), ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(0) { @@ -695,35 +756,228 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, } } -ExprWithCleanups::ExprWithCleanups(ASTContext &C, - Expr *subexpr, - CXXTemporary **temps, - unsigned numtemps) +LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit, + LambdaCaptureKind Kind, VarDecl *Var, + SourceLocation EllipsisLoc) + : VarAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc) +{ + unsigned Bits = 0; + if (Implicit) + Bits |= Capture_Implicit; + + switch (Kind) { + case LCK_This: + assert(Var == 0 && "'this' capture cannot have a variable!"); + break; + + case LCK_ByCopy: + Bits |= Capture_ByCopy; + // Fall through + case LCK_ByRef: + assert(Var && "capture must have a variable!"); + break; + } + VarAndBits.setInt(Bits); +} + +LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const { + if (capturesThis()) + return LCK_This; + + return (VarAndBits.getInt() & Capture_ByCopy)? LCK_ByCopy : LCK_ByRef; +} + +LambdaExpr::LambdaExpr(QualType T, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + ArrayRef<Capture> Captures, + bool ExplicitParams, + bool ExplicitResultType, + ArrayRef<Expr *> CaptureInits, + ArrayRef<VarDecl *> ArrayIndexVars, + ArrayRef<unsigned> ArrayIndexStarts, + SourceLocation ClosingBrace) + : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, + T->isDependentType(), T->isDependentType(), T->isDependentType(), + /*ContainsUnexpandedParameterPack=*/false), + IntroducerRange(IntroducerRange), + NumCaptures(Captures.size()), + CaptureDefault(CaptureDefault), + ExplicitParams(ExplicitParams), + ExplicitResultType(ExplicitResultType), + ClosingBrace(ClosingBrace) +{ + assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments"); + CXXRecordDecl *Class = getLambdaClass(); + CXXRecordDecl::LambdaDefinitionData &Data = Class->getLambdaData(); + + // FIXME: Propagate "has unexpanded parameter pack" bit. + + // Copy captures. + ASTContext &Context = Class->getASTContext(); + Data.NumCaptures = NumCaptures; + Data.NumExplicitCaptures = 0; + Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures); + Capture *ToCapture = Data.Captures; + for (unsigned I = 0, N = Captures.size(); I != N; ++I) { + if (Captures[I].isExplicit()) + ++Data.NumExplicitCaptures; + + *ToCapture++ = Captures[I]; + } + + // Copy initialization expressions for the non-static data members. + Stmt **Stored = getStoredStmts(); + for (unsigned I = 0, N = CaptureInits.size(); I != N; ++I) + *Stored++ = CaptureInits[I]; + + // Copy the body of the lambda. + *Stored++ = getCallOperator()->getBody(); + + // Copy the array index variables, if any. + HasArrayIndexVars = !ArrayIndexVars.empty(); + if (HasArrayIndexVars) { + assert(ArrayIndexStarts.size() == NumCaptures); + memcpy(getArrayIndexVars(), ArrayIndexVars.data(), + sizeof(VarDecl *) * ArrayIndexVars.size()); + memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), + sizeof(unsigned) * Captures.size()); + getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size(); + } +} + +LambdaExpr *LambdaExpr::Create(ASTContext &Context, + CXXRecordDecl *Class, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + ArrayRef<Capture> Captures, + bool ExplicitParams, + bool ExplicitResultType, + ArrayRef<Expr *> CaptureInits, + ArrayRef<VarDecl *> ArrayIndexVars, + ArrayRef<unsigned> ArrayIndexStarts, + SourceLocation ClosingBrace) { + // Determine the type of the expression (i.e., the type of the + // function object we're creating). + QualType T = Context.getTypeDeclType(Class); + + unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (Captures.size() + 1); + if (!ArrayIndexVars.empty()) + Size += sizeof(VarDecl *) * ArrayIndexVars.size() + + sizeof(unsigned) * (Captures.size() + 1); + void *Mem = Context.Allocate(Size); + return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, + Captures, ExplicitParams, ExplicitResultType, + CaptureInits, ArrayIndexVars, ArrayIndexStarts, + ClosingBrace); +} + +LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures, + unsigned NumArrayIndexVars) { + unsigned Size = sizeof(LambdaExpr) + sizeof(Stmt *) * (NumCaptures + 1); + if (NumArrayIndexVars) + Size += sizeof(VarDecl) * NumArrayIndexVars + + sizeof(unsigned) * (NumCaptures + 1); + void *Mem = C.Allocate(Size); + return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0); +} + +LambdaExpr::capture_iterator LambdaExpr::capture_begin() const { + return getLambdaClass()->getLambdaData().Captures; +} + +LambdaExpr::capture_iterator LambdaExpr::capture_end() const { + return capture_begin() + NumCaptures; +} + +LambdaExpr::capture_iterator LambdaExpr::explicit_capture_begin() const { + return capture_begin(); +} + +LambdaExpr::capture_iterator LambdaExpr::explicit_capture_end() const { + struct CXXRecordDecl::LambdaDefinitionData &Data + = getLambdaClass()->getLambdaData(); + return Data.Captures + Data.NumExplicitCaptures; +} + +LambdaExpr::capture_iterator LambdaExpr::implicit_capture_begin() const { + return explicit_capture_end(); +} + +LambdaExpr::capture_iterator LambdaExpr::implicit_capture_end() const { + return capture_end(); +} + +ArrayRef<VarDecl *> +LambdaExpr::getCaptureInitIndexVars(capture_init_iterator Iter) const { + assert(HasArrayIndexVars && "No array index-var data?"); + + unsigned Index = Iter - capture_init_begin(); + assert(Index < getLambdaClass()->getLambdaData().NumCaptures && + "Capture index out-of-range"); + VarDecl **IndexVars = getArrayIndexVars(); + unsigned *IndexStarts = getArrayIndexStarts(); + return ArrayRef<VarDecl *>(IndexVars + IndexStarts[Index], + IndexVars + IndexStarts[Index + 1]); +} + +CXXRecordDecl *LambdaExpr::getLambdaClass() const { + return getType()->getAsCXXRecordDecl(); +} + +CXXMethodDecl *LambdaExpr::getCallOperator() const { + CXXRecordDecl *Record = getLambdaClass(); + DeclarationName Name + = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + DeclContext::lookup_result Calls = Record->lookup(Name); + assert(Calls.first != Calls.second && "Missing lambda call operator!"); + CXXMethodDecl *Result = cast<CXXMethodDecl>(*Calls.first++); + assert(Calls.first == Calls.second && "More than lambda one call operator?"); + return Result; +} + +CompoundStmt *LambdaExpr::getBody() const { + if (!getStoredStmts()[NumCaptures]) + getStoredStmts()[NumCaptures] = getCallOperator()->getBody(); + + return reinterpret_cast<CompoundStmt *>(getStoredStmts()[NumCaptures]); +} + +bool LambdaExpr::isMutable() const { + return (getCallOperator()->getTypeQualifiers() & Qualifiers::Const) == 0; +} + +ExprWithCleanups::ExprWithCleanups(Expr *subexpr, + ArrayRef<CleanupObject> objects) : Expr(ExprWithCleanupsClass, subexpr->getType(), subexpr->getValueKind(), subexpr->getObjectKind(), subexpr->isTypeDependent(), subexpr->isValueDependent(), subexpr->isInstantiationDependent(), subexpr->containsUnexpandedParameterPack()), - SubExpr(subexpr), Temps(0), NumTemps(0) { - if (numtemps) { - setNumTemporaries(C, numtemps); - for (unsigned i = 0; i != numtemps; ++i) - Temps[i] = temps[i]; - } + SubExpr(subexpr) { + ExprWithCleanupsBits.NumObjects = objects.size(); + for (unsigned i = 0, e = objects.size(); i != e; ++i) + getObjectsBuffer()[i] = objects[i]; } -void ExprWithCleanups::setNumTemporaries(ASTContext &C, unsigned N) { - assert(Temps == 0 && "Cannot resize with this"); - NumTemps = N; - Temps = new (C) CXXTemporary*[NumTemps]; +ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, Expr *subexpr, + ArrayRef<CleanupObject> objects) { + size_t size = sizeof(ExprWithCleanups) + + objects.size() * sizeof(CleanupObject); + void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>()); + return new (buffer) ExprWithCleanups(subexpr, objects); } +ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) + : Expr(ExprWithCleanupsClass, empty) { + ExprWithCleanupsBits.NumObjects = numObjects; +} -ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, - Expr *SubExpr, - CXXTemporary **Temps, - unsigned NumTemps) { - return new (C) ExprWithCleanups(C, SubExpr, Temps, NumTemps); +ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, EmptyShell empty, + unsigned numObjects) { + size_t size = sizeof(ExprWithCleanups) + numObjects * sizeof(CleanupObject); + void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>()); + return new (buffer) ExprWithCleanups(empty, numObjects); } CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, @@ -781,7 +1035,8 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) @@ -793,7 +1048,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, ->containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasExplicitTemplateArgs(TemplateArgs != 0), + HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid()), OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { @@ -801,11 +1056,14 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, bool Dependent = true; bool InstantiationDependent = true; bool ContainsUnexpandedParameterPack = false; - getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent, - InstantiationDependent, - ContainsUnexpandedParameterPack); + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs, + Dependent, + InstantiationDependent, + ContainsUnexpandedParameterPack); if (ContainsUnexpandedParameterPack) ExprBits.ContainsUnexpandedParameterPack = true; + } else if (TemplateKWLoc.isValid()) { + getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); } } @@ -824,8 +1082,8 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, containsUnexpandedParameterPack()) || MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), - HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), - QualifierLoc(QualifierLoc), + HasTemplateKWAndArgsInfo(false), + OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { } @@ -834,47 +1092,50 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { - if (!TemplateArgs) + if (!TemplateArgs && !TemplateKWLoc.isValid()) return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, FirstQualifierFoundInScope, MemberNameInfo); - std::size_t size = sizeof(CXXDependentScopeMemberExpr); - if (TemplateArgs) - size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs); + unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0; + std::size_t size = sizeof(CXXDependentScopeMemberExpr) + + ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, + TemplateKWLoc, FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs); } CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { - if (!HasExplicitTemplateArgs) + if (!HasTemplateKWAndArgsInfo) return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), - 0, SourceLocation(), + 0, SourceLocation(), NestedNameSpecifierLoc(), 0, DeclarationNameInfo()); std::size_t size = sizeof(CXXDependentScopeMemberExpr) + - ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); + ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<CXXDependentScopeMemberExpr>()); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), - 0, SourceLocation(), - NestedNameSpecifierLoc(), 0, + 0, SourceLocation(), + NestedNameSpecifierLoc(), + SourceLocation(), 0, DeclarationNameInfo(), 0); - E->HasExplicitTemplateArgs = true; + E->HasTemplateKWAndArgsInfo = true; return E; } @@ -913,12 +1174,13 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedMemberExprClass, C, QualifierLoc, MemberNameInfo, - TemplateArgs, Begin, End, + : OverloadExpr(UnresolvedMemberExprClass, C, QualifierLoc, TemplateKWLoc, + MemberNameInfo, TemplateArgs, Begin, End, // Dependent ((Base && Base->isTypeDependent()) || BaseType->isDependentType()), @@ -949,31 +1211,34 @@ UnresolvedMemberExpr::Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) { std::size_t size = sizeof(UnresolvedMemberExpr); if (TemplateArgs) - size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs); + size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size()); + else if (TemplateKWLoc.isValid()) + size += ASTTemplateKWAndArgsInfo::sizeFor(0); void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>()); return new (Mem) UnresolvedMemberExpr(C, HasUnresolvedUsing, Base, BaseType, - IsArrow, OperatorLoc, QualifierLoc, + IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End); } UnresolvedMemberExpr * -UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, +UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedMemberExpr); - if (HasExplicitTemplateArgs) - size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs); + if (HasTemplateKWAndArgsInfo) + size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedMemberExpr>()); UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); - E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; + E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo; return E; } @@ -1020,4 +1285,51 @@ TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const { return TemplateArgument(Arguments, NumArguments); } +TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc, + bool Value) + : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, + /*ValueDependent=*/false, + /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), + Loc(Loc), RParenLoc(RParenLoc) +{ + TypeTraitExprBits.Kind = Kind; + TypeTraitExprBits.Value = Value; + TypeTraitExprBits.NumArgs = Args.size(); + + TypeSourceInfo **ToArgs = getTypeSourceInfos(); + + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (Args[I]->getType()->isDependentType()) + setValueDependent(true); + if (Args[I]->getType()->isInstantiationDependentType()) + setInstantiationDependent(true); + if (Args[I]->getType()->containsUnexpandedParameterPack()) + setContainsUnexpandedParameterPack(true); + + ToArgs[I] = Args[I]; + } +} + +TypeTraitExpr *TypeTraitExpr::Create(ASTContext &C, QualType T, + SourceLocation Loc, + TypeTrait Kind, + ArrayRef<TypeSourceInfo *> Args, + SourceLocation RParenLoc, + bool Value) { + unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * Args.size(); + void *Mem = C.Allocate(Size); + return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value); +} + +TypeTraitExpr *TypeTraitExpr::CreateDeserialized(ASTContext &C, + unsigned NumArgs) { + unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs; + void *Mem = C.Allocate(Size); + return new (Mem) TypeTraitExpr(EmptyShell()); +} +void ArrayTypeTraitExpr::anchor() { } diff --git a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp index 49c6821..b091e19 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprClassification.cpp @@ -47,7 +47,6 @@ static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang, return Cl::CL_XValue; } llvm_unreachable("Invalid value category of implicit cast."); - return Cl::CL_PRValue; } Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { @@ -56,7 +55,7 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { Cl::Kinds kind = ClassifyInternal(Ctx, this); // C99 6.3.2.1: An lvalue is an expression with an object type or an // incomplete type other than void. - if (!Ctx.getLangOptions().CPlusPlus) { + if (!Ctx.getLangOpts().CPlusPlus) { // Thus, no functions. if (TR->isFunctionType() || TR == Ctx.OverloadTy) kind = Cl::CL_Function; @@ -90,17 +89,17 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // This function takes the first stab at classifying expressions. - const LangOptions &Lang = Ctx.getLangOptions(); + const LangOptions &Lang = Ctx.getLangOpts(); switch (E->getStmtClass()) { - // First come the expressions that are always lvalues, unconditionally. case Stmt::NoStmtClass: #define ABSTRACT_STMT(Kind) #define STMT(Kind, Base) case Expr::Kind##Class: #define EXPR(Kind, Base) #include "clang/AST/StmtNodes.inc" llvm_unreachable("cannot classify a statement"); - break; + + // First come the expressions that are always lvalues, unconditionally. case Expr::ObjCIsaExprClass: // C++ [expr.prim.general]p1: A string literal is an lvalue. case Expr::StringLiteralClass: @@ -109,6 +108,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // __func__ and friends are too. case Expr::PredefinedExprClass: // Property references are lvalues + case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCPropertyRefExprClass: // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of... case Expr::CXXTypeidExprClass: @@ -122,10 +122,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // FIXME: ObjC++0x might have different rules case Expr::ObjCIvarRefExprClass: return Cl::CL_LValue; + // C99 6.5.2.5p5 says that compound literals are lvalues. // In C++, they're class temporaries. case Expr::CompoundLiteralExprClass: - return Ctx.getLangOptions().CPlusPlus? Cl::CL_ClassTemporary + return Ctx.getLangOpts().CPlusPlus? Cl::CL_ClassTemporary : Cl::CL_LValue; // Expressions that are prvalues. @@ -151,13 +152,17 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCProtocolExprClass: case Expr::ObjCStringLiteralClass: + case Expr::ObjCNumericLiteralClass: + case Expr::ObjCArrayLiteralClass: + case Expr::ObjCDictionaryLiteralClass: + case Expr::ObjCBoolLiteralExprClass: case Expr::ParenListExprClass: - case Expr::InitListExprClass: case Expr::SizeOfPackExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: case Expr::AsTypeExprClass: @@ -184,9 +189,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return isa<FunctionDecl>(cast<DeclRefExpr>(E)->getDecl()) ? Cl::CL_PRValue : Cl::CL_LValue; return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl()); - // We deal with names referenced from blocks the same way. - case Expr::BlockDeclRefExprClass: - return ClassifyDecl(Ctx, cast<BlockDeclRefExpr>(E)->getDecl()); // Member access is complex. case Expr::MemberExprClass: @@ -229,21 +231,24 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { } case Expr::OpaqueValueExprClass: + return ClassifyExprValueKind(Lang, E, E->getValueKind()); + + // Pseudo-object expressions can produce l-values with reference magic. + case Expr::PseudoObjectExprClass: return ClassifyExprValueKind(Lang, E, - cast<OpaqueValueExpr>(E)->getValueKind()); + cast<PseudoObjectExpr>(E)->getValueKind()); // Implicit casts are lvalues if they're lvalue casts. Other than that, we // only specifically record class temporaries. case Expr::ImplicitCastExprClass: - return ClassifyExprValueKind(Lang, E, - cast<ImplicitCastExpr>(E)->getValueKind()); + return ClassifyExprValueKind(Lang, E, E->getValueKind()); // C++ [expr.prim.general]p4: The presence of parentheses does not affect // whether the expression is an lvalue. case Expr::ParenExprClass: return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr()); - // C1X 6.5.1.1p4: [A generic selection] is an lvalue, a function designator, + // C11 6.5.1.1p4: [A generic selection] is an lvalue, a function designator, // or a void expression if its result expression is, respectively, an // lvalue, a function designator, or a void expression. case Expr::GenericSelectionExprClass: @@ -261,6 +266,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: case Expr::CXXMemberCallExprClass: + case Expr::UserDefinedLiteralClass: case Expr::CUDAKernelCallExprClass: return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType()); @@ -328,35 +334,46 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // Some C++ expressions are always class temporaries. case Expr::CXXConstructExprClass: case Expr::CXXTemporaryObjectExprClass: + case Expr::LambdaExprClass: return Cl::CL_ClassTemporary; case Expr::VAArgExprClass: return ClassifyUnnamed(Ctx, E->getType()); - + case Expr::DesignatedInitExprClass: return ClassifyInternal(Ctx, cast<DesignatedInitExpr>(E)->getInit()); - + case Expr::StmtExprClass: { const CompoundStmt *S = cast<StmtExpr>(E)->getSubStmt(); if (const Expr *LastExpr = dyn_cast_or_null<Expr>(S->body_back())) return ClassifyUnnamed(Ctx, LastExpr->getType()); return Cl::CL_PRValue; } - + case Expr::CXXUuidofExprClass: return Cl::CL_LValue; - + case Expr::PackExpansionExprClass: return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern()); - + case Expr::MaterializeTemporaryExprClass: return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference() ? Cl::CL_LValue : Cl::CL_XValue; + + case Expr::InitListExprClass: + // An init list can be an lvalue if it is bound to a reference and + // contains only one element. In that case, we look at that element + // for an exact classification. Init list creation takes care of the + // value kind for us, so we only need to fine-tune. + if (E->isRValue()) + return ClassifyExprValueKind(Lang, E, E->getValueKind()); + assert(cast<InitListExpr>(E)->getNumInits() == 1 && + "Only 1-element init lists can be glvalues."); + return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0)); } - + llvm_unreachable("unhandled expression kind in classification"); - return Cl::CL_LValue; } /// ClassifyDecl - Return the classification of an expression referencing the @@ -379,7 +396,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { else islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || - (Ctx.getLangOptions().CPlusPlus && + (Ctx.getLangOpts().CPlusPlus && (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D))); return islvalue ? Cl::CL_LValue : Cl::CL_PRValue; @@ -390,7 +407,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { /// calls and casts. static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) { // In C, function calls are always rvalues. - if (!Ctx.getLangOptions().CPlusPlus) return Cl::CL_PRValue; + if (!Ctx.getLangOpts().CPlusPlus) return Cl::CL_PRValue; // C++ [expr.call]p10: A function call is an lvalue if the result type is an // lvalue reference type or an rvalue reference to function type, an xvalue @@ -411,7 +428,7 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { ? Cl::CL_PRValue : Cl::CL_LValue); // Handle C first, it's easier. - if (!Ctx.getLangOptions().CPlusPlus) { + if (!Ctx.getLangOpts().CPlusPlus) { // C99 6.5.2.3p3 // For dot access, the expression is an lvalue if the first part is. For // arrow access, it always is an lvalue. @@ -463,7 +480,7 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { } static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { - assert(Ctx.getLangOptions().CPlusPlus && + assert(Ctx.getLangOpts().CPlusPlus && "This is only relevant for C++."); // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand. // Except we override this for writes to ObjC properties. @@ -480,14 +497,16 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { // is a pointer to a data member is of the same value category as its first // operand. if (E->getOpcode() == BO_PtrMemD) - return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy) + return (E->getType()->isFunctionType() || + E->hasPlaceholderType(BuiltinType::BoundMember)) ? Cl::CL_MemberFunction : ClassifyInternal(Ctx, E->getLHS()); // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its // second operand is a pointer to data member and a prvalue otherwise. if (E->getOpcode() == BO_PtrMemI) - return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy) + return (E->getType()->isFunctionType() || + E->hasPlaceholderType(BuiltinType::BoundMember)) ? Cl::CL_MemberFunction : Cl::CL_LValue; @@ -497,7 +516,7 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True, const Expr *False) { - assert(Ctx.getLangOptions().CPlusPlus && + assert(Ctx.getLangOpts().CPlusPlus && "This is only relevant for C++."); // C++ [expr.cond]p2 @@ -536,18 +555,9 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // This is the lvalue case. // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6) - if (Ctx.getLangOptions().CPlusPlus && E->getType()->isFunctionType()) + if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType()) return Cl::CM_Function; - // You cannot assign to a variable outside a block from within the block if - // it is not marked __block, e.g. - // void takeclosure(void (^C)(void)); - // void func() { int x = 1; takeclosure(^{ x = 7; }); } - if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E)) { - if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl())) - return Cl::CM_NotBlockQualified; - } - // Assignment to a property in ObjC is an implicit setter access. But a // setter might not exist. if (const ObjCPropertyRefExpr *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) { @@ -559,6 +569,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Const stuff is obviously not modifiable. if (CT.isConstQualified()) return Cl::CM_ConstQualified; + // Arrays are not modifiable, only their elements are. if (CT->isArrayType()) return Cl::CM_ArrayType; @@ -569,7 +580,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Records with any const fields (recursively) are not modifiable. if (const RecordType *R = CT->getAs<RecordType>()) { assert((E->getObjectKind() == OK_ObjCProperty || - !Ctx.getLangOptions().CPlusPlus) && + !Ctx.getLangOpts().CPlusPlus) && "C++ struct assignment should be resolved by the " "copy assignment operator."); if (R->hasConstFields()) @@ -624,7 +635,6 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { case Cl::CM_Function: return MLV_NotObjectType; case Cl::CM_LValueCast: llvm_unreachable("CM_LValueCast and CL_LValue don't match"); - case Cl::CM_NotBlockQualified: return MLV_NotBlockQualified; case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty; case Cl::CM_ConstQualified: return MLV_ConstQualified; case Cl::CM_ArrayType: return MLV_ArrayType; diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index df75bc8..01c9fe7 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -9,6 +9,28 @@ // // This file implements the Expr constant evaluator. // +// Constant expression evaluation produces four main results: +// +// * A success/failure flag indicating whether constant folding was successful. +// This is the 'bool' return value used by most of the code in this file. A +// 'false' return value indicates that constant folding has failed, and any +// appropriate diagnostic has already been produced. +// +// * An evaluated result, valid only if constant folding has not failed. +// +// * A flag indicating if evaluation encountered (unevaluated) side-effects. +// These arise in cases such as (sideEffect(), 0) and (sideEffect() || 1), +// where it is possible to determine the evaluated result regardless. +// +// * A set of notes indicating why the evaluation was not a constant expression +// (under the C++11 rules only, at the moment), or, if folding failed too, +// why the expression could not be folded. +// +// If we are checking for a potential constant expression, failure to constant +// fold a potential constant sub-expression will be indicated by a 'false' +// return value (the expression could not be folded) and no diagnostic (the +// expression is not necessarily non-constant). +// //===----------------------------------------------------------------------===// #include "clang/AST/APValue.h" @@ -23,46 +45,612 @@ #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" #include <cstring> +#include <functional> using namespace clang; using llvm::APSInt; using llvm::APFloat; -/// EvalInfo - This is a private struct used by the evaluator to capture -/// information about a subexpression as it is folded. It retains information -/// about the AST context, but also maintains information about the folded -/// expression. -/// -/// If an expression could be evaluated, it is still possible it is not a C -/// "integer constant expression" or constant expression. If not, this struct -/// captures information about how and why not. -/// -/// One bit of information passed *into* the request for constant folding -/// indicates whether the subexpression is "evaluated" or not according to C -/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can -/// evaluate the expression regardless of what the RHS is, but C only allows -/// certain things in certain situations. +static bool IsGlobalLValue(APValue::LValueBase B); + namespace { + struct LValue; + struct CallStackFrame; + struct EvalInfo; + + static QualType getType(APValue::LValueBase B) { + if (!B) return QualType(); + if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) + return D->getType(); + return B.get<const Expr*>()->getType(); + } + + /// Get an LValue path entry, which is known to not be an array index, as a + /// field or base class. + static + APValue::BaseOrMemberType getAsBaseOrMember(APValue::LValuePathEntry E) { + APValue::BaseOrMemberType Value; + Value.setFromOpaqueValue(E.BaseOrMember); + return Value; + } + + /// Get an LValue path entry, which is known to not be an array index, as a + /// field declaration. + static const FieldDecl *getAsField(APValue::LValuePathEntry E) { + return dyn_cast<FieldDecl>(getAsBaseOrMember(E).getPointer()); + } + /// Get an LValue path entry, which is known to not be an array index, as a + /// base class declaration. + static const CXXRecordDecl *getAsBaseClass(APValue::LValuePathEntry E) { + return dyn_cast<CXXRecordDecl>(getAsBaseOrMember(E).getPointer()); + } + /// Determine whether this LValue path entry for a base class names a virtual + /// base class. + static bool isVirtualBaseClass(APValue::LValuePathEntry E) { + return getAsBaseOrMember(E).getInt(); + } + + /// Find the path length and type of the most-derived subobject in the given + /// path, and find the size of the containing array, if any. + static + unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base, + ArrayRef<APValue::LValuePathEntry> Path, + uint64_t &ArraySize, QualType &Type) { + unsigned MostDerivedLength = 0; + Type = Base; + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + if (Type->isArrayType()) { + const ConstantArrayType *CAT = + cast<ConstantArrayType>(Ctx.getAsArrayType(Type)); + Type = CAT->getElementType(); + ArraySize = CAT->getSize().getZExtValue(); + MostDerivedLength = I + 1; + } else if (Type->isAnyComplexType()) { + const ComplexType *CT = Type->castAs<ComplexType>(); + Type = CT->getElementType(); + ArraySize = 2; + MostDerivedLength = I + 1; + } else if (const FieldDecl *FD = getAsField(Path[I])) { + Type = FD->getType(); + ArraySize = 0; + MostDerivedLength = I + 1; + } else { + // Path[I] describes a base class. + ArraySize = 0; + } + } + return MostDerivedLength; + } + + // The order of this enum is important for diagnostics. + enum CheckSubobjectKind { + CSK_Base, CSK_Derived, CSK_Field, CSK_ArrayToPointer, CSK_ArrayIndex, + CSK_This, CSK_Real, CSK_Imag + }; + + /// A path from a glvalue to a subobject of that glvalue. + struct SubobjectDesignator { + /// True if the subobject was named in a manner not supported by C++11. Such + /// lvalues can still be folded, but they are not core constant expressions + /// and we cannot perform lvalue-to-rvalue conversions on them. + bool Invalid : 1; + + /// Is this a pointer one past the end of an object? + bool IsOnePastTheEnd : 1; + + /// The length of the path to the most-derived object of which this is a + /// subobject. + unsigned MostDerivedPathLength : 30; + + /// The size of the array of which the most-derived object is an element, or + /// 0 if the most-derived object is not an array element. + uint64_t MostDerivedArraySize; + + /// The type of the most derived object referred to by this address. + QualType MostDerivedType; + + typedef APValue::LValuePathEntry PathEntry; + + /// The entries on the path from the glvalue to the designated subobject. + SmallVector<PathEntry, 8> Entries; + + SubobjectDesignator() : Invalid(true) {} + + explicit SubobjectDesignator(QualType T) + : Invalid(false), IsOnePastTheEnd(false), MostDerivedPathLength(0), + MostDerivedArraySize(0), MostDerivedType(T) {} + + SubobjectDesignator(ASTContext &Ctx, const APValue &V) + : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), + MostDerivedPathLength(0), MostDerivedArraySize(0) { + if (!Invalid) { + IsOnePastTheEnd = V.isLValueOnePastTheEnd(); + ArrayRef<PathEntry> VEntries = V.getLValuePath(); + Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); + if (V.getLValueBase()) + MostDerivedPathLength = + findMostDerivedSubobject(Ctx, getType(V.getLValueBase()), + V.getLValuePath(), MostDerivedArraySize, + MostDerivedType); + } + } + + void setInvalid() { + Invalid = true; + Entries.clear(); + } + + /// Determine whether this is a one-past-the-end pointer. + bool isOnePastTheEnd() const { + if (IsOnePastTheEnd) + return true; + if (MostDerivedArraySize && + Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize) + return true; + return false; + } + + /// Check that this refers to a valid subobject. + bool isValidSubobject() const { + if (Invalid) + return false; + return !isOnePastTheEnd(); + } + /// Check that this refers to a valid subobject, and if not, produce a + /// relevant diagnostic and set the designator as invalid. + bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK); + + /// Update this designator to refer to the first element within this array. + void addArrayUnchecked(const ConstantArrayType *CAT) { + PathEntry Entry; + Entry.ArrayIndex = 0; + Entries.push_back(Entry); + + // This is a most-derived object. + MostDerivedType = CAT->getElementType(); + MostDerivedArraySize = CAT->getSize().getZExtValue(); + MostDerivedPathLength = Entries.size(); + } + /// Update this designator to refer to the given base or member of this + /// object. + void addDeclUnchecked(const Decl *D, bool Virtual = false) { + PathEntry Entry; + APValue::BaseOrMemberType Value(D, Virtual); + Entry.BaseOrMember = Value.getOpaqueValue(); + Entries.push_back(Entry); + + // If this isn't a base class, it's a new most-derived object. + if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + MostDerivedType = FD->getType(); + MostDerivedArraySize = 0; + MostDerivedPathLength = Entries.size(); + } + } + /// Update this designator to refer to the given complex component. + void addComplexUnchecked(QualType EltTy, bool Imag) { + PathEntry Entry; + Entry.ArrayIndex = Imag; + Entries.push_back(Entry); + + // This is technically a most-derived object, though in practice this + // is unlikely to matter. + MostDerivedType = EltTy; + MostDerivedArraySize = 2; + MostDerivedPathLength = Entries.size(); + } + void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N); + /// Add N to the address of this subobject. + void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { + if (Invalid) return; + if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize) { + Entries.back().ArrayIndex += N; + if (Entries.back().ArrayIndex > MostDerivedArraySize) { + diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex); + setInvalid(); + } + return; + } + // [expr.add]p4: For the purposes of these operators, a pointer to a + // nonarray object behaves the same as a pointer to the first element of + // an array of length one with the type of the object as its element type. + if (IsOnePastTheEnd && N == (uint64_t)-1) + IsOnePastTheEnd = false; + else if (!IsOnePastTheEnd && N == 1) + IsOnePastTheEnd = true; + else if (N != 0) { + diagnosePointerArithmetic(Info, E, uint64_t(IsOnePastTheEnd) + N); + setInvalid(); + } + } + }; + + /// A stack frame in the constexpr call stack. + struct CallStackFrame { + EvalInfo &Info; + + /// Parent - The caller of this stack frame. + CallStackFrame *Caller; + + /// CallLoc - The location of the call expression for this call. + SourceLocation CallLoc; + + /// Callee - The function which was called. + const FunctionDecl *Callee; + + /// Index - The call index of this call. + unsigned Index; + + /// This - The binding for the this pointer in this call, if any. + const LValue *This; + + /// ParmBindings - Parameter bindings for this function call, indexed by + /// parameters' function scope indices. + const APValue *Arguments; + + typedef llvm::DenseMap<const Expr*, APValue> MapTy; + typedef MapTy::const_iterator temp_iterator; + /// Temporaries - Temporary lvalues materialized within this stack frame. + MapTy Temporaries; + + CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, + const FunctionDecl *Callee, const LValue *This, + const APValue *Arguments); + ~CallStackFrame(); + }; + + /// A partial diagnostic which we might know in advance that we are not going + /// to emit. + class OptionalDiagnostic { + PartialDiagnostic *Diag; + + public: + explicit OptionalDiagnostic(PartialDiagnostic *Diag = 0) : Diag(Diag) {} + + template<typename T> + OptionalDiagnostic &operator<<(const T &v) { + if (Diag) + *Diag << v; + return *this; + } + + OptionalDiagnostic &operator<<(const APSInt &I) { + if (Diag) { + llvm::SmallVector<char, 32> Buffer; + I.toString(Buffer); + *Diag << StringRef(Buffer.data(), Buffer.size()); + } + return *this; + } + + OptionalDiagnostic &operator<<(const APFloat &F) { + if (Diag) { + llvm::SmallVector<char, 32> Buffer; + F.toString(Buffer); + *Diag << StringRef(Buffer.data(), Buffer.size()); + } + return *this; + } + }; + + /// EvalInfo - This is a private struct used by the evaluator to capture + /// information about a subexpression as it is folded. It retains information + /// about the AST context, but also maintains information about the folded + /// expression. + /// + /// If an expression could be evaluated, it is still possible it is not a C + /// "integer constant expression" or constant expression. If not, this struct + /// captures information about how and why not. + /// + /// One bit of information passed *into* the request for constant folding + /// indicates whether the subexpression is "evaluated" or not according to C + /// rules. For example, the RHS of (0 && foo()) is not evaluated. We can + /// evaluate the expression regardless of what the RHS is, but C only allows + /// certain things in certain situations. struct EvalInfo { - const ASTContext &Ctx; + ASTContext &Ctx; + + /// EvalStatus - Contains information about the evaluation. + Expr::EvalStatus &EvalStatus; + + /// CurrentCall - The top of the constexpr call stack. + CallStackFrame *CurrentCall; - /// EvalResult - Contains information about the evaluation. - Expr::EvalResult &EvalResult; + /// CallStackDepth - The number of calls in the call stack right now. + unsigned CallStackDepth; + + /// NextCallIndex - The next call index to assign. + unsigned NextCallIndex; typedef llvm::DenseMap<const OpaqueValueExpr*, APValue> MapTy; + /// OpaqueValues - Values used as the common expression in a + /// BinaryConditionalOperator. MapTy OpaqueValues; + + /// BottomFrame - The frame in which evaluation started. This must be + /// initialized after CurrentCall and CallStackDepth. + CallStackFrame BottomFrame; + + /// EvaluatingDecl - This is the declaration whose initializer is being + /// evaluated, if any. + const VarDecl *EvaluatingDecl; + + /// EvaluatingDeclValue - This is the value being constructed for the + /// declaration whose initializer is being evaluated, if any. + APValue *EvaluatingDeclValue; + + /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further + /// notes attached to it will also be stored, otherwise they will not be. + bool HasActiveDiagnostic; + + /// CheckingPotentialConstantExpression - Are we checking whether the + /// expression is a potential constant expression? If so, some diagnostics + /// are suppressed. + bool CheckingPotentialConstantExpression; + + EvalInfo(const ASTContext &C, Expr::EvalStatus &S) + : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0), + CallStackDepth(0), NextCallIndex(1), + BottomFrame(*this, SourceLocation(), 0, 0, 0), + EvaluatingDecl(0), EvaluatingDeclValue(0), HasActiveDiagnostic(false), + CheckingPotentialConstantExpression(false) {} + const APValue *getOpaqueValue(const OpaqueValueExpr *e) const { MapTy::const_iterator i = OpaqueValues.find(e); if (i == OpaqueValues.end()) return 0; return &i->second; } - EvalInfo(const ASTContext &ctx, Expr::EvalResult &evalresult) - : Ctx(ctx), EvalResult(evalresult) {} + void setEvaluatingDecl(const VarDecl *VD, APValue &Value) { + EvaluatingDecl = VD; + EvaluatingDeclValue = &Value; + } + + const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } + + bool CheckCallLimit(SourceLocation Loc) { + // Don't perform any constexpr calls (other than the call we're checking) + // when checking a potential constant expression. + if (CheckingPotentialConstantExpression && CallStackDepth > 1) + return false; + if (NextCallIndex == 0) { + // NextCallIndex has wrapped around. + Diag(Loc, diag::note_constexpr_call_limit_exceeded); + return false; + } + if (CallStackDepth <= getLangOpts().ConstexprCallDepth) + return true; + Diag(Loc, diag::note_constexpr_depth_limit_exceeded) + << getLangOpts().ConstexprCallDepth; + return false; + } - const LangOptions &getLangOpts() { return Ctx.getLangOptions(); } + CallStackFrame *getCallFrame(unsigned CallIndex) { + assert(CallIndex && "no call index in getCallFrame"); + // We will eventually hit BottomFrame, which has Index 1, so Frame can't + // be null in this loop. + CallStackFrame *Frame = CurrentCall; + while (Frame->Index > CallIndex) + Frame = Frame->Caller; + return (Frame->Index == CallIndex) ? Frame : 0; + } + + private: + /// Add a diagnostic to the diagnostics list. + PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId) { + PartialDiagnostic PD(DiagId, Ctx.getDiagAllocator()); + EvalStatus.Diag->push_back(std::make_pair(Loc, PD)); + return EvalStatus.Diag->back().second; + } + + /// Add notes containing a call stack to the current point of evaluation. + void addCallStack(unsigned Limit); + + public: + /// Diagnose that the evaluation cannot be folded. + OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId + = diag::note_invalid_subexpr_in_const_expr, + unsigned ExtraNotes = 0) { + // If we have a prior diagnostic, it will be noting that the expression + // isn't a constant expression. This diagnostic is more important. + // FIXME: We might want to show both diagnostics to the user. + if (EvalStatus.Diag) { + unsigned CallStackNotes = CallStackDepth - 1; + unsigned Limit = Ctx.getDiagnostics().getConstexprBacktraceLimit(); + if (Limit) + CallStackNotes = std::min(CallStackNotes, Limit + 1); + if (CheckingPotentialConstantExpression) + CallStackNotes = 0; + + HasActiveDiagnostic = true; + EvalStatus.Diag->clear(); + EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes); + addDiag(Loc, DiagId); + if (!CheckingPotentialConstantExpression) + addCallStack(Limit); + return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second); + } + HasActiveDiagnostic = false; + return OptionalDiagnostic(); + } + + OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId + = diag::note_invalid_subexpr_in_const_expr, + unsigned ExtraNotes = 0) { + if (EvalStatus.Diag) + return Diag(E->getExprLoc(), DiagId, ExtraNotes); + HasActiveDiagnostic = false; + return OptionalDiagnostic(); + } + + /// Diagnose that the evaluation does not produce a C++11 core constant + /// expression. + template<typename LocArg> + OptionalDiagnostic CCEDiag(LocArg Loc, diag::kind DiagId + = diag::note_invalid_subexpr_in_const_expr, + unsigned ExtraNotes = 0) { + // Don't override a previous diagnostic. + if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) { + HasActiveDiagnostic = false; + return OptionalDiagnostic(); + } + return Diag(Loc, DiagId, ExtraNotes); + } + + /// Add a note to a prior diagnostic. + OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId) { + if (!HasActiveDiagnostic) + return OptionalDiagnostic(); + return OptionalDiagnostic(&addDiag(Loc, DiagId)); + } + + /// Add a stack of notes to a prior diagnostic. + void addNotes(ArrayRef<PartialDiagnosticAt> Diags) { + if (HasActiveDiagnostic) { + EvalStatus.Diag->insert(EvalStatus.Diag->end(), + Diags.begin(), Diags.end()); + } + } + + /// Should we continue evaluation as much as possible after encountering a + /// construct which can't be folded? + bool keepEvaluatingAfterFailure() { + return CheckingPotentialConstantExpression && + EvalStatus.Diag && EvalStatus.Diag->empty(); + } }; + /// Object used to treat all foldable expressions as constant expressions. + struct FoldConstant { + bool Enabled; + + explicit FoldConstant(EvalInfo &Info) + : Enabled(Info.EvalStatus.Diag && Info.EvalStatus.Diag->empty() && + !Info.EvalStatus.HasSideEffects) { + } + // Treat the value we've computed since this object was created as constant. + void Fold(EvalInfo &Info) { + if (Enabled && !Info.EvalStatus.Diag->empty() && + !Info.EvalStatus.HasSideEffects) + Info.EvalStatus.Diag->clear(); + } + }; + + /// RAII object used to suppress diagnostics and side-effects from a + /// speculative evaluation. + class SpeculativeEvaluationRAII { + EvalInfo &Info; + Expr::EvalStatus Old; + + public: + SpeculativeEvaluationRAII(EvalInfo &Info, + llvm::SmallVectorImpl<PartialDiagnosticAt> + *NewDiag = 0) + : Info(Info), Old(Info.EvalStatus) { + Info.EvalStatus.Diag = NewDiag; + } + ~SpeculativeEvaluationRAII() { + Info.EvalStatus = Old; + } + }; +} + +bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, + CheckSubobjectKind CSK) { + if (Invalid) + return false; + if (isOnePastTheEnd()) { + Info.CCEDiag(E, diag::note_constexpr_past_end_subobject) + << CSK; + setInvalid(); + return false; + } + return true; +} + +void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, + const Expr *E, uint64_t N) { + if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize) + Info.CCEDiag(E, diag::note_constexpr_array_index) + << static_cast<int>(N) << /*array*/ 0 + << static_cast<unsigned>(MostDerivedArraySize); + else + Info.CCEDiag(E, diag::note_constexpr_array_index) + << static_cast<int>(N) << /*non-array*/ 1; + setInvalid(); +} + +CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, + const FunctionDecl *Callee, const LValue *This, + const APValue *Arguments) + : Info(Info), Caller(Info.CurrentCall), CallLoc(CallLoc), Callee(Callee), + Index(Info.NextCallIndex++), This(This), Arguments(Arguments) { + Info.CurrentCall = this; + ++Info.CallStackDepth; +} + +CallStackFrame::~CallStackFrame() { + assert(Info.CurrentCall == this && "calls retired out of order"); + --Info.CallStackDepth; + Info.CurrentCall = Caller; +} + +/// Produce a string describing the given constexpr call. +static void describeCall(CallStackFrame *Frame, llvm::raw_ostream &Out) { + unsigned ArgIndex = 0; + bool IsMemberCall = isa<CXXMethodDecl>(Frame->Callee) && + !isa<CXXConstructorDecl>(Frame->Callee) && + cast<CXXMethodDecl>(Frame->Callee)->isInstance(); + + if (!IsMemberCall) + Out << *Frame->Callee << '('; + + for (FunctionDecl::param_const_iterator I = Frame->Callee->param_begin(), + E = Frame->Callee->param_end(); I != E; ++I, ++ArgIndex) { + if (ArgIndex > (unsigned)IsMemberCall) + Out << ", "; + + const ParmVarDecl *Param = *I; + const APValue &Arg = Frame->Arguments[ArgIndex]; + Arg.printPretty(Out, Frame->Info.Ctx, Param->getType()); + + if (ArgIndex == 0 && IsMemberCall) + Out << "->" << *Frame->Callee << '('; + } + + Out << ')'; +} + +void EvalInfo::addCallStack(unsigned Limit) { + // Determine which calls to skip, if any. + unsigned ActiveCalls = CallStackDepth - 1; + unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart; + if (Limit && Limit < ActiveCalls) { + SkipStart = Limit / 2 + Limit % 2; + SkipEnd = ActiveCalls - Limit / 2; + } + + // Walk the call stack and add the diagnostics. + unsigned CallIdx = 0; + for (CallStackFrame *Frame = CurrentCall; Frame != &BottomFrame; + Frame = Frame->Caller, ++CallIdx) { + // Skip this call? + if (CallIdx >= SkipStart && CallIdx < SkipEnd) { + if (CallIdx == SkipStart) { + // Note that we're skipping calls. + addDiag(Frame->CallLoc, diag::note_constexpr_calls_suppressed) + << unsigned(ActiveCalls - Limit); + } + continue; + } + + llvm::SmallVector<char, 128> Buffer; + llvm::raw_svector_ostream Out(Buffer); + describeCall(Frame, Out); + addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str(); + } +} + +namespace { struct ComplexValue { private: bool IsInt; @@ -104,28 +692,203 @@ namespace { }; struct LValue { - const Expr *Base; + APValue::LValueBase Base; CharUnits Offset; + unsigned CallIndex; + SubobjectDesignator Designator; + + const APValue::LValueBase getLValueBase() const { return Base; } + CharUnits &getLValueOffset() { return Offset; } + const CharUnits &getLValueOffset() const { return Offset; } + unsigned getLValueCallIndex() const { return CallIndex; } + SubobjectDesignator &getLValueDesignator() { return Designator; } + const SubobjectDesignator &getLValueDesignator() const { return Designator;} + + void moveInto(APValue &V) const { + if (Designator.Invalid) + V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex); + else + V = APValue(Base, Offset, Designator.Entries, + Designator.IsOnePastTheEnd, CallIndex); + } + void setFrom(ASTContext &Ctx, const APValue &V) { + assert(V.isLValue()); + Base = V.getLValueBase(); + Offset = V.getLValueOffset(); + CallIndex = V.getLValueCallIndex(); + Designator = SubobjectDesignator(Ctx, V); + } - const Expr *getLValueBase() { return Base; } - CharUnits getLValueOffset() { return Offset; } + void set(APValue::LValueBase B, unsigned I = 0) { + Base = B; + Offset = CharUnits::Zero(); + CallIndex = I; + Designator = SubobjectDesignator(getType(B)); + } - void moveInto(APValue &v) const { - v = APValue(Base, Offset); + // Check that this LValue is not based on a null pointer. If it is, produce + // a diagnostic and mark the designator as invalid. + bool checkNullPointer(EvalInfo &Info, const Expr *E, + CheckSubobjectKind CSK) { + if (Designator.Invalid) + return false; + if (!Base) { + Info.CCEDiag(E, diag::note_constexpr_null_subobject) + << CSK; + Designator.setInvalid(); + return false; + } + return true; } - void setFrom(const APValue &v) { - assert(v.isLValue()); - Base = v.getLValueBase(); - Offset = v.getLValueOffset(); + + // Check this LValue refers to an object. If not, set the designator to be + // invalid and emit a diagnostic. + bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { + // Outside C++11, do not build a designator referring to a subobject of + // any object: we won't use such a designator for anything. + if (!Info.getLangOpts().CPlusPlus0x) + Designator.setInvalid(); + return checkNullPointer(Info, E, CSK) && + Designator.checkSubobject(Info, E, CSK); + } + + void addDecl(EvalInfo &Info, const Expr *E, + const Decl *D, bool Virtual = false) { + if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base)) + Designator.addDeclUnchecked(D, Virtual); + } + void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { + if (checkSubobject(Info, E, CSK_ArrayToPointer)) + Designator.addArrayUnchecked(CAT); + } + void addComplex(EvalInfo &Info, const Expr *E, QualType EltTy, bool Imag) { + if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) + Designator.addComplexUnchecked(EltTy, Imag); } + void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { + if (checkNullPointer(Info, E, CSK_ArrayIndex)) + Designator.adjustIndex(Info, E, N); + } + }; + + struct MemberPtr { + MemberPtr() {} + explicit MemberPtr(const ValueDecl *Decl) : + DeclAndIsDerivedMember(Decl, false), Path() {} + + /// The member or (direct or indirect) field referred to by this member + /// pointer, or 0 if this is a null member pointer. + const ValueDecl *getDecl() const { + return DeclAndIsDerivedMember.getPointer(); + } + /// Is this actually a member of some type derived from the relevant class? + bool isDerivedMember() const { + return DeclAndIsDerivedMember.getInt(); + } + /// Get the class which the declaration actually lives in. + const CXXRecordDecl *getContainingRecord() const { + return cast<CXXRecordDecl>( + DeclAndIsDerivedMember.getPointer()->getDeclContext()); + } + + void moveInto(APValue &V) const { + V = APValue(getDecl(), isDerivedMember(), Path); + } + void setFrom(const APValue &V) { + assert(V.isMemberPointer()); + DeclAndIsDerivedMember.setPointer(V.getMemberPointerDecl()); + DeclAndIsDerivedMember.setInt(V.isMemberPointerToDerivedMember()); + Path.clear(); + ArrayRef<const CXXRecordDecl*> P = V.getMemberPointerPath(); + Path.insert(Path.end(), P.begin(), P.end()); + } + + /// DeclAndIsDerivedMember - The member declaration, and a flag indicating + /// whether the member is a member of some class derived from the class type + /// of the member pointer. + llvm::PointerIntPair<const ValueDecl*, 1, bool> DeclAndIsDerivedMember; + /// Path - The path of base/derived classes from the member declaration's + /// class (exclusive) to the class type of the member pointer (inclusive). + SmallVector<const CXXRecordDecl*, 4> Path; + + /// Perform a cast towards the class of the Decl (either up or down the + /// hierarchy). + bool castBack(const CXXRecordDecl *Class) { + assert(!Path.empty()); + const CXXRecordDecl *Expected; + if (Path.size() >= 2) + Expected = Path[Path.size() - 2]; + else + Expected = getContainingRecord(); + if (Expected->getCanonicalDecl() != Class->getCanonicalDecl()) { + // C++11 [expr.static.cast]p12: In a conversion from (D::*) to (B::*), + // if B does not contain the original member and is not a base or + // derived class of the class containing the original member, the result + // of the cast is undefined. + // C++11 [conv.mem]p2 does not cover this case for a cast from (B::*) to + // (D::*). We consider that to be a language defect. + return false; + } + Path.pop_back(); + return true; + } + /// Perform a base-to-derived member pointer cast. + bool castToDerived(const CXXRecordDecl *Derived) { + if (!getDecl()) + return true; + if (!isDerivedMember()) { + Path.push_back(Derived); + return true; + } + if (!castBack(Derived)) + return false; + if (Path.empty()) + DeclAndIsDerivedMember.setInt(false); + return true; + } + /// Perform a derived-to-base member pointer cast. + bool castToBase(const CXXRecordDecl *Base) { + if (!getDecl()) + return true; + if (Path.empty()) + DeclAndIsDerivedMember.setInt(true); + if (isDerivedMember()) { + Path.push_back(Base); + return true; + } + return castBack(Base); + } + }; + + /// Compare two member pointers, which are assumed to be of the same type. + static bool operator==(const MemberPtr &LHS, const MemberPtr &RHS) { + if (!LHS.getDecl() || !RHS.getDecl()) + return !LHS.getDecl() && !RHS.getDecl(); + if (LHS.getDecl()->getCanonicalDecl() != RHS.getDecl()->getCanonicalDecl()) + return false; + return LHS.Path == RHS.Path; + } + + /// Kinds of constant expression checking, for diagnostics. + enum CheckConstantExpressionKind { + CCEK_Constant, ///< A normal constant. + CCEK_ReturnValue, ///< A constexpr function return value. + CCEK_MemberInit ///< A constexpr constructor mem-initializer. }; } -static bool Evaluate(EvalInfo &info, const Expr *E); +static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E); +static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, + const LValue &This, const Expr *E, + CheckConstantExpressionKind CCEK = CCEK_Constant, + bool AllowNonLiteralTypes = false); static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); +static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, + EvalInfo &Info); +static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); -static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, +static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); @@ -134,116 +897,306 @@ static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); // Misc utilities //===----------------------------------------------------------------------===// -static bool IsGlobalLValue(const Expr* E) { - if (!E) return true; +/// Should this call expression be treated as a string literal? +static bool IsStringLiteralCall(const CallExpr *E) { + unsigned Builtin = E->isBuiltinCall(); + return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || + Builtin == Builtin::BI__builtin___NSStringMakeConstantString); +} - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { - if (isa<FunctionDecl>(DRE->getDecl())) - return true; - if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) +static bool IsGlobalLValue(APValue::LValueBase B) { + // C++11 [expr.const]p3 An address constant expression is a prvalue core + // constant expression of pointer type that evaluates to... + + // ... a null pointer value, or a prvalue core constant expression of type + // std::nullptr_t. + if (!B) return true; + + if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { + // ... the address of an object with static storage duration, + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->hasGlobalStorage(); - return false; + // ... the address of a function, + return isa<FunctionDecl>(D); } - if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(E)) - return CLE->isFileScope(); + const Expr *E = B.get<const Expr*>(); + switch (E->getStmtClass()) { + default: + return false; + case Expr::CompoundLiteralExprClass: { + const CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E); + return CLE->isFileScope() && CLE->isLValue(); + } + // A string literal has static storage duration. + case Expr::StringLiteralClass: + case Expr::PredefinedExprClass: + case Expr::ObjCStringLiteralClass: + case Expr::ObjCEncodeExprClass: + case Expr::CXXTypeidExprClass: + return true; + case Expr::CallExprClass: + return IsStringLiteralCall(cast<CallExpr>(E)); + // For GCC compatibility, &&label has static storage duration. + case Expr::AddrLabelExprClass: + return true; + // A Block literal expression may be used as the initialization value for + // Block variables at global or local static scope. + case Expr::BlockExprClass: + return !cast<BlockExpr>(E)->getBlockDecl()->hasCaptures(); + case Expr::ImplicitValueInitExprClass: + // FIXME: + // We can never form an lvalue with an implicit value initialization as its + // base through expression evaluation, so these only appear in one case: the + // implicit variable declaration we invent when checking whether a constexpr + // constructor can produce a constant expression. We must assume that such + // an expression might be a global lvalue. + return true; + } +} - return true; +static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { + assert(Base && "no location for a null lvalue"); + const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); + if (VD) + Info.Note(VD->getLocation(), diag::note_declared_at); + else + Info.Note(Base.dyn_cast<const Expr*>()->getExprLoc(), + diag::note_constexpr_temporary_here); } -static bool EvalPointerValueAsBool(LValue& Value, bool& Result) { - const Expr* Base = Value.Base; +/// Check that this reference or pointer core constant expression is a valid +/// value for an address or reference constant expression. Return true if we +/// can fold this expression, whether or not it's a constant expression. +static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, + QualType Type, const LValue &LVal) { + bool IsReferenceType = Type->isReferenceType(); - // A null base expression indicates a null pointer. These are always - // evaluatable, and they are false unless the offset is zero. + APValue::LValueBase Base = LVal.getLValueBase(); + const SubobjectDesignator &Designator = LVal.getLValueDesignator(); + + // Check that the object is a global. Note that the fake 'this' object we + // manufacture when checking potential constant expressions is conservatively + // assumed to be global here. + if (!IsGlobalLValue(Base)) { + if (Info.getLangOpts().CPlusPlus0x) { + const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); + Info.Diag(Loc, diag::note_constexpr_non_global, 1) + << IsReferenceType << !Designator.Entries.empty() + << !!VD << VD; + NoteLValueLocation(Info, Base); + } else { + Info.Diag(Loc); + } + // Don't allow references to temporaries to escape. + return false; + } + assert((Info.CheckingPotentialConstantExpression || + LVal.getLValueCallIndex() == 0) && + "have call index for global lvalue"); + + // Allow address constant expressions to be past-the-end pointers. This is + // an extension: the standard requires them to point to an object. + if (!IsReferenceType) + return true; + + // A reference constant expression must refer to an object. if (!Base) { - Result = !Value.Offset.isZero(); + // FIXME: diagnostic + Info.CCEDiag(Loc); return true; } - // Require the base expression to be a global l-value. - if (!IsGlobalLValue(Base)) return false; + // Does this refer one past the end of some object? + if (Designator.isOnePastTheEnd()) { + const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>(); + Info.Diag(Loc, diag::note_constexpr_past_end, 1) + << !Designator.Entries.empty() << !!VD << VD; + NoteLValueLocation(Info, Base); + } - // We have a non-null base expression. These are generally known to - // be true, but if it'a decl-ref to a weak symbol it can be null at - // runtime. - Result = true; + return true; +} - const DeclRefExpr* DeclRef = dyn_cast<DeclRefExpr>(Base); - if (!DeclRef) +/// Check that this core constant expression is of literal type, and if not, +/// produce an appropriate diagnostic. +static bool CheckLiteralType(EvalInfo &Info, const Expr *E) { + if (!E->isRValue() || E->getType()->isLiteralType()) return true; - // If it's a weak symbol, it isn't constant-evaluable. - const ValueDecl* Decl = DeclRef->getDecl(); - if (Decl->hasAttr<WeakAttr>() || - Decl->hasAttr<WeakRefAttr>() || - Decl->isWeakImported()) - return false; + // Prvalue constant expressions must be of literal types. + if (Info.getLangOpts().CPlusPlus0x) + Info.Diag(E, diag::note_constexpr_nonliteral) + << E->getType(); + else + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; +} +/// Check that this core constant expression value is a valid value for a +/// constant expression. If not, report an appropriate diagnostic. Does not +/// check that the expression is of literal type. +static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, + QualType Type, const APValue &Value) { + // Core issue 1454: For a literal constant expression of array or class type, + // each subobject of its value shall have been initialized by a constant + // expression. + if (Value.isArray()) { + QualType EltTy = Type->castAsArrayTypeUnsafe()->getElementType(); + for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) { + if (!CheckConstantExpression(Info, DiagLoc, EltTy, + Value.getArrayInitializedElt(I))) + return false; + } + if (!Value.hasArrayFiller()) + return true; + return CheckConstantExpression(Info, DiagLoc, EltTy, + Value.getArrayFiller()); + } + if (Value.isUnion() && Value.getUnionField()) { + return CheckConstantExpression(Info, DiagLoc, + Value.getUnionField()->getType(), + Value.getUnionValue()); + } + if (Value.isStruct()) { + RecordDecl *RD = Type->castAs<RecordType>()->getDecl(); + if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) { + unsigned BaseIndex = 0; + for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(), + End = CD->bases_end(); I != End; ++I, ++BaseIndex) { + if (!CheckConstantExpression(Info, DiagLoc, I->getType(), + Value.getStructBase(BaseIndex))) + return false; + } + } + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I) { + if (!CheckConstantExpression(Info, DiagLoc, (*I)->getType(), + Value.getStructField((*I)->getFieldIndex()))) + return false; + } + } + + if (Value.isLValue()) { + LValue LVal; + LVal.setFrom(Info.Ctx, Value); + return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal); + } + + // Everything else is fine. return true; } -static bool HandleConversionToBool(const Expr* E, bool& Result, - EvalInfo &Info) { - if (E->getType()->isIntegralOrEnumerationType()) { - APSInt IntResult; - if (!EvaluateInteger(E, IntResult, Info)) - return false; - Result = IntResult != 0; +const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { + return LVal.Base.dyn_cast<const ValueDecl*>(); +} + +static bool IsLiteralLValue(const LValue &Value) { + return Value.Base.dyn_cast<const Expr*>() && !Value.CallIndex; +} + +static bool IsWeakLValue(const LValue &Value) { + const ValueDecl *Decl = GetLValueBaseDecl(Value); + return Decl && Decl->isWeak(); +} + +static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { + // A null base expression indicates a null pointer. These are always + // evaluatable, and they are false unless the offset is zero. + if (!Value.getLValueBase()) { + Result = !Value.getLValueOffset().isZero(); return true; - } else if (E->getType()->isRealFloatingType()) { - APFloat FloatResult(0.0); - if (!EvaluateFloat(E, FloatResult, Info)) - return false; - Result = !FloatResult.isZero(); + } + + // We have a non-null base. These are generally known to be true, but if it's + // a weak declaration it can be null at runtime. + Result = true; + const ValueDecl *Decl = Value.getLValueBase().dyn_cast<const ValueDecl*>(); + return !Decl || !Decl->isWeak(); +} + +static bool HandleConversionToBool(const APValue &Val, bool &Result) { + switch (Val.getKind()) { + case APValue::Uninitialized: + return false; + case APValue::Int: + Result = Val.getInt().getBoolValue(); return true; - } else if (E->getType()->hasPointerRepresentation()) { - LValue PointerResult; - if (!EvaluatePointer(E, PointerResult, Info)) - return false; - return EvalPointerValueAsBool(PointerResult, Result); - } else if (E->getType()->isAnyComplexType()) { - ComplexValue ComplexResult; - if (!EvaluateComplex(E, ComplexResult, Info)) - return false; - if (ComplexResult.isComplexFloat()) { - Result = !ComplexResult.getComplexFloatReal().isZero() || - !ComplexResult.getComplexFloatImag().isZero(); - } else { - Result = ComplexResult.getComplexIntReal().getBoolValue() || - ComplexResult.getComplexIntImag().getBoolValue(); - } + case APValue::Float: + Result = !Val.getFloat().isZero(); + return true; + case APValue::ComplexInt: + Result = Val.getComplexIntReal().getBoolValue() || + Val.getComplexIntImag().getBoolValue(); return true; + case APValue::ComplexFloat: + Result = !Val.getComplexFloatReal().isZero() || + !Val.getComplexFloatImag().isZero(); + return true; + case APValue::LValue: + return EvalPointerValueAsBool(Val, Result); + case APValue::MemberPointer: + Result = Val.getMemberPointerDecl(); + return true; + case APValue::Vector: + case APValue::Array: + case APValue::Struct: + case APValue::Union: + case APValue::AddrLabelDiff: + return false; } + llvm_unreachable("unknown APValue kind"); +} + +static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result, + EvalInfo &Info) { + assert(E->isRValue() && "missing lvalue-to-rvalue conv in bool condition"); + APValue Val; + if (!Evaluate(Val, Info, E)) + return false; + return HandleConversionToBool(Val, Result); +} + +template<typename T> +static bool HandleOverflow(EvalInfo &Info, const Expr *E, + const T &SrcValue, QualType DestType) { + Info.Diag(E, diag::note_constexpr_overflow) + << SrcValue << DestType; return false; } -static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, - APFloat &Value, const ASTContext &Ctx) { - unsigned DestWidth = Ctx.getIntWidth(DestType); +static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, + QualType SrcType, const APFloat &Value, + QualType DestType, APSInt &Result) { + unsigned DestWidth = Info.Ctx.getIntWidth(DestType); // Determine whether we are converting to unsigned or signed. bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); - // FIXME: Warning for overflow. - APSInt Result(DestWidth, !DestSigned); + Result = APSInt(DestWidth, !DestSigned); bool ignored; - (void)Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored); - return Result; + if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored) + & APFloat::opInvalidOp) + return HandleOverflow(Info, E, Value, DestType); + return true; } -static APFloat HandleFloatToFloatCast(QualType DestType, QualType SrcType, - APFloat &Value, const ASTContext &Ctx) { +static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, + QualType SrcType, QualType DestType, + APFloat &Result) { + APFloat Value = Result; bool ignored; - APFloat Result = Value; - Result.convert(Ctx.getFloatTypeSemantics(DestType), - APFloat::rmNearestTiesToEven, &ignored); - return Result; + if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), + APFloat::rmNearestTiesToEven, &ignored) + & APFloat::opOverflow) + return HandleOverflow(Info, E, Value, DestType); + return true; } -static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType, - APSInt &Value, const ASTContext &Ctx) { - unsigned DestWidth = Ctx.getIntWidth(DestType); +static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, + QualType DestType, QualType SrcType, + APSInt &Value) { + unsigned DestWidth = Info.Ctx.getIntWidth(DestType); APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. @@ -252,22 +1205,1071 @@ static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType, return Result; } -static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, - APSInt &Value, const ASTContext &Ctx) { +static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, + QualType SrcType, const APSInt &Value, + QualType DestType, APFloat &Result) { + Result = APFloat(Info.Ctx.getFloatTypeSemantics(DestType), 1); + if (Result.convertFromAPInt(Value, Value.isSigned(), + APFloat::rmNearestTiesToEven) + & APFloat::opOverflow) + return HandleOverflow(Info, E, Value, DestType); + return true; +} - APFloat Result(Ctx.getFloatTypeSemantics(DestType), 1); - Result.convertFromAPInt(Value, Value.isSigned(), - APFloat::rmNearestTiesToEven); - return Result; +static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, + llvm::APInt &Res) { + APValue SVal; + if (!Evaluate(SVal, Info, E)) + return false; + if (SVal.isInt()) { + Res = SVal.getInt(); + return true; + } + if (SVal.isFloat()) { + Res = SVal.getFloat().bitcastToAPInt(); + return true; + } + if (SVal.isVector()) { + QualType VecTy = E->getType(); + unsigned VecSize = Info.Ctx.getTypeSize(VecTy); + QualType EltTy = VecTy->castAs<VectorType>()->getElementType(); + unsigned EltSize = Info.Ctx.getTypeSize(EltTy); + bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); + Res = llvm::APInt::getNullValue(VecSize); + for (unsigned i = 0; i < SVal.getVectorLength(); i++) { + APValue &Elt = SVal.getVectorElt(i); + llvm::APInt EltAsInt; + if (Elt.isInt()) { + EltAsInt = Elt.getInt(); + } else if (Elt.isFloat()) { + EltAsInt = Elt.getFloat().bitcastToAPInt(); + } else { + // Don't try to handle vectors of anything other than int or float + // (not sure if it's possible to hit this case). + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + unsigned BaseEltSize = EltAsInt.getBitWidth(); + if (BigEndian) + Res |= EltAsInt.zextOrTrunc(VecSize).rotr(i*EltSize+BaseEltSize); + else + Res |= EltAsInt.zextOrTrunc(VecSize).rotl(i*EltSize); + } + return true; + } + // Give up if the input isn't an int, float, or vector. For example, we + // reject "(v4i16)(intptr_t)&a". + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; +} + +/// Cast an lvalue referring to a base subobject to a derived class, by +/// truncating the lvalue's path to the given length. +static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, + const RecordDecl *TruncatedType, + unsigned TruncatedElements) { + SubobjectDesignator &D = Result.Designator; + + // Check we actually point to a derived class object. + if (TruncatedElements == D.Entries.size()) + return true; + assert(TruncatedElements >= D.MostDerivedPathLength && + "not casting to a derived class"); + if (!Result.checkSubobject(Info, E, CSK_Derived)) + return false; + + // Truncate the path to the subobject, and remove any derived-to-base offsets. + const RecordDecl *RD = TruncatedType; + for (unsigned I = TruncatedElements, N = D.Entries.size(); I != N; ++I) { + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); + const CXXRecordDecl *Base = getAsBaseClass(D.Entries[I]); + if (isVirtualBaseClass(D.Entries[I])) + Result.Offset -= Layout.getVBaseClassOffset(Base); + else + Result.Offset -= Layout.getBaseClassOffset(Base); + RD = Base; + } + D.Entries.resize(TruncatedElements); + return true; +} + +static void HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj, + const CXXRecordDecl *Derived, + const CXXRecordDecl *Base, + const ASTRecordLayout *RL = 0) { + if (!RL) RL = &Info.Ctx.getASTRecordLayout(Derived); + Obj.getLValueOffset() += RL->getBaseClassOffset(Base); + Obj.addDecl(Info, E, Base, /*Virtual*/ false); +} + +static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, + const CXXRecordDecl *DerivedDecl, + const CXXBaseSpecifier *Base) { + const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); + + if (!Base->isVirtual()) { + HandleLValueDirectBase(Info, E, Obj, DerivedDecl, BaseDecl); + return true; + } + + SubobjectDesignator &D = Obj.Designator; + if (D.Invalid) + return false; + + // Extract most-derived object and corresponding type. + DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); + if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) + return false; + + // Find the virtual base class. + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); + Obj.getLValueOffset() += Layout.getVBaseClassOffset(BaseDecl); + Obj.addDecl(Info, E, BaseDecl, /*Virtual*/ true); + return true; +} + +/// Update LVal to refer to the given field, which must be a member of the type +/// currently described by LVal. +static void HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, + const FieldDecl *FD, + const ASTRecordLayout *RL = 0) { + if (!RL) + RL = &Info.Ctx.getASTRecordLayout(FD->getParent()); + + unsigned I = FD->getFieldIndex(); + LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)); + LVal.addDecl(Info, E, FD); +} + +/// Update LVal to refer to the given indirect field. +static void HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, + LValue &LVal, + const IndirectFieldDecl *IFD) { + for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), + CE = IFD->chain_end(); C != CE; ++C) + HandleLValueMember(Info, E, LVal, cast<FieldDecl>(*C)); +} + +/// Get the size of the given type in char units. +static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, + QualType Type, CharUnits &Size) { + // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc + // extension. + if (Type->isVoidType() || Type->isFunctionType()) { + Size = CharUnits::One(); + return true; + } + + if (!Type->isConstantSizeType()) { + // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. + // FIXME: Better diagnostic. + Info.Diag(Loc); + return false; + } + + Size = Info.Ctx.getTypeSizeInChars(Type); + return true; +} + +/// Update a pointer value to model pointer arithmetic. +/// \param Info - Information about the ongoing evaluation. +/// \param E - The expression being evaluated, for diagnostic purposes. +/// \param LVal - The pointer value to be updated. +/// \param EltTy - The pointee type represented by LVal. +/// \param Adjustment - The adjustment, in objects of type EltTy, to add. +static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, + LValue &LVal, QualType EltTy, + int64_t Adjustment) { + CharUnits SizeOfPointee; + if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) + return false; + + // Compute the new offset in the appropriate width. + LVal.Offset += Adjustment * SizeOfPointee; + LVal.adjustIndex(Info, E, Adjustment); + return true; +} + +/// Update an lvalue to refer to a component of a complex number. +/// \param Info - Information about the ongoing evaluation. +/// \param LVal - The lvalue to be updated. +/// \param EltTy - The complex number's component type. +/// \param Imag - False for the real component, true for the imaginary. +static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, + LValue &LVal, QualType EltTy, + bool Imag) { + if (Imag) { + CharUnits SizeOfComponent; + if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfComponent)) + return false; + LVal.Offset += SizeOfComponent; + } + LVal.addComplex(Info, E, EltTy, Imag); + return true; +} + +/// Try to evaluate the initializer for a variable declaration. +static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E, + const VarDecl *VD, + CallStackFrame *Frame, APValue &Result) { + // If this is a parameter to an active constexpr function call, perform + // argument substitution. + if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(VD)) { + // Assume arguments of a potential constant expression are unknown + // constant expressions. + if (Info.CheckingPotentialConstantExpression) + return false; + if (!Frame || !Frame->Arguments) { + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + Result = Frame->Arguments[PVD->getFunctionScopeIndex()]; + return true; + } + + // Dig out the initializer, and use the declaration which it's attached to. + const Expr *Init = VD->getAnyInitializer(VD); + if (!Init || Init->isValueDependent()) { + // If we're checking a potential constant expression, the variable could be + // initialized later. + if (!Info.CheckingPotentialConstantExpression) + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + + // If we're currently evaluating the initializer of this declaration, use that + // in-flight value. + if (Info.EvaluatingDecl == VD) { + Result = *Info.EvaluatingDeclValue; + return !Result.isUninit(); + } + + // Never evaluate the initializer of a weak variable. We can't be sure that + // this is the definition which will be used. + if (VD->isWeak()) { + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + + // Check that we can fold the initializer. In C++, we will have already done + // this in the cases where it matters for conformance. + llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + if (!VD->evaluateValue(Notes)) { + Info.Diag(E, diag::note_constexpr_var_init_non_constant, + Notes.size() + 1) << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + Info.addNotes(Notes); + return false; + } else if (!VD->checkInitIsICE()) { + Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, + Notes.size() + 1) << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + Info.addNotes(Notes); + } + + Result = *VD->getEvaluatedValue(); + return true; +} + +static bool IsConstNonVolatile(QualType T) { + Qualifiers Quals = T.getQualifiers(); + return Quals.hasConst() && !Quals.hasVolatile(); +} + +/// Get the base index of the given base class within an APValue representing +/// the given derived class. +static unsigned getBaseIndex(const CXXRecordDecl *Derived, + const CXXRecordDecl *Base) { + Base = Base->getCanonicalDecl(); + unsigned Index = 0; + for (CXXRecordDecl::base_class_const_iterator I = Derived->bases_begin(), + E = Derived->bases_end(); I != E; ++I, ++Index) { + if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == Base) + return Index; + } + + llvm_unreachable("base class missing from derived class's bases list"); +} + +/// Extract the value of a character from a string literal. +static APSInt ExtractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, + uint64_t Index) { + // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant + const StringLiteral *S = dyn_cast<StringLiteral>(Lit); + assert(S && "unexpected string literal expression kind"); + + APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), + Lit->getType()->getArrayElementTypeNoTypeQual()->isUnsignedIntegerType()); + if (Index < S->getLength()) + Value = S->getCodeUnit(Index); + return Value; +} + +/// Extract the designated sub-object of an rvalue. +static bool ExtractSubobject(EvalInfo &Info, const Expr *E, + APValue &Obj, QualType ObjType, + const SubobjectDesignator &Sub, QualType SubType) { + if (Sub.Invalid) + // A diagnostic will have already been produced. + return false; + if (Sub.isOnePastTheEnd()) { + Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + (unsigned)diag::note_constexpr_read_past_end : + (unsigned)diag::note_invalid_subexpr_in_const_expr); + return false; + } + if (Sub.Entries.empty()) + return true; + if (Info.CheckingPotentialConstantExpression && Obj.isUninit()) + // This object might be initialized later. + return false; + + APValue *O = &Obj; + // Walk the designator's path to find the subobject. + for (unsigned I = 0, N = Sub.Entries.size(); I != N; ++I) { + if (ObjType->isArrayType()) { + // Next subobject is an array element. + const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); + assert(CAT && "vla in literal type?"); + uint64_t Index = Sub.Entries[I].ArrayIndex; + if (CAT->getSize().ule(Index)) { + // Note, it should not be possible to form a pointer with a valid + // designator which points more than one past the end of the array. + Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + (unsigned)diag::note_constexpr_read_past_end : + (unsigned)diag::note_invalid_subexpr_in_const_expr); + return false; + } + // 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()); + Obj = APValue(ExtractStringLiteralCharacter( + Info, O->getLValueBase().get<const Expr*>(), Index)); + return true; + } else if (O->getArrayInitializedElts() > Index) + O = &O->getArrayInitializedElt(Index); + else + O = &O->getArrayFiller(); + ObjType = CAT->getElementType(); + } else if (ObjType->isAnyComplexType()) { + // Next subobject is a complex number. + uint64_t Index = Sub.Entries[I].ArrayIndex; + if (Index > 1) { + Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? + (unsigned)diag::note_constexpr_read_past_end : + (unsigned)diag::note_invalid_subexpr_in_const_expr); + return false; + } + assert(I == N - 1 && "extracting subobject of scalar?"); + if (O->isComplexInt()) { + Obj = APValue(Index ? O->getComplexIntImag() + : O->getComplexIntReal()); + } else { + assert(O->isComplexFloat()); + Obj = APValue(Index ? O->getComplexFloatImag() + : O->getComplexFloatReal()); + } + return true; + } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { + if (Field->isMutable()) { + Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) + << Field; + Info.Note(Field->getLocation(), diag::note_declared_at); + return false; + } + + // Next subobject is a class, struct or union field. + RecordDecl *RD = ObjType->castAs<RecordType>()->getDecl(); + if (RD->isUnion()) { + const FieldDecl *UnionField = O->getUnionField(); + if (!UnionField || + UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { + Info.Diag(E, diag::note_constexpr_read_inactive_union_member) + << Field << !UnionField << UnionField; + return false; + } + O = &O->getUnionValue(); + } else + O = &O->getStructField(Field->getFieldIndex()); + ObjType = Field->getType(); + + if (ObjType.isVolatileQualified()) { + if (Info.getLangOpts().CPlusPlus) { + // FIXME: Include a description of the path to the volatile subobject. + Info.Diag(E, diag::note_constexpr_ltor_volatile_obj, 1) + << 2 << Field; + Info.Note(Field->getLocation(), diag::note_declared_at); + } else { + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + } + return false; + } + } else { + // Next subobject is a base class. + const CXXRecordDecl *Derived = ObjType->getAsCXXRecordDecl(); + const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]); + O = &O->getStructBase(getBaseIndex(Derived, Base)); + ObjType = Info.Ctx.getRecordType(Base); + } + + if (O->isUninit()) { + if (!Info.CheckingPotentialConstantExpression) + Info.Diag(E, diag::note_constexpr_read_uninit); + return false; + } + } + + // This may look super-stupid, but it serves an important purpose: if we just + // swapped Obj and *O, we'd create an object which had itself as a subobject. + // To avoid the leak, we ensure that Tmp ends up owning the original complete + // object, which is destroyed by Tmp's destructor. + APValue Tmp; + O->swap(Tmp); + Obj.swap(Tmp); + return true; +} + +/// Find the position where two subobject designators diverge, or equivalently +/// the length of the common initial subsequence. +static unsigned FindDesignatorMismatch(QualType ObjType, + const SubobjectDesignator &A, + const SubobjectDesignator &B, + bool &WasArrayIndex) { + unsigned I = 0, N = std::min(A.Entries.size(), B.Entries.size()); + for (/**/; I != N; ++I) { + if (!ObjType.isNull() && + (ObjType->isArrayType() || ObjType->isAnyComplexType())) { + // Next subobject is an array element. + if (A.Entries[I].ArrayIndex != B.Entries[I].ArrayIndex) { + WasArrayIndex = true; + return I; + } + if (ObjType->isAnyComplexType()) + ObjType = ObjType->castAs<ComplexType>()->getElementType(); + else + ObjType = ObjType->castAsArrayTypeUnsafe()->getElementType(); + } else { + if (A.Entries[I].BaseOrMember != B.Entries[I].BaseOrMember) { + WasArrayIndex = false; + return I; + } + if (const FieldDecl *FD = getAsField(A.Entries[I])) + // Next subobject is a field. + ObjType = FD->getType(); + else + // Next subobject is a base class. + ObjType = QualType(); + } + } + WasArrayIndex = false; + return I; +} + +/// Determine whether the given subobject designators refer to elements of the +/// same array object. +static bool AreElementsOfSameArray(QualType ObjType, + const SubobjectDesignator &A, + const SubobjectDesignator &B) { + if (A.Entries.size() != B.Entries.size()) + return false; + + bool IsArray = A.MostDerivedArraySize != 0; + if (IsArray && A.MostDerivedPathLength != A.Entries.size()) + // A is a subobject of the array element. + return false; + + // If A (and B) designates an array element, the last entry will be the array + // index. That doesn't have to match. Otherwise, we're in the 'implicit array + // of length 1' case, and the entire path must match. + bool WasArrayIndex; + unsigned CommonLength = FindDesignatorMismatch(ObjType, A, B, WasArrayIndex); + return CommonLength >= A.Entries.size() - IsArray; +} + +/// HandleLValueToRValueConversion - Perform an lvalue-to-rvalue conversion on +/// the given lvalue. This can also be used for 'lvalue-to-lvalue' conversions +/// for looking up the glvalue referred to by an entity of reference type. +/// +/// \param Info - Information about the ongoing evaluation. +/// \param Conv - The expression for which we are performing the conversion. +/// Used for diagnostics. +/// \param Type - The type we expect this conversion to produce, before +/// stripping cv-qualifiers in the case of a non-clas type. +/// \param LVal - The glvalue on which we are attempting to perform this action. +/// \param RVal - The produced value will be placed here. +static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, + QualType Type, + const LValue &LVal, APValue &RVal) { + if (LVal.Designator.Invalid) + // A diagnostic will have already been produced. + return false; + + const Expr *Base = LVal.Base.dyn_cast<const Expr*>(); + + if (!LVal.Base) { + // FIXME: Indirection through a null pointer deserves a specific diagnostic. + Info.Diag(Conv, diag::note_invalid_subexpr_in_const_expr); + return false; + } + + CallStackFrame *Frame = 0; + if (LVal.CallIndex) { + Frame = Info.getCallFrame(LVal.CallIndex); + if (!Frame) { + Info.Diag(Conv, diag::note_constexpr_lifetime_ended, 1) << !Base; + NoteLValueLocation(Info, LVal.Base); + return false; + } + } + + // C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type + // is not a constant expression (even if the object is non-volatile). We also + // apply this rule to C++98, in order to conform to the expected 'volatile' + // semantics. + if (Type.isVolatileQualified()) { + if (Info.getLangOpts().CPlusPlus) + Info.Diag(Conv, diag::note_constexpr_ltor_volatile_type) << Type; + else + Info.Diag(Conv); + return false; + } + + if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) { + // In C++98, const, non-volatile integers initialized with ICEs are ICEs. + // In C++11, constexpr, non-volatile variables initialized with constant + // expressions are constant expressions too. Inside constexpr functions, + // parameters are constant expressions even if they're non-const. + // In C, such things can also be folded, although they are not ICEs. + const VarDecl *VD = dyn_cast<VarDecl>(D); + if (VD) { + if (const VarDecl *VDef = VD->getDefinition(Info.Ctx)) + VD = VDef; + } + if (!VD || VD->isInvalidDecl()) { + Info.Diag(Conv); + return false; + } + + // DR1313: If the object is volatile-qualified but the glvalue was not, + // behavior is undefined so the result is not a constant expression. + QualType VT = VD->getType(); + if (VT.isVolatileQualified()) { + if (Info.getLangOpts().CPlusPlus) { + Info.Diag(Conv, diag::note_constexpr_ltor_volatile_obj, 1) << 1 << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + } else { + Info.Diag(Conv); + } + return false; + } + + if (!isa<ParmVarDecl>(VD)) { + if (VD->isConstexpr()) { + // OK, we can read this variable. + } else if (VT->isIntegralOrEnumerationType()) { + if (!VT.isConstQualified()) { + if (Info.getLangOpts().CPlusPlus) { + Info.Diag(Conv, diag::note_constexpr_ltor_non_const_int, 1) << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + } else { + Info.Diag(Conv); + } + return false; + } + } else if (VT->isFloatingType() && VT.isConstQualified()) { + // We support folding of const floating-point types, in order to make + // static const data members of such types (supported as an extension) + // more useful. + if (Info.getLangOpts().CPlusPlus0x) { + Info.CCEDiag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + } else { + Info.CCEDiag(Conv); + } + } else { + // FIXME: Allow folding of values of any literal type in all languages. + if (Info.getLangOpts().CPlusPlus0x) { + Info.Diag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + } else { + Info.Diag(Conv); + } + return false; + } + } + + if (!EvaluateVarDeclInit(Info, Conv, VD, Frame, RVal)) + return false; + + if (isa<ParmVarDecl>(VD) || !VD->getAnyInitializer()->isLValue()) + return ExtractSubobject(Info, Conv, RVal, VT, LVal.Designator, Type); + + // The declaration was initialized by an lvalue, with no lvalue-to-rvalue + // conversion. This happens when the declaration and the lvalue should be + // considered synonymous, for instance when initializing an array of char + // from a string literal. Continue as if the initializer lvalue was the + // value we were originally given. + assert(RVal.getLValueOffset().isZero() && + "offset for lvalue init of non-reference"); + Base = RVal.getLValueBase().get<const Expr*>(); + + if (unsigned CallIndex = RVal.getLValueCallIndex()) { + Frame = Info.getCallFrame(CallIndex); + if (!Frame) { + Info.Diag(Conv, diag::note_constexpr_lifetime_ended, 1) << !Base; + NoteLValueLocation(Info, RVal.getLValueBase()); + return false; + } + } else { + Frame = 0; + } + } + + // Volatile temporary objects cannot be read in constant expressions. + if (Base->getType().isVolatileQualified()) { + if (Info.getLangOpts().CPlusPlus) { + Info.Diag(Conv, diag::note_constexpr_ltor_volatile_obj, 1) << 0; + Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here); + } else { + Info.Diag(Conv); + } + return false; + } + + if (Frame) { + // If this is a temporary expression with a nontrivial initializer, grab the + // value from the relevant stack frame. + RVal = Frame->Temporaries[Base]; + } else if (const CompoundLiteralExpr *CLE + = dyn_cast<CompoundLiteralExpr>(Base)) { + // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the + // initializer until now for such expressions. Such an expression can't be + // an ICE in C, so this only matters for fold. + assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); + if (!Evaluate(RVal, Info, CLE->getInitializer())) + return false; + } else if (isa<StringLiteral>(Base)) { + // We represent a string literal array as an lvalue pointing at the + // corresponding expression, rather than building an array of chars. + // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant + RVal = APValue(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); + } else { + Info.Diag(Conv, diag::note_invalid_subexpr_in_const_expr); + return false; + } + + return ExtractSubobject(Info, Conv, RVal, Base->getType(), LVal.Designator, + Type); +} + +/// Build an lvalue for the object argument of a member function call. +static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, + LValue &This) { + if (Object->getType()->isPointerType()) + return EvaluatePointer(Object, This, Info); + + if (Object->isGLValue()) + return EvaluateLValue(Object, This, Info); + + if (Object->getType()->isLiteralType()) + return EvaluateTemporary(Object, This, Info); + + return false; +} + +/// HandleMemberPointerAccess - Evaluate a member access operation and build an +/// lvalue referring to the result. +/// +/// \param Info - Information about the ongoing evaluation. +/// \param BO - The member pointer access operation. +/// \param LV - Filled in with a reference to the resulting object. +/// \param IncludeMember - Specifies whether the member itself is included in +/// the resulting LValue subobject designator. This is not possible when +/// creating a bound member function. +/// \return The field or method declaration to which the member pointer refers, +/// or 0 if evaluation fails. +static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, + const BinaryOperator *BO, + LValue &LV, + bool IncludeMember = true) { + assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); + + bool EvalObjOK = EvaluateObjectArgument(Info, BO->getLHS(), LV); + if (!EvalObjOK && !Info.keepEvaluatingAfterFailure()) + return 0; + + MemberPtr MemPtr; + if (!EvaluateMemberPointer(BO->getRHS(), MemPtr, Info)) + return 0; + + // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to + // member value, the behavior is undefined. + if (!MemPtr.getDecl()) + return 0; + + if (!EvalObjOK) + return 0; + + if (MemPtr.isDerivedMember()) { + // This is a member of some derived class. Truncate LV appropriately. + // The end of the derived-to-base path for the base object must match the + // derived-to-base path for the member pointer. + if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > + LV.Designator.Entries.size()) + return 0; + unsigned PathLengthToMember = + LV.Designator.Entries.size() - MemPtr.Path.size(); + for (unsigned I = 0, N = MemPtr.Path.size(); I != N; ++I) { + const CXXRecordDecl *LVDecl = getAsBaseClass( + LV.Designator.Entries[PathLengthToMember + I]); + const CXXRecordDecl *MPDecl = MemPtr.Path[I]; + if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) + return 0; + } + + // Truncate the lvalue to the appropriate derived class. + if (!CastToDerivedClass(Info, BO, LV, MemPtr.getContainingRecord(), + PathLengthToMember)) + return 0; + } else if (!MemPtr.Path.empty()) { + // Extend the LValue path with the member pointer's path. + LV.Designator.Entries.reserve(LV.Designator.Entries.size() + + MemPtr.Path.size() + IncludeMember); + + // Walk down to the appropriate base class. + QualType LVType = BO->getLHS()->getType(); + if (const PointerType *PT = LVType->getAs<PointerType>()) + LVType = PT->getPointeeType(); + const CXXRecordDecl *RD = LVType->getAsCXXRecordDecl(); + assert(RD && "member pointer access on non-class-type expression"); + // The first class in the path is that of the lvalue. + for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { + const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; + HandleLValueDirectBase(Info, BO, LV, RD, Base); + RD = Base; + } + // Finally cast to the class containing the member. + HandleLValueDirectBase(Info, BO, LV, RD, MemPtr.getContainingRecord()); + } + + // Add the member. Note that we cannot build bound member functions here. + if (IncludeMember) { + if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl())) + HandleLValueMember(Info, BO, LV, FD); + else if (const IndirectFieldDecl *IFD = + dyn_cast<IndirectFieldDecl>(MemPtr.getDecl())) + HandleLValueIndirectMember(Info, BO, LV, IFD); + else + llvm_unreachable("can't construct reference to bound member function"); + } + + return MemPtr.getDecl(); +} + +/// HandleBaseToDerivedCast - Apply the given base-to-derived cast operation on +/// the provided lvalue, which currently refers to the base object. +static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, + LValue &Result) { + SubobjectDesignator &D = Result.Designator; + if (D.Invalid || !Result.checkNullPointer(Info, E, CSK_Derived)) + return false; + + QualType TargetQT = E->getType(); + if (const PointerType *PT = TargetQT->getAs<PointerType>()) + TargetQT = PT->getPointeeType(); + + // Check this cast lands within the final derived-to-base subobject path. + if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) { + Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) + << D.MostDerivedType << TargetQT; + return false; + } + + // Check the type of the final cast. We don't need to check the path, + // since a cast can only be formed if the path is unique. + unsigned NewEntriesSize = D.Entries.size() - E->path_size(); + const CXXRecordDecl *TargetType = TargetQT->getAsCXXRecordDecl(); + const CXXRecordDecl *FinalType; + if (NewEntriesSize == D.MostDerivedPathLength) + FinalType = D.MostDerivedType->getAsCXXRecordDecl(); + else + FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]); + if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) { + Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) + << D.MostDerivedType << TargetQT; + return false; + } + + // Truncate the lvalue to the appropriate derived class. + return CastToDerivedClass(Info, E, Result, TargetType, NewEntriesSize); +} + +namespace { +enum EvalStmtResult { + /// Evaluation failed. + ESR_Failed, + /// Hit a 'return' statement. + ESR_Returned, + /// Evaluation succeeded. + ESR_Succeeded +}; +} + +// Evaluate a statement. +static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info, + const Stmt *S) { + switch (S->getStmtClass()) { + default: + return ESR_Failed; + + case Stmt::NullStmtClass: + case Stmt::DeclStmtClass: + return ESR_Succeeded; + + case Stmt::ReturnStmtClass: { + const Expr *RetExpr = cast<ReturnStmt>(S)->getRetValue(); + if (!Evaluate(Result, Info, RetExpr)) + return ESR_Failed; + return ESR_Returned; + } + + case Stmt::CompoundStmtClass: { + const CompoundStmt *CS = cast<CompoundStmt>(S); + for (CompoundStmt::const_body_iterator BI = CS->body_begin(), + BE = CS->body_end(); BI != BE; ++BI) { + EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI); + if (ESR != ESR_Succeeded) + return ESR; + } + return ESR_Succeeded; + } + } +} + +/// CheckTrivialDefaultConstructor - Check whether a constructor is a trivial +/// default constructor. If so, we'll fold it whether or not it's marked as +/// constexpr. If it is marked as constexpr, we will never implicitly define it, +/// so we need special handling. +static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, + const CXXConstructorDecl *CD, + bool IsValueInitialization) { + if (!CD->isTrivial() || !CD->isDefaultConstructor()) + return false; + + // Value-initialization does not call a trivial default constructor, so such a + // call is a core constant expression whether or not the constructor is + // constexpr. + if (!CD->isConstexpr() && !IsValueInitialization) { + if (Info.getLangOpts().CPlusPlus0x) { + // FIXME: If DiagDecl is an implicitly-declared special member function, + // we should be much more explicit about why it's not constexpr. + Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) + << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD; + Info.Note(CD->getLocation(), diag::note_declared_at); + } else { + Info.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); + } + } + return true; +} + +/// CheckConstexprFunction - Check that a function can be called in a constant +/// expression. +static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, + const FunctionDecl *Declaration, + const FunctionDecl *Definition) { + // Potential constant expressions can contain calls to declared, but not yet + // defined, constexpr functions. + if (Info.CheckingPotentialConstantExpression && !Definition && + Declaration->isConstexpr()) + return false; + + // Can we evaluate this function call? + if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl()) + return true; + + if (Info.getLangOpts().CPlusPlus0x) { + const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; + // FIXME: If DiagDecl is an implicitly-declared special member function, we + // should be much more explicit about why it's not constexpr. + Info.Diag(CallLoc, diag::note_constexpr_invalid_function, 1) + << DiagDecl->isConstexpr() << isa<CXXConstructorDecl>(DiagDecl) + << DiagDecl; + Info.Note(DiagDecl->getLocation(), diag::note_declared_at); + } else { + Info.Diag(CallLoc, diag::note_invalid_subexpr_in_const_expr); + } + return false; +} + +namespace { +typedef SmallVector<APValue, 8> ArgVector; +} + +/// EvaluateArgs - Evaluate the arguments to a function call. +static bool EvaluateArgs(ArrayRef<const Expr*> Args, ArgVector &ArgValues, + EvalInfo &Info) { + bool Success = true; + for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { + if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) { + // If we're checking for a potential constant expression, evaluate all + // initializers even if some of them fail. + if (!Info.keepEvaluatingAfterFailure()) + return false; + Success = false; + } + } + return Success; +} + +/// Evaluate a function call. +static bool HandleFunctionCall(SourceLocation CallLoc, + const FunctionDecl *Callee, const LValue *This, + ArrayRef<const Expr*> Args, const Stmt *Body, + EvalInfo &Info, APValue &Result) { + ArgVector ArgValues(Args.size()); + if (!EvaluateArgs(Args, ArgValues, Info)) + return false; + + if (!Info.CheckCallLimit(CallLoc)) + return false; + + CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); + return EvaluateStmt(Result, Info, Body) == ESR_Returned; +} + +/// Evaluate a constructor call. +static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, + ArrayRef<const Expr*> Args, + const CXXConstructorDecl *Definition, + EvalInfo &Info, APValue &Result) { + ArgVector ArgValues(Args.size()); + if (!EvaluateArgs(Args, ArgValues, Info)) + return false; + + if (!Info.CheckCallLimit(CallLoc)) + return false; + + const CXXRecordDecl *RD = Definition->getParent(); + if (RD->getNumVBases()) { + Info.Diag(CallLoc, diag::note_constexpr_virtual_base) << RD; + return false; + } + + CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues.data()); + + // If it's a delegating constructor, just delegate. + if (Definition->isDelegatingConstructor()) { + CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); + return EvaluateInPlace(Result, Info, This, (*I)->getInit()); + } + + // For a trivial copy or move constructor, perform an APValue copy. This is + // essential for unions, where the operations performed by the constructor + // cannot be represented by ctor-initializers. + if (Definition->isDefaulted() && + ((Definition->isCopyConstructor() && Definition->isTrivial()) || + (Definition->isMoveConstructor() && Definition->isTrivial()))) { + LValue RHS; + RHS.setFrom(Info.Ctx, ArgValues[0]); + return HandleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), + RHS, Result); + } + + // Reserve space for the struct members. + if (!RD->isUnion() && Result.isUninit()) + Result = APValue(APValue::UninitStruct(), RD->getNumBases(), + std::distance(RD->field_begin(), RD->field_end())); + + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); + + bool Success = true; + unsigned BasesSeen = 0; +#ifndef NDEBUG + CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin(); +#endif + for (CXXConstructorDecl::init_const_iterator I = Definition->init_begin(), + E = Definition->init_end(); I != E; ++I) { + LValue Subobject = This; + APValue *Value = &Result; + + // Determine the subobject to initialize. + if ((*I)->isBaseInitializer()) { + QualType BaseType((*I)->getBaseClass(), 0); +#ifndef NDEBUG + // Non-virtual base classes are initialized in the order in the class + // definition. We have already checked for virtual base classes. + assert(!BaseIt->isVirtual() && "virtual base for literal type"); + assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && + "base class initializers not in expected order"); + ++BaseIt; +#endif + HandleLValueDirectBase(Info, (*I)->getInit(), Subobject, RD, + BaseType->getAsCXXRecordDecl(), &Layout); + Value = &Result.getStructBase(BasesSeen++); + } else if (FieldDecl *FD = (*I)->getMember()) { + HandleLValueMember(Info, (*I)->getInit(), Subobject, FD, &Layout); + if (RD->isUnion()) { + Result = APValue(FD); + Value = &Result.getUnionValue(); + } else { + Value = &Result.getStructField(FD->getFieldIndex()); + } + } else if (IndirectFieldDecl *IFD = (*I)->getIndirectMember()) { + // Walk the indirect field decl's chain to find the object to initialize, + // and make sure we've initialized every step along it. + for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(), + CE = IFD->chain_end(); + C != CE; ++C) { + FieldDecl *FD = cast<FieldDecl>(*C); + CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent()); + // Switch the union field if it differs. This happens if we had + // preceding zero-initialization, and we're now initializing a union + // subobject other than the first. + // FIXME: In this case, the values of the other subobjects are + // specified, since zero-initialization sets all padding bits to zero. + if (Value->isUninit() || + (Value->isUnion() && Value->getUnionField() != FD)) { + if (CD->isUnion()) + *Value = APValue(FD); + else + *Value = APValue(APValue::UninitStruct(), CD->getNumBases(), + std::distance(CD->field_begin(), CD->field_end())); + } + HandleLValueMember(Info, (*I)->getInit(), Subobject, FD); + if (CD->isUnion()) + Value = &Value->getUnionValue(); + else + Value = &Value->getStructField(FD->getFieldIndex()); + } + } else { + llvm_unreachable("unknown base initializer kind"); + } + + if (!EvaluateInPlace(*Value, Info, Subobject, (*I)->getInit(), + (*I)->isBaseInitializer() + ? CCEK_Constant : CCEK_MemberInit)) { + // If we're checking for a potential constant expression, evaluate all + // initializers even if some of them fail. + if (!Info.keepEvaluatingAfterFailure()) + return false; + Success = false; + } + } + + return Success; } namespace { class HasSideEffect : public ConstStmtVisitor<HasSideEffect, bool> { - EvalInfo &Info; + const ASTContext &Ctx; public: - HasSideEffect(EvalInfo &info) : Info(info) {} + HasSideEffect(const ASTContext &C) : Ctx(C) {} // Unhandled nodes conservatively default to having side effects. bool VisitStmt(const Stmt *S) { @@ -279,17 +2281,12 @@ public: return Visit(E->getResultExpr()); } bool VisitDeclRefExpr(const DeclRefExpr *E) { - if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) + if (Ctx.getCanonicalType(E->getType()).isVolatileQualified()) return true; return false; } bool VisitObjCIvarRefExpr(const ObjCIvarRefExpr *E) { - if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) - return true; - return false; - } - bool VisitBlockDeclRefExpr (const BlockDeclRefExpr *E) { - if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) + if (Ctx.getCanonicalType(E->getType()).isVolatileQualified()) return true; return false; } @@ -310,7 +2307,7 @@ public: bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { return Visit(E->getLHS()) || Visit(E->getRHS()); } bool VisitChooseExpr(const ChooseExpr *E) - { return Visit(E->getChosenSubExpr(Info.Ctx)); } + { return Visit(E->getChosenSubExpr(Ctx)); } bool VisitCastExpr(const CastExpr *E) { return Visit(E->getSubExpr()); } bool VisitBinAssign(const BinaryOperator *E) { return true; } bool VisitCompoundAssignOperator(const BinaryOperator *E) { return true; } @@ -321,7 +2318,7 @@ public: bool VisitUnaryPreDec(const UnaryOperator *E) { return true; } bool VisitUnaryPostDec(const UnaryOperator *E) { return true; } bool VisitUnaryDeref(const UnaryOperator *E) { - if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified()) + if (Ctx.getCanonicalType(E->getType()).isVolatileQualified()) return true; return Visit(E->getSubExpr()); } @@ -349,16 +2346,18 @@ public: : info(info), opaqueValue(opaqueValue) { // If evaluation fails, fail immediately. - if (!Evaluate(info, value)) { + if (!Evaluate(info.OpaqueValues[opaqueValue], info, value)) { this->opaqueValue = 0; return; } - info.OpaqueValues[opaqueValue] = info.EvalResult.Val; } bool hasError() const { return opaqueValue == 0; } ~OpaqueValueEvaluation() { + // FIXME: For a recursive constexpr call, an outer stack frame might have + // been using this opaque value too, and will now have to re-evaluate the + // source expression. if (opaqueValue) info.OpaqueValues.erase(opaqueValue); } }; @@ -370,18 +2369,55 @@ public: //===----------------------------------------------------------------------===// namespace { -template <class Derived, typename RetTy=void> +// FIXME: RetTy is always bool. Remove it. +template <class Derived, typename RetTy=bool> class ExprEvaluatorBase : public ConstStmtVisitor<Derived, RetTy> { private: RetTy DerivedSuccess(const APValue &V, const Expr *E) { return static_cast<Derived*>(this)->Success(V, E); } - RetTy DerivedError(const Expr *E) { - return static_cast<Derived*>(this)->Error(E); + RetTy DerivedZeroInitialization(const Expr *E) { + return static_cast<Derived*>(this)->ZeroInitialization(E); } - RetTy DerivedValueInitialization(const Expr *E) { - return static_cast<Derived*>(this)->ValueInitialization(E); + + // Check whether a conditional operator with a non-constant condition is a + // potential constant expression. If neither arm is a potential constant + // expression, then the conditional operator is not either. + template<typename ConditionalOperator> + void CheckPotentialConstantConditional(const ConditionalOperator *E) { + assert(Info.CheckingPotentialConstantExpression); + + // Speculatively evaluate both arms. + { + llvm::SmallVector<PartialDiagnosticAt, 8> Diag; + SpeculativeEvaluationRAII Speculate(Info, &Diag); + + StmtVisitorTy::Visit(E->getFalseExpr()); + if (Diag.empty()) + return; + + Diag.clear(); + StmtVisitorTy::Visit(E->getTrueExpr()); + if (Diag.empty()) + return; + } + + Error(E, diag::note_constexpr_conditional_never_const); + } + + + template<typename ConditionalOperator> + bool HandleConditionalOperator(const ConditionalOperator *E) { + bool BoolResult; + if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { + if (Info.CheckingPotentialConstantExpression) + CheckPotentialConstantConditional(E); + return false; + } + + Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); + return StmtVisitorTy::Visit(EvalExpr); } protected: @@ -389,16 +2425,32 @@ protected: typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; - RetTy ValueInitialization(const Expr *E) { return DerivedError(E); } + OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { + return Info.CCEDiag(E, D); + } + + RetTy ZeroInitialization(const Expr *E) { return Error(E); } public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} + EvalInfo &getEvalInfo() { return Info; } + + /// Report an evaluation error. This should only be called when an error is + /// first discovered. When propagating an error, just return false. + bool Error(const Expr *E, diag::kind D) { + Info.Diag(E, D); + return false; + } + bool Error(const Expr *E) { + return Error(E, diag::note_invalid_subexpr_in_const_expr); + } + RetTy VisitStmt(const Stmt *) { llvm_unreachable("Expression evaluator should not be called on stmts"); } RetTy VisitExpr(const Expr *E) { - return DerivedError(E); + return Error(E); } RetTy VisitParenExpr(const ParenExpr *E) @@ -413,186 +2465,573 @@ public: { return StmtVisitorTy::Visit(E->getResultExpr()); } RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { return StmtVisitorTy::Visit(E->getReplacement()); } + RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) + { return StmtVisitorTy::Visit(E->getExpr()); } + // We cannot create any objects for which cleanups are required, so there is + // nothing to do here; all cleanups must come from unevaluated subexpressions. + RetTy VisitExprWithCleanups(const ExprWithCleanups *E) + { return StmtVisitorTy::Visit(E->getSubExpr()); } + + RetTy VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { + CCEDiag(E, diag::note_constexpr_invalid_cast) << 0; + return static_cast<Derived*>(this)->VisitCastExpr(E); + } + RetTy VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { + CCEDiag(E, diag::note_constexpr_invalid_cast) << 1; + return static_cast<Derived*>(this)->VisitCastExpr(E); + } + + RetTy VisitBinaryOperator(const BinaryOperator *E) { + switch (E->getOpcode()) { + default: + return Error(E); + + case BO_Comma: + VisitIgnoredValue(E->getLHS()); + return StmtVisitorTy::Visit(E->getRHS()); + + case BO_PtrMemD: + case BO_PtrMemI: { + LValue Obj; + if (!HandleMemberPointerAccess(Info, E, Obj)) + return false; + APValue Result; + if (!HandleLValueToRValueConversion(Info, E, E->getType(), Obj, Result)) + return false; + return DerivedSuccess(Result, E); + } + } + } RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { + // Cache the value of the common expression. OpaqueValueEvaluation opaque(Info, E->getOpaqueValue(), E->getCommon()); if (opaque.hasError()) - return DerivedError(E); - - bool cond; - if (!HandleConversionToBool(E->getCond(), cond, Info)) - return DerivedError(E); + return false; - return StmtVisitorTy::Visit(cond ? E->getTrueExpr() : E->getFalseExpr()); + return HandleConditionalOperator(E); } RetTy VisitConditionalOperator(const ConditionalOperator *E) { - bool BoolResult; - if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) - return DerivedError(E); + bool IsBcpCall = false; + // If the condition (ignoring parens) is a __builtin_constant_p call, + // the result is a constant expression if it can be folded without + // side-effects. This is an important GNU extension. See GCC PR38377 + // for discussion. + if (const CallExpr *CallCE = + dyn_cast<CallExpr>(E->getCond()->IgnoreParenCasts())) + if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) + IsBcpCall = true; + + // Always assume __builtin_constant_p(...) ? ... : ... is a potential + // constant expression; we can't check whether it's potentially foldable. + if (Info.CheckingPotentialConstantExpression && IsBcpCall) + return false; - Expr* EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); - return StmtVisitorTy::Visit(EvalExpr); + FoldConstant Fold(Info); + + if (!HandleConditionalOperator(E)) + return false; + + if (IsBcpCall) + Fold.Fold(Info); + + return true; } RetTy VisitOpaqueValueExpr(const OpaqueValueExpr *E) { - const APValue *value = Info.getOpaqueValue(E); - if (!value) - return (E->getSourceExpr() ? StmtVisitorTy::Visit(E->getSourceExpr()) - : DerivedError(E)); - return DerivedSuccess(*value, E); + const APValue *Value = Info.getOpaqueValue(E); + if (!Value) { + const Expr *Source = E->getSourceExpr(); + if (!Source) + return Error(E); + if (Source == E) { // sanity checking. + assert(0 && "OpaqueValueExpr recursively refers to itself"); + return Error(E); + } + return StmtVisitorTy::Visit(Source); + } + return DerivedSuccess(*Value, E); } + RetTy VisitCallExpr(const CallExpr *E) { + const Expr *Callee = E->getCallee()->IgnoreParens(); + QualType CalleeType = Callee->getType(); + + const FunctionDecl *FD = 0; + LValue *This = 0, ThisVal; + llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + bool HasQualifier = false; + + // Extract function decl and 'this' pointer from the callee. + if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { + const ValueDecl *Member = 0; + if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) { + // Explicit bound member calls, such as x.f() or p->g(); + if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal)) + return false; + Member = ME->getMemberDecl(); + This = &ThisVal; + HasQualifier = ME->hasQualifier(); + } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) { + // Indirect bound member calls ('.*' or '->*'). + Member = HandleMemberPointerAccess(Info, BE, ThisVal, false); + if (!Member) return false; + This = &ThisVal; + } else + return Error(Callee); + + FD = dyn_cast<FunctionDecl>(Member); + if (!FD) + return Error(Callee); + } else if (CalleeType->isFunctionPointerType()) { + LValue Call; + if (!EvaluatePointer(Callee, Call, Info)) + return false; + + if (!Call.getLValueOffset().isZero()) + return Error(Callee); + FD = dyn_cast_or_null<FunctionDecl>( + Call.getLValueBase().dyn_cast<const ValueDecl*>()); + if (!FD) + return Error(Callee); + + // Overloaded operator calls to member functions are represented as normal + // calls with '*this' as the first argument. + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + if (MD && !MD->isStatic()) { + // FIXME: When selecting an implicit conversion for an overloaded + // operator delete, we sometimes try to evaluate calls to conversion + // operators without a 'this' parameter! + if (Args.empty()) + return Error(E); + + if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) + return false; + This = &ThisVal; + Args = Args.slice(1); + } + + // Don't call function pointers which have been cast to some other type. + if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType())) + return Error(E); + } else + return Error(E); + + if (This && !This->checkSubobject(Info, E, CSK_This)) + return false; + + // DR1358 allows virtual constexpr functions in some cases. Don't allow + // calls to such functions in constant expressions. + if (This && !HasQualifier && + isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual()) + return Error(E, diag::note_constexpr_virtual_call); + + const FunctionDecl *Definition = 0; + Stmt *Body = FD->getBody(Definition); + APValue Result; + + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) || + !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, + Info, Result)) + return false; + + return DerivedSuccess(Result, E); + } + + RetTy VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { + return StmtVisitorTy::Visit(E->getInitializer()); + } RetTy VisitInitListExpr(const InitListExpr *E) { - if (Info.getLangOpts().CPlusPlus0x) { - if (E->getNumInits() == 0) - return DerivedValueInitialization(E); - if (E->getNumInits() == 1) - return StmtVisitorTy::Visit(E->getInit(0)); - } - return DerivedError(E); + if (E->getNumInits() == 0) + return DerivedZeroInitialization(E); + if (E->getNumInits() == 1) + return StmtVisitorTy::Visit(E->getInit(0)); + return Error(E); } RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { - return DerivedValueInitialization(E); + return DerivedZeroInitialization(E); } RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { - return DerivedValueInitialization(E); + return DerivedZeroInitialization(E); + } + RetTy VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { + return DerivedZeroInitialization(E); + } + + /// A member expression where the object is a prvalue is itself a prvalue. + RetTy VisitMemberExpr(const MemberExpr *E) { + assert(!E->isArrow() && "missing call to bound member function?"); + + APValue Val; + if (!Evaluate(Val, Info, E->getBase())) + return false; + + QualType BaseTy = E->getBase()->getType(); + + const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); + if (!FD) return Error(E); + assert(!FD->getType()->isReferenceType() && "prvalue reference?"); + assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() == + FD->getParent()->getCanonicalDecl() && "record / field mismatch"); + + SubobjectDesignator Designator(BaseTy); + Designator.addDeclUnchecked(FD); + + return ExtractSubobject(Info, E, Val, BaseTy, Designator, E->getType()) && + DerivedSuccess(Val, E); + } + + RetTy VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + break; + + case CK_AtomicToNonAtomic: + case CK_NonAtomicToAtomic: + case CK_NoOp: + case CK_UserDefinedConversion: + return StmtVisitorTy::Visit(E->getSubExpr()); + + case CK_LValueToRValue: { + LValue LVal; + if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) + return false; + APValue RVal; + // Note, we use the subexpression's type in order to retain cv-qualifiers. + if (!HandleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), + LVal, RVal)) + return false; + return DerivedSuccess(RVal, E); + } + } + + return Error(E); } + /// Visit a value which is evaluated, but whose value is ignored. + void VisitIgnoredValue(const Expr *E) { + APValue Scratch; + if (!Evaluate(Scratch, Info, E)) + Info.EvalStatus.HasSideEffects = true; + } }; } //===----------------------------------------------------------------------===// -// LValue Evaluation +// Common base class for lvalue and temporary evaluation. //===----------------------------------------------------------------------===// namespace { -class LValueExprEvaluator - : public ExprEvaluatorBase<LValueExprEvaluator, bool> { +template<class Derived> +class LValueExprEvaluatorBase + : public ExprEvaluatorBase<Derived, bool> { +protected: LValue &Result; - const Decl *PrevDecl; + typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; + typedef ExprEvaluatorBase<Derived, bool> ExprEvaluatorBaseTy; - bool Success(const Expr *E) { - Result.Base = E; - Result.Offset = CharUnits::Zero(); + bool Success(APValue::LValueBase B) { + Result.set(B); return true; } -public: - LValueExprEvaluator(EvalInfo &info, LValue &Result) : - ExprEvaluatorBaseTy(info), Result(Result), PrevDecl(0) {} +public: + LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result) : + ExprEvaluatorBaseTy(Info), Result(Result) {} bool Success(const APValue &V, const Expr *E) { - Result.setFrom(V); + Result.setFrom(this->Info.Ctx, V); return true; } - bool Error(const Expr *E) { - return false; + + bool VisitMemberExpr(const MemberExpr *E) { + // Handle non-static data members. + QualType BaseTy; + if (E->isArrow()) { + if (!EvaluatePointer(E->getBase(), Result, this->Info)) + return false; + BaseTy = E->getBase()->getType()->getAs<PointerType>()->getPointeeType(); + } else if (E->getBase()->isRValue()) { + assert(E->getBase()->getType()->isRecordType()); + if (!EvaluateTemporary(E->getBase(), Result, this->Info)) + return false; + BaseTy = E->getBase()->getType(); + } else { + if (!this->Visit(E->getBase())) + return false; + BaseTy = E->getBase()->getType(); + } + + const ValueDecl *MD = E->getMemberDecl(); + if (const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) { + assert(BaseTy->getAs<RecordType>()->getDecl()->getCanonicalDecl() == + FD->getParent()->getCanonicalDecl() && "record / field mismatch"); + (void)BaseTy; + HandleLValueMember(this->Info, E, Result, FD); + } else if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(MD)) { + HandleLValueIndirectMember(this->Info, E, Result, IFD); + } else + return this->Error(E); + + if (MD->getType()->isReferenceType()) { + APValue RefValue; + if (!HandleLValueToRValueConversion(this->Info, E, MD->getType(), Result, + RefValue)) + return false; + return Success(RefValue, E); + } + return true; } - + + bool VisitBinaryOperator(const BinaryOperator *E) { + switch (E->getOpcode()) { + default: + return ExprEvaluatorBaseTy::VisitBinaryOperator(E); + + case BO_PtrMemD: + case BO_PtrMemI: + return HandleMemberPointerAccess(this->Info, E, Result); + } + } + + bool VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: { + if (!this->Visit(E->getSubExpr())) + return false; + + // Now figure out the necessary offset to add to the base LV to get from + // the derived class to the base class. + QualType Type = E->getSubExpr()->getType(); + + for (CastExpr::path_const_iterator PathI = E->path_begin(), + PathE = E->path_end(); PathI != PathE; ++PathI) { + if (!HandleLValueBase(this->Info, E, Result, Type->getAsCXXRecordDecl(), + *PathI)) + return false; + Type = (*PathI)->getType(); + } + + return true; + } + } + } +}; +} + +//===----------------------------------------------------------------------===// +// LValue Evaluation +// +// This is used for evaluating lvalues (in C and C++), xvalues (in C++11), +// function designators (in C), decl references to void objects (in C), and +// temporaries (if building with -Wno-address-of-temporary). +// +// LValue evaluation produces values comprising a base expression of one of the +// following types: +// - Declarations +// * VarDecl +// * FunctionDecl +// - Literals +// * CompoundLiteralExpr in C +// * StringLiteral +// * CXXTypeidExpr +// * PredefinedExpr +// * ObjCStringLiteralExpr +// * ObjCEncodeExpr +// * AddrLabelExpr +// * BlockExpr +// * CallExpr for a MakeStringConstant builtin +// - Locals and temporaries +// * Any Expr, with a CallIndex indicating the function in which the temporary +// was evaluated. +// plus an offset in bytes. +//===----------------------------------------------------------------------===// +namespace { +class LValueExprEvaluator + : public LValueExprEvaluatorBase<LValueExprEvaluator> { +public: + LValueExprEvaluator(EvalInfo &Info, LValue &Result) : + LValueExprEvaluatorBaseTy(Info, Result) {} + + bool VisitVarDecl(const Expr *E, const VarDecl *VD); + bool VisitDeclRefExpr(const DeclRefExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); } + bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); bool VisitMemberExpr(const MemberExpr *E); bool VisitStringLiteral(const StringLiteral *E) { return Success(E); } bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); } + bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); bool VisitUnaryDeref(const UnaryOperator *E); + bool VisitUnaryReal(const UnaryOperator *E); + bool VisitUnaryImag(const UnaryOperator *E); bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: - return false; + return LValueExprEvaluatorBaseTy::VisitCastExpr(E); - case CK_NoOp: case CK_LValueBitCast: - return Visit(E->getSubExpr()); + this->CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + if (!Visit(E->getSubExpr())) + return false; + Result.Designator.setInvalid(); + return true; - // FIXME: Support CK_DerivedToBase and friends. + case CK_BaseToDerived: + if (!Visit(E->getSubExpr())) + return false; + return HandleBaseToDerivedCast(Info, E, Result); } } - - // FIXME: Missing: __real__, __imag__ - }; } // end anonymous namespace +/// Evaluate an expression as an lvalue. This can be legitimately called on +/// expressions which are not glvalues, in a few cases: +/// * function designators in C, +/// * "extern void" objects, +/// * temporaries, if building with -Wno-address-of-temporary. static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) { + assert((E->isGLValue() || E->getType()->isFunctionType() || + E->getType()->isVoidType() || isa<CXXTemporaryObjectExpr>(E)) && + "can't evaluate expression as an lvalue"); return LValueExprEvaluator(Info, Result).Visit(E); } bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { - if (isa<FunctionDecl>(E->getDecl())) { - return Success(E); - } else if (const VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) { - if (!VD->getType()->isReferenceType()) - return Success(E); - // Reference parameters can refer to anything even if they have an - // "initializer" in the form of a default argument. - if (!isa<ParmVarDecl>(VD)) { - // FIXME: Check whether VD might be overridden! + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) + return Success(FD); + if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) + return VisitVarDecl(E, VD); + return Error(E); +} - // Check for recursive initializers of references. - if (PrevDecl == VD) - return Error(E); - PrevDecl = VD; - if (const Expr *Init = VD->getAnyInitializer()) - return Visit(Init); +bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { + if (!VD->getType()->isReferenceType()) { + if (isa<ParmVarDecl>(VD)) { + Result.set(VD, Info.CurrentCall->Index); + return true; } + return Success(VD); } - return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); + APValue V; + if (!EvaluateVarDeclInit(Info, E, VD, Info.CurrentCall, V)) + return false; + return Success(V, E); +} + +bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( + const MaterializeTemporaryExpr *E) { + if (E->GetTemporaryExpr()->isRValue()) { + if (E->getType()->isRecordType()) + return EvaluateTemporary(E->GetTemporaryExpr(), Result, Info); + + Result.set(E, Info.CurrentCall->Index); + return EvaluateInPlace(Info.CurrentCall->Temporaries[E], Info, + Result, E->GetTemporaryExpr()); + } + + // Materialization of an lvalue temporary occurs when we need to force a copy + // (for instance, if it's a bitfield). + // FIXME: The AST should contain an lvalue-to-rvalue node for such cases. + if (!Visit(E->GetTemporaryExpr())) + return false; + if (!HandleLValueToRValueConversion(Info, E, E->getType(), Result, + Info.CurrentCall->Temporaries[E])) + return false; + Result.set(E, Info.CurrentCall->Index); + return true; } bool LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { + assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?"); + // Defer visiting the literal until the lvalue-to-rvalue conversion. We can + // only see this when folding in C, so there's no standard to follow here. return Success(E); } -bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { - QualType Ty; - if (E->isArrow()) { - if (!EvaluatePointer(E->getBase(), Result, Info)) - return false; - Ty = E->getBase()->getType()->getAs<PointerType>()->getPointeeType(); - } else { - if (!Visit(E->getBase())) - return false; - Ty = E->getBase()->getType(); +bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { + if (E->isTypeOperand()) + return Success(E); + CXXRecordDecl *RD = E->getExprOperand()->getType()->getAsCXXRecordDecl(); + if (RD && RD->isPolymorphic()) { + Info.Diag(E, diag::note_constexpr_typeid_polymorphic) + << E->getExprOperand()->getType() + << E->getExprOperand()->getSourceRange(); + return false; } + return Success(E); +} - const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); - const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); - - const FieldDecl *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); - if (!FD) // FIXME: deal with other kinds of member expressions - return false; +bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { + // Handle static data members. + if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) { + VisitIgnoredValue(E->getBase()); + return VisitVarDecl(E, VD); + } - if (FD->getType()->isReferenceType()) - return false; + // Handle static member functions. + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) { + if (MD->isStatic()) { + VisitIgnoredValue(E->getBase()); + return Success(MD); + } + } - unsigned i = FD->getFieldIndex(); - Result.Offset += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i)); - return true; + // Handle non-static data members. + return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); } bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { + // FIXME: Deal with vectors as array subscript bases. + if (E->getBase()->getType()->isVectorType()) + return Error(E); + if (!EvaluatePointer(E->getBase(), Result, Info)) return false; APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) return false; + int64_t IndexValue + = Index.isSigned() ? Index.getSExtValue() + : static_cast<int64_t>(Index.getZExtValue()); - CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType()); - Result.Offset += Index.getSExtValue() * ElementSize; - return true; + return HandleLValueArrayAdjustment(Info, E, Result, E->getType(), IndexValue); } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { return EvaluatePointer(E->getSubExpr(), Result, Info); } +bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { + if (!Visit(E->getSubExpr())) + return false; + // __real is a no-op on scalar lvalues. + if (E->getSubExpr()->getType()->isAnyComplexType()) + HandleLValueComplexElement(Info, E, Result, E->getType(), false); + return true; +} + +bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { + assert(E->getSubExpr()->getType()->isAnyComplexType() && + "lvalue __imag__ on scalar?"); + if (!Visit(E->getSubExpr())) + return false; + HandleLValueComplexElement(Info, E, Result, E->getType(), true); + return true; +} + //===----------------------------------------------------------------------===// // Pointer Evaluation //===----------------------------------------------------------------------===// @@ -603,8 +3042,7 @@ class PointerExprEvaluator LValue &Result; bool Success(const Expr *E) { - Result.Base = E; - Result.Offset = CharUnits::Zero(); + Result.set(E); return true; } public: @@ -613,13 +3051,10 @@ public: : ExprEvaluatorBaseTy(info), Result(Result) {} bool Success(const APValue &V, const Expr *E) { - Result.setFrom(V); + Result.setFrom(Info.Ctx, V); return true; } - bool Error(const Stmt *S) { - return false; - } - bool ValueInitialization(const Expr *E) { + bool ZeroInitialization(const Expr *E) { return Success((Expr*)0); } @@ -628,71 +3063,64 @@ public: bool VisitUnaryAddrOf(const UnaryOperator *E); bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } + bool VisitObjCNumericLiteral(const ObjCNumericLiteral *E) + { return Success(E); } bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBlockExpr(const BlockExpr *E) { if (!E->getBlockDecl()->hasCaptures()) return Success(E); - return false; + return Error(E); + } + bool VisitCXXThisExpr(const CXXThisExpr *E) { + if (!Info.CurrentCall->This) + return Error(E); + Result = *Info.CurrentCall->This; + return true; } - bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) - { return ValueInitialization(E); } // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) { - assert(E->getType()->hasPointerRepresentation()); + assert(E->isRValue() && E->getType()->hasPointerRepresentation()); return PointerExprEvaluator(Info, Result).Visit(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->getOpcode() != BO_Add && E->getOpcode() != BO_Sub) - return false; + return ExprEvaluatorBaseTy::VisitBinaryOperator(E); const Expr *PExp = E->getLHS(); const Expr *IExp = E->getRHS(); if (IExp->getType()->isPointerType()) std::swap(PExp, IExp); - if (!EvaluatePointer(PExp, Result, Info)) + bool EvalPtrOK = EvaluatePointer(PExp, Result, Info); + if (!EvalPtrOK && !Info.keepEvaluatingAfterFailure()) return false; llvm::APSInt Offset; - if (!EvaluateInteger(IExp, Offset, Info)) + if (!EvaluateInteger(IExp, Offset, Info) || !EvalPtrOK) return false; int64_t AdditionalOffset = Offset.isSigned() ? Offset.getSExtValue() : static_cast<int64_t>(Offset.getZExtValue()); + if (E->getOpcode() == BO_Sub) + AdditionalOffset = -AdditionalOffset; - // Compute the new offset in the appropriate width. - - QualType PointeeType = - PExp->getType()->getAs<PointerType>()->getPointeeType(); - CharUnits SizeOfPointee; - - // Explicitly handle GNU void* and function pointer arithmetic extensions. - if (PointeeType->isVoidType() || PointeeType->isFunctionType()) - SizeOfPointee = CharUnits::One(); - else - SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType); - - if (E->getOpcode() == BO_Add) - Result.Offset += AdditionalOffset * SizeOfPointee; - else - Result.Offset -= AdditionalOffset * SizeOfPointee; - - return true; + QualType Pointee = PExp->getType()->getAs<PointerType>()->getPointeeType(); + return HandleLValueArrayAdjustment(Info, E, Result, Pointee, + AdditionalOffset); } bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { return EvaluateLValue(E->getSubExpr(), Result, Info); } - bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { const Expr* SubExpr = E->getSubExpr(); @@ -700,260 +3128,654 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { default: break; - case CK_NoOp: case CK_BitCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: - return Visit(SubExpr); + if (!Visit(SubExpr)) + return false; + // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are + // permitted in constant expressions in C++11. Bitcasts from cv void* are + // also static_casts, but we disallow them as a resolution to DR1312. + if (!E->getType()->isVoidPointerType()) { + Result.Designator.setInvalid(); + if (SubExpr->getType()->isVoidPointerType()) + CCEDiag(E, diag::note_constexpr_invalid_cast) + << 3 << SubExpr->getType(); + else + CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + } + return true; case CK_DerivedToBase: case CK_UncheckedDerivedToBase: { - LValue BaseLV; - if (!EvaluatePointer(E->getSubExpr(), BaseLV, Info)) + if (!EvaluatePointer(E->getSubExpr(), Result, Info)) return false; + if (!Result.Base && Result.Offset.isZero()) + return true; - // Now figure out the necessary offset to add to the baseLV to get from + // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. - CharUnits Offset = CharUnits::Zero(); + QualType Type = + E->getSubExpr()->getType()->castAs<PointerType>()->getPointeeType(); - QualType Ty = E->getSubExpr()->getType(); - const CXXRecordDecl *DerivedDecl = - Ty->getAs<PointerType>()->getPointeeType()->getAsCXXRecordDecl(); - - for (CastExpr::path_const_iterator PathI = E->path_begin(), + for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { - const CXXBaseSpecifier *Base = *PathI; - - // FIXME: If the base is virtual, we'd need to determine the type of the - // most derived class and we don't support that right now. - if (Base->isVirtual()) + if (!HandleLValueBase(Info, E, Result, Type->getAsCXXRecordDecl(), + *PathI)) return false; - - const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); - const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); - - Offset += Layout.getBaseClassOffset(BaseDecl); - DerivedDecl = BaseDecl; + Type = (*PathI)->getType(); } - Result.Base = BaseLV.getLValueBase(); - Result.Offset = BaseLV.getLValueOffset() + Offset; return true; } - case CK_NullToPointer: { - Result.Base = 0; - Result.Offset = CharUnits::Zero(); - return true; - } + case CK_BaseToDerived: + if (!Visit(E->getSubExpr())) + return false; + if (!Result.Base && Result.Offset.isZero()) + return true; + return HandleBaseToDerivedCast(Info, E, Result); + + case CK_NullToPointer: + VisitIgnoredValue(E->getSubExpr()); + return ZeroInitialization(E); case CK_IntegralToPointer: { + CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; if (Value.isInt()) { - Value.getInt() = Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); - Result.Base = 0; - Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue()); + unsigned Size = Info.Ctx.getTypeSize(E->getType()); + uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); + Result.Base = (Expr*)0; + Result.Offset = CharUnits::fromQuantity(N); + Result.CallIndex = 0; + Result.Designator.setInvalid(); return true; } else { // Cast is of an lvalue, no need to change value. - Result.Base = Value.getLValueBase(); - Result.Offset = Value.getLValueOffset(); + Result.setFrom(Info.Ctx, Value); return true; } } case CK_ArrayToPointerDecay: + if (SubExpr->isGLValue()) { + if (!EvaluateLValue(SubExpr, Result, Info)) + return false; + } else { + Result.set(SubExpr, Info.CurrentCall->Index); + if (!EvaluateInPlace(Info.CurrentCall->Temporaries[SubExpr], + Info, Result, SubExpr)) + return false; + } + // The result is a pointer to the first element of the array. + if (const ConstantArrayType *CAT + = Info.Ctx.getAsConstantArrayType(SubExpr->getType())) + Result.addArray(Info, E, CAT); + else + Result.Designator.setInvalid(); + return true; + case CK_FunctionToPointerDecay: return EvaluateLValue(SubExpr, Result, Info); } - return false; + return ExprEvaluatorBaseTy::VisitCastExpr(E); } bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { - if (E->isBuiltinCall(Info.Ctx) == - Builtin::BI__builtin___CFStringMakeConstantString || - E->isBuiltinCall(Info.Ctx) == - Builtin::BI__builtin___NSStringMakeConstantString) + if (IsStringLiteralCall(E)) return Success(E); return ExprEvaluatorBaseTy::VisitCallExpr(E); } //===----------------------------------------------------------------------===// +// Member Pointer Evaluation +//===----------------------------------------------------------------------===// + +namespace { +class MemberPointerExprEvaluator + : public ExprEvaluatorBase<MemberPointerExprEvaluator, bool> { + MemberPtr &Result; + + bool Success(const ValueDecl *D) { + Result = MemberPtr(D); + return true; + } +public: + + MemberPointerExprEvaluator(EvalInfo &Info, MemberPtr &Result) + : ExprEvaluatorBaseTy(Info), Result(Result) {} + + bool Success(const APValue &V, const Expr *E) { + Result.setFrom(V); + return true; + } + bool ZeroInitialization(const Expr *E) { + return Success((const ValueDecl*)0); + } + + bool VisitCastExpr(const CastExpr *E); + bool VisitUnaryAddrOf(const UnaryOperator *E); +}; +} // end anonymous namespace + +static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, + EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isMemberPointerType()); + return MemberPointerExprEvaluator(Info, Result).Visit(E); +} + +bool MemberPointerExprEvaluator::VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + + case CK_NullToMemberPointer: + VisitIgnoredValue(E->getSubExpr()); + return ZeroInitialization(E); + + case CK_BaseToDerivedMemberPointer: { + if (!Visit(E->getSubExpr())) + return false; + if (E->path_empty()) + return true; + // Base-to-derived member pointer casts store the path in derived-to-base + // order, so iterate backwards. The CXXBaseSpecifier also provides us with + // the wrong end of the derived->base arc, so stagger the path by one class. + typedef std::reverse_iterator<CastExpr::path_const_iterator> ReverseIter; + for (ReverseIter PathI(E->path_end() - 1), PathE(E->path_begin()); + PathI != PathE; ++PathI) { + assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); + const CXXRecordDecl *Derived = (*PathI)->getType()->getAsCXXRecordDecl(); + if (!Result.castToDerived(Derived)) + return Error(E); + } + const Type *FinalTy = E->getType()->castAs<MemberPointerType>()->getClass(); + if (!Result.castToDerived(FinalTy->getAsCXXRecordDecl())) + return Error(E); + return true; + } + + case CK_DerivedToBaseMemberPointer: + if (!Visit(E->getSubExpr())) + return false; + for (CastExpr::path_const_iterator PathI = E->path_begin(), + PathE = E->path_end(); PathI != PathE; ++PathI) { + assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); + const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); + if (!Result.castToBase(Base)) + return Error(E); + } + return true; + } +} + +bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { + // C++11 [expr.unary.op]p3 has very strict rules on how the address of a + // member can be formed. + return Success(cast<DeclRefExpr>(E->getSubExpr())->getDecl()); +} + +//===----------------------------------------------------------------------===// +// Record Evaluation +//===----------------------------------------------------------------------===// + +namespace { + class RecordExprEvaluator + : public ExprEvaluatorBase<RecordExprEvaluator, bool> { + const LValue &This; + APValue &Result; + public: + + RecordExprEvaluator(EvalInfo &info, const LValue &This, APValue &Result) + : ExprEvaluatorBaseTy(info), This(This), Result(Result) {} + + bool Success(const APValue &V, const Expr *E) { + Result = V; + return true; + } + bool ZeroInitialization(const Expr *E); + + bool VisitCastExpr(const CastExpr *E); + bool VisitInitListExpr(const InitListExpr *E); + bool VisitCXXConstructExpr(const CXXConstructExpr *E); + }; +} + +/// Perform zero-initialization on an object of non-union class type. +/// C++11 [dcl.init]p5: +/// To zero-initialize an object or reference of type T means: +/// [...] +/// -- if T is a (possibly cv-qualified) non-union class type, +/// each non-static data member and each base-class subobject is +/// zero-initialized +static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, + const RecordDecl *RD, + const LValue &This, APValue &Result) { + assert(!RD->isUnion() && "Expected non-union class type"); + const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD); + Result = APValue(APValue::UninitStruct(), CD ? CD->getNumBases() : 0, + std::distance(RD->field_begin(), RD->field_end())); + + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); + + if (CD) { + unsigned Index = 0; + for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(), + End = CD->bases_end(); I != End; ++I, ++Index) { + const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl(); + LValue Subobject = This; + HandleLValueDirectBase(Info, E, Subobject, CD, Base, &Layout); + if (!HandleClassZeroInitialization(Info, E, Base, Subobject, + Result.getStructBase(Index))) + return false; + } + } + + for (RecordDecl::field_iterator I = RD->field_begin(), End = RD->field_end(); + I != End; ++I) { + // -- if T is a reference type, no initialization is performed. + if ((*I)->getType()->isReferenceType()) + continue; + + LValue Subobject = This; + HandleLValueMember(Info, E, Subobject, *I, &Layout); + + ImplicitValueInitExpr VIE((*I)->getType()); + if (!EvaluateInPlace( + Result.getStructField((*I)->getFieldIndex()), Info, Subobject, &VIE)) + return false; + } + + return true; +} + +bool RecordExprEvaluator::ZeroInitialization(const Expr *E) { + const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); + if (RD->isUnion()) { + // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the + // object's first non-static named data member is zero-initialized + RecordDecl::field_iterator I = RD->field_begin(); + if (I == RD->field_end()) { + Result = APValue((const FieldDecl*)0); + return true; + } + + LValue Subobject = This; + HandleLValueMember(Info, E, Subobject, *I); + Result = APValue(*I); + ImplicitValueInitExpr VIE((*I)->getType()); + return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, &VIE); + } + + if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->getNumVBases()) { + Info.Diag(E, diag::note_constexpr_virtual_base) << RD; + return false; + } + + return HandleClassZeroInitialization(Info, E, RD, This, Result); +} + +bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + + case CK_ConstructorConversion: + return Visit(E->getSubExpr()); + + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: { + APValue DerivedObject; + if (!Evaluate(DerivedObject, Info, E->getSubExpr())) + return false; + if (!DerivedObject.isStruct()) + return Error(E->getSubExpr()); + + // Derived-to-base rvalue conversion: just slice off the derived part. + APValue *Value = &DerivedObject; + const CXXRecordDecl *RD = E->getSubExpr()->getType()->getAsCXXRecordDecl(); + for (CastExpr::path_const_iterator PathI = E->path_begin(), + PathE = E->path_end(); PathI != PathE; ++PathI) { + assert(!(*PathI)->isVirtual() && "record rvalue with virtual base"); + const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); + Value = &Value->getStructBase(getBaseIndex(RD, Base)); + RD = Base; + } + Result = *Value; + return true; + } + } +} + +bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + // Cannot constant-evaluate std::initializer_list inits. + if (E->initializesStdInitializerList()) + return false; + + const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl(); + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); + + if (RD->isUnion()) { + const FieldDecl *Field = E->getInitializedFieldInUnion(); + Result = APValue(Field); + if (!Field) + return true; + + // If the initializer list for a union does not contain any elements, the + // first element of the union is value-initialized. + ImplicitValueInitExpr VIE(Field->getType()); + const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE; + + LValue Subobject = This; + HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout); + return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr); + } + + assert((!isa<CXXRecordDecl>(RD) || !cast<CXXRecordDecl>(RD)->getNumBases()) && + "initializer list for class with base classes"); + Result = APValue(APValue::UninitStruct(), 0, + std::distance(RD->field_begin(), RD->field_end())); + unsigned ElementNo = 0; + bool Success = true; + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { + // Anonymous bit-fields are not considered members of the class for + // purposes of aggregate initialization. + if (Field->isUnnamedBitfield()) + continue; + + LValue Subobject = This; + + bool HaveInit = ElementNo < E->getNumInits(); + + // FIXME: Diagnostics here should point to the end of the initializer + // list, not the start. + HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E, Subobject, + *Field, &Layout); + + // Perform an implicit value-initialization for members beyond the end of + // the initializer list. + ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); + + if (!EvaluateInPlace( + Result.getStructField((*Field)->getFieldIndex()), + Info, Subobject, HaveInit ? E->getInit(ElementNo++) : &VIE)) { + if (!Info.keepEvaluatingAfterFailure()) + return false; + Success = false; + } + } + + return Success; +} + +bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { + const CXXConstructorDecl *FD = E->getConstructor(); + bool ZeroInit = E->requiresZeroInitialization(); + if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { + // If we've already performed zero-initialization, we're already done. + if (!Result.isUninit()) + return true; + + if (ZeroInit) + return ZeroInitialization(E); + + const CXXRecordDecl *RD = FD->getParent(); + if (RD->isUnion()) + Result = APValue((FieldDecl*)0); + else + Result = APValue(APValue::UninitStruct(), RD->getNumBases(), + std::distance(RD->field_begin(), RD->field_end())); + return true; + } + + const FunctionDecl *Definition = 0; + FD->getBody(Definition); + + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + return false; + + // Avoid materializing a temporary for an elidable copy/move constructor. + if (E->isElidable() && !ZeroInit) + if (const MaterializeTemporaryExpr *ME + = dyn_cast<MaterializeTemporaryExpr>(E->getArg(0))) + return Visit(ME->GetTemporaryExpr()); + + if (ZeroInit && !ZeroInitialization(E)) + return false; + + llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + return HandleConstructorCall(E->getExprLoc(), This, Args, + cast<CXXConstructorDecl>(Definition), Info, + Result); +} + +static bool EvaluateRecord(const Expr *E, const LValue &This, + APValue &Result, EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isRecordType() && + "can't evaluate expression as a record rvalue"); + return RecordExprEvaluator(Info, This, Result).Visit(E); +} + +//===----------------------------------------------------------------------===// +// Temporary Evaluation +// +// Temporaries are represented in the AST as rvalues, but generally behave like +// lvalues. The full-object of which the temporary is a subobject is implicitly +// materialized so that a reference can bind to it. +//===----------------------------------------------------------------------===// +namespace { +class TemporaryExprEvaluator + : public LValueExprEvaluatorBase<TemporaryExprEvaluator> { +public: + TemporaryExprEvaluator(EvalInfo &Info, LValue &Result) : + LValueExprEvaluatorBaseTy(Info, Result) {} + + /// Visit an expression which constructs the value of this temporary. + bool VisitConstructExpr(const Expr *E) { + Result.set(E, Info.CurrentCall->Index); + return EvaluateInPlace(Info.CurrentCall->Temporaries[E], Info, Result, E); + } + + bool VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return LValueExprEvaluatorBaseTy::VisitCastExpr(E); + + case CK_ConstructorConversion: + return VisitConstructExpr(E->getSubExpr()); + } + } + bool VisitInitListExpr(const InitListExpr *E) { + return VisitConstructExpr(E); + } + bool VisitCXXConstructExpr(const CXXConstructExpr *E) { + return VisitConstructExpr(E); + } + bool VisitCallExpr(const CallExpr *E) { + return VisitConstructExpr(E); + } +}; +} // end anonymous namespace + +/// Evaluate an expression of record type as a temporary. +static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isRecordType()); + return TemporaryExprEvaluator(Info, Result).Visit(E); +} + +//===----------------------------------------------------------------------===// // Vector Evaluation //===----------------------------------------------------------------------===// namespace { class VectorExprEvaluator - : public ExprEvaluatorBase<VectorExprEvaluator, APValue> { - APValue GetZeroVector(QualType VecType); + : public ExprEvaluatorBase<VectorExprEvaluator, bool> { + APValue &Result; public: - VectorExprEvaluator(EvalInfo &info) : ExprEvaluatorBaseTy(info) {} + VectorExprEvaluator(EvalInfo &info, APValue &Result) + : ExprEvaluatorBaseTy(info), Result(Result) {} - APValue Success(const APValue &V, const Expr *E) { return V; } - APValue Error(const Expr *E) { return APValue(); } - APValue ValueInitialization(const Expr *E) - { return GetZeroVector(E->getType()); } + bool Success(const ArrayRef<APValue> &V, const Expr *E) { + assert(V.size() == E->getType()->castAs<VectorType>()->getNumElements()); + // FIXME: remove this APValue copy. + Result = APValue(V.data(), V.size()); + return true; + } + bool Success(const APValue &V, const Expr *E) { + assert(V.isVector()); + Result = V; + return true; + } + bool ZeroInitialization(const Expr *E); - APValue VisitUnaryReal(const UnaryOperator *E) + bool VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - APValue VisitCastExpr(const CastExpr* E); - APValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); - APValue VisitInitListExpr(const InitListExpr *E); - APValue VisitUnaryImag(const UnaryOperator *E); + bool VisitCastExpr(const CastExpr* E); + bool VisitInitListExpr(const InitListExpr *E); + bool VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div, // binary comparisons, binary and/or/xor, // shufflevector, ExtVectorElementExpr - // (Note that these require implementing conversions - // between vector types.) }; } // end anonymous namespace static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { - if (!E->getType()->isVectorType()) - return false; - Result = VectorExprEvaluator(Info).Visit(E); - return !Result.isUninit(); + assert(E->isRValue() && E->getType()->isVectorType() &&"not a vector rvalue"); + return VectorExprEvaluator(Info, Result).Visit(E); } -APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { - const VectorType *VTy = E->getType()->getAs<VectorType>(); - QualType EltTy = VTy->getElementType(); +bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { + const VectorType *VTy = E->getType()->castAs<VectorType>(); unsigned NElts = VTy->getNumElements(); - unsigned EltWidth = Info.Ctx.getTypeSize(EltTy); - const Expr* SE = E->getSubExpr(); + const Expr *SE = E->getSubExpr(); QualType SETy = SE->getType(); switch (E->getCastKind()) { case CK_VectorSplat: { - APValue Result = APValue(); + APValue Val = APValue(); if (SETy->isIntegerType()) { APSInt IntResult; if (!EvaluateInteger(SE, IntResult, Info)) - return APValue(); - Result = APValue(IntResult); + return false; + Val = APValue(IntResult); } else if (SETy->isRealFloatingType()) { APFloat F(0.0); if (!EvaluateFloat(SE, F, Info)) - return APValue(); - Result = APValue(F); + return false; + Val = APValue(F); } else { - return APValue(); + return Error(E); } // Splat and create vector APValue. - SmallVector<APValue, 4> Elts(NElts, Result); - return APValue(&Elts[0], Elts.size()); + SmallVector<APValue, 4> Elts(NElts, Val); + return Success(Elts, E); } case CK_BitCast: { - if (SETy->isVectorType()) - return Visit(SE); - - if (!SETy->isIntegerType()) - return APValue(); - - APSInt Init; - if (!EvaluateInteger(SE, Init, Info)) - return APValue(); - - assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) && - "Vectors must be composed of ints or floats"); - + // Evaluate the operand into an APInt we can extract from. + llvm::APInt SValInt; + if (!EvalAndBitcastToAPInt(Info, SE, SValInt)) + return false; + // Extract the elements + QualType EltTy = VTy->getElementType(); + unsigned EltSize = Info.Ctx.getTypeSize(EltTy); + bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); SmallVector<APValue, 4> Elts; - for (unsigned i = 0; i != NElts; ++i) { - APSInt Tmp = Init.extOrTrunc(EltWidth); - - if (EltTy->isIntegerType()) - Elts.push_back(APValue(Tmp)); - else - Elts.push_back(APValue(APFloat(Tmp))); - - Init >>= EltWidth; + if (EltTy->isRealFloatingType()) { + const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); + bool isIEESem = &Sem != &APFloat::PPCDoubleDouble; + unsigned FloatEltSize = EltSize; + if (&Sem == &APFloat::x87DoubleExtended) + FloatEltSize = 80; + for (unsigned i = 0; i < NElts; i++) { + llvm::APInt Elt; + if (BigEndian) + Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); + else + Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); + Elts.push_back(APValue(APFloat(Elt, isIEESem))); + } + } else if (EltTy->isIntegerType()) { + for (unsigned i = 0; i < NElts; i++) { + llvm::APInt Elt; + if (BigEndian) + Elt = SValInt.rotl(i*EltSize+EltSize).zextOrTrunc(EltSize); + else + Elt = SValInt.rotr(i*EltSize).zextOrTrunc(EltSize); + Elts.push_back(APValue(APSInt(Elt, EltTy->isSignedIntegerType()))); + } + } else { + return Error(E); } - return APValue(&Elts[0], Elts.size()); + return Success(Elts, E); } - case CK_LValueToRValue: - case CK_NoOp: - return Visit(SE); default: - return APValue(); + return ExprEvaluatorBaseTy::VisitCastExpr(E); } } -APValue -VectorExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { - return this->Visit(E->getInitializer()); -} - -APValue +bool VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { - const VectorType *VT = E->getType()->getAs<VectorType>(); + const VectorType *VT = E->getType()->castAs<VectorType>(); unsigned NumInits = E->getNumInits(); unsigned NumElements = VT->getNumElements(); QualType EltTy = VT->getElementType(); SmallVector<APValue, 4> Elements; - // If a vector is initialized with a single element, that value - // becomes every element of the vector, not just the first. - // This is the behavior described in the IBM AltiVec documentation. - if (NumInits == 1) { - - // Handle the case where the vector is initialized by a another - // vector (OpenCL 6.1.6). - if (E->getInit(0)->getType()->isVectorType()) - return this->Visit(const_cast<Expr*>(E->getInit(0))); - - APValue InitValue; - if (EltTy->isIntegerType()) { + // The number of initializers can be less than the number of + // vector elements. For OpenCL, this can be due to nested vector + // initialization. For GCC compatibility, missing trailing elements + // should be initialized with zeroes. + unsigned CountInits = 0, CountElts = 0; + while (CountElts < NumElements) { + // Handle nested vector initialization. + if (CountInits < NumInits + && E->getInit(CountInits)->getType()->isExtVectorType()) { + APValue v; + if (!EvaluateVector(E->getInit(CountInits), v, Info)) + return Error(E); + unsigned vlen = v.getVectorLength(); + for (unsigned j = 0; j < vlen; j++) + Elements.push_back(v.getVectorElt(j)); + CountElts += vlen; + } else if (EltTy->isIntegerType()) { llvm::APSInt sInt(32); - if (!EvaluateInteger(E->getInit(0), sInt, Info)) - return APValue(); - InitValue = APValue(sInt); + if (CountInits < NumInits) { + if (!EvaluateInteger(E->getInit(CountInits), sInt, Info)) + return false; + } else // trailing integer zero. + sInt = Info.Ctx.MakeIntValue(0, EltTy); + Elements.push_back(APValue(sInt)); + CountElts++; } else { llvm::APFloat f(0.0); - if (!EvaluateFloat(E->getInit(0), f, Info)) - return APValue(); - InitValue = APValue(f); - } - for (unsigned i = 0; i < NumElements; i++) { - Elements.push_back(InitValue); - } - } else { - for (unsigned i = 0; i < NumElements; i++) { - if (EltTy->isIntegerType()) { - llvm::APSInt sInt(32); - if (i < NumInits) { - if (!EvaluateInteger(E->getInit(i), sInt, Info)) - return APValue(); - } else { - sInt = Info.Ctx.MakeIntValue(0, EltTy); - } - Elements.push_back(APValue(sInt)); - } else { - llvm::APFloat f(0.0); - if (i < NumInits) { - if (!EvaluateFloat(E->getInit(i), f, Info)) - return APValue(); - } else { - f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); - } - Elements.push_back(APValue(f)); - } + if (CountInits < NumInits) { + if (!EvaluateFloat(E->getInit(CountInits), f, Info)) + return false; + } else // trailing float zero. + f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); + Elements.push_back(APValue(f)); + CountElts++; } + CountInits++; } - return APValue(&Elements[0], Elements.size()); + return Success(Elements, E); } -APValue -VectorExprEvaluator::GetZeroVector(QualType T) { - const VectorType *VT = T->getAs<VectorType>(); +bool +VectorExprEvaluator::ZeroInitialization(const Expr *E) { + const VectorType *VT = E->getType()->getAs<VectorType>(); QualType EltTy = VT->getElementType(); APValue ZeroElement; if (EltTy->isIntegerType()) @@ -963,17 +3785,175 @@ VectorExprEvaluator::GetZeroVector(QualType T) { APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy))); SmallVector<APValue, 4> Elements(VT->getNumElements(), ZeroElement); - return APValue(&Elements[0], Elements.size()); + return Success(Elements, E); +} + +bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { + VisitIgnoredValue(E->getSubExpr()); + return ZeroInitialization(E); +} + +//===----------------------------------------------------------------------===// +// Array Evaluation +//===----------------------------------------------------------------------===// + +namespace { + class ArrayExprEvaluator + : public ExprEvaluatorBase<ArrayExprEvaluator, bool> { + const LValue &This; + APValue &Result; + public: + + ArrayExprEvaluator(EvalInfo &Info, const LValue &This, APValue &Result) + : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} + + bool Success(const APValue &V, const Expr *E) { + assert((V.isArray() || V.isLValue()) && + "expected array or string literal"); + Result = V; + return true; + } + + bool ZeroInitialization(const Expr *E) { + const ConstantArrayType *CAT = + Info.Ctx.getAsConstantArrayType(E->getType()); + if (!CAT) + return Error(E); + + Result = APValue(APValue::UninitArray(), 0, + CAT->getSize().getZExtValue()); + if (!Result.hasArrayFiller()) return true; + + // Zero-initialize all elements. + LValue Subobject = This; + Subobject.addArray(Info, E, CAT); + ImplicitValueInitExpr VIE(CAT->getElementType()); + return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE); + } + + bool VisitInitListExpr(const InitListExpr *E); + bool VisitCXXConstructExpr(const CXXConstructExpr *E); + }; +} // end anonymous namespace + +static bool EvaluateArray(const Expr *E, const LValue &This, + APValue &Result, EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue"); + return ArrayExprEvaluator(Info, This, Result).Visit(E); } -APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { - if (!E->getSubExpr()->isEvaluatable(Info.Ctx)) - Info.EvalResult.HasSideEffects = true; - return GetZeroVector(E->getType()); +bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType()); + if (!CAT) + return Error(E); + + // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...] + // an appropriately-typed string literal enclosed in braces. + if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() && + Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) { + LValue LV; + if (!EvaluateLValue(E->getInit(0), LV, Info)) + return false; + APValue Val; + LV.moveInto(Val); + return Success(Val, E); + } + + bool Success = true; + + Result = APValue(APValue::UninitArray(), E->getNumInits(), + CAT->getSize().getZExtValue()); + LValue Subobject = This; + Subobject.addArray(Info, E, CAT); + unsigned Index = 0; + for (InitListExpr::const_iterator I = E->begin(), End = E->end(); + I != End; ++I, ++Index) { + if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), + Info, Subobject, cast<Expr>(*I)) || + !HandleLValueArrayAdjustment(Info, cast<Expr>(*I), Subobject, + CAT->getElementType(), 1)) { + if (!Info.keepEvaluatingAfterFailure()) + return false; + Success = false; + } + } + + if (!Result.hasArrayFiller()) return Success; + assert(E->hasArrayFiller() && "no array filler for incomplete init list"); + // FIXME: The Subobject here isn't necessarily right. This rarely matters, + // but sometimes does: + // struct S { constexpr S() : p(&p) {} void *p; }; + // S s[10] = {}; + return EvaluateInPlace(Result.getArrayFiller(), Info, + Subobject, E->getArrayFiller()) && Success; +} + +bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { + const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType()); + if (!CAT) + return Error(E); + + bool HadZeroInit = !Result.isUninit(); + if (!HadZeroInit) + Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue()); + if (!Result.hasArrayFiller()) + return true; + + const CXXConstructorDecl *FD = E->getConstructor(); + + bool ZeroInit = E->requiresZeroInitialization(); + if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { + if (HadZeroInit) + return true; + + if (ZeroInit) { + LValue Subobject = This; + Subobject.addArray(Info, E, CAT); + ImplicitValueInitExpr VIE(CAT->getElementType()); + return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE); + } + + const CXXRecordDecl *RD = FD->getParent(); + if (RD->isUnion()) + Result.getArrayFiller() = APValue((FieldDecl*)0); + else + Result.getArrayFiller() = + APValue(APValue::UninitStruct(), RD->getNumBases(), + std::distance(RD->field_begin(), RD->field_end())); + return true; + } + + const FunctionDecl *Definition = 0; + FD->getBody(Definition); + + if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition)) + return false; + + // FIXME: The Subobject here isn't necessarily right. This rarely matters, + // but sometimes does: + // struct S { constexpr S() : p(&p) {} void *p; }; + // S s[10]; + LValue Subobject = This; + Subobject.addArray(Info, E, CAT); + + if (ZeroInit && !HadZeroInit) { + ImplicitValueInitExpr VIE(CAT->getElementType()); + if (!EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE)) + return false; + } + + llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + return HandleConstructorCall(E->getExprLoc(), Subobject, Args, + cast<CXXConstructorDecl>(Definition), + Info, Result.getArrayFiller()); } //===----------------------------------------------------------------------===// // Integer Evaluation +// +// As a GNU extension, we support casting pointers to sufficiently-wide integer +// types and back in constant folding. Integer values are thus represented +// either as an integer-valued APValue, or as an lvalue-valued APValue. //===----------------------------------------------------------------------===// namespace { @@ -984,7 +3964,7 @@ public: IntExprEvaluator(EvalInfo &info, APValue &result) : ExprEvaluatorBaseTy(info), Result(result) {} - bool Success(const llvm::APSInt &SI, const Expr *E) { + bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && @@ -994,8 +3974,11 @@ public: 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) { + bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && @@ -1005,37 +3988,33 @@ public: E->getType()->isUnsignedIntegerOrEnumerationType()); return true; } + bool Success(const llvm::APInt &I, const Expr *E) { + return Success(I, E, Result); + } - bool Success(uint64_t Value, const Expr *E) { + bool Success(uint64_t Value, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "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); } - - bool Error(SourceLocation L, diag::kind D, const Expr *E) { - // Take the first error. - if (Info.EvalResult.Diag == 0) { - Info.EvalResult.DiagLoc = L; - Info.EvalResult.Diag = D; - Info.EvalResult.DiagExpr = E; - } - return false; - } - bool Success(const APValue &V, const Expr *E) { + if (V.isLValue() || V.isAddrLabelDiff()) { + Result = V; + return true; + } return Success(V.getInt(), E); } - bool Error(const Expr *E) { - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); - } - bool ValueInitialization(const Expr *E) { return Success(0, E); } + bool ZeroInitialization(const Expr *E) { return Success(0, E); } //===--------------------------------------------------------------------===// // Visitor Methods @@ -1057,8 +4036,7 @@ public: } bool VisitMemberExpr(const MemberExpr *E) { if (CheckReferencedDecl(E, E->getMemberDecl())) { - // Conservatively assume a MemberExpr will have side-effects - Info.EvalResult.HasSideEffects = true; + VisitIgnoredValue(E->getBase()); return true; } @@ -1077,9 +4055,13 @@ public: return Success(E->getValue(), E); } + bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { + return Success(E->getValue(), E); + } + // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { - return ValueInitialization(E); + return ZeroInitialization(E); } bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { @@ -1090,6 +4072,10 @@ public: return Success(E->getValue(), E); } + bool VisitTypeTraitExpr(const TypeTraitExpr *E) { + return Success(E->getValue(), E); + } + bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { return Success(E->getValue(), E); } @@ -1107,27 +4093,43 @@ public: private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); - static QualType GetObjectType(const Expr *E); + static QualType GetObjectType(APValue::LValueBase B); bool TryEvaluateBuiltinObjectSize(const CallExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace -static bool EvaluateIntegerOrLValue(const Expr* E, APValue &Result, EvalInfo &Info) { - assert(E->getType()->isIntegralOrEnumerationType()); +/// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and +/// produce either the integer value or a pointer. +/// +/// GCC has a heinous extension which folds casts between pointer types and +/// pointer-sized integral types. We support this by allowing the evaluation of +/// an integer rvalue to produce a pointer (represented as an lvalue) instead. +/// Some simple arithmetic on such values is supported (they are treated much +/// like char*). +static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, + EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType()); return IntExprEvaluator(Info, Result).Visit(E); } -static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { - assert(E->getType()->isIntegralOrEnumerationType()); - +static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { APValue Val; - if (!EvaluateIntegerOrLValue(E, Val, Info) || !Val.isInt()) + if (!EvaluateIntegerOrLValue(E, Val, Info)) return false; + if (!Val.isInt()) { + // FIXME: It would be better to produce the diagnostic for casting + // a pointer to an integer. + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } Result = Val.getInt(); return true; } +/// 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. bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // Enums are integer constant exprs. if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { @@ -1149,43 +4151,6 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { return Success(Val, E); } } - - // In C++, const, non-volatile integers initialized with ICEs are ICEs. - // In C, they can also be folded, although they are not ICEs. - if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() - == Qualifiers::Const) { - - if (isa<ParmVarDecl>(D)) - return false; - - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (const Expr *Init = VD->getAnyInitializer()) { - if (APValue *V = VD->getEvaluatedValue()) { - if (V->isInt()) - return Success(V->getInt(), E); - return false; - } - - if (VD->isEvaluatingValue()) - return false; - - VD->setEvaluatingValue(); - - Expr::EvalResult EResult; - if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects && - EResult.Val.isInt()) { - // Cache the evaluated value in the variable declaration. - Result = EResult.Val; - VD->setEvaluatedValue(Result); - return true; - } - - VD->setEvaluatedValue(APValue()); - } - } - } - - // Otherwise, random variable references are not constants. return false; } @@ -1242,17 +4207,72 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) { return union_type_class; else // FIXME: offset_type_class, method_type_class, & lang_type_class? llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); - return -1; +} + +/// EvaluateBuiltinConstantPForLValue - Determine the result of +/// __builtin_constant_p when applied to the given lvalue. +/// +/// 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(); +} + +/// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to +/// GCC as we can manage. +static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { + QualType ArgType = Arg->getType(); + + // __builtin_constant_p always has one operand. The rules which gcc follows + // are not precisely documented, but are as follows: + // + // - 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. + // + // 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) + return false; + + APValue &V = Result.Val; + if (V.getKind() == APValue::Int) + return true; + + 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); + if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info) + : EvaluatePointer(Arg, LV, Info)) && + !Status.HasSideEffects) + return EvaluateBuiltinConstantPForLValue(LV); + } + + // Anything else isn't considered to be sufficiently constant. + return false; } /// Retrieves the "underlying object type" of the given expression, /// as used by __builtin_object_size. -QualType IntExprEvaluator::GetObjectType(const Expr *E) { - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { - if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) +QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) { + if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) return VD->getType(); - } else if (isa<CompoundLiteralExpr>(E)) { - return E->getType(); + } else if (const Expr *E = B.get<const Expr*>()) { + if (isa<CompoundLiteralExpr>(E)) + return E->getType(); } return QualType(); @@ -1265,16 +4285,15 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { return false; // If we can prove the base is null, lower to zero now. - const Expr *LVBase = Base.getLValueBase(); - if (!LVBase) return Success(0, E); + if (!Base.getLValueBase()) return Success(0, E); - QualType T = GetObjectType(LVBase); + QualType T = GetObjectType(Base.getLValueBase()); if (T.isNull() || T->isIncompleteType() || T->isFunctionType() || T->isVariablyModifiedType() || T->isDependentType()) - return false; + return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(T); CharUnits Offset = Base.getLValueOffset(); @@ -1287,7 +4306,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { - switch (E->isBuiltinCall(Info.Ctx)) { + switch (unsigned BuiltinOp = E->isBuiltinCall()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -1303,17 +4322,15 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(0, E); } - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return Error(E); } case Builtin::BI__builtin_classify_type: return Success(EvaluateBuiltinClassifyType(E), E); case Builtin::BI__builtin_constant_p: - // __builtin_constant_p always has one operand: it returns true if that - // operand can be folded, false otherwise. - return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E); - + return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); + case Builtin::BI__builtin_eh_return_data_regno: { int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); @@ -1322,8 +4339,15 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_expect: return Visit(E->getArg(0)); - + case Builtin::BIstrlen: + // A call to strlen is not a constant expression. + if (Info.getLangOpts().CPlusPlus0x) + Info.CCEDiag(E, diag::note_constexpr_invalid_function) + << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'"; + else + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); + // Fall through. case Builtin::BI__builtin_strlen: // As an extension, we support strlen() and __builtin_strlen() as constant // expressions when the argument is a string literal. @@ -1339,57 +4363,482 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(Str.size(), E); } - return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + return Error(E); + + case Builtin::BI__atomic_always_lock_free: + case Builtin::BI__atomic_is_lock_free: + case Builtin::BI__c11_atomic_is_lock_free: { + APSInt SizeVal; + if (!EvaluateInteger(E->getArg(0), SizeVal, Info)) + return false; + + // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power + // of two less than the maximum inline atomic width, we know it is + // lock-free. If the size isn't a power of two, or greater than the + // maximum alignment where we promote atomics, we know it is not lock-free + // (at least not in the sense of atomic_is_lock_free). Otherwise, + // the answer can only be determined at runtime; for example, 16-byte + // atomics have lock-free implementations on some, but not all, + // x86-64 processors. + + // Check power-of-two. + CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); + if (Size.isPowerOfTwo()) { + // Check against inlining width. + unsigned InlineWidthBits = + Info.Ctx.getTargetInfo().getMaxAtomicInlineWidth(); + if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits)) { + if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || + Size == CharUnits::One() || + E->getArg(1)->isNullPointerConstant(Info.Ctx, + Expr::NPC_NeverValueDependent)) + // OK, we will inline appropriately-aligned operations of this size, + // and _Atomic(T) is appropriately-aligned. + return Success(1, E); + + QualType PointeeType = E->getArg(1)->IgnoreImpCasts()->getType()-> + castAs<PointerType>()->getPointeeType(); + if (!PointeeType->isIncompleteType() && + Info.Ctx.getTypeAlignInChars(PointeeType) >= Size) { + // OK, we will inline operations on this object. + return Success(1, E); + } + } + } + + return BuiltinOp == Builtin::BI__atomic_always_lock_free ? + Success(0, E) : Error(E); + } } } -bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { - if (E->getOpcode() == BO_Comma) { - if (!Visit(E->getRHS())) +static bool HasSameBase(const LValue &A, const LValue &B) { + if (!A.getLValueBase()) + return !B.getLValueBase(); + if (!B.getLValueBase()) + return false; + + if (A.getLValueBase().getOpaqueValue() != + B.getLValueBase().getOpaqueValue()) { + const Decl *ADecl = GetLValueBaseDecl(A); + if (!ADecl) + return false; + const Decl *BDecl = GetLValueBaseDecl(B); + if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl()) return false; + } - // If we can't evaluate the LHS, it might have side effects; - // conservatively mark it. - if (!E->getLHS()->isEvaluatable(Info.Ctx)) - Info.EvalResult.HasSideEffects = true; + return IsGlobalLValue(A.getLValueBase()) || + A.getLValueCallIndex() == B.getLValueCallIndex(); +} +/// Perform the given integer operation, which is known to need at most BitWidth +/// bits, and check for overflow in the original type (if that type was not an +/// unsigned type). +template<typename Operation> +static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E, + const APSInt &LHS, const APSInt &RHS, + unsigned BitWidth, Operation Op) { + if (LHS.isUnsigned()) + return Op(LHS, RHS); + + APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); + APSInt Result = Value.trunc(LHS.getBitWidth()); + if (Result.extend(BitWidth) != Value) + HandleOverflow(Info, E, Value, E->getType()); + return Result; +} + +namespace { + +/// \brief Data recursive integer evaluator of certain binary operators. +/// +/// We use a data recursive algorithm for binary operators so that we are able +/// to handle extreme cases of chained binary operators without causing stack +/// overflow. +class DataRecursiveIntBinOpEvaluator { + struct EvalResult { + APValue Val; + bool Failed; + + EvalResult() : Failed(false) { } + + void swap(EvalResult &RHS) { + Val.swap(RHS.Val); + Failed = RHS.Failed; + RHS.Failed = false; + } + }; + + struct Job { + const Expr *E; + EvalResult LHSResult; // meaningful only for binary operator expression. + enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; + + Job() : StoredInfo(0) { } + void startSpeculativeEval(EvalInfo &Info) { + OldEvalStatus = Info.EvalStatus; + Info.EvalStatus.Diag = 0; + StoredInfo = &Info; + } + ~Job() { + if (StoredInfo) { + StoredInfo->EvalStatus = OldEvalStatus; + } + } + private: + EvalInfo *StoredInfo; // non-null if status changed. + Expr::EvalStatus OldEvalStatus; + }; + + SmallVector<Job, 16> Queue; + + IntExprEvaluator &IntEval; + EvalInfo &Info; + APValue &FinalResult; + +public: + DataRecursiveIntBinOpEvaluator(IntExprEvaluator &IntEval, APValue &Result) + : IntEval(IntEval), Info(IntEval.getEvalInfo()), FinalResult(Result) { } + + /// \brief True if \param E is a binary operator that we are going to handle + /// data recursively. + /// We handle binary operators that are comma, logical, or that have operands + /// with integral or enumeration type. + static bool shouldEnqueue(const BinaryOperator *E) { + return E->getOpcode() == BO_Comma || + E->isLogicalOp() || + (E->getLHS()->getType()->isIntegralOrEnumerationType() && + E->getRHS()->getType()->isIntegralOrEnumerationType()); + } + + bool Traverse(const BinaryOperator *E) { + enqueue(E); + EvalResult PrevResult; + while (!Queue.empty()) + process(PrevResult); + + if (PrevResult.Failed) return false; + + FinalResult.swap(PrevResult.Val); return true; } - if (E->isLogicalOp()) { - // These need to be handled specially because the operands aren't - // necessarily integral - bool lhsResult, rhsResult; +private: + bool Success(uint64_t Value, const Expr *E, APValue &Result) { + return IntEval.Success(Value, E, Result); + } + bool Success(const APSInt &Value, const Expr *E, APValue &Result) { + return IntEval.Success(Value, E, Result); + } + bool Error(const Expr *E) { + return IntEval.Error(E); + } + bool Error(const Expr *E, diag::kind D) { + return IntEval.Error(E, D); + } + + OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { + return Info.CCEDiag(E, D); + } + + // \brief Returns true if visiting the RHS is necessary, false otherwise. + bool VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, + bool &SuppressRHSDiags); + + bool VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, + const BinaryOperator *E, APValue &Result); + + void EvaluateExpr(const Expr *E, EvalResult &Result) { + Result.Failed = !Evaluate(Result.Val, Info, E); + if (Result.Failed) + Result.Val = APValue(); + } - if (HandleConversionToBool(E->getLHS(), lhsResult, Info)) { + void process(EvalResult &Result); + + void enqueue(const Expr *E) { + E = E->IgnoreParens(); + Queue.resize(Queue.size()+1); + Queue.back().E = E; + Queue.back().Kind = Job::AnyExprKind; + } +}; + +} + +bool DataRecursiveIntBinOpEvaluator:: + VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, + bool &SuppressRHSDiags) { + if (E->getOpcode() == BO_Comma) { + // Ignore LHS but note if we could not evaluate it. + if (LHSResult.Failed) + Info.EvalStatus.HasSideEffects = true; + return true; + } + + if (E->isLogicalOp()) { + bool lhsResult; + if (HandleConversionToBool(LHSResult.Val, lhsResult)) { // We were able to evaluate the LHS, see if we can get away with not // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 - if (lhsResult == (E->getOpcode() == BO_LOr)) - return Success(lhsResult, E); + if (lhsResult == (E->getOpcode() == BO_LOr)) { + Success(lhsResult, E, LHSResult.Val); + return false; // Ignore RHS + } + } else { + // Since we weren't able to evaluate the left hand side, it + // must have had side effects. + Info.EvalStatus.HasSideEffects = true; + + // We can't evaluate the LHS; however, sometimes the result + // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. + // Don't ignore RHS and suppress diagnostics from this arm. + SuppressRHSDiags = true; + } + + return true; + } + + assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && + E->getRHS()->getType()->isIntegralOrEnumerationType()); + + if (LHSResult.Failed && !Info.keepEvaluatingAfterFailure()) + return false; // Ignore RHS; + + return true; +} - if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) { +bool DataRecursiveIntBinOpEvaluator:: + VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, + const BinaryOperator *E, APValue &Result) { + if (E->getOpcode() == BO_Comma) { + if (RHSResult.Failed) + return false; + Result = RHSResult.Val; + return true; + } + + if (E->isLogicalOp()) { + bool lhsResult, rhsResult; + bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult); + bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult); + + if (LHSIsOK) { + if (RHSIsOK) { if (E->getOpcode() == BO_LOr) - return Success(lhsResult || rhsResult, E); + return Success(lhsResult || rhsResult, E, Result); else - return Success(lhsResult && rhsResult, E); + return Success(lhsResult && rhsResult, E, Result); } } else { - if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) { + if (RHSIsOK) { // We can't evaluate the LHS; however, sometimes the result // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. - if (rhsResult == (E->getOpcode() == BO_LOr) || - !rhsResult == (E->getOpcode() == BO_LAnd)) { - // Since we weren't able to evaluate the left hand side, it - // must have had side effects. - Info.EvalResult.HasSideEffects = true; + if (rhsResult == (E->getOpcode() == BO_LOr)) + return Success(rhsResult, E, Result); + } + } + + return false; + } + + assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && + E->getRHS()->getType()->isIntegralOrEnumerationType()); + + if (LHSResult.Failed || RHSResult.Failed) + return false; + + const APValue &LHSVal = LHSResult.Val; + const APValue &RHSVal = RHSResult.Val; + + // Handle cases like (unsigned long)&a + 4. + if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) { + Result = LHSVal; + CharUnits AdditionalOffset = CharUnits::fromQuantity( + RHSVal.getInt().getZExtValue()); + if (E->getOpcode() == BO_Add) + Result.getLValueOffset() += AdditionalOffset; + else + Result.getLValueOffset() -= AdditionalOffset; + return true; + } + + // Handle cases like 4 + (unsigned long)&a + if (E->getOpcode() == BO_Add && + RHSVal.isLValue() && LHSVal.isInt()) { + Result = RHSVal; + Result.getLValueOffset() += CharUnits::fromQuantity( + LHSVal.getInt().getZExtValue()); + return true; + } + + if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue()) { + // Handle (intptr_t)&&A - (intptr_t)&&B. + if (!LHSVal.getLValueOffset().isZero() || + !RHSVal.getLValueOffset().isZero()) + return false; + const Expr *LHSExpr = LHSVal.getLValueBase().dyn_cast<const Expr*>(); + const Expr *RHSExpr = RHSVal.getLValueBase().dyn_cast<const Expr*>(); + if (!LHSExpr || !RHSExpr) + return false; + const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr); + const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr); + if (!LHSAddrExpr || !RHSAddrExpr) + return false; + // Make sure both labels come from the same function. + if (LHSAddrExpr->getLabel()->getDeclContext() != + RHSAddrExpr->getLabel()->getDeclContext()) + return false; + Result = APValue(LHSAddrExpr, RHSAddrExpr); + return true; + } + + // All the following cases expect both operands to be an integer + if (!LHSVal.isInt() || !RHSVal.isInt()) + return Error(E); + + const APSInt &LHS = LHSVal.getInt(); + APSInt RHS = RHSVal.getInt(); + + switch (E->getOpcode()) { + default: + return Error(E); + case BO_Mul: + return Success(CheckedIntArithmetic(Info, E, LHS, RHS, + LHS.getBitWidth() * 2, + std::multiplies<APSInt>()), E, + Result); + case BO_Add: + return Success(CheckedIntArithmetic(Info, E, LHS, RHS, + LHS.getBitWidth() + 1, + std::plus<APSInt>()), E, Result); + case BO_Sub: + return Success(CheckedIntArithmetic(Info, E, LHS, RHS, + LHS.getBitWidth() + 1, + std::minus<APSInt>()), E, Result); + case BO_And: return Success(LHS & RHS, E, Result); + case BO_Xor: return Success(LHS ^ RHS, E, Result); + case BO_Or: return Success(LHS | RHS, E, Result); + case BO_Div: + case BO_Rem: + if (RHS == 0) + return Error(E, diag::note_expr_divide_by_zero); + // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. The latter is + // not actually undefined behavior in C++11 due to a language defect. + if (RHS.isNegative() && RHS.isAllOnesValue() && + LHS.isSigned() && LHS.isMinSignedValue()) + HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); + return Success(E->getOpcode() == BO_Rem ? LHS % RHS : LHS / RHS, E, + Result); + case BO_Shl: { + // During constant-folding, a negative shift is an opposite shift. Such + // a shift is not a constant expression. + if (RHS.isSigned() && RHS.isNegative()) { + CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; + RHS = -RHS; + goto shift_right; + } + + shift_left: + // C++11 [expr.shift]p1: Shift width must be less than the bit width of + // the shifted type. + unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); + if (SA != RHS) { + CCEDiag(E, diag::note_constexpr_large_shift) + << RHS << E->getType() << LHS.getBitWidth(); + } else if (LHS.isSigned()) { + // C++11 [expr.shift]p2: A signed left shift must have a non-negative + // operand, and must not overflow the corresponding unsigned type. + if (LHS.isNegative()) + CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; + else if (LHS.countLeadingZeros() < SA) + CCEDiag(E, diag::note_constexpr_lshift_discards); + } + + return Success(LHS << SA, E, Result); + } + case BO_Shr: { + // During constant-folding, a negative shift is an opposite shift. Such a + // shift is not a constant expression. + if (RHS.isSigned() && RHS.isNegative()) { + CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; + RHS = -RHS; + goto shift_left; + } + + shift_right: + // C++11 [expr.shift]p1: Shift width must be less than the bit width of the + // shifted type. + unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); + if (SA != RHS) + CCEDiag(E, diag::note_constexpr_large_shift) + << RHS << E->getType() << LHS.getBitWidth(); + + return Success(LHS >> SA, E, Result); + } + + case BO_LT: return Success(LHS < RHS, E, Result); + case BO_GT: return Success(LHS > RHS, E, Result); + case BO_LE: return Success(LHS <= RHS, E, Result); + case BO_GE: return Success(LHS >= RHS, E, Result); + case BO_EQ: return Success(LHS == RHS, E, Result); + case BO_NE: return Success(LHS != RHS, E, Result); + } +} - return Success(rhsResult, E); +void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { + Job &job = Queue.back(); + + switch (job.Kind) { + case Job::AnyExprKind: { + if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(job.E)) { + if (shouldEnqueue(Bop)) { + job.Kind = Job::BinOpKind; + enqueue(Bop->getLHS()); + return; } } + + EvaluateExpr(job.E, Result); + Queue.pop_back(); + return; + } + + case Job::BinOpKind: { + const BinaryOperator *Bop = cast<BinaryOperator>(job.E); + bool SuppressRHSDiags = false; + if (!VisitBinOpLHSOnly(Result, Bop, SuppressRHSDiags)) { + Queue.pop_back(); + return; + } + if (SuppressRHSDiags) + job.startSpeculativeEval(Info); + job.LHSResult.swap(Result); + job.Kind = Job::BinOpVisitedLHSKind; + enqueue(Bop->getRHS()); + return; + } + + case Job::BinOpVisitedLHSKind: { + const BinaryOperator *Bop = cast<BinaryOperator>(job.E); + EvalResult RHS; + RHS.swap(Result); + Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val); + Queue.pop_back(); + return; } - - return false; } + + llvm_unreachable("Invalid Job::Kind!"); +} + +bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + if (E->isAssignmentOp()) + return Error(E); + + if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E)) + return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E); QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); @@ -1398,10 +4847,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { assert(RHSTy->isAnyComplexType() && "Invalid comparison"); ComplexValue LHS, RHS; - if (!EvaluateComplex(E->getLHS(), LHS, Info)) + bool LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); + if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; - if (!EvaluateComplex(E->getRHS(), RHS, Info)) + if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS.isComplexFloat()) { @@ -1440,10 +4890,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { RHSTy->isRealFloatingType()) { APFloat RHS(0.0), LHS(0.0); - if (!EvaluateFloat(E->getRHS(), RHS, Info)) + bool LHSOK = EvaluateFloat(E->getRHS(), RHS, Info); + if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; - if (!EvaluateFloat(E->getLHS(), LHS, Info)) + if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK) return false; APFloat::cmpResult CR = LHS.compare(RHS); @@ -1470,155 +4921,232 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } if (LHSTy->isPointerType() && RHSTy->isPointerType()) { - if (E->getOpcode() == BO_Sub || E->isEqualityOp()) { - LValue LHSValue; - if (!EvaluatePointer(E->getLHS(), LHSValue, Info)) + if (E->getOpcode() == BO_Sub || E->isComparisonOp()) { + LValue LHSValue, RHSValue; + + bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); + if (!LHSOK && Info.keepEvaluatingAfterFailure()) return false; - LValue RHSValue; - if (!EvaluatePointer(E->getRHS(), RHSValue, Info)) + if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; - // Reject any bases from the normal codepath; we special-case comparisons - // to null. - if (LHSValue.getLValueBase()) { - if (!E->isEqualityOp()) - return false; - if (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero()) - return false; - bool bres; - if (!EvalPointerValueAsBool(LHSValue, bres)) - return false; - return Success(bres ^ (E->getOpcode() == BO_EQ), E); - } else if (RHSValue.getLValueBase()) { + // Reject differing bases from the normal codepath; we special-case + // comparisons to null. + if (!HasSameBase(LHSValue, RHSValue)) { + if (E->getOpcode() == BO_Sub) { + // Handle &&A - &&B. + if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero()) + return false; + const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>(); + const Expr *RHSExpr = LHSValue.Base.dyn_cast<const Expr*>(); + if (!LHSExpr || !RHSExpr) + return false; + const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr); + const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr); + if (!LHSAddrExpr || !RHSAddrExpr) + return false; + // Make sure both labels come from the same function. + if (LHSAddrExpr->getLabel()->getDeclContext() != + RHSAddrExpr->getLabel()->getDeclContext()) + return false; + Result = APValue(LHSAddrExpr, RHSAddrExpr); + return true; + } + // Inequalities and subtractions between unrelated pointers have + // unspecified or undefined behavior. if (!E->isEqualityOp()) - return false; - if (LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero()) - return false; - bool bres; - if (!EvalPointerValueAsBool(RHSValue, bres)) - return false; - return Success(bres ^ (E->getOpcode() == BO_EQ), E); + return Error(E); + // A constant address may compare equal to the address of a symbol. + // The one exception is that address of an object cannot compare equal + // to a null pointer constant. + if ((!LHSValue.Base && !LHSValue.Offset.isZero()) || + (!RHSValue.Base && !RHSValue.Offset.isZero())) + return Error(E); + // It's implementation-defined whether distinct literals will have + // distinct addresses. In clang, the result of such a comparison is + // unspecified, so it is not a constant expression. However, we do know + // that the address of a literal will be non-null. + if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) && + LHSValue.Base && RHSValue.Base) + return Error(E); + // We can't tell whether weak symbols will end up pointing to the same + // object. + if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) + return Error(E); + // Pointers with different bases cannot represent the same object. + // (Note that clang defaults to -fmerge-all-constants, which can + // lead to inconsistent results for comparisons involving the address + // of a constant; this generally doesn't matter in practice.) + return Success(E->getOpcode() == BO_NE, E); } + const CharUnits &LHSOffset = LHSValue.getLValueOffset(); + const CharUnits &RHSOffset = RHSValue.getLValueOffset(); + + SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator(); + SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator(); + if (E->getOpcode() == BO_Sub) { + // C++11 [expr.add]p6: + // Unless both pointers point to elements of the same array object, or + // one past the last element of the array object, the behavior is + // undefined. + if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && + !AreElementsOfSameArray(getType(LHSValue.Base), + LHSDesignator, RHSDesignator)) + CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array); + QualType Type = E->getLHS()->getType(); QualType ElementType = Type->getAs<PointerType>()->getPointeeType(); - CharUnits ElementSize = CharUnits::One(); - if (!ElementType->isVoidType() && !ElementType->isFunctionType()) - ElementSize = Info.Ctx.getTypeSizeInChars(ElementType); + CharUnits ElementSize; + if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize)) + return false; - CharUnits Diff = LHSValue.getLValueOffset() - - RHSValue.getLValueOffset(); - return Success(Diff / ElementSize, E); + // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime, + // and produce incorrect results when it overflows. Such behavior + // appears to be non-conforming, but is common, so perhaps we should + // assume the standard intended for such cases to be undefined behavior + // and check for them. + + // Compute (LHSOffset - RHSOffset) / Size carefully, checking for + // overflow in the final conversion to ptrdiff_t. + APSInt LHS( + llvm::APInt(65, (int64_t)LHSOffset.getQuantity(), true), false); + APSInt RHS( + llvm::APInt(65, (int64_t)RHSOffset.getQuantity(), true), false); + APSInt ElemSize( + llvm::APInt(65, (int64_t)ElementSize.getQuantity(), true), false); + APSInt TrueResult = (LHS - RHS) / ElemSize; + APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType())); + + if (Result.extend(65) != TrueResult) + HandleOverflow(Info, E, TrueResult, E->getType()); + return Success(Result, E); } - bool Result; - if (E->getOpcode() == BO_EQ) { - Result = LHSValue.getLValueOffset() == RHSValue.getLValueOffset(); - } else { - Result = LHSValue.getLValueOffset() != RHSValue.getLValueOffset(); - } - return Success(Result, E); - } - } - if (!LHSTy->isIntegralOrEnumerationType() || - !RHSTy->isIntegralOrEnumerationType()) { - // We can't continue from here for non-integral types, and they - // could potentially confuse the following operations. - return false; - } - - // The LHS of a constant expr is always evaluated and needed. - if (!Visit(E->getLHS())) - return false; // error in subexpression. - APValue RHSVal; - if (!EvaluateIntegerOrLValue(E->getRHS(), RHSVal, Info)) - return false; + // C++11 [expr.rel]p3: + // Pointers to void (after pointer conversions) can be compared, with a + // result defined as follows: If both pointers represent the same + // address or are both the null pointer value, the result is true if the + // operator is <= or >= and false otherwise; otherwise the result is + // unspecified. + // We interpret this as applying to pointers to *cv* void. + if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && + E->isRelationalOp()) + CCEDiag(E, diag::note_constexpr_void_comparison); + + // C++11 [expr.rel]p2: + // - If two pointers point to non-static data members of the same object, + // or to subobjects or array elements fo such members, recursively, the + // pointer to the later declared member compares greater provided the + // two members have the same access control and provided their class is + // not a union. + // [...] + // - Otherwise pointer comparisons are unspecified. + if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && + E->isRelationalOp()) { + bool WasArrayIndex; + unsigned Mismatch = + FindDesignatorMismatch(getType(LHSValue.Base), LHSDesignator, + RHSDesignator, WasArrayIndex); + // At the point where the designators diverge, the comparison has a + // specified value if: + // - we are comparing array indices + // - we are comparing fields of a union, or fields with the same access + // Otherwise, the result is unspecified and thus the comparison is not a + // constant expression. + if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() && + Mismatch < RHSDesignator.Entries.size()) { + const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]); + const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]); + if (!LF && !RF) + CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes); + else if (!LF) + CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) + << getAsBaseClass(LHSDesignator.Entries[Mismatch]) + << RF->getParent() << RF; + else if (!RF) + CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) + << getAsBaseClass(RHSDesignator.Entries[Mismatch]) + << LF->getParent() << LF; + else if (!LF->getParent()->isUnion() && + LF->getAccess() != RF->getAccess()) + CCEDiag(E, diag::note_constexpr_pointer_comparison_differing_access) + << LF << LF->getAccess() << RF << RF->getAccess() + << LF->getParent(); + } + } - // Handle cases like (unsigned long)&a + 4. - if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) { - CharUnits Offset = Result.getLValueOffset(); - CharUnits AdditionalOffset = CharUnits::fromQuantity( - RHSVal.getInt().getZExtValue()); - if (E->getOpcode() == BO_Add) - Offset += AdditionalOffset; - else - Offset -= AdditionalOffset; - Result = APValue(Result.getLValueBase(), Offset); - return true; + switch (E->getOpcode()) { + default: llvm_unreachable("missing comparison operator"); + case BO_LT: return Success(LHSOffset < RHSOffset, E); + case BO_GT: return Success(LHSOffset > RHSOffset, E); + case BO_LE: return Success(LHSOffset <= RHSOffset, E); + case BO_GE: return Success(LHSOffset >= RHSOffset, E); + case BO_EQ: return Success(LHSOffset == RHSOffset, E); + case BO_NE: return Success(LHSOffset != RHSOffset, E); + } + } } - // Handle cases like 4 + (unsigned long)&a - if (E->getOpcode() == BO_Add && - RHSVal.isLValue() && Result.isInt()) { - CharUnits Offset = RHSVal.getLValueOffset(); - Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue()); - Result = APValue(RHSVal.getLValueBase(), Offset); - return true; - } + if (LHSTy->isMemberPointerType()) { + assert(E->isEqualityOp() && "unexpected member pointer operation"); + assert(RHSTy->isMemberPointerType() && "invalid comparison"); - // All the following cases expect both operands to be an integer - if (!Result.isInt() || !RHSVal.isInt()) - return false; + MemberPtr LHSValue, RHSValue; - APSInt& RHS = RHSVal.getInt(); + bool LHSOK = EvaluateMemberPointer(E->getLHS(), LHSValue, Info); + if (!LHSOK && Info.keepEvaluatingAfterFailure()) + return false; - switch (E->getOpcode()) { - default: - return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E); - case BO_Mul: return Success(Result.getInt() * RHS, E); - case BO_Add: return Success(Result.getInt() + RHS, E); - case BO_Sub: return Success(Result.getInt() - RHS, E); - case BO_And: return Success(Result.getInt() & RHS, E); - case BO_Xor: return Success(Result.getInt() ^ RHS, E); - case BO_Or: return Success(Result.getInt() | RHS, E); - case BO_Div: - if (RHS == 0) - return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E); - return Success(Result.getInt() / RHS, E); - case BO_Rem: - if (RHS == 0) - return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E); - return Success(Result.getInt() % RHS, E); - case BO_Shl: { - // During constant-folding, a negative shift is an opposite shift. - if (RHS.isSigned() && RHS.isNegative()) { - RHS = -RHS; - goto shift_right; - } + if (!EvaluateMemberPointer(E->getRHS(), RHSValue, Info) || !LHSOK) + return false; - shift_left: - unsigned SA - = (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1); - return Success(Result.getInt() << SA, E); - } - case BO_Shr: { - // During constant-folding, a negative shift is an opposite shift. - if (RHS.isSigned() && RHS.isNegative()) { - RHS = -RHS; - goto shift_left; + // C++11 [expr.eq]p2: + // If both operands are null, they compare equal. Otherwise if only one is + // null, they compare unequal. + if (!LHSValue.getDecl() || !RHSValue.getDecl()) { + bool Equal = !LHSValue.getDecl() && !RHSValue.getDecl(); + return Success(E->getOpcode() == BO_EQ ? Equal : !Equal, E); } - shift_right: - unsigned SA = - (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1); - return Success(Result.getInt() >> SA, E); - } - - case BO_LT: return Success(Result.getInt() < RHS, E); - case BO_GT: return Success(Result.getInt() > RHS, E); - case BO_LE: return Success(Result.getInt() <= RHS, E); - case BO_GE: return Success(Result.getInt() >= RHS, E); - case BO_EQ: return Success(Result.getInt() == RHS, E); - case BO_NE: return Success(Result.getInt() != RHS, E); - } + // Otherwise if either is a pointer to a virtual member function, the + // result is unspecified. + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LHSValue.getDecl())) + if (MD->isVirtual()) + CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(RHSValue.getDecl())) + if (MD->isVirtual()) + CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; + + // Otherwise they compare equal if and only if they would refer to the + // same member of the same most derived object or the same subobject if + // they were dereferenced with a hypothetical object of the associated + // class type. + bool Equal = LHSValue == RHSValue; + return Success(E->getOpcode() == BO_EQ ? Equal : !Equal, E); + } + + if (LHSTy->isNullPtrType()) { + assert(E->isComparisonOp() && "unexpected nullptr operation"); + assert(RHSTy->isNullPtrType() && "missing pointer conversion"); + // C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t + // are compared, the result is true of the operator is <=, >= or ==, and + // false otherwise. + BinaryOperator::Opcode Opcode = E->getOpcode(); + return Success(Opcode == BO_EQ || Opcode == BO_LE || Opcode == BO_GE, E); + } + + assert((!LHSTy->isIntegralOrEnumerationType() || + !RHSTy->isIntegralOrEnumerationType()) && + "DataRecursiveIntBinOpEvaluator should have handled integral types"); + // We can't continue from here for non-integral types. + return ExprEvaluatorBaseTy::VisitBinaryOperator(E); } CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { - // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, - // the result is the size of the referenced type." // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the // result shall be the alignment of the referenced type." if (const ReferenceType *Ref = T->getAs<ReferenceType>()) @@ -1678,34 +5206,24 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( QualType SrcTy = E->getTypeOfArgument(); // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, // the result is the size of the referenced type." - // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the - // result shall be the alignment of the referenced type." if (const ReferenceType *Ref = SrcTy->getAs<ReferenceType>()) SrcTy = Ref->getPointeeType(); - // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc - // extension. - if (SrcTy->isVoidType() || SrcTy->isFunctionType()) - return Success(1, E); - - // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. - if (!SrcTy->isConstantSizeType()) + CharUnits Sizeof; + if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof)) return false; - - // Get information about the size. - return Success(Info.Ctx.getTypeSizeInChars(SrcTy), E); + return Success(Sizeof, E); } } llvm_unreachable("unknown expr/type trait"); - return false; } bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CharUnits Result; unsigned n = OOE->getNumComponents(); if (n == 0) - return false; + return Error(OOE); QualType CurrentType = OOE->getTypeSourceInfo()->getType(); for (unsigned i = 0; i != n; ++i) { OffsetOfExpr::OffsetOfNode ON = OOE->getComponent(i); @@ -1717,18 +5235,18 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { return false; const ArrayType *AT = Info.Ctx.getAsArrayType(CurrentType); if (!AT) - return false; + return Error(OOE); CurrentType = AT->getElementType(); CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType); Result += IdxResult.getSExtValue() * ElementSize; break; } - + case OffsetOfExpr::OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); const RecordType *RT = CurrentType->getAs<RecordType>(); - if (!RT) - return false; + if (!RT) + return Error(OOE); RecordDecl *RD = RT->getDecl(); const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); unsigned i = MemberDecl->getFieldIndex(); @@ -1737,20 +5255,19 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CurrentType = MemberDecl->getType().getNonReferenceType(); break; } - + case OffsetOfExpr::OffsetOfNode::Identifier: llvm_unreachable("dependent __builtin_offsetof"); - return false; - + case OffsetOfExpr::OffsetOfNode::Base: { CXXBaseSpecifier *BaseSpec = ON.getBase(); if (BaseSpec->isVirtual()) - return false; + return Error(OOE); // Find the layout of the class whose base we are looking into. const RecordType *RT = CurrentType->getAs<RecordType>(); - if (!RT) - return false; + if (!RT) + return Error(OOE); RecordDecl *RD = RT->getDecl(); const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); @@ -1758,7 +5275,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CurrentType = BaseSpec->getType(); const RecordType *BaseRT = CurrentType->getAs<RecordType>(); if (!BaseRT) - return false; + return Error(OOE); // Add the offset to the base. Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl())); @@ -1770,41 +5287,41 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { } bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { - if (E->getOpcode() == UO_LNot) { - // LNot's operand isn't necessarily an integer, so we handle it specially. - bool bres; - if (!HandleConversionToBool(E->getSubExpr(), bres, Info)) - return false; - return Success(!bres, E); - } - - // Only handle integral operations... - if (!E->getSubExpr()->getType()->isIntegralOrEnumerationType()) - return false; - - // Get the operand value into 'Result'. - if (!Visit(E->getSubExpr())) - return false; - switch (E->getOpcode()) { default: // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. // See C99 6.6p3. - return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E); + return Error(E); case UO_Extension: // FIXME: Should extension allow i-c-e extension expressions in its scope? // If so, we could clear the diagnostic ID. - return true; + return Visit(E->getSubExpr()); case UO_Plus: - // The result is always just the subexpr. - return true; - case UO_Minus: - if (!Result.isInt()) return false; - return Success(-Result.getInt(), E); - case UO_Not: - if (!Result.isInt()) return false; + // The result is just the value. + 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()) + HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), + E->getType()); + return Success(-Value, E); + } + case UO_Not: { + if (!Visit(E->getSubExpr())) + return false; + if (!Result.isInt()) return Error(E); return Success(~Result.getInt(), E); } + case UO_LNot: { + bool bres; + if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) + return false; + return Success(!bres, E); + } + } } /// HandleCast - This is used to evaluate implicit or explicit casts where the @@ -1826,6 +5343,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_NullToMemberPointer: case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: + case CK_ReinterpretMemberPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_ToVoid: @@ -1847,18 +5365,20 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_BitCast: case CK_Dependent: - case CK_GetObjCProperty: case CK_LValueBitCast: - case CK_UserDefinedConversion: case CK_ARCProduceObject: case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: - return false; + case CK_CopyAndAutoreleaseBlockObject: + return Error(E); + case CK_UserDefinedConversion: case CK_LValueToRValue: + case CK_AtomicToNonAtomic: + case CK_NonAtomicToAtomic: case CK_NoOp: - return Visit(E->getSubExpr()); + return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_MemberPointerToBoolean: case CK_PointerToBoolean: @@ -1867,7 +5387,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { bool BoolResult; - if (!HandleConversionToBool(SubExpr, BoolResult, Info)) + if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) return false; return Success(BoolResult, E); } @@ -1877,31 +5397,44 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return false; if (!Result.isInt()) { + // Allow casts of address-of-label differences if they are no-ops + // or narrowing. (The narrowing case isn't actually guaranteed to + // be constant-evaluatable except in some narrow cases which are hard + // to detect here. We let it through on the assumption the user knows + // what they are doing.) + if (Result.isAddrLabelDiff()) + return Info.Ctx.getTypeSize(DestType) <= Info.Ctx.getTypeSize(SrcType); // Only allow casts of lvalues if they are lossless. return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); } - return Success(HandleIntToIntCast(DestType, SrcType, - Result.getInt(), Info.Ctx), E); + return Success(HandleIntToIntCast(Info, E, DestType, SrcType, + Result.getInt()), E); } case CK_PointerToIntegral: { + CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + LValue LV; if (!EvaluatePointer(SubExpr, LV, Info)) return false; if (LV.getLValueBase()) { // Only allow based lvalue casts if they are lossless. + // FIXME: Allow a larger integer size than the pointer size, and allow + // narrowing back down to pointer width in subsequent integral casts. + // FIXME: Check integer type's active bits, not its type size. if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType)) - return false; + return Error(E); + LV.Designator.setInvalid(); LV.moveInto(Result); return true; } APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(), SrcType); - return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E); + return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } case CK_IntegralComplexToReal: { @@ -1916,19 +5449,23 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { if (!EvaluateFloat(SubExpr, F, Info)) return false; - return Success(HandleFloatToIntCast(DestType, SrcType, F, Info.Ctx), E); + APSInt Value; + if (!HandleFloatToIntCast(Info, E, SrcType, F, DestType, Value)) + return false; + return Success(Value, E); } } llvm_unreachable("unknown cast resulting in integral value"); - return false; } bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue LV; - if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt()) - return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E); + if (!EvaluateComplex(E->getSubExpr(), LV, Info)) + return false; + if (!LV.isComplexInt()) + return Error(E); return Success(LV.getComplexIntReal(), E); } @@ -1938,13 +5475,14 @@ bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isComplexIntegerType()) { ComplexValue LV; - if (!EvaluateComplex(E->getSubExpr(), LV, Info) || !LV.isComplexInt()) - return Error(E->getExprLoc(), diag::note_invalid_subexpr_in_ice, E); + if (!EvaluateComplex(E->getSubExpr(), LV, Info)) + return false; + if (!LV.isComplexInt()) + return Error(E); return Success(LV.getComplexIntImag(), E); } - if (!E->getSubExpr()->isEvaluatable(Info.Ctx)) - Info.EvalResult.HasSideEffects = true; + VisitIgnoredValue(E->getSubExpr()); return Success(0, E); } @@ -1972,11 +5510,8 @@ public: Result = V.getFloat(); return true; } - bool Error(const Stmt *S) { - return false; - } - bool ValueInitialization(const Expr *E) { + bool ZeroInitialization(const Expr *E) { Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); return true; } @@ -1991,15 +5526,12 @@ public: bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); - bool VisitDeclRefExpr(const DeclRefExpr *E); - - // FIXME: Missing: array subscript of vector, member of vector, - // ImplicitValueInitExpr + // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { - assert(E->getType()->isRealFloatingType()); + assert(E->isRValue() && E->getType()->isRealFloatingType()); return FloatExprEvaluator(Info, Result).Visit(E); } @@ -2029,7 +5561,7 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, } bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { - switch (E->isBuiltinCall(Info.Ctx)) { + switch (E->isBuiltinCall()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -2048,16 +5580,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nans: case Builtin::BI__builtin_nansf: case Builtin::BI__builtin_nansl: - return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), - true, Result); + if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), + true, Result)) + return Error(E); + return true; case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. - return TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), - false, Result); + if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), + false, Result)) + return Error(E); + return true; case Builtin::BI__builtin_fabs: case Builtin::BI__builtin_fabsf: @@ -2082,48 +5618,6 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { } } -bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { - if (ExprEvaluatorBaseTy::VisitDeclRefExpr(E)) - return true; - - const Decl *D = E->getDecl(); - if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D)) return false; - const VarDecl *VD = cast<VarDecl>(D); - - // Require the qualifiers to be const and not volatile. - CanQualType T = Info.Ctx.getCanonicalType(E->getType()); - if (!T.isConstQualified() || T.isVolatileQualified()) - return false; - - const Expr *Init = VD->getAnyInitializer(); - if (!Init) return false; - - if (APValue *V = VD->getEvaluatedValue()) { - if (V->isFloat()) { - Result = V->getFloat(); - return true; - } - return false; - } - - if (VD->isEvaluatingValue()) - return false; - - VD->setEvaluatingValue(); - - Expr::EvalResult InitResult; - if (Init->Evaluate(InitResult, Info.Ctx) && !InitResult.HasSideEffects && - InitResult.Val.isFloat()) { - // Cache the evaluated value in the variable declaration. - Result = InitResult.Val.getFloat(); - VD->setEvaluatedValue(InitResult.Val); - return true; - } - - VD->setEvaluatedValue(APValue()); - return false; -} - bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue CV; @@ -2145,70 +5639,55 @@ bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { return true; } - if (!E->getSubExpr()->isEvaluatable(Info.Ctx)) - Info.EvalResult.HasSideEffects = true; + VisitIgnoredValue(E->getSubExpr()); const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); Result = llvm::APFloat::getZero(Sem); return true; } bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { - if (E->getOpcode() == UO_Deref) - return false; - - if (!EvaluateFloat(E->getSubExpr(), Result, Info)) - return false; - switch (E->getOpcode()) { - default: return false; + default: return Error(E); case UO_Plus: - return true; + return EvaluateFloat(E->getSubExpr(), Result, Info); case UO_Minus: + if (!EvaluateFloat(E->getSubExpr(), Result, Info)) + return false; Result.changeSign(); return true; } } bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { - if (E->getOpcode() == BO_Comma) { - if (!EvaluateFloat(E->getRHS(), Result, Info)) - return false; - - // If we can't evaluate the LHS, it might have side effects; - // conservatively mark it. - if (!E->getLHS()->isEvaluatable(Info.Ctx)) - Info.EvalResult.HasSideEffects = true; - - return true; - } - - // We can't evaluate pointer-to-member operations. - if (E->isPtrMemOp()) - return false; + if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) + return ExprEvaluatorBaseTy::VisitBinaryOperator(E); - // FIXME: Diagnostics? I really don't understand how the warnings - // and errors are supposed to work. APFloat RHS(0.0); - if (!EvaluateFloat(E->getLHS(), Result, Info)) + bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info); + if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; - if (!EvaluateFloat(E->getRHS(), RHS, Info)) + if (!EvaluateFloat(E->getRHS(), RHS, Info) || !LHSOK) return false; switch (E->getOpcode()) { - default: return false; + default: return Error(E); case BO_Mul: Result.multiply(RHS, APFloat::rmNearestTiesToEven); - return true; + break; case BO_Add: Result.add(RHS, APFloat::rmNearestTiesToEven); - return true; + break; case BO_Sub: Result.subtract(RHS, APFloat::rmNearestTiesToEven); - return true; + break; case BO_Div: Result.divide(RHS, APFloat::rmNearestTiesToEven); - return true; + break; } + + if (Result.isInfinity() || Result.isNaN()) + CCEDiag(E, diag::note_constexpr_float_arithmetic) << Result.isNaN(); + return true; } bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { @@ -2221,27 +5700,20 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: - return false; - - case CK_LValueToRValue: - case CK_NoOp: - return Visit(SubExpr); + return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_IntegralToFloating: { APSInt IntResult; - if (!EvaluateInteger(SubExpr, IntResult, Info)) - return false; - Result = HandleIntToFloatCast(E->getType(), SubExpr->getType(), - IntResult, Info.Ctx); - return true; + return EvaluateInteger(SubExpr, IntResult, Info) && + HandleIntToFloatCast(Info, E, SubExpr->getType(), IntResult, + E->getType(), Result); } case CK_FloatingCast: { if (!Visit(SubExpr)) return false; - Result = HandleFloatToFloatCast(E->getType(), SubExpr->getType(), - Result, Info.Ctx); - return true; + return HandleFloatToFloatCast(Info, E, SubExpr->getType(), E->getType(), + Result); } case CK_FloatingComplexToReal: { @@ -2252,8 +5724,6 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { return true; } } - - return false; } //===----------------------------------------------------------------------===// @@ -2273,30 +5743,43 @@ public: Result.setFrom(V); return true; } - bool Error(const Expr *E) { - return false; - } + + bool ZeroInitialization(const Expr *E); //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// bool VisitImaginaryLiteral(const ImaginaryLiteral *E); - bool VisitCastExpr(const CastExpr *E); - bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); - // FIXME Missing: ImplicitValueInitExpr, InitListExpr + bool VisitInitListExpr(const InitListExpr *E); }; } // end anonymous namespace static bool EvaluateComplex(const Expr *E, ComplexValue &Result, EvalInfo &Info) { - assert(E->getType()->isAnyComplexType()); + assert(E->isRValue() && E->getType()->isAnyComplexType()); return ComplexExprEvaluator(Info, Result).Visit(E); } +bool ComplexExprEvaluator::ZeroInitialization(const Expr *E) { + QualType ElemTy = E->getType()->getAs<ComplexType>()->getElementType(); + if (ElemTy->isRealFloatingType()) { + Result.makeComplexFloat(); + APFloat Zero = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy)); + Result.FloatReal = Zero; + Result.FloatImag = Zero; + } else { + Result.makeComplexInt(); + APSInt Zero = Info.Ctx.MakeIntValue(0, ElemTy); + Result.IntReal = Zero; + Result.IntImag = Zero; + } + return true; +} + bool ComplexExprEvaluator::VisitImaginaryLiteral(const ImaginaryLiteral *E) { const Expr* SubExpr = E->getSubExpr(); @@ -2338,6 +5821,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: case CK_MemberPointerToBoolean: + case CK_ReinterpretMemberPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_PointerToIntegral: @@ -2362,17 +5846,19 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: + case CK_CopyAndAutoreleaseBlockObject: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: + case CK_AtomicToNonAtomic: + case CK_NonAtomicToAtomic: case CK_NoOp: - return Visit(E->getSubExpr()); + return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_Dependent: - case CK_GetObjCProperty: case CK_LValueBitCast: case CK_UserDefinedConversion: - return false; + return Error(E); case CK_FloatingRealToComplex: { APFloat &Real = Result.FloatReal; @@ -2392,11 +5878,8 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { QualType From = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType(); - Result.FloatReal - = HandleFloatToFloatCast(To, From, Result.FloatReal, Info.Ctx); - Result.FloatImag - = HandleFloatToFloatCast(To, From, Result.FloatImag, Info.Ctx); - return true; + return HandleFloatToFloatCast(Info, E, From, To, Result.FloatReal) && + HandleFloatToFloatCast(Info, E, From, To, Result.FloatImag); } case CK_FloatingComplexToIntegralComplex: { @@ -2407,9 +5890,10 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { QualType From = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType(); Result.makeComplexInt(); - Result.IntReal = HandleFloatToIntCast(To, From, Result.FloatReal, Info.Ctx); - Result.IntImag = HandleFloatToIntCast(To, From, Result.FloatImag, Info.Ctx); - return true; + return HandleFloatToIntCast(Info, E, From, Result.FloatReal, + To, Result.IntReal) && + HandleFloatToIntCast(Info, E, From, Result.FloatImag, + To, Result.IntImag); } case CK_IntegralRealToComplex: { @@ -2430,8 +5914,8 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { QualType From = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType(); - Result.IntReal = HandleIntToIntCast(To, From, Result.IntReal, Info.Ctx); - Result.IntImag = HandleIntToIntCast(To, From, Result.IntImag, Info.Ctx); + Result.IntReal = HandleIntToIntCast(Info, E, To, From, Result.IntReal); + Result.IntImag = HandleIntToIntCast(Info, E, To, From, Result.IntImag); return true; } @@ -2443,39 +5927,32 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { QualType From = E->getSubExpr()->getType()->getAs<ComplexType>()->getElementType(); Result.makeComplexFloat(); - Result.FloatReal = HandleIntToFloatCast(To, From, Result.IntReal, Info.Ctx); - Result.FloatImag = HandleIntToFloatCast(To, From, Result.IntImag, Info.Ctx); - return true; + return HandleIntToFloatCast(Info, E, From, Result.IntReal, + To, Result.FloatReal) && + HandleIntToFloatCast(Info, E, From, Result.IntImag, + To, Result.FloatImag); } } llvm_unreachable("unknown cast resulting in complex value"); - return false; } bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { - if (E->getOpcode() == BO_Comma) { - if (!Visit(E->getRHS())) - return false; - - // If we can't evaluate the LHS, it might have side effects; - // conservatively mark it. - if (!E->getLHS()->isEvaluatable(Info.Ctx)) - Info.EvalResult.HasSideEffects = true; + if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) + return ExprEvaluatorBaseTy::VisitBinaryOperator(E); - return true; - } - if (!Visit(E->getLHS())) + bool LHSOK = Visit(E->getLHS()); + if (!LHSOK && !Info.keepEvaluatingAfterFailure()) return false; ComplexValue RHS; - if (!EvaluateComplex(E->getRHS(), RHS, Info)) + if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; assert(Result.isComplexFloat() == RHS.isComplexFloat() && "Invalid operands to binary operator."); switch (E->getOpcode()) { - default: return false; + default: return Error(E); case BO_Add: if (Result.isComplexFloat()) { Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), @@ -2559,10 +6036,9 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven); Res_i.divide(Den, APFloat::rmNearestTiesToEven); } else { - if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) { - // FIXME: what about diagnostics? - return false; - } + if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) + return Error(E, diag::note_expr_divide_by_zero); + ComplexValue LHS = Result; APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + RHS.getComplexIntImag() * RHS.getComplexIntImag(); @@ -2586,8 +6062,7 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { default: - // FIXME: what about diagnostics? - return false; + return Error(E); case UO_Extension: return true; case UO_Plus: @@ -2612,109 +6087,279 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } } +bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { + if (E->getNumInits() == 2) { + if (E->getType()->isComplexType()) { + Result.makeComplexFloat(); + if (!EvaluateFloat(E->getInit(0), Result.FloatReal, Info)) + return false; + if (!EvaluateFloat(E->getInit(1), Result.FloatImag, Info)) + return false; + } else { + Result.makeComplexInt(); + if (!EvaluateInteger(E->getInit(0), Result.IntReal, Info)) + return false; + if (!EvaluateInteger(E->getInit(1), Result.IntImag, Info)) + return false; + } + return true; + } + return ExprEvaluatorBaseTy::VisitInitListExpr(E); +} + //===----------------------------------------------------------------------===// -// Top level Expr::Evaluate method. +// Void expression evaluation, primarily for a cast to void on the LHS of a +// comma operator //===----------------------------------------------------------------------===// -static bool Evaluate(EvalInfo &Info, const Expr *E) { - if (E->getType()->isVectorType()) { - if (!EvaluateVector(E, Info.EvalResult.Val, Info)) +namespace { +class VoidExprEvaluator + : public ExprEvaluatorBase<VoidExprEvaluator, bool> { +public: + VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} + + bool Success(const APValue &V, const Expr *e) { return true; } + + bool VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + case CK_ToVoid: + VisitIgnoredValue(E->getSubExpr()); + return true; + } + } +}; +} // end anonymous namespace + +static bool EvaluateVoid(const Expr *E, EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isVoidType()); + return VoidExprEvaluator(Info).Visit(E); +} + +//===----------------------------------------------------------------------===// +// Top level Expr::EvaluateAsRValue method. +//===----------------------------------------------------------------------===// + +static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { + // In C, function designators are not lvalues, but we evaluate them as if they + // are. + if (E->isGLValue() || E->getType()->isFunctionType()) { + LValue LV; + if (!EvaluateLValue(E, LV, Info)) return false; - } else if (E->getType()->isIntegralOrEnumerationType()) { - if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(E)) + LV.moveInto(Result); + } else if (E->getType()->isVectorType()) { + if (!EvaluateVector(E, Result, Info)) return false; - if (Info.EvalResult.Val.isLValue() && - !IsGlobalLValue(Info.EvalResult.Val.getLValueBase())) + } else if (E->getType()->isIntegralOrEnumerationType()) { + if (!IntExprEvaluator(Info, Result).Visit(E)) return false; } else if (E->getType()->hasPointerRepresentation()) { LValue LV; if (!EvaluatePointer(E, LV, Info)) return false; - if (!IsGlobalLValue(LV.Base)) - return false; - LV.moveInto(Info.EvalResult.Val); + LV.moveInto(Result); } else if (E->getType()->isRealFloatingType()) { llvm::APFloat F(0.0); if (!EvaluateFloat(E, F, Info)) return false; - - Info.EvalResult.Val = APValue(F); + Result = APValue(F); } else if (E->getType()->isAnyComplexType()) { ComplexValue C; if (!EvaluateComplex(E, C, Info)) return false; - C.moveInto(Info.EvalResult.Val); - } else + C.moveInto(Result); + } else if (E->getType()->isMemberPointerType()) { + MemberPtr P; + if (!EvaluateMemberPointer(E, P, Info)) + return false; + P.moveInto(Result); + return true; + } else if (E->getType()->isArrayType()) { + LValue LV; + LV.set(E, Info.CurrentCall->Index); + if (!EvaluateArray(E, LV, Info.CurrentCall->Temporaries[E], Info)) + return false; + Result = Info.CurrentCall->Temporaries[E]; + } else if (E->getType()->isRecordType()) { + LValue LV; + LV.set(E, Info.CurrentCall->Index); + if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info)) + return false; + Result = Info.CurrentCall->Temporaries[E]; + } else if (E->getType()->isVoidType()) { + if (Info.getLangOpts().CPlusPlus0x) + Info.CCEDiag(E, diag::note_constexpr_nonliteral) + << E->getType(); + else + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); + if (!EvaluateVoid(E, Info)) + return false; + } else if (Info.getLangOpts().CPlusPlus0x) { + Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; + } else { + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } return true; } -/// Evaluate - Return true if this is a constant which we can fold using +/// EvaluateInPlace - Evaluate an expression in-place in an APValue. In some +/// cases, the in-place evaluation is essential, since later initializers for +/// an object can indirectly refer to subobjects which were initialized earlier. +static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, + const Expr *E, CheckConstantExpressionKind CCEK, + bool AllowNonLiteralTypes) { + if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E)) + return false; + + if (E->isRValue()) { + // Evaluate arrays and record types in-place, so that later initializers can + // refer to earlier-initialized members of the object. + if (E->getType()->isArrayType()) + return EvaluateArray(E, This, Result, Info); + else if (E->getType()->isRecordType()) + return EvaluateRecord(E, This, Result, Info); + } + + // For any other type, in-place evaluation is unimportant. + return Evaluate(Result, Info, E); +} + +/// EvaluateAsRValue - Try to evaluate this expression, performing an implicit +/// lvalue-to-rvalue cast if it is an lvalue. +static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { + if (!CheckLiteralType(Info, E)) + return false; + + if (!::Evaluate(Result, Info, E)) + return false; + + if (E->isGLValue()) { + LValue LV; + LV.setFrom(Info.Ctx, Result); + if (!HandleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) + return false; + } + + // Check this core constant expression is a constant expression. + return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result); +} + +/// 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 -/// in Result. -bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const { +/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion +/// will be applied to the result. +bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { + // Fast-path evaluations of integer literals, since we sometimes see files + // containing vast quantities of these. + if (const IntegerLiteral *L = dyn_cast<IntegerLiteral>(this)) { + Result.Val = APValue(APSInt(L->getValue(), + L->getType()->isUnsignedIntegerType())); + return true; + } + + // FIXME: Evaluating values of large array and record types can cause + // performance problems. Only do so in C++11 for now. + if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && + !Ctx.getLangOpts().CPlusPlus0x) + return false; + EvalInfo Info(Ctx, Result); - return ::Evaluate(Info, this); + return ::EvaluateAsRValue(Info, this, Result.Val); } bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const { EvalResult Scratch; - EvalInfo Info(Ctx, Scratch); - - return HandleConversionToBool(this, Result, Info); + return EvaluateAsRValue(Scratch, Ctx) && + HandleConversionToBool(Scratch.Val, Result); } -bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const { - EvalResult Scratch; - EvalInfo Info(Ctx, Scratch); +bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects) const { + if (!getType()->isIntegralOrEnumerationType()) + return false; + + EvalResult ExprResult; + if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() || + (!AllowSideEffects && ExprResult.HasSideEffects)) + return false; - return EvaluateInteger(this, Result, Info) && !Scratch.HasSideEffects; + Result = ExprResult.Val.getInt(); + return true; } bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); LValue LV; - if (EvaluateLValue(this, LV, Info) && - !Result.HasSideEffects && - IsGlobalLValue(LV.Base)) { - LV.moveInto(Result.Val); - return true; - } - return false; + if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects || + !CheckLValueConstantExpression(Info, getExprLoc(), + Ctx.getLValueReferenceType(getType()), LV)) + return false; + + LV.moveInto(Result.Val); + return true; } -bool Expr::EvaluateAsAnyLValue(EvalResult &Result, - const ASTContext &Ctx) const { - EvalInfo Info(Ctx, Result); +bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, + const VarDecl *VD, + llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + // FIXME: Evaluating initializers for large array and record types can cause + // performance problems. Only do so in C++11 for now. + if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && + !Ctx.getLangOpts().CPlusPlus0x) + return false; - LValue LV; - if (EvaluateLValue(this, LV, Info)) { - LV.moveInto(Result.Val); - return true; + Expr::EvalStatus EStatus; + EStatus.Diag = &Notes; + + EvalInfo InitInfo(Ctx, EStatus); + InitInfo.setEvaluatingDecl(VD, Value); + + LValue LVal; + LVal.set(VD); + + // C++11 [basic.start.init]p2: + // Variables with static storage duration or thread storage duration shall be + // zero-initialized before any other initialization takes place. + // This behavior is not present in C. + if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && + !VD->getType()->isReferenceType()) { + ImplicitValueInitExpr VIE(VD->getType()); + if (!EvaluateInPlace(Value, InitInfo, LVal, &VIE, CCEK_Constant, + /*AllowNonLiteralTypes=*/true)) + return false; } - return false; + + if (!EvaluateInPlace(Value, InitInfo, LVal, this, CCEK_Constant, + /*AllowNonLiteralTypes=*/true) || + EStatus.HasSideEffects) + return false; + + return CheckConstantExpression(InitInfo, VD->getLocation(), VD->getType(), + Value); } -/// isEvaluatable - Call Evaluate to see if this expression can be constant -/// folded, but discard the result. +/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be +/// constant folded, but discard the result. bool Expr::isEvaluatable(const ASTContext &Ctx) const { EvalResult Result; - return Evaluate(Result, Ctx) && !Result.HasSideEffects; + return EvaluateAsRValue(Result, Ctx) && !Result.HasSideEffects; } bool Expr::HasSideEffects(const ASTContext &Ctx) const { - Expr::EvalResult Result; - EvalInfo Info(Ctx, Result); - return HasSideEffect(Info).Visit(this); + return HasSideEffect(Ctx).Visit(this); } APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { EvalResult EvalResult; - bool Result = Evaluate(EvalResult, Ctx); + bool Result = EvaluateAsRValue(EvalResult, Ctx); (void)Result; assert(Result && "Could not evaluate expression"); assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); @@ -2746,7 +6391,7 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx) const { // value, it calls into Evalute. // // Meanings of Val: -// 0: This expression is an ICE if it can be evaluated by Evaluate. +// 0: This expression is an ICE. // 1: This expression is not an ICE, but if it isn't evaluated, it's // a legal subexpression for an ICE. This return value is used to handle // the comma operator in C99 mode. @@ -2769,7 +6414,7 @@ static ICEDiag NoDiag() { return ICEDiag(); } static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) { Expr::EvalResult EVResult; - if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects || + if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || !EVResult.Val.isInt()) { return ICEDiag(2, E->getLocStart()); } @@ -2808,6 +6453,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: case Expr::CXXNullPtrLiteralExprClass: + case Expr::UserDefinedLiteralClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: case Expr::CXXNewExprClass: @@ -2823,16 +6469,19 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXDependentScopeMemberExprClass: case Expr::UnresolvedMemberExprClass: case Expr::ObjCStringLiteralClass: + case Expr::ObjCNumericLiteralClass: + case Expr::ObjCArrayLiteralClass: + case Expr::ObjCDictionaryLiteralClass: case Expr::ObjCEncodeExprClass: case Expr::ObjCMessageExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCProtocolExprClass: case Expr::ObjCIvarRefExprClass: case Expr::ObjCPropertyRefExprClass: + case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIsaExprClass: case Expr::ShuffleVectorExprClass: case Expr::BlockExprClass: - case Expr::BlockDeclRefExprClass: case Expr::NoStmtClass: case Expr::OpaqueValueExprClass: case Expr::PackExpansionExprClass: @@ -2840,18 +6489,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: - return ICEDiag(2, E->getLocStart()); - case Expr::InitListExprClass: - if (Ctx.getLangOptions().CPlusPlus0x) { - const InitListExpr *ILE = cast<InitListExpr>(E); - if (ILE->getNumInits() == 0) - return NoDiag(); - if (ILE->getNumInits() == 1) - return CheckICE(ILE->getInit(0), Ctx); - // Fall through for more than 1 expression. - } + case Expr::LambdaExprClass: return ICEDiag(2, E->getLocStart()); case Expr::SizeOfPackExprClass: @@ -2869,28 +6510,32 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx); case Expr::IntegerLiteralClass: case Expr::CharacterLiteralClass: + case Expr::ObjCBoolLiteralExprClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: return NoDiag(); case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: { + // C99 6.6/3 allows function calls within unevaluated subexpressions of + // constant expressions, but they can never be ICEs because an ICE cannot + // contain an operand of (pointer to) function type. const CallExpr *CE = cast<CallExpr>(E); - if (CE->isBuiltinCall(Ctx)) + if (CE->isBuiltinCall()) return CheckEvalInICE(E, Ctx); return ICEDiag(2, E->getLocStart()); } - case Expr::DeclRefExprClass: + case Expr::DeclRefExprClass: { if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) return NoDiag(); - if (Ctx.getLangOptions().CPlusPlus && - E->getType().getCVRQualifiers() == Qualifiers::Const) { - const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl(); - + const ValueDecl *D = dyn_cast<ValueDecl>(cast<DeclRefExpr>(E)->getDecl()); + if (Ctx.getLangOpts().CPlusPlus && + D && IsConstNonVolatile(D->getType())) { // Parameter variables are never constants. Without this check, // getAnyInitializer() can find a default argument, which leads // to chaos. @@ -2901,40 +6546,20 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // A variable of non-volatile const-qualified integral or enumeration // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) { - Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers(); - if (Quals.hasVolatile() || !Quals.hasConst()) + if (!Dcl->getType()->isIntegralOrEnumerationType()) return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - - // Look for a declaration of this variable that has an initializer. - const VarDecl *ID = 0; - const Expr *Init = Dcl->getAnyInitializer(ID); - if (Init) { - if (ID->isInitKnownICE()) { - // We have already checked whether this subexpression is an - // integral constant expression. - if (ID->isInitICE()) - return NoDiag(); - else - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - } - - // It's an ICE whether or not the definition we found is - // out-of-line. See DR 721 and the discussion in Clang PR - // 6206 for details. - - if (Dcl->isCheckingICE()) { - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - } - Dcl->setCheckingICE(); - ICEDiag Result = CheckICE(Init, Ctx); - // Cache the result of the ICE test. - Dcl->setInitKnownICE(Result.Val == 0); - return Result; - } + const VarDecl *VD; + // Look for a declaration of this variable that has an initializer, and + // check whether it is an ICE. + if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE()) + return NoDiag(); + else + return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); } } return ICEDiag(2, E->getLocStart()); + } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast<UnaryOperator>(E); switch (Exp->getOpcode()) { @@ -2944,6 +6569,9 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case UO_PreDec: case UO_AddrOf: case UO_Deref: + // C99 6.6/3 allows increment and decrement within unevaluated + // subexpressions of constant expressions, but they can never be ICEs + // because an ICE cannot contain an lvalue operand. return ICEDiag(2, E->getLocStart()); case UO_Extension: case UO_LNot: @@ -2959,8 +6587,8 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using - // Evaluate matches the proposed gcc behavior for cases like - // "offsetof(struct s{int x[4];}, x[!.0])". This doesn't affect + // EvaluateAsRValue matches the proposed gcc behavior for cases like + // "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect // compliance: we should warn earlier for offsetof expressions with // array subscripts that aren't ICEs, and if the array subscripts // are ICEs, the value of the offsetof must be an integer constant. @@ -2989,6 +6617,9 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: + // C99 6.6/3 allows assignments within unevaluated subexpressions of + // constant expressions, but they can never be ICEs because an ICE cannot + // contain an lvalue operand. return ICEDiag(2, E->getLocStart()); case BO_Mul: @@ -3012,7 +6643,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (Exp->getOpcode() == BO_Div || Exp->getOpcode() == BO_Rem) { - // Evaluate gives an error for undefined Div/Rem, so make sure + // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure // we don't evaluate one. if (LHSResult.Val == 0 && RHSResult.Val == 0) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); @@ -3026,7 +6657,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { } } if (Exp->getOpcode() == BO_Comma) { - if (Ctx.getLangOptions().C99) { + if (Ctx.getLangOpts().C99) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. if (LHSResult.Val == 0 && RHSResult.Val == 0) @@ -3043,21 +6674,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case BO_LAnd: case BO_LOr: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); - - // C++0x [expr.const]p2: - // [...] subexpressions of logical AND (5.14), logical OR - // (5.15), and condi- tional (5.16) operations that are not - // evaluated are not considered. - if (Ctx.getLangOptions().CPlusPlus0x && LHSResult.Val == 0) { - if (Exp->getOpcode() == BO_LAnd && - Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0) - return LHSResult; - - if (Exp->getOpcode() == BO_LOr && - Exp->getLHS()->EvaluateKnownConstInt(Ctx) != 0) - return LHSResult; - } - ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (LHSResult.Val == 0 && RHSResult.Val == 1) { // Rare case where the RHS has a comma "side-effect"; we need @@ -3080,18 +6696,35 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXFunctionalCastExprClass: case Expr::CXXStaticCastExprClass: case Expr::CXXReinterpretCastExprClass: - case Expr::CXXConstCastExprClass: + case Expr::CXXConstCastExprClass: case Expr::ObjCBridgedCastExprClass: { const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr(); + if (isa<ExplicitCastExpr>(E)) { + if (const FloatingLiteral *FL + = dyn_cast<FloatingLiteral>(SubExpr->IgnoreParenImpCasts())) { + unsigned DestWidth = Ctx.getIntWidth(E->getType()); + bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType(); + APSInt IgnoredVal(DestWidth, !DestSigned); + bool Ignored; + // If the value does not fit in the destination type, the behavior is + // undefined, so we are not required to treat it as a constant + // expression. + if (FL->getValue().convertToInteger(IgnoredVal, + llvm::APFloat::rmTowardZero, + &Ignored) & APFloat::opInvalidOp) + return ICEDiag(2, E->getLocStart()); + return NoDiag(); + } + } switch (cast<CastExpr>(E)->getCastKind()) { case CK_LValueToRValue: + case CK_AtomicToNonAtomic: + case CK_NonAtomicToAtomic: case CK_NoOp: case CK_IntegralToBoolean: case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: - if (isa<FloatingLiteral>(SubExpr->IgnoreParens())) - return NoDiag(); return ICEDiag(2, E->getLocStart()); } } @@ -3114,30 +6747,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // extension. See GCC PR38377 for discussion. if (const CallExpr *CallCE = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts())) - if (CallCE->isBuiltinCall(Ctx) == Builtin::BI__builtin_constant_p) { - Expr::EvalResult EVResult; - if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects || - !EVResult.Val.isInt()) { - return ICEDiag(2, E->getLocStart()); - } - return NoDiag(); - } + if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) + return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); if (CondResult.Val == 2) return CondResult; - // C++0x [expr.const]p2: - // subexpressions of [...] conditional (5.16) operations that - // are not evaluated are not considered - bool TrueBranch = Ctx.getLangOptions().CPlusPlus0x - ? Exp->getCond()->EvaluateKnownConstInt(Ctx) != 0 - : false; - ICEDiag TrueResult = NoDiag(); - if (!Ctx.getLangOptions().CPlusPlus0x || TrueBranch) - TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); - ICEDiag FalseResult = NoDiag(); - if (!Ctx.getLangOptions().CPlusPlus0x || !TrueBranch) - FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); + ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); + ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); if (TrueResult.Val == 2) return TrueResult; @@ -3162,22 +6779,116 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { } } - // Silence a GCC warning - return ICEDiag(2, E->getLocStart()); + llvm_unreachable("Invalid StmtClass!"); } -bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, - SourceLocation *Loc, bool isEvaluated) const { +/// Evaluate an expression as a C++11 integral constant expression. +static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx, + const Expr *E, + llvm::APSInt *Value, + SourceLocation *Loc) { + if (!E->getType()->isIntegralOrEnumerationType()) { + if (Loc) *Loc = E->getExprLoc(); + return false; + } + + APValue Result; + if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) + return false; + + assert(Result.isInt() && "pointer cast to int is not an ICE"); + if (Value) *Value = Result.getInt(); + return true; +} + +bool Expr::isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { + if (Ctx.getLangOpts().CPlusPlus0x) + return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc); + ICEDiag d = CheckICE(this, Ctx); if (d.Val != 0) { if (Loc) *Loc = d.Loc; return false; } - EvalResult EvalResult; - if (!Evaluate(EvalResult, Ctx)) + return true; +} + +bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, + SourceLocation *Loc, bool isEvaluated) const { + if (Ctx.getLangOpts().CPlusPlus0x) + return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); + + if (!isIntegerConstantExpr(Ctx, Loc)) + return false; + if (!EvaluateAsInt(Value, Ctx)) llvm_unreachable("ICE cannot be evaluated!"); - assert(!EvalResult.HasSideEffects && "ICE with side effects!"); - assert(EvalResult.Val.isInt() && "ICE that isn't integer!"); - Result = EvalResult.Val.getInt(); return true; } + +bool Expr::isCXX98IntegralConstantExpr(ASTContext &Ctx) const { + return CheckICE(this, Ctx).Val == 0; +} + +bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, + SourceLocation *Loc) const { + // We support this checking in C++98 mode in order to diagnose compatibility + // issues. + assert(Ctx.getLangOpts().CPlusPlus); + + // Build evaluation settings. + Expr::EvalStatus Status; + llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + Status.Diag = &Diags; + EvalInfo Info(Ctx, Status); + + APValue Scratch; + bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch); + + if (!Diags.empty()) { + IsConstExpr = false; + if (Loc) *Loc = Diags[0].first; + } else if (!IsConstExpr) { + // FIXME: This shouldn't happen. + if (Loc) *Loc = getExprLoc(); + } + + return IsConstExpr; +} + +bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, + llvm::SmallVectorImpl< + PartialDiagnosticAt> &Diags) { + // FIXME: It would be useful to check constexpr function templates, but at the + // moment the constant expression evaluator cannot cope with the non-rigorous + // ASTs which we build for dependent expressions. + if (FD->isDependentContext()) + return true; + + Expr::EvalStatus Status; + Status.Diag = &Diags; + + EvalInfo Info(FD->getASTContext(), Status); + Info.CheckingPotentialConstantExpression = true; + + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); + const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 0; + + // FIXME: Fabricate an arbitrary expression on the stack and pretend that it + // is a temporary being used as the 'this' pointer. + LValue This; + ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy); + This.set(&VIE, Info.CurrentCall->Index); + + ArrayRef<const Expr*> Args; + + SourceLocation Loc = FD->getLocation(); + + APValue Scratch; + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) + HandleConstructorCall(Loc, This, Args, CD, Info, Scratch); + else + HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : 0, + Args, FD->getBody(), Info, Scratch); + + return Diags.empty(); +} diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index acedf70..d7b6354 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -40,14 +40,38 @@ using namespace clang; namespace { +/// \brief Retrieve the declaration context that should be used when mangling +/// the given declaration. +static const DeclContext *getEffectiveDeclContext(const Decl *D) { + // The ABI assumes that lambda closure types that occur within + // default arguments live in the context of the function. However, due to + // the way in which Clang parses and creates function declarations, this is + // not the case: the lambda closure type ends up living in the context + // where the function itself resides, because the function declaration itself + // had not yet been created. Fix the context here. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { + if (RD->isLambda()) + if (ParmVarDecl *ContextParam + = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) + return ContextParam->getDeclContext(); + } + + return D->getDeclContext(); +} + +static const DeclContext *getEffectiveParentContext(const DeclContext *DC) { + return getEffectiveDeclContext(cast<Decl>(DC)); +} + static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { const DeclContext *DC = dyn_cast<DeclContext>(ND); if (!DC) - DC = ND->getDeclContext(); + DC = getEffectiveDeclContext(ND); while (!DC->isNamespace() && !DC->isTranslationUnit()) { - if (isa<FunctionDecl>(DC->getParent())) + const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC)); + if (isa<FunctionDecl>(Parent)) return dyn_cast<CXXRecordDecl>(DC); - DC = DC->getParent(); + DC = Parent; } return 0; } @@ -63,7 +87,7 @@ static const NamedDecl *getStructor(const NamedDecl *decl) { const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl); return (fn ? getStructor(fn) : decl); } - + static const unsigned UnknownArity = ~0U; class ItaniumMangleContext : public MangleContext { @@ -122,6 +146,13 @@ public: } bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + // Lambda closure types with external linkage (indicated by a + // non-zero lambda mangling number) have their own numbering scheme, so + // they do not need a discriminator. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND)) + if (RD->isLambda() && RD->getLambdaManglingNumber() > 0) + return false; + unsigned &discriminator = Uniquifier[ND]; if (!discriminator) discriminator = ++Discriminator; @@ -272,6 +303,7 @@ private: void mangleUnscopedTemplateName(TemplateName); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); + void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, @@ -332,8 +364,8 @@ private: static bool isInCLinkageSpecification(const Decl *D) { D = D->getCanonicalDecl(); - for (const DeclContext *DC = D->getDeclContext(); - !DC->isTranslationUnit(); DC = DC->getParent()) { + for (const DeclContext *DC = getEffectiveDeclContext(D); + !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) return Linkage->getLanguage() == LinkageSpecDecl::lang_c; } @@ -343,7 +375,7 @@ static bool isInCLinkageSpecification(const Decl *D) { bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { // In C, functions with no attributes never need to be mangled. Fastpath them. - if (!getASTContext().getLangOptions().CPlusPlus && !D->hasAttrs()) + if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) return false; // Any decl can be declared with __asm("foo") on it, and this takes precedence @@ -360,22 +392,22 @@ bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { return true; // Otherwise, no mangling is done outside C++ mode. - if (!getASTContext().getLangOptions().CPlusPlus) + if (!getASTContext().getLangOpts().CPlusPlus) return false; // Variables at global scope with non-internal linkage are not mangled if (!FD) { - const DeclContext *DC = D->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(D); // Check for extern variable declared locally. if (DC->isFunctionOrMethod() && D->hasLinkage()) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage) return false; } // Class members are always mangled. - if (D->getDeclContext()->isRecord()) + if (getEffectiveDeclContext(D)->isRecord()) return true; // C functions and "main" are not mangled. @@ -458,7 +490,7 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { while (isa<LinkageSpecDecl>(DC)) { - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); } return DC; @@ -466,7 +498,8 @@ static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { /// isStd - Return whether a given namespace is the 'std' namespace. static bool isStd(const NamespaceDecl *NS) { - if (!IgnoreLinkageSpecDecls(NS->getParent())->isTranslationUnit()) + if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS)) + ->isTranslationUnit()) return false; const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); @@ -502,26 +535,35 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { return 0; } +static bool isLambda(const NamedDecl *ND) { + const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + void CXXNameMangler::mangleName(const NamedDecl *ND) { // <name> ::= <nested-name> // ::= <unscoped-name> // ::= <unscoped-template-name> <template-args> // ::= <local-name> // - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. - if (isa<FunctionDecl>(DC) && ND->hasLinkage()) + // FIXME: This is a hack; extern variables declared locally should have + // a proper semantic declaration context! + if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) - DC = DC->getParent(); + DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { mangleLocalName(ND); return; } - while (isa<LinkageSpecDecl>(DC)) - DC = DC->getParent(); + DC = IgnoreLinkageSpecDecls(DC); if (DC->isTranslationUnit() || isStdNamespace(DC)) { // Check if we have a template. @@ -547,7 +589,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { void CXXNameMangler::mangleName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs) { - const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext()); + const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD)); if (DC->isTranslationUnit() || isStdNamespace(DC)) { mangleUnscopedTemplateName(TD); @@ -561,7 +603,8 @@ void CXXNameMangler::mangleName(const TemplateDecl *TD, void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { // <unscoped-name> ::= <unqualified-name> // ::= St <unqualified-name> # ::std:: - if (isStdNamespace(ND->getDeclContext())) + + if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND)))) Out << "St"; mangleUnqualifiedName(ND); @@ -610,17 +653,41 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { // representation (IEEE on Itanium), high-order bytes first, // without leading zeroes. For example: "Lf bf800000 E" is -1.0f // on Itanium. - // APInt::toString uses uppercase hexadecimal, and it's not really - // worth embellishing that interface for this use case, so we just - // do a second pass to lowercase things. - typedef llvm::SmallString<20> buffer_t; - buffer_t buffer; - f.bitcastToAPInt().toString(buffer, 16, false); + // The 'without leading zeroes' thing seems to be an editorial + // mistake; see the discussion on cxx-abi-dev beginning on + // 2012-01-16. + + // Our requirements here are just barely wierd enough to justify + // using a custom algorithm instead of post-processing APInt::toString(). + + llvm::APInt valueBits = f.bitcastToAPInt(); + unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4; + assert(numCharacters != 0); - for (buffer_t::iterator i = buffer.begin(), e = buffer.end(); i != e; ++i) - if (isupper(*i)) *i = tolower(*i); + // Allocate a buffer of the right number of characters. + llvm::SmallVector<char, 20> buffer; + buffer.set_size(numCharacters); - Out.write(buffer.data(), buffer.size()); + // Fill the buffer left-to-right. + for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) { + // The bit-index of the next hex digit. + unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1); + + // Project out 4 bits starting at 'digitIndex'. + llvm::integerPart hexDigit + = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth]; + hexDigit >>= (digitBitIndex % llvm::integerPartWidth); + hexDigit &= 0xF; + + // Map that over to a lowercase hex digit. + static const char charForHex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + buffer[stringIndex] = charForHex[hexDigit]; + } + + Out.write(buffer.data(), numCharacters); } void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) { @@ -997,7 +1064,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // This naming convention is the same as that followed by GCC, // though it shouldn't actually matter. if (ND && ND->getLinkage() == InternalLinkage && - ND->getDeclContext()->isFileContext()) + getEffectiveDeclContext(ND)->isFileContext()) Out << 'L'; mangleSourceName(II); @@ -1052,13 +1119,24 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, break; } + // <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'. + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { + if (Record->isLambda() && Record->getLambdaManglingNumber()) { + mangleLambda(Record); + break; + } + } + // Get a unique id for the anonymous struct. uint64_t AnonStructId = Context.getAnonymousStructId(TD); // Mangle it as a source name in the form // [n] $_<id> // where n is the length of the string. - llvm::SmallString<8> Str; + SmallString<8> Str; Str += "$_"; Str += llvm::utostr(AnonStructId); @@ -1180,8 +1258,10 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] + // <local-name> := Z <function encoding> E d [ <parameter number> ] + // _ <entity name> // <discriminator> := _ <non-negative number> - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) { // Don't add objc method name mangling to locally declared function mangleUnqualifiedName(ND); @@ -1193,23 +1273,46 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(MD); } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) { - mangleFunctionEncoding(cast<FunctionDecl>(RD->getDeclContext())); + mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD))); Out << 'E'; + // The parameter number is omitted for the last parameter, 0 for the + // second-to-last parameter, 1 for the third-to-last parameter, etc. The + // <entity name> will of course contain a <closure-type-name>: Its + // numbering will be local to the particular argument in which it appears + // -- other default arguments do not affect its encoding. + bool SkipDiscriminator = false; + if (RD->isLambda()) { + if (const ParmVarDecl *Parm + = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) { + if (const FunctionDecl *Func + = dyn_cast<FunctionDecl>(Parm->getDeclContext())) { + Out << 'd'; + unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex(); + if (Num > 1) + mangleNumber(Num - 2); + Out << '_'; + SkipDiscriminator = true; + } + } + } + // Mangle the name relative to the closest enclosing function. if (ND == RD) // equality ok because RD derived from ND above mangleUnqualifiedName(ND); else mangleNestedName(ND, DC, true /*NoFunction*/); - unsigned disc; - if (Context.getNextDiscriminator(RD, disc)) { - if (disc < 10) - Out << '_' << disc; - else - Out << "__" << disc << '_'; + if (!SkipDiscriminator) { + unsigned disc; + if (Context.getNextDiscriminator(RD, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } } - + return; } else @@ -1219,6 +1322,48 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { mangleUnqualifiedName(ND); } +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 + // <prefix> of the form: + // + // <data-member-prefix> := <member source-name> M + // + // Technically, the data-member-prefix is part of the <prefix>. However, + // since a closure type will always be mangled with a prefix, it's easier + // to emit that last part of the prefix here. + if (Decl *Context = Lambda->getLambdaContextDecl()) { + if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast<NamedDecl>(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + + Out << "Ul"; + DeclarationName Name + = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); + const FunctionProtoType *Proto + = cast<CXXMethodDecl>(*Lambda->lookup(Name).first)->getType()-> + getAs<FunctionProtoType>(); + mangleBareFunctionType(Proto, /*MangleReturnType=*/false); + Out << "E"; + + // The number is omitted for the first closure type with a given + // <lambda-sig> in a given context; it is n-2 for the nth closure type + // (in lexical order) with that same <lambda-sig> and context. + // + // The AST keeps track of the number for us. + unsigned Number = Lambda->getLambdaManglingNumber(); + assert(Number > 0 && "Lambda should be mangled as an unnamed class"); + if (Number > 1) + mangleNumber(Number - 2); + Out << '_'; +} + void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { switch (qualifier->getKind()) { case NestedNameSpecifier::Global: @@ -1258,15 +1403,14 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= # empty // ::= <substitution> - while (isa<LinkageSpecDecl>(DC)) - DC = DC->getParent(); + DC = IgnoreLinkageSpecDecls(DC); if (DC->isTranslationUnit()) return; if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) { - manglePrefix(DC->getParent(), NoFunction); - llvm::SmallString<64> Name; + manglePrefix(getEffectiveParentContext(DC), NoFunction); + SmallString<64> Name; llvm::raw_svector_ostream NameStream(Name); Context.mangleBlock(Block, NameStream); NameStream.flush(); @@ -1274,26 +1418,27 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { return; } - if (mangleSubstitution(cast<NamedDecl>(DC))) + const NamedDecl *ND = cast<NamedDecl>(DC); + if (mangleSubstitution(ND)) return; - + // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; - if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); mangleTemplateArgs(*TemplateParameters, *TemplateArgs); } - else if(NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))) + else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND))) return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) + else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) mangleObjCMethodName(Method); else { - manglePrefix(DC->getParent(), NoFunction); - mangleUnqualifiedName(cast<NamedDecl>(DC)); + manglePrefix(getEffectiveDeclContext(ND), NoFunction); + mangleUnqualifiedName(ND); } - addSubstitution(cast<NamedDecl>(DC)); + addSubstitution(ND); } void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { @@ -1336,7 +1481,7 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { return; } - manglePrefix(ND->getDeclContext()); + manglePrefix(getEffectiveDeclContext(ND)); mangleUnqualifiedName(ND->getTemplatedDecl()); addSubstitution(ND); } @@ -1370,7 +1515,6 @@ void CXXNameMangler::mangleType(TemplateName TN) { case TemplateName::OverloadedTemplate: llvm_unreachable("can't mangle an overloaded template name as a <type>"); - break; case TemplateName::DependentTemplate: { const DependentTemplateName *Dependent = TN.getAsDependentTemplateName(); @@ -1531,7 +1675,7 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { // // where <address-space-number> is a source name consisting of 'AS' // followed by the address space <number>. - llvm::SmallString<64> ASString; + SmallString<64> ASString; ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace()); Out << 'U' << ASString.size() << ASString; } @@ -1632,8 +1776,8 @@ void CXXNameMangler::mangleType(QualType T) { } while (true); } SplitQualType split = T.split(); - Qualifiers quals = split.second; - const Type *ty = split.first; + Qualifiers quals = split.Quals; + const Type *ty = split.Ty; bool isSubstitutable = quals || !isa<BuiltinType>(T); if (isSubstitutable && mangleSubstitution(T)) @@ -1735,12 +1879,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::LongDouble: Out << 'e'; break; case BuiltinType::NullPtr: Out << "Dn"; break; - case BuiltinType::Overload: +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - case BuiltinType::BoundMember: - case BuiltinType::UnknownAny: llvm_unreachable("mangling a placeholder type"); - break; case BuiltinType::ObjCId: Out << "11objc_object"; break; case BuiltinType::ObjCClass: Out << "10objc_class"; break; case BuiltinType::ObjCSel: Out << "13objc_selector"; break; @@ -2217,15 +2361,12 @@ recurse: // These all can only appear in local or variable-initialization // contexts and so should never appear in a mangling. case Expr::AddrLabelExprClass: - case Expr::BlockDeclRefExprClass: case Expr::CXXThisExprClass: case Expr::DesignatedInitExprClass: case Expr::ImplicitValueInitExprClass: - case Expr::InitListExprClass: case Expr::ParenListExprClass: - case Expr::CXXScalarValueInitExprClass: + case Expr::LambdaExprClass: llvm_unreachable("unexpected statement kind"); - break; // FIXME: invent manglings for all these. case Expr::BlockExprClass: @@ -2242,6 +2383,10 @@ recurse: case Expr::ObjCProtocolExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCStringLiteralClass: + case Expr::ObjCNumericLiteralClass: + case Expr::ObjCArrayLiteralClass: + case Expr::ObjCDictionaryLiteralClass: + case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::OffsetOfExprClass: case Expr::PredefinedExprClass: @@ -2249,6 +2394,7 @@ recurse: case Expr::StmtExprClass: case Expr::UnaryTypeTraitExprClass: case Expr::BinaryTypeTraitExprClass: + case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: @@ -2256,6 +2402,7 @@ recurse: case Expr::CXXNoexceptExprClass: case Expr::CUDAKernelCallExprClass: case Expr::AsTypeExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: { // As bad as this diagnostic is, it's better than crashing. @@ -2282,6 +2429,16 @@ recurse: case Expr::OpaqueValueExprClass: llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); + case Expr::InitListExprClass: { + // Proposal by Jason Merrill, 2012-01-03 + Out << "il"; + const InitListExpr *InitList = cast<InitListExpr>(E); + for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) + mangleExpression(InitList->getInit(i)); + Out << "E"; + break; + } + case Expr::CXXDefaultArgExprClass: mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity); break; @@ -2291,6 +2448,9 @@ recurse: Arity); break; + case Expr::UserDefinedLiteralClass: + // We follow g++'s approach of mangling a UDL as a call to the literal + // operator. case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { const CallExpr *CE = cast<CallExpr>(E); @@ -2318,7 +2478,6 @@ recurse: } case Expr::CXXNewExprClass: { - // Proposal from David Vandervoorde, 2010.06.30 const CXXNewExpr *New = cast<CXXNewExpr>(E); if (New->isGlobalNew()) Out << "gs"; Out << (New->isArray() ? "na" : "nw"); @@ -2328,10 +2487,29 @@ recurse: Out << '_'; mangleType(New->getAllocatedType()); if (New->hasInitializer()) { - Out << "pi"; - for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(), - E = New->constructor_arg_end(); I != E; ++I) - mangleExpression(*I); + // Proposal by Jason Merrill, 2012-01-03 + if (New->getInitializationStyle() == CXXNewExpr::ListInit) + Out << "il"; + else + Out << "pi"; + const Expr *Init = New->getInitializer(); + if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) { + // Directly inline the initializers. + for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(), + E = CCE->arg_end(); + I != E; ++I) + mangleExpression(*I); + } else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) { + for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i) + mangleExpression(PLE->getExpr(i)); + } else if (New->getInitializationStyle() == CXXNewExpr::ListInit && + isa<InitListExpr>(Init)) { + // Only take InitListExprs apart for list-initialization. + const InitListExpr *InitList = cast<InitListExpr>(Init); + for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i) + mangleExpression(InitList->getInit(i)); + } else + mangleExpression(Init); } Out << 'E'; break; @@ -2395,7 +2573,11 @@ recurse: const CXXConstructExpr *CE = cast<CXXConstructExpr>(E); unsigned N = CE->getNumArgs(); - Out << "cv"; + // Proposal by Jason Merrill, 2012-01-03 + if (CE->isListInitialization()) + Out << "tl"; + else + Out << "cv"; mangleType(CE->getType()); if (N != 1) Out << '_'; for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I)); @@ -2403,6 +2585,12 @@ recurse: break; } + case Expr::CXXScalarValueInitExprClass: + Out <<"cv"; + mangleType(E->getType()); + Out <<"_E"; + break; + case Expr::UnaryExprOrTypeTraitExprClass: { const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E); @@ -2642,6 +2830,13 @@ recurse: Out << 'E'; break; + // FIXME. __objc_yes/__objc_no are mangled same as true/false + case Expr::ObjCBoolLiteralExprClass: + Out << "Lb"; + Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0'); + Out << 'E'; + break; + case Expr::CXXBoolLiteralExprClass: Out << "Lb"; Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0'); @@ -2897,23 +3092,48 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P, Out << "Dp"; mangleType(A.getAsTemplateOrTemplatePattern()); break; - case TemplateArgument::Expression: + case TemplateArgument::Expression: { + // It's possible to end up with a DeclRefExpr here in certain + // dependent cases, in which case we should mangle as a + // declaration. + const Expr *E = A.getAsExpr()->IgnoreParens(); + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + const ValueDecl *D = DRE->getDecl(); + if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) { + Out << "L"; + mangle(D, "_Z"); + Out << 'E'; + break; + } + } + Out << 'X'; - mangleExpression(A.getAsExpr()); + mangleExpression(E); Out << 'E'; break; + } case TemplateArgument::Integral: mangleIntegerLiteral(A.getIntegralType(), *A.getAsIntegral()); break; case TemplateArgument::Declaration: { assert(P && "Missing template parameter for declaration argument"); // <expr-primary> ::= L <mangled-name> E # external name - + // <expr-primary> ::= L <type> 0 E // Clang produces AST's where pointer-to-member-function expressions // and pointer-to-function expressions are represented as a declaration not // an expression. We compensate for it here to produce the correct mangling. - NamedDecl *D = cast<NamedDecl>(A.getAsDecl()); const NonTypeTemplateParmDecl *Parameter = cast<NonTypeTemplateParmDecl>(P); + + // Handle NULL pointer arguments. + if (!A.getAsDecl()) { + Out << "L"; + mangleType(Parameter->getType()); + Out << "0E"; + break; + } + + + NamedDecl *D = cast<NamedDecl>(A.getAsDecl()); bool compensateMangling = !Parameter->getType()->isReferenceType(); if (compensateMangling) { Out << 'X'; @@ -2982,8 +3202,15 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { return mangleSubstitution(reinterpret_cast<uintptr_t>(ND)); } +/// \brief Determine whether the given type has any qualifiers that are +/// relevant for substitutions. +static bool hasMangledSubstitutionQualifiers(QualType T) { + Qualifiers Qs = T.getQualifiers(); + return Qs.getCVRQualifiers() || Qs.hasAddressSpace(); +} + bool CXXNameMangler::mangleSubstitution(QualType T) { - if (!T.getCVRQualifiers()) { + if (!hasMangledSubstitutionQualifiers(T)) { if (const RecordType *RT = T->getAs<RecordType>()) return mangleSubstitution(RT->getDecl()); } @@ -3059,7 +3286,7 @@ static bool isCharSpecialization(QualType T, const char *Name) { if (!SD) return false; - if (!isStdNamespace(SD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); @@ -3101,7 +3328,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { } if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) { - if (!isStdNamespace(TD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(TD))) return false; // <substitution> ::= Sa # ::std::allocator @@ -3119,7 +3346,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { if (const ClassTemplateSpecializationDecl *SD = dyn_cast<ClassTemplateSpecializationDecl>(ND)) { - if (!isStdNamespace(SD->getDeclContext())) + if (!isStdNamespace(getEffectiveDeclContext(SD))) return false; // <substitution> ::= Ss # ::std::basic_string<char, @@ -3169,7 +3396,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { } void CXXNameMangler::addSubstitution(QualType T) { - if (!T.getCVRQualifiers()) { + if (!hasMangledSubstitutionQualifiers(T)) { if (const RecordType *RT = T->getAs<RecordType>()) { addSubstitution(RT->getDecl()); return; diff --git a/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp b/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp new file mode 100644 index 0000000..f5272a7 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/LambdaMangleContext.cpp @@ -0,0 +1,30 @@ +//===--- LambdaMangleContext.cpp - Context for mangling lambdas -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LambdaMangleContext class, which keeps track of +// the Itanium C++ ABI mangling numbers for lambda expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/AST/LambdaMangleContext.h" +#include "clang/AST/DeclCXX.h" + +using namespace clang; + +unsigned LambdaMangleContext::getManglingNumber(CXXMethodDecl *CallOperator) { + const FunctionProtoType *Proto + = CallOperator->getType()->getAs<FunctionProtoType>(); + ASTContext &Context = CallOperator->getASTContext(); + + QualType Key = Context.getFunctionType(Context.VoidTy, + Proto->arg_type_begin(), + Proto->getNumArgs(), + FunctionProtoType::ExtProtoInfo()); + Key = Context.getCanonicalType(Key); + return ++ManglingNumbers[Key->castAs<FunctionProtoType>()]; +} diff --git a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp index 5cb8f47..73c9f57 100644 --- a/contrib/llvm/tools/clang/lib/AST/Mangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Mangle.cpp @@ -59,6 +59,8 @@ static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) { } +void MangleContext::anchor() { } + void MangleContext::mangleGlobalBlock(const BlockDecl *BD, raw_ostream &Out) { Out << "__block_global_" << getBlockId(BD, false); @@ -68,7 +70,7 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, raw_ostream &ResStream) { checkMangleDC(CD, BD); - llvm::SmallString<64> Buffer; + SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); mangleCXXCtor(CD, CT, Out); Out.flush(); @@ -79,7 +81,7 @@ void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, CXXDtorType DT, const BlockDecl *BD, raw_ostream &ResStream) { checkMangleDC(DD, BD); - llvm::SmallString<64> Buffer; + SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); mangleCXXDtor(DD, DT, Out); Out.flush(); @@ -91,7 +93,7 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); checkMangleDC(DC, BD); - llvm::SmallString<64> Buffer; + SmallString<64> Buffer; llvm::raw_svector_ostream Stream(Buffer); if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { mangleObjCMethodName(Method, Stream); @@ -114,7 +116,7 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &Out) { - llvm::SmallString<64> Name; + SmallString<64> Name; llvm::raw_svector_ostream OS(Name); const ObjCContainerDecl *CD = @@ -122,7 +124,7 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, assert (CD && "Missing container decl in GetNameForMethod"); OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) - OS << '(' << CID << ')'; + OS << '(' << *CID << ')'; OS << ' ' << MD->getSelector().getAsString() << ']'; Out << OS.str().size() << OS.str(); diff --git a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp index 1515db4..ba9856a 100644 --- a/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -119,7 +119,7 @@ static bool isInCLinkageSpecification(const Decl *D) { bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) { // In C, functions with no attributes never need to be mangled. Fastpath them. - if (!getASTContext().getLangOptions().CPlusPlus && !D->hasAttrs()) + if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) return false; // Any decl can be declared with __asm("foo") on it, and this takes precedence @@ -136,7 +136,7 @@ bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) { return true; // Otherwise, no mangling is done outside C++ mode. - if (!getASTContext().getLangOptions().CPlusPlus) + if (!getASTContext().getLangOpts().CPlusPlus) return false; // Variables at global scope with internal linkage are not mangled. @@ -335,10 +335,12 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, llvm_unreachable("Can't mangle Objective-C selector names here!"); case DeclarationName::CXXConstructorName: - llvm_unreachable("Can't mangle constructors yet!"); + Out << "?0"; + break; case DeclarationName::CXXDestructorName: - llvm_unreachable("Can't mangle destructors yet!"); + Out << "?1"; + break; case DeclarationName::CXXConversionFunctionName: // <operator-name> ::= ?B # (cast) @@ -701,12 +703,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::WChar_S: case BuiltinType::WChar_U: Out << "_W"; break; - case BuiltinType::Overload: +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - case BuiltinType::UnknownAny: - case BuiltinType::BoundMember: - llvm_unreachable( - "Overloaded and dependent types shouldn't get to name mangling"); + llvm_unreachable("placeholder types shouldn't get to name mangling"); + case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; @@ -715,7 +718,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Char32: case BuiltinType::Half: case BuiltinType::NullPtr: - llvm_unreachable("Don't know how to mangle this type"); + assert(0 && "Don't know how to mangle this type yet"); } } @@ -1167,13 +1170,15 @@ void MicrosoftMangleContext::mangleCXXRTTIName(QualType T, } void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - raw_ostream &) { - llvm_unreachable("Can't yet mangle constructors!"); + raw_ostream & Out) { + MicrosoftCXXNameMangler mangler(*this, Out); + mangler.mangle(D); } void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - raw_ostream &) { - llvm_unreachable("Can't yet mangle destructors!"); + raw_ostream & Out) { + MicrosoftCXXNameMangler mangler(*this, Out); + mangler.mangle(D); } void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *, raw_ostream &) { diff --git a/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp new file mode 100644 index 0000000..f5ea2c5 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/NSAPI.cpp @@ -0,0 +1,312 @@ +//===--- 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. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/NSAPI.h" +#include "clang/AST/ASTContext.h" + +using namespace clang; + +NSAPI::NSAPI(ASTContext &ctx) + : Ctx(ctx), ClassIds() { +} + +IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { + static const char *ClassName[NumClassIds] = { + "NSObject", + "NSString", + "NSArray", + "NSMutableArray", + "NSDictionary", + "NSMutableDictionary", + "NSNumber" + }; + + if (!ClassIds[K]) + return (ClassIds[K] = &Ctx.Idents.get(ClassName[K])); + + return ClassIds[K]; +} + +Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const { + if (NSStringSelectors[MK].isNull()) { + Selector Sel; + switch (MK) { + case NSStr_stringWithString: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString")); + break; + case NSStr_initWithString: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString")); + break; + } + return (NSStringSelectors[MK] = Sel); + } + + return NSStringSelectors[MK]; +} + +Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { + if (NSArraySelectors[MK].isNull()) { + Selector Sel; + switch (MK) { + case NSArr_array: + Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array")); + break; + case NSArr_arrayWithArray: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray")); + break; + case NSArr_arrayWithObject: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject")); + break; + case NSArr_arrayWithObjects: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects")); + break; + case NSArr_arrayWithObjectsCount: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("arrayWithObjects"), + &Ctx.Idents.get("count") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSArr_initWithArray: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray")); + break; + case NSArr_initWithObjects: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects")); + break; + case NSArr_objectAtIndex: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex")); + break; + case NSMutableArr_replaceObjectAtIndex: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("replaceObjectAtIndex"), + &Ctx.Idents.get("withObject") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + } + return (NSArraySelectors[MK] = Sel); + } + + return NSArraySelectors[MK]; +} + +llvm::Optional<NSAPI::NSArrayMethodKind> +NSAPI::getNSArrayMethodKind(Selector Sel) { + for (unsigned i = 0; i != NumNSArrayMethods; ++i) { + NSArrayMethodKind MK = NSArrayMethodKind(i); + if (Sel == getNSArraySelector(MK)) + return MK; + } + + return llvm::Optional<NSArrayMethodKind>(); +} + +Selector NSAPI::getNSDictionarySelector( + NSDictionaryMethodKind MK) const { + if (NSDictionarySelectors[MK].isNull()) { + Selector Sel; + switch (MK) { + case NSDict_dictionary: + Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary")); + break; + case NSDict_dictionaryWithDictionary: + Sel = Ctx.Selectors.getUnarySelector( + &Ctx.Idents.get("dictionaryWithDictionary")); + break; + case NSDict_dictionaryWithObjectForKey: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("dictionaryWithObject"), + &Ctx.Idents.get("forKey") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSDict_dictionaryWithObjectsForKeys: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("dictionaryWithObjects"), + &Ctx.Idents.get("forKeys") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + case NSDict_dictionaryWithObjectsForKeysCount: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("dictionaryWithObjects"), + &Ctx.Idents.get("forKeys"), + &Ctx.Idents.get("count") + }; + Sel = Ctx.Selectors.getSelector(3, KeyIdents); + break; + } + case NSDict_dictionaryWithObjectsAndKeys: + Sel = Ctx.Selectors.getUnarySelector( + &Ctx.Idents.get("dictionaryWithObjectsAndKeys")); + break; + case NSDict_initWithDictionary: + Sel = Ctx.Selectors.getUnarySelector( + &Ctx.Idents.get("initWithDictionary")); + break; + case NSDict_initWithObjectsAndKeys: + Sel = Ctx.Selectors.getUnarySelector( + &Ctx.Idents.get("initWithObjectsAndKeys")); + break; + case NSDict_objectForKey: + Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey")); + break; + case NSMutableDict_setObjectForKey: { + IdentifierInfo *KeyIdents[] = { + &Ctx.Idents.get("setObject"), + &Ctx.Idents.get("forKey") + }; + Sel = Ctx.Selectors.getSelector(2, KeyIdents); + break; + } + } + return (NSDictionarySelectors[MK] = Sel); + } + + return NSDictionarySelectors[MK]; +} + +llvm::Optional<NSAPI::NSDictionaryMethodKind> +NSAPI::getNSDictionaryMethodKind(Selector Sel) { + for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) { + NSDictionaryMethodKind MK = NSDictionaryMethodKind(i); + if (Sel == getNSDictionarySelector(MK)) + return MK; + } + + return llvm::Optional<NSDictionaryMethodKind>(); +} + +Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, + bool Instance) const { + static const char *ClassSelectorName[NumNSNumberLiteralMethods] = { + "numberWithChar", + "numberWithUnsignedChar", + "numberWithShort", + "numberWithUnsignedShort", + "numberWithInt", + "numberWithUnsignedInt", + "numberWithLong", + "numberWithUnsignedLong", + "numberWithLongLong", + "numberWithUnsignedLongLong", + "numberWithFloat", + "numberWithDouble", + "numberWithBool", + "numberWithInteger", + "numberWithUnsignedInteger" + }; + static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = { + "initWithChar", + "initWithUnsignedChar", + "initWithShort", + "initWithUnsignedShort", + "initWithInt", + "initWithUnsignedInt", + "initWithLong", + "initWithUnsignedLong", + "initWithLongLong", + "initWithUnsignedLongLong", + "initWithFloat", + "initWithDouble", + "initWithBool", + "initWithInteger", + "initWithUnsignedInteger" + }; + + Selector *Sels; + const char **Names; + if (Instance) { + Sels = NSNumberInstanceSelectors; + Names = InstanceSelectorName; + } else { + Sels = NSNumberClassSelectors; + Names = ClassSelectorName; + } + + if (Sels[MK].isNull()) + Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK])); + return Sels[MK]; +} + +llvm::Optional<NSAPI::NSNumberLiteralMethodKind> +NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { + for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) { + NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i); + if (isNSNumberLiteralSelector(MK, Sel)) + return MK; + } + + return llvm::Optional<NSNumberLiteralMethodKind>(); +} + +llvm::Optional<NSAPI::NSNumberLiteralMethodKind> +NSAPI::getNSNumberFactoryMethodKind(QualType T) { + const BuiltinType *BT = T->getAs<BuiltinType>(); + if (!BT) + return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); + + switch (BT->getKind()) { + case BuiltinType::Char_S: + case BuiltinType::SChar: + return NSAPI::NSNumberWithChar; + case BuiltinType::Char_U: + case BuiltinType::UChar: + return NSAPI::NSNumberWithUnsignedChar; + case BuiltinType::Short: + return NSAPI::NSNumberWithShort; + case BuiltinType::UShort: + return NSAPI::NSNumberWithUnsignedShort; + case BuiltinType::Int: + return NSAPI::NSNumberWithInt; + case BuiltinType::UInt: + return NSAPI::NSNumberWithUnsignedInt; + case BuiltinType::Long: + return NSAPI::NSNumberWithLong; + case BuiltinType::ULong: + return NSAPI::NSNumberWithUnsignedLong; + case BuiltinType::LongLong: + return NSAPI::NSNumberWithLongLong; + case BuiltinType::ULongLong: + return NSAPI::NSNumberWithUnsignedLongLong; + case BuiltinType::Float: + return NSAPI::NSNumberWithFloat; + case BuiltinType::Double: + return NSAPI::NSNumberWithDouble; + case BuiltinType::Bool: + return NSAPI::NSNumberWithBool; + + case BuiltinType::Void: + case BuiltinType::WChar_U: + case BuiltinType::WChar_S: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Int128: + case BuiltinType::LongDouble: + case BuiltinType::UInt128: + case BuiltinType::NullPtr: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCId: + case BuiltinType::ObjCSel: + case BuiltinType::BoundMember: + case BuiltinType::Dependent: + case BuiltinType::Overload: + case BuiltinType::UnknownAny: + case BuiltinType::ARCUnbridgedCast: + case BuiltinType::Half: + case BuiltinType::PseudoObject: + break; + } + + return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); +} diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 1ff2e71..dbf267b 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -130,7 +130,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { return TypeSpecWithTemplate; } - return Global; + llvm_unreachable("Invalid NNS Kind!"); } /// \brief Retrieve the namespace stored in this nested name @@ -170,8 +170,7 @@ bool NestedNameSpecifier::isDependent() const { return getAsType()->isDependentType(); } - // Necessary to suppress a GCC warning. - return false; + llvm_unreachable("Invalid NNS Kind!"); } /// \brief Whether this nested name specifier refers to a dependent @@ -191,9 +190,8 @@ bool NestedNameSpecifier::isInstantiationDependent() const { case TypeSpecWithTemplate: return getAsType()->isInstantiationDependentType(); } - - // Necessary to suppress a GCC warning. - return false; + + llvm_unreachable("Invalid NNS Kind!"); } bool NestedNameSpecifier::containsUnexpandedParameterPack() const { @@ -211,8 +209,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { return getAsType()->containsUnexpandedParameterPack(); } - // Necessary to suppress a GCC warning. - return false; + llvm_unreachable("Invalid NNS Kind!"); } /// \brief Print this nested name specifier to the given output @@ -229,6 +226,9 @@ NestedNameSpecifier::print(raw_ostream &OS, break; case Namespace: + if (getAsNamespace()->isAnonymousNamespace()) + return; + OS << getAsNamespace()->getName(); break; @@ -379,8 +379,8 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { LoadSourceLocation(Data, Offset + sizeof(void*))); } } - - return SourceRange(); + + llvm_unreachable("Invalid NNS Kind!"); } TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { @@ -434,9 +434,6 @@ namespace { } } -NestedNameSpecifierLocBuilder::NestedNameSpecifierLocBuilder() - : Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { } - NestedNameSpecifierLocBuilder:: NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) : Representation(Other.Representation), Buffer(0), @@ -499,11 +496,6 @@ operator=(const NestedNameSpecifierLocBuilder &Other) { return *this; } -NestedNameSpecifierLocBuilder::~NestedNameSpecifierLocBuilder() { - if (BufferCapacity) - free(Buffer); -} - void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, diff --git a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp index 5eef83a..64016d9 100644 --- a/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ParentMap.cpp @@ -26,6 +26,10 @@ static void BuildParentMap(MapTy& M, Stmt* S) { M[*I] = S; BuildParentMap(M, *I); } + + // Also include the source expr tree of an OpaqueValueExpr in the map. + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) + BuildParentMap(M, OVE->getSourceExpr()); } ParentMap::ParentMap(Stmt* S) : Impl(0) { diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp index ccc591a..0114eba 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayout.cpp @@ -43,7 +43,8 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, // Constructor for C++ records. ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, - CharUnits vbptroffset, CharUnits datasize, + CharUnits vfptroffset, CharUnits vbptroffset, + CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, CharUnits nonvirtualsize, @@ -68,6 +69,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx, CXXInfo->SizeOfLargestEmptySubobject = SizeOfLargestEmptySubobject; CXXInfo->BaseOffsets = BaseOffsets; CXXInfo->VBaseOffsets = VBaseOffsets; + CXXInfo->VFPtrOffset = vfptroffset; CXXInfo->VBPtrOffset = vbptroffset; #ifndef NDEBUG diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index bbd3fc0..c2d9294 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -558,6 +558,14 @@ protected: SmallVector<uint64_t, 16> FieldOffsets; + /// \brief Whether the external AST source has provided a layout for this + /// record. + unsigned ExternalLayout : 1; + + /// \brief Whether we need to infer alignment, even when we have an + /// externally-provided layout. + unsigned InferAlignment : 1; + /// Packed - Whether the record is packed or not. unsigned Packed : 1; @@ -592,6 +600,9 @@ protected: /// out is virtual. bool PrimaryBaseIsVirtual; + /// VFPtrOffset - Virtual function table offset. Only for MS layout. + CharUnits VFPtrOffset; + /// VBPtrOffset - Virtual base table offset. Only for MS layout. CharUnits VBPtrOffset; @@ -615,19 +626,47 @@ protected: /// avoid visiting virtual bases more than once. llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases; - RecordLayoutBuilder(const ASTContext &Context, EmptySubobjectMap - *EmptySubobjects, CharUnits Alignment) + /// \brief Externally-provided size. + uint64_t ExternalSize; + + /// \brief Externally-provided alignment. + uint64_t ExternalAlign; + + /// \brief Externally-provided field offsets. + llvm::DenseMap<const FieldDecl *, uint64_t> ExternalFieldOffsets; + + /// \brief Externally-provided direct, non-virtual base offsets. + llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalBaseOffsets; + + /// \brief Externally-provided virtual base offsets. + llvm::DenseMap<const CXXRecordDecl *, CharUnits> ExternalVirtualBaseOffsets; + + RecordLayoutBuilder(const ASTContext &Context, + EmptySubobjectMap *EmptySubobjects) : Context(Context), EmptySubobjects(EmptySubobjects), Size(0), - Alignment(Alignment), UnpackedAlignment(Alignment), - Packed(false), IsUnion(false), - IsMac68kAlign(false), IsMsStruct(false), + Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()), + ExternalLayout(false), InferAlignment(false), + Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), ZeroLengthBitfield(0), PrimaryBase(0), - PrimaryBaseIsVirtual(false), VBPtrOffset(CharUnits::fromQuantity(-1)), + PrimaryBaseIsVirtual(false), + VFPtrOffset(CharUnits::fromQuantity(-1)), + VBPtrOffset(CharUnits::fromQuantity(-1)), FirstNearlyEmptyVBase(0) { } + /// Reset this RecordLayoutBuilder to a fresh state, using the given + /// alignment as the initial alignment. This is used for the + /// correct layout of vb-table pointers in MSVC. + void resetWithTargetAlignment(CharUnits TargetAlignment) { + const ASTContext &Context = this->Context; + EmptySubobjectMap *EmptySubobjects = this->EmptySubobjects; + this->~RecordLayoutBuilder(); + new (this) RecordLayoutBuilder(Context, EmptySubobjects); + Alignment = UnpackedAlignment = TargetAlignment; + } + void Layout(const RecordDecl *D); void Layout(const CXXRecordDecl *D); void Layout(const ObjCInterfaceDecl *D); @@ -637,8 +676,12 @@ protected: void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize, bool FieldPacked, const FieldDecl *D); void LayoutBitField(const FieldDecl *D); + + bool isMicrosoftCXXABI() const { + return Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft; + } + void MSLayoutVirtualBases(const CXXRecordDecl *RD); - void MSLayout(const CXXRecordDecl *RD); /// BaseSubobjectInfoAllocator - Allocator for BaseSubobjectInfo objects. llvm::SpecificBumpPtrAllocator<BaseSubobjectInfo> BaseSubobjectInfoAllocator; @@ -669,7 +712,7 @@ protected: void SelectPrimaryVBase(const CXXRecordDecl *RD); - CharUnits GetVirtualPointersSize(const CXXRecordDecl *RD) const; + void EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign); /// LayoutNonVirtualBases - Determines the primary base class (if any) and /// lays it out. Will then proceed to lay out all non-virtual base clasess. @@ -681,6 +724,10 @@ protected: void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, CharUnits Offset); + bool needsVFTable(const CXXRecordDecl *RD) const; + bool hasNewVirtualFunction(const CXXRecordDecl *RD) const; + bool isPossiblePrimaryBase(const CXXRecordDecl *Base) const; + /// LayoutVirtualBases - Lays out all the virtual bases. void LayoutVirtualBases(const CXXRecordDecl *RD, const CXXRecordDecl *MostDerivedClass); @@ -704,6 +751,14 @@ protected: UpdateAlignment(NewAlignment, NewAlignment); } + /// \brief Retrieve the externally-supplied field offset for the given + /// field. + /// + /// \param Field The field whose offset is being queried. + /// \param ComputedOffset The offset that we've computed for this field. + uint64_t updateExternalFieldOffset(const FieldDecl *Field, + uint64_t ComputedOffset); + void CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset, unsigned UnpackedAlign, bool isPacked, const FieldDecl *D); @@ -730,20 +785,10 @@ protected: void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); } void setDataSize(uint64_t NewSize) { DataSize = NewSize; } - bool HasVBPtr(const CXXRecordDecl *RD) const; - bool HasNewVirtualFunction(const CXXRecordDecl *RD) const; - - /// Add vbptr or vfptr to layout. - void AddVPointer(); - RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT public: static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); - - virtual ~RecordLayoutBuilder() { } - - CharUnits GetVBPtrOffset() const { return VBPtrOffset; } }; } // end anonymous namespace @@ -778,11 +823,6 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) { } } -CharUnits -RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const { - return Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); -} - /// DeterminePrimaryBase - Determine the primary base of the given class. void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { // If the class isn't dynamic, it won't have a primary base. @@ -805,7 +845,7 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (Base->isDynamicClass()) { + if (isPossiblePrimaryBase(Base)) { // We found it. PrimaryBase = Base; PrimaryBaseIsVirtual = false; @@ -813,44 +853,30 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { } } - // Otherwise, it is the first nearly empty virtual base that is not an - // indirect primary virtual base class, if one exists. + // The Microsoft ABI doesn't have primary virtual bases. + if (isMicrosoftCXXABI()) { + assert(!PrimaryBase && "Should not get here with a primary base!"); + return; + } + + // Under the Itanium ABI, if there is no non-virtual primary base class, + // try to compute the primary virtual base. The primary virtual base is + // the first nearly empty virtual base that is not an indirect primary + // virtual base class, if one exists. if (RD->getNumVBases() != 0) { SelectPrimaryVBase(RD); if (PrimaryBase) return; } - // Otherwise, it is the first nearly empty virtual base that is not an - // indirect primary virtual base class, if one exists. + // Otherwise, it is the first indirect primary base class, if one exists. if (FirstNearlyEmptyVBase) { PrimaryBase = FirstNearlyEmptyVBase; PrimaryBaseIsVirtual = true; return; } - // Otherwise there is no primary base class. assert(!PrimaryBase && "Should not get here with a primary base!"); - - // Allocate the virtual table pointer at offset zero. - assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); - - // Update the size. - setSize(getSize() + GetVirtualPointersSize(RD)); - setDataSize(getSize()); - - CharUnits UnpackedBaseAlign = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); - CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; - - // The maximum field alignment overrides base align. - if (!MaxFieldAlignment.isZero()) { - BaseAlign = std::min(BaseAlign, MaxFieldAlignment); - UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment); - } - - // Update the alignment. - UpdateAlignment(BaseAlign, UnpackedBaseAlign); } BaseSubobjectInfo * @@ -959,6 +985,24 @@ void RecordLayoutBuilder::ComputeBaseSubobjectInfo(const CXXRecordDecl *RD) { } void +RecordLayoutBuilder::EnsureVTablePointerAlignment(CharUnits UnpackedBaseAlign) { + CharUnits BaseAlign = (Packed) ? CharUnits::One() : UnpackedBaseAlign; + + // The maximum field alignment overrides base align. + if (!MaxFieldAlignment.isZero()) { + BaseAlign = std::min(BaseAlign, MaxFieldAlignment); + UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment); + } + + // Round up the current record size to pointer alignment. + setSize(getSize().RoundUpToAlignment(BaseAlign)); + setDataSize(getSize()); + + // Update the alignment. + UpdateAlignment(BaseAlign, UnpackedBaseAlign); +} + +void RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { // Then, determine the primary base class. DeterminePrimaryBase(RD); @@ -990,20 +1034,45 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { LayoutNonVirtualBase(PrimaryBaseInfo); } + + // If this class needs a vtable/vf-table and didn't get one from a + // primary base, add it in now. + } else if (needsVFTable(RD)) { + assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); + CharUnits PtrWidth = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + CharUnits PtrAlign = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); + EnsureVTablePointerAlignment(PtrAlign); + if (isMicrosoftCXXABI()) + VFPtrOffset = getSize(); + setSize(getSize() + PtrWidth); + setDataSize(getSize()); } + bool HasDirectVirtualBases = false; + bool HasNonVirtualBaseWithVBTable = false; + // Now lay out the non-virtual bases. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { - // Ignore virtual bases. - if (I->isVirtual()) + // Ignore virtual bases, but remember that we saw one. + if (I->isVirtual()) { + HasDirectVirtualBases = true; continue; + } const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + + // Remember if this base has virtual bases itself. + if (BaseDecl->getNumVBases()) + HasNonVirtualBaseWithVBTable = true; - // Skip the primary base. + // Skip the primary base, because we've already laid it out. The + // !PrimaryBaseIsVirtual check is required because we might have a + // non-virtual base of the same type as a primary virtual base. if (BaseDecl == PrimaryBase && !PrimaryBaseIsVirtual) continue; @@ -1013,6 +1082,37 @@ RecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { LayoutNonVirtualBase(BaseInfo); } + + // In the MS ABI, add the vb-table pointer if we need one, which is + // whenever we have a virtual base and we can't re-use a vb-table + // pointer from a non-virtual base. + if (isMicrosoftCXXABI() && + HasDirectVirtualBases && !HasNonVirtualBaseWithVBTable) { + CharUnits PtrWidth = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + CharUnits PtrAlign = + Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerAlign(0)); + + // MSVC potentially over-aligns the vb-table pointer by giving it + // the max alignment of all the non-virtual objects in the class. + // This is completely unnecessary, but we're not here to pass + // judgment. + // + // Note that we've only laid out the non-virtual bases, so on the + // first pass Alignment won't be set correctly here, but if the + // vb-table doesn't end up aligned correctly we'll come through + // and redo the layout from scratch with the right alignment. + // + // TODO: Instead of doing this, just lay out the fields as if the + // vb-table were at offset zero, then retroactively bump the field + // offsets up. + PtrAlign = std::max(PtrAlign, Alignment); + + EnsureVTablePointerAlignment(PtrAlign); + VBPtrOffset = getSize(); + setSize(getSize() + PtrWidth); + setDataSize(getSize()); + } } void RecordLayoutBuilder::LayoutNonVirtualBase(const BaseSubobjectInfo *Base) { @@ -1061,43 +1161,81 @@ RecordLayoutBuilder::AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info, } } -void RecordLayoutBuilder::AddVPointer() { - CharUnits PtrWidth = - Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); - setSize(getSize() + PtrWidth); - setDataSize(getSize()); - - if (Alignment > PtrWidth) { - setSize(getSize() + (Alignment - PtrWidth)); - setDataSize(getSize()); - } +/// needsVFTable - Return true if this class needs a vtable or vf-table +/// when laid out as a base class. These are treated the same because +/// they're both always laid out at offset zero. +/// +/// This function assumes that the class has no primary base. +bool RecordLayoutBuilder::needsVFTable(const CXXRecordDecl *RD) const { + assert(!PrimaryBase); + + // In the Itanium ABI, every dynamic class needs a vtable: even if + // this class has no virtual functions as a base class (i.e. it's + // non-polymorphic or only has virtual functions from virtual + // bases),x it still needs a vtable to locate its virtual bases. + if (!isMicrosoftCXXABI()) + return RD->isDynamicClass(); + + // In the MS ABI, we need a vfptr if the class has virtual functions + // other than those declared by its virtual bases. The AST doesn't + // tell us that directly, and checking manually for virtual + // functions that aren't overrides is expensive, but there are + // some important shortcuts: + + // - Non-polymorphic classes have no virtual functions at all. + if (!RD->isPolymorphic()) return false; + + // - Polymorphic classes with no virtual bases must either declare + // virtual functions directly or inherit them, but in the latter + // case we would have a primary base. + if (RD->getNumVBases() == 0) return true; + + return hasNewVirtualFunction(RD); } +/// hasNewVirtualFunction - Does the given polymorphic class declare a +/// virtual function that does not override a method from any of its +/// base classes? bool -RecordLayoutBuilder::HasNewVirtualFunction(const CXXRecordDecl *RD) const { +RecordLayoutBuilder::hasNewVirtualFunction(const CXXRecordDecl *RD) const { + assert(RD->isPolymorphic()); + if (!RD->getNumBases()) + return true; + for (CXXRecordDecl::method_iterator method = RD->method_begin(); method != RD->method_end(); ++method) { - if (method->isVirtual() && - !method->size_overridden_methods()) { + if (method->isVirtual() && !method->size_overridden_methods()) { return true; } } return false; } -bool -RecordLayoutBuilder::HasVBPtr(const CXXRecordDecl *RD) const { - if (!RD->getNumBases()) - return false; - - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (!I->isVirtual()) { - return false; - } - } - return true; +/// isPossiblePrimaryBase - Is the given base class an acceptable +/// primary base class? +bool +RecordLayoutBuilder::isPossiblePrimaryBase(const CXXRecordDecl *Base) const { + // In the Itanium ABI, a class can be a primary base class if it has + // a vtable for any reason. + if (!isMicrosoftCXXABI()) + return Base->isDynamicClass(); + + // In the MS ABI, a class can only be a primary base class if it + // provides a vf-table at a static offset. That means it has to be + // non-virtual base. The existence of a separate vb-table means + // that it's possible to get virtual functions only from a virtual + // base, which we have to guard against. + + // First off, it has to have virtual functions. + if (!Base->isPolymorphic()) return false; + + // If it has no virtual bases, then everything is at a static offset. + if (!Base->getNumVBases()) return true; + + // Okay, just ask the base class's layout. + return (Context.getASTRecordLayout(Base).getVFPtrOffset() + != CharUnits::fromQuantity(-1)); } void @@ -1121,7 +1259,7 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, "Cannot layout class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); if (I->isVirtual()) { if (PrimaryBase != BaseDecl || !PrimaryBaseIsVirtual) { @@ -1149,6 +1287,23 @@ RecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD, } } +void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *RD) { + + if (!RD->getNumVBases()) + return; + + // This is substantially simplified because there are no virtual + // primary bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = I->getType()->getAsCXXRecordDecl(); + const BaseSubobjectInfo *BaseInfo = VirtualBaseInfo.lookup(BaseDecl); + assert(BaseInfo && "Did not find virtual base info!"); + + LayoutVirtualBase(BaseInfo); + } +} + void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) { assert(!Base->Derived && "Trying to lay out a primary virtual base!"); @@ -1165,8 +1320,31 @@ void RecordLayoutBuilder::LayoutVirtualBase(const BaseSubobjectInfo *Base) { CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base->Class); + + CharUnits Offset; + + // Query the external layout to see if it provides an offset. + bool HasExternalLayout = false; + if (ExternalLayout) { + llvm::DenseMap<const CXXRecordDecl *, CharUnits>::iterator Known; + if (Base->IsVirtual) { + Known = ExternalVirtualBaseOffsets.find(Base->Class); + if (Known != ExternalVirtualBaseOffsets.end()) { + Offset = Known->second; + HasExternalLayout = true; + } + } else { + Known = ExternalBaseOffsets.find(Base->Class); + if (Known != ExternalBaseOffsets.end()) { + Offset = Known->second; + HasExternalLayout = true; + } + } + } + // If we have an empty base class, try to place it at offset 0. if (Base->Class->isEmpty() && + (!HasExternalLayout || Offset == CharUnits::Zero()) && EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) { setSize(std::max(getSize(), Layout.getSize())); @@ -1182,13 +1360,19 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { UnpackedBaseAlign = std::min(UnpackedBaseAlign, MaxFieldAlignment); } - // Round up the current record size to the base's alignment boundary. - CharUnits Offset = getDataSize().RoundUpToAlignment(BaseAlign); - - // Try to place the base. - while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset)) - Offset += BaseAlign; + if (!HasExternalLayout) { + // Round up the current record size to the base's alignment boundary. + Offset = getDataSize().RoundUpToAlignment(BaseAlign); + // Try to place the base. + while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset)) + Offset += BaseAlign; + } else { + bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset); + (void)Allowed; + assert(Allowed && "Base subobject externally placed at overlapping offset"); + } + if (!Base->Class->isEmpty()) { // Update the data size. setDataSize(Offset + Layout.getNonVirtualSize()); @@ -1212,7 +1396,7 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { IsMsStruct = D->hasAttr<MsStructAttr>(); // Honor the default struct packing maximum alignment flag. - if (unsigned DefaultMaxFieldAlignment = Context.getLangOptions().PackStruct) { + if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) { MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment); } @@ -1231,6 +1415,28 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { if (unsigned MaxAlign = D->getMaxAlignment()) UpdateAlignment(Context.toCharUnitsFromBits(MaxAlign)); } + + // If there is an external AST source, ask it for the various offsets. + if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) + if (ExternalASTSource *External = Context.getExternalSource()) { + ExternalLayout = External->layoutRecordType(RD, + ExternalSize, + ExternalAlign, + ExternalFieldOffsets, + ExternalBaseOffsets, + ExternalVirtualBaseOffsets); + + // Update based on external alignment. + if (ExternalLayout) { + if (ExternalAlign > 0) { + Alignment = Context.toCharUnitsFromBits(ExternalAlign); + UnpackedAlignment = Alignment; + } else { + // The external source didn't have alignment information; infer it. + InferAlignment = true; + } + } + } } void RecordLayoutBuilder::Layout(const RecordDecl *D) { @@ -1243,11 +1449,6 @@ void RecordLayoutBuilder::Layout(const RecordDecl *D) { } void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { - if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft) { - MSLayout(RD); - return ; - } - InitializeLayout(RD); // Lay out the vtable and the non-virtual bases. @@ -1260,13 +1461,27 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { Context.getTargetInfo().getCharAlign())); NonVirtualAlignment = Alignment; - // Lay out the virtual bases and add the primary virtual base offsets. - LayoutVirtualBases(RD, RD); + if (isMicrosoftCXXABI() && + NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) { + CharUnits AlignMember = + NonVirtualSize.RoundUpToAlignment(Alignment) - NonVirtualSize; - VisitedVirtualBases.clear(); + setSize(getSize() + AlignMember); + setDataSize(getSize()); - // Finally, round the size of the total struct up to the alignment of the - // struct itself. + NonVirtualSize = Context.toCharUnitsFromBits( + llvm::RoundUpToAlignment(getSizeInBits(), + Context.getTargetInfo().getCharAlign())); + + MSLayoutVirtualBases(RD); + + } else { + // Lay out the virtual bases and add the primary virtual base offsets. + LayoutVirtualBases(RD, RD); + } + + // Finally, round the size of the total struct up to the alignment + // of the struct itself. FinishLayout(RD); #ifndef NDEBUG @@ -1350,13 +1565,21 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { uint64_t TypeSize = FieldInfo.first; unsigned FieldAlign = FieldInfo.second; // This check is needed for 'long long' in -m32 mode. - if (TypeSize > FieldAlign) + if (TypeSize > FieldAlign && + (Context.hasSameType(FD->getType(), + Context.UnsignedLongLongTy) + ||Context.hasSameType(FD->getType(), + Context.LongLongTy))) FieldAlign = TypeSize; FieldInfo = Context.getTypeInfo(LastFD->getType()); uint64_t TypeSizeLastFD = FieldInfo.first; unsigned FieldAlignLastFD = FieldInfo.second; // This check is needed for 'long long' in -m32 mode. - if (TypeSizeLastFD > FieldAlignLastFD) + if (TypeSizeLastFD > FieldAlignLastFD && + (Context.hasSameType(LastFD->getType(), + Context.UnsignedLongLongTy) + || Context.hasSameType(LastFD->getType(), + Context.LongLongTy))) FieldAlignLastFD = TypeSizeLastFD; if (TypeSizeLastFD != TypeSize) { @@ -1435,7 +1658,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize, bool FieldPacked, const FieldDecl *D) { - assert(Context.getLangOptions().CPlusPlus && + assert(Context.getLangOpts().CPlusPlus && "Can only have wide bit-fields in C++!"); // Itanium C++ ABI 2.4: @@ -1507,7 +1730,10 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { unsigned FieldAlign = FieldInfo.second; // This check is needed for 'long long' in -m32 mode. - if (IsMsStruct && (TypeSize > FieldAlign)) + if (IsMsStruct && (TypeSize > FieldAlign) && + (Context.hasSameType(D->getType(), + Context.UnsignedLongLongTy) + || Context.hasSameType(D->getType(), Context.LongLongTy))) FieldAlign = TypeSize; if (ZeroLengthBitfield) { @@ -1557,18 +1783,21 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment()); // The maximum field alignment overrides the aligned attribute. - if (!MaxFieldAlignment.isZero()) { + if (!MaxFieldAlignment.isZero() && FieldSize != 0) { unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); } // Check if we need to add padding to give the field the correct alignment. - if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) + if (FieldSize == 0 || + (MaxFieldAlignment.isZero() && + (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); if (FieldSize == 0 || - (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize) + (MaxFieldAlignment.isZero() && + (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldAlign); @@ -1580,11 +1809,15 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { if (!IsMsStruct) ZeroLengthBitfield = 0; + if (ExternalLayout) + FieldOffset = updateExternalFieldOffset(D, FieldOffset); + // Place this field at the current location. FieldOffsets.push_back(FieldOffset); - CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset, - UnpackedFieldAlign, FieldPacked, D); + if (!ExternalLayout) + CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset, + UnpackedFieldAlign, FieldPacked, D); // Update DataSize to include the last byte containing (part of) the bitfield. if (IsUnion) { @@ -1606,7 +1839,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { Context.toCharUnitsFromBits(UnpackedFieldAlign)); } -void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { +void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { if (D->isBitField()) { LayoutBitField(D); return; @@ -1667,7 +1900,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { ZeroLengthBitfield = 0; } - if (Context.getLangOptions().MSBitfields || IsMsStruct) { + if (Context.getLangOpts().MSBitfields || IsMsStruct) { // If MS bitfield layout is required, figure out what type is being // laid out and align the field to the width of that type. @@ -1705,136 +1938,56 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { UnpackedFieldOffset = UnpackedFieldOffset.RoundUpToAlignment(UnpackedFieldAlign); - if (!IsUnion && EmptySubobjects) { - // Check if we can place the field at this offset. - while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) { - // We couldn't place the field at the offset. Try again at a new offset. - FieldOffset += FieldAlign; + if (ExternalLayout) { + FieldOffset = Context.toCharUnitsFromBits( + updateExternalFieldOffset(D, Context.toBits(FieldOffset))); + + if (!IsUnion && EmptySubobjects) { + // Record the fact that we're placing a field at this offset. + bool Allowed = EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset); + (void)Allowed; + assert(Allowed && "Externally-placed field cannot be placed here"); + } + } else { + if (!IsUnion && EmptySubobjects) { + // Check if we can place the field at this offset. + while (!EmptySubobjects->CanPlaceFieldAtOffset(D, FieldOffset)) { + // We couldn't place the field at the offset. Try again at a new offset. + FieldOffset += FieldAlign; + } } } - + // Place this field at the current location. FieldOffsets.push_back(Context.toBits(FieldOffset)); - CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset, - Context.toBits(UnpackedFieldOffset), - Context.toBits(UnpackedFieldAlign), FieldPacked, D); + if (!ExternalLayout) + CheckFieldPadding(Context.toBits(FieldOffset), UnpaddedFieldOffset, + Context.toBits(UnpackedFieldOffset), + Context.toBits(UnpackedFieldAlign), FieldPacked, D); // Reserve space for this field. uint64_t FieldSizeInBits = Context.toBits(FieldSize); if (IsUnion) - setSize(std::max(getSizeInBits(), FieldSizeInBits)); + setDataSize(std::max(getDataSizeInBits(), FieldSizeInBits)); else - setSize(FieldOffset + FieldSize); + setDataSize(FieldOffset + FieldSize); - // Update the data size. - setDataSize(getSizeInBits()); + // Update the size. + setSize(std::max(getSizeInBits(), getDataSizeInBits())); // Remember max struct/class alignment. UpdateAlignment(FieldAlign, UnpackedFieldAlign); } -void RecordLayoutBuilder::MSLayoutVirtualBases(const CXXRecordDecl *RD) { - - if (!RD->getNumVBases()) +void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { + if (ExternalLayout) { + setSize(ExternalSize); return; - - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - - const CXXRecordDecl* BaseDecl = I->getType()->getAsCXXRecordDecl(); - const BaseSubobjectInfo* BaseInfo = VirtualBaseInfo.lookup(BaseDecl); - - assert(BaseInfo && "Did not find virtual base info!"); - - LayoutVirtualBase(BaseInfo); - } -} - -void RecordLayoutBuilder::MSLayout(const CXXRecordDecl *RD) { - - bool IsVBPtrAddedToLayout = false; - - InitializeLayout(RD); - - if (HasVBPtr(RD)) { - // If all bases are virtual and the class declares a new virtual function, - // MSVC builds a vfptr. - if (HasNewVirtualFunction(RD)) { - AddVPointer(); - } - - VBPtrOffset = getSize(); - AddVPointer(); - IsVBPtrAddedToLayout = true; - - ComputeBaseSubobjectInfo(RD); - } else { - LayoutNonVirtualBases(RD); - } - - if (RD->getNumVBases() && - !IsVBPtrAddedToLayout) { - // Add vbptr. - VBPtrOffset = getSize(); - AddVPointer(); - } - - LayoutFields(RD); - - NonVirtualSize = Context.toCharUnitsFromBits( - llvm::RoundUpToAlignment(getSizeInBits(), - Context.getTargetInfo().getCharAlign())); - NonVirtualAlignment = Alignment; - - if (NonVirtualSize != NonVirtualSize.RoundUpToAlignment(Alignment)) { - CharUnits AlignMember = - NonVirtualSize.RoundUpToAlignment(Alignment) - NonVirtualSize; - - setSize(getSize() + AlignMember); - setDataSize(getSize()); - - NonVirtualSize = Context.toCharUnitsFromBits( - llvm::RoundUpToAlignment(getSizeInBits(), - Context.getTargetInfo().getCharAlign())); - } - - MSLayoutVirtualBases(RD); - - VisitedVirtualBases.clear(); - - // Finally, round the size of the total struct up to the alignment of the - // struct itself. - if (!RD->getNumVBases()) - FinishLayout(RD); - -#ifndef NDEBUG - // Check that we have base offsets for all bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual()) - continue; - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - assert(Bases.count(BaseDecl) && "Did not find base offset!"); - } - - // And all virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - assert(VBases.count(BaseDecl) && "Did not find base offset!"); } -#endif -} - -void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { + // In C++, records cannot be of size 0. - if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) { + if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { // Compatibility with gcc requires a class (pod or non-pod) // which is not empty but of size 0; such as having fields of @@ -1845,6 +1998,13 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { else setSize(CharUnits::One()); } + + // MSVC doesn't round up to the alignment of the record with virtual bases. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { + if (isMicrosoftCXXABI() && RD->getNumVBases()) + return; + } + // Finally, round the size of the record up to the alignment of the // record itself. uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte; @@ -1881,8 +2041,9 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment, CharUnits UnpackedNewAlignment) { - // The alignment is not modified when using 'mac68k' alignment. - if (IsMac68kAlign) + // The alignment is not modified when using 'mac68k' alignment or when + // we have an externally-supplied layout that also provides overall alignment. + if (IsMac68kAlign || (ExternalLayout && !InferAlignment)) return; if (NewAlignment > Alignment) { @@ -1898,6 +2059,25 @@ void RecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment, } } +uint64_t +RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, + uint64_t ComputedOffset) { + assert(ExternalFieldOffsets.find(Field) != ExternalFieldOffsets.end() && + "Field does not have an external offset"); + + uint64_t ExternalFieldOffset = ExternalFieldOffsets[Field]; + + if (InferAlignment && ExternalFieldOffset < ComputedOffset) { + // The externally-supplied field offset is before the field offset we + // computed. Assume that the structure is packed. + Alignment = CharUnits::fromQuantity(1); + InferAlignment = false; + } + + // Use the externally-supplied field offset. + return ExternalFieldOffset; +} + void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset, @@ -2007,6 +2187,10 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // as soon as we begin to parse the definition. That definition is // not a complete definition (which is what isDefinition() tests) // until we *finish* parsing the definition. + + if (D->hasExternalLexicalStorage() && !D->getDefinition()) + getExternalSource()->CompleteType(const_cast<RecordDecl*>(D)); + D = D->getDefinition(); assert(D && "Cannot get layout of forward declarations!"); assert(D->isCompleteDefinition() && "Cannot layout type before complete!"); @@ -2021,36 +2205,21 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { EmptySubobjectMap EmptySubobjects(*this, RD); - - llvm::OwningPtr<RecordLayoutBuilder> Builder; - CharUnits TargetAlign = CharUnits::One(); - - Builder.reset(new RecordLayoutBuilder(*this, - &EmptySubobjects, - TargetAlign)); - - // Recover resources if we crash before exiting this method. - llvm::CrashRecoveryContextCleanupRegistrar<RecordLayoutBuilder> - RecordBuilderCleanup(Builder.get()); - - Builder->Layout(RD); - - TargetAlign = Builder->getAligment(); - - if (getTargetInfo().getCXXABI() == CXXABI_Microsoft && - TargetAlign.getQuantity() > 4) { - // MSVC rounds the vtable pointer to the struct alignment in what must - // be a multi-pass operation. For now, let the builder figure out the - // alignment and recalculate the layout once its known. - Builder.reset(new RecordLayoutBuilder(*this, - &EmptySubobjects, - TargetAlign)); - - Builder->Layout(RD); - - // Recover resources if we crash before exiting this method. - llvm::CrashRecoveryContextCleanupRegistrar<RecordLayoutBuilder> - RecordBuilderCleanup(Builder.get()); + RecordLayoutBuilder Builder(*this, &EmptySubobjects); + Builder.Layout(RD); + + // MSVC gives the vb-table pointer an alignment equal to that of + // the non-virtual part of the structure. That's an inherently + // multi-pass operation. If our first pass doesn't give us + // adequate alignment, try again with the specified minimum + // alignment. This is *much* more maintainable than computing the + // alignment in advance in a separately-coded pass; it's also + // significantly more efficient in the common case where the + // vb-table doesn't need extra padding. + if (Builder.VBPtrOffset != CharUnits::fromQuantity(-1) && + (Builder.VBPtrOffset % Builder.NonVirtualAlignment) != 0) { + Builder.resetWithTargetAlignment(Builder.NonVirtualAlignment); + Builder.Layout(RD); } // FIXME: This is not always correct. See the part about bitfields at @@ -2058,30 +2227,30 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout. // This does not affect the calculations of MSVC layouts bool IsPODForThePurposeOfLayout = - (getTargetInfo().getCXXABI() == CXXABI_Microsoft) || - cast<CXXRecordDecl>(D)->isPOD(); + (!Builder.isMicrosoftCXXABI() && cast<CXXRecordDecl>(D)->isPOD()); // FIXME: This should be done in FinalizeLayout. CharUnits DataSize = - IsPODForThePurposeOfLayout ? Builder->getSize() : Builder->getDataSize(); + IsPODForThePurposeOfLayout ? Builder.getSize() : Builder.getDataSize(); CharUnits NonVirtualSize = - IsPODForThePurposeOfLayout ? DataSize : Builder->NonVirtualSize; + IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; NewEntry = - new (*this) ASTRecordLayout(*this, Builder->getSize(), - Builder->Alignment, - Builder->GetVBPtrOffset(), + new (*this) ASTRecordLayout(*this, Builder.getSize(), + Builder.Alignment, + Builder.VFPtrOffset, + Builder.VBPtrOffset, DataSize, - Builder->FieldOffsets.data(), - Builder->FieldOffsets.size(), + Builder.FieldOffsets.data(), + Builder.FieldOffsets.size(), NonVirtualSize, - Builder->NonVirtualAlignment, + Builder.NonVirtualAlignment, EmptySubobjects.SizeOfLargestEmptySubobject, - Builder->PrimaryBase, - Builder->PrimaryBaseIsVirtual, - Builder->Bases, Builder->VBases); + Builder.PrimaryBase, + Builder.PrimaryBaseIsVirtual, + Builder.Bases, Builder.VBases); } else { - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0, CharUnits::One()); + RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); Builder.Layout(D); NewEntry = @@ -2094,9 +2263,9 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { ASTRecordLayouts[D] = NewEntry; - if (getLangOptions().DumpRecordLayouts) { + if (getLangOpts().DumpRecordLayouts) { llvm::errs() << "\n*** Dumping AST Record Layout\n"; - DumpRecordLayout(D, llvm::errs()); + DumpRecordLayout(D, llvm::errs(), getLangOpts().DumpRecordLayoutsSimple); } return *NewEntry; @@ -2113,6 +2282,28 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { return Entry; } +static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD) { + const ASTRecordLayout &Layout = C.getASTRecordLayout(FD->getParent()); + return Layout.getFieldOffset(FD->getFieldIndex()); +} + +uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const { + uint64_t OffsetInBits; + if (const FieldDecl *FD = dyn_cast<FieldDecl>(VD)) { + OffsetInBits = ::getFieldOffset(*this, FD); + } else { + const IndirectFieldDecl *IFD = cast<IndirectFieldDecl>(VD); + + OffsetInBits = 0; + for (IndirectFieldDecl::chain_iterator CI = IFD->chain_begin(), + CE = IFD->chain_end(); + CI != CE; ++CI) + OffsetInBits += ::getFieldOffset(*this, cast<FieldDecl>(*CI)); + } + + return OffsetInBits; +} + /// getObjCLayout - Get or compute information about the layout of the /// given interface. /// @@ -2121,7 +2312,11 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { const ASTRecordLayout & ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const { - assert(!D->isForwardDecl() && "Invalid interface decl!"); + // Retrieve the definition + if (D->hasExternalLexicalStorage() && !D->getDefinition()) + getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D)); + D = D->getDefinition(); + assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!"); // Look up this layout, if already laid out, return what we have. ObjCContainerDecl *Key = @@ -2140,7 +2335,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, return getObjCLayout(D, 0); } - RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0, CharUnits::One()); + RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0); Builder.Layout(D); const ASTRecordLayout *NewEntry = @@ -2157,7 +2352,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel) { - OS << llvm::format("%4d | ", Offset.getQuantity()); + OS << llvm::format("%4" PRId64 " | ", (int64_t)Offset.getQuantity()); OS.indent(IndentLevel * 2); } @@ -2180,22 +2375,16 @@ static void DumpCXXRecordLayout(raw_ostream &OS, IndentLevel++; const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + bool HasVfptr = Layout.getVFPtrOffset() != CharUnits::fromQuantity(-1); bool HasVbptr = Layout.getVBPtrOffset() != CharUnits::fromQuantity(-1); // Vtable pointer. - if (RD->isDynamicClass() && !PrimaryBase) { + if (RD->isDynamicClass() && !PrimaryBase && + C.getTargetInfo().getCXXABI() != CXXABI_Microsoft) { PrintOffset(OS, Offset, IndentLevel); OS << '(' << *RD << " vtable pointer)\n"; } - if (HasVbptr && !PrimaryBase) { - PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); - OS << '(' << *RD << " vbtable pointer)\n"; - - // one vbtable per class - HasVbptr = false; - } - // Dump (non-virtual) bases for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { @@ -2213,7 +2402,12 @@ static void DumpCXXRecordLayout(raw_ostream &OS, Base == PrimaryBase ? "(primary base)" : "(base)", /*IncludeVirtualBases=*/false); } - // vbptr + + // vfptr and vbptr (for Microsoft C++ ABI) + if (HasVfptr) { + PrintOffset(OS, Offset + Layout.getVFPtrOffset(), IndentLevel); + OS << '(' << *RD << " vftable pointer)\n"; + } if (HasVbptr) { PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); OS << '(' << *RD << " vbtable pointer)\n"; @@ -2266,16 +2460,20 @@ static void DumpCXXRecordLayout(raw_ostream &OS, } void ASTContext::DumpRecordLayout(const RecordDecl *RD, - raw_ostream &OS) const { + raw_ostream &OS, + bool Simple) const { const ASTRecordLayout &Info = getASTRecordLayout(RD); if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) - return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, 0, - /*IncludeVirtualBases=*/true); + if (!Simple) + return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, 0, + /*IncludeVirtualBases=*/true); OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n"; - OS << "Record: "; - RD->dump(); + if (!Simple) { + OS << "Record: "; + RD->dump(); + } OS << "\nLayout: "; OS << "<ASTRecordLayout\n"; OS << " Size:" << toBits(Info.getSize()) << "\n"; diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index e7b87e4..6af20df 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -78,11 +78,9 @@ void Stmt::addStmtClass(StmtClass s) { ++getStmtInfoTableEntry(s).Counter; } -static bool StatSwitch = false; - -bool Stmt::CollectingStats(bool Enable) { - if (Enable) StatSwitch = true; - return StatSwitch; +bool Stmt::StatisticsEnabled = false; +void Stmt::EnableStatistics() { + StatisticsEnabled = true; } Stmt *Stmt::IgnoreImplicit() { @@ -164,7 +162,6 @@ Stmt::child_range Stmt::children() { #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind!"); - return child_range(); } SourceRange Stmt::getSourceRange() const { @@ -177,7 +174,72 @@ SourceRange Stmt::getSourceRange() const { #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind!"); - return SourceRange(); +} + +// Amusing macro metaprogramming hack: check whether a class provides +// a more specific implementation of getLocStart() and getLocEnd(). +// +// See also Expr.cpp:getExprLoc(). +namespace { + /// This implementation is used when a class provides a custom + /// implementation of getLocStart. + template <class S, class T> + SourceLocation getLocStartImpl(const Stmt *stmt, + SourceLocation (T::*v)() const) { + return static_cast<const S*>(stmt)->getLocStart(); + } + + /// This implementation is used when a class doesn't provide a custom + /// implementation of getLocStart. Overload resolution should pick it over + /// the implementation above because it's more specialized according to + /// function template partial ordering. + template <class S> + SourceLocation getLocStartImpl(const Stmt *stmt, + SourceLocation (Stmt::*v)() const) { + return static_cast<const S*>(stmt)->getSourceRange().getBegin(); + } + + /// This implementation is used when a class provides a custom + /// implementation of getLocEnd. + template <class S, class T> + SourceLocation getLocEndImpl(const Stmt *stmt, + SourceLocation (T::*v)() const) { + return static_cast<const S*>(stmt)->getLocEnd(); + } + + /// This implementation is used when a class doesn't provide a custom + /// implementation of getLocEnd. Overload resolution should pick it over + /// the implementation above because it's more specialized according to + /// function template partial ordering. + template <class S> + SourceLocation getLocEndImpl(const Stmt *stmt, + SourceLocation (Stmt::*v)() const) { + return static_cast<const S*>(stmt)->getSourceRange().getEnd(); + } +} + +SourceLocation Stmt::getLocStart() const { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: \ + return getLocStartImpl<type>(this, &type::getLocStart); +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("unknown statement kind"); +} + +SourceLocation Stmt::getLocEnd() const { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: \ + return getLocEndImpl<type>(this, &type::getLocEnd); +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("unknown statement kind"); } void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { @@ -631,9 +693,9 @@ void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) { return; } - SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), - V->getSourceRange().getBegin(), - V->getSourceRange().getEnd()); + SourceRange VarRange = V->getSourceRange(); + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), + VarRange.getEnd()); } ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, @@ -662,9 +724,9 @@ void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) { return; } - SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), - V->getSourceRange().getBegin(), - V->getSourceRange().getEnd()); + SourceRange VarRange = V->getSourceRange(); + SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), + VarRange.getEnd()); } SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond) @@ -689,9 +751,9 @@ void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { return; } - SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), - V->getSourceRange().getBegin(), - V->getSourceRange().getEnd()); + SourceRange VarRange = V->getSourceRange(); + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), + VarRange.getEnd()); } Stmt *SwitchCase::getSubStmt() { @@ -722,10 +784,10 @@ void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { SubExprs[VAR] = 0; return; } - - SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), - V->getSourceRange().getBegin(), - V->getSourceRange().getEnd()); + + SourceRange VarRange = V->getSourceRange(); + SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), + VarRange.getEnd()); } // IndirectGotoStmt diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp index 2968739..b5e298c 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp @@ -112,6 +112,7 @@ namespace { case OK_Ordinary: break; case OK_BitField: OS << " bitfield"; break; case OK_ObjCProperty: OS << " objcproperty"; break; + case OK_ObjCSubscript: OS << " objcsubscript"; break; case OK_VectorComponent: OS << " vectorcomponent"; break; } } @@ -148,6 +149,7 @@ namespace { void VisitCompoundAssignOperator(CompoundAssignOperator *Node); void VisitAddrLabelExpr(AddrLabelExpr *Node); void VisitBlockExpr(BlockExpr *Node); + void VisitOpaqueValueExpr(OpaqueValueExpr *Node); // C++ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); @@ -167,7 +169,9 @@ namespace { void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node); + void VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node); void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); + void VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node); }; } @@ -250,7 +254,7 @@ void StmtDumper::DumpDeclarator(Decl *D) { std::string Name = VD->getNameAsString(); VD->getType().getAsStringInternal(Name, - PrintingPolicy(VD->getASTContext().getLangOptions())); + PrintingPolicy(VD->getASTContext().getLangOpts())); OS << Name; // If this is a vardecl with an initializer, emit it. @@ -283,10 +287,10 @@ void StmtDumper::DumpDeclarator(Decl *D) { const char *tn = UD->isTypeName() ? "typename " : ""; OS << '"' << UD->getDeclKindName() << tn; UD->getQualifier()->print(OS, - PrintingPolicy(UD->getASTContext().getLangOptions())); + PrintingPolicy(UD->getASTContext().getLangOpts())); OS << ";\""; } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) { - OS << "label " << LD->getNameAsString(); + OS << "label " << *LD; } else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) { OS << "\"static_assert(\n"; DumpSubTree(SAD->getAssertExpr()); @@ -425,7 +429,7 @@ void StmtDumper::VisitPredefinedExpr(PredefinedExpr *Node) { void StmtDumper::VisitCharacterLiteral(CharacterLiteral *Node) { DumpExpr(Node); - OS << Node->getValue(); + OS << " " << Node->getValue(); } void StmtDumper::VisitIntegerLiteral(IntegerLiteral *Node) { @@ -503,8 +507,10 @@ void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { void StmtDumper::VisitBlockExpr(BlockExpr *Node) { DumpExpr(Node); - IndentLevel++; BlockDecl *block = Node->getBlockDecl(); + OS << " decl=" << block; + + IndentLevel++; if (block->capturesCXXThis()) { OS << '\n'; Indent(); OS << "(capture this)"; } @@ -515,15 +521,26 @@ void StmtDumper::VisitBlockExpr(BlockExpr *Node) { OS << "(capture "; if (i->isByRef()) OS << "byref "; if (i->isNested()) OS << "nested "; - DumpDeclRef(i->getVariable()); + if (i->getVariable()) + DumpDeclRef(i->getVariable()); if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr()); OS << ")"; } IndentLevel--; + OS << '\n'; DumpSubTree(block->getBody()); } +void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { + DumpExpr(Node); + + if (Expr *Source = Node->getSourceExpr()) { + OS << '\n'; + DumpSubTree(Source); + } +} + // GNU extensions. void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { @@ -580,10 +597,12 @@ void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) { DumpExpr(Node); ++IndentLevel; - for (unsigned i = 0, e = Node->getNumTemporaries(); i != e; ++i) { + for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) { OS << "\n"; Indent(); - DumpCXXTemporary(Node->getTemporary(i)); + OS << "(cleanup "; + DumpDeclRef(Node->getObject(i)); + OS << ")"; } --IndentLevel; } @@ -667,6 +686,40 @@ void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { if (Node->isSuperReceiver()) OS << " super"; + + OS << " Messaging="; + if (Node->isMessagingGetter() && Node->isMessagingSetter()) + OS << "Getter&Setter"; + else if (Node->isMessagingGetter()) + OS << "Getter"; + else if (Node->isMessagingSetter()) + OS << "Setter"; +} + +void StmtDumper::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { + DumpExpr(Node); + if (Node->isArraySubscriptRefExpr()) + OS << " Kind=ArraySubscript GetterForArray=\""; + else + OS << " Kind=DictionarySubscript GetterForDictionary=\""; + if (Node->getAtIndexMethodDecl()) + OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); + else + OS << "(null)"; + + if (Node->isArraySubscriptRefExpr()) + OS << "\" SetterForArray=\""; + else + OS << "\" SetterForDictionary=\""; + if (Node->setAtIndexMethodDecl()) + OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); + else + OS << "(null)"; +} + +void StmtDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) { + DumpExpr(Node); + OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp index daaa354..3a44183 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtPrinter.cpp @@ -17,9 +17,9 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/PrettyPrinter.h" -#include "llvm/Support/Format.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "llvm/ADT/SmallString.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -305,6 +305,22 @@ void StmtPrinter::VisitCXXForRangeStmt(CXXForRangeStmt *Node) { Indent() << "}\n"; } +void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) { + Indent(); + if (Node->isIfExists()) + OS << "__if_exists ("; + else + OS << "__if_not_exists ("; + + if (NestedNameSpecifier *Qualifier + = Node->getQualifierLoc().getNestedNameSpecifier()) + Qualifier->print(OS, Policy); + + OS << Node->getNameInfo() << ") "; + + PrintRawCompoundStmt(Node->getSubStmt()); +} + void StmtPrinter::VisitGotoStmt(GotoStmt *Node) { Indent() << "goto " << Node->getLabel()->getName() << ";\n"; } @@ -528,6 +544,8 @@ void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); + if (Node->hasTemplateKeyword()) + OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) OS << TemplateSpecializationType::PrintTemplateArgumentList( @@ -540,6 +558,8 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *Node) { if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); + if (Node->hasTemplateKeyword()) + OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) OS << TemplateSpecializationType::PrintTemplateArgumentList( @@ -551,6 +571,8 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr( void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { if (Node->getQualifier()) Node->getQualifier()->print(OS, Policy); + if (Node->hasTemplateKeyword()) + OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) OS << TemplateSpecializationType::PrintTemplateArgumentList( @@ -581,6 +603,14 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { OS << Node->getExplicitProperty()->getName(); } +void StmtPrinter::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *Node) { + + PrintExpr(Node->getBaseExpr()); + OS << "["; + PrintExpr(Node->getKeyExpr()); + OS << "]"; +} + void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) { switch (Node->getIdentType()) { default: @@ -644,7 +674,8 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { if (value < 256 && isprint(value)) { OS << "'" << (char)value << "'"; } else if (value < 256) { - OS << "'\\x" << llvm::format("%x", value) << "'"; + OS << "'\\x"; + OS.write_hex(value) << "'"; } else { // FIXME what to really do here? OS << value; @@ -659,16 +690,23 @@ void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { // Emit suffixes. Integer literals are always a builtin integer type. switch (Node->getType()->getAs<BuiltinType>()->getKind()) { default: llvm_unreachable("Unexpected type for integer literal!"); + // FIXME: The Short and UShort cases are to handle cases where a short + // integeral literal is formed during template instantiation. They should + // be removed when template instantiation no longer needs integer literals. + case BuiltinType::Short: + case BuiltinType::UShort: case BuiltinType::Int: break; // no suffix. case BuiltinType::UInt: OS << 'U'; break; case BuiltinType::Long: OS << 'L'; break; case BuiltinType::ULong: OS << "UL"; break; case BuiltinType::LongLong: OS << "LL"; break; case BuiltinType::ULongLong: OS << "ULL"; break; + case BuiltinType::Int128: OS << "i128"; break; + case BuiltinType::UInt128: OS << "Ui128"; break; } } void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) { - llvm::SmallString<16> Str; + SmallString<16> Str; Node->getValue().toString(Str); OS << Str; } @@ -687,22 +725,74 @@ void StmtPrinter::VisitStringLiteral(StringLiteral *Str) { case StringLiteral::UTF32: OS << 'U'; break; } OS << '"'; + static char Hex[] = "0123456789ABCDEF"; - // FIXME: this doesn't print wstrings right. - StringRef StrData = Str->getString(); - for (StringRef::iterator I = StrData.begin(), E = StrData.end(); - I != E; ++I) { - unsigned char Char = *I; - - switch (Char) { + unsigned LastSlashX = Str->getLength(); + for (unsigned I = 0, N = Str->getLength(); I != N; ++I) { + switch (uint32_t Char = Str->getCodeUnit(I)) { default: - if (isprint(Char)) + // FIXME: Convert UTF-8 back to codepoints before rendering. + + // Convert UTF-16 surrogate pairs back to codepoints before rendering. + // Leave invalid surrogates alone; we'll use \x for those. + if (Str->getKind() == StringLiteral::UTF16 && I != N - 1 && + Char >= 0xd800 && Char <= 0xdbff) { + uint32_t Trail = Str->getCodeUnit(I + 1); + if (Trail >= 0xdc00 && Trail <= 0xdfff) { + Char = 0x10000 + ((Char - 0xd800) << 10) + (Trail - 0xdc00); + ++I; + } + } + + if (Char > 0xff) { + // If this is a wide string, output characters over 0xff using \x + // escapes. Otherwise, this is a UTF-16 or UTF-32 string, and Char is a + // codepoint: use \x escapes for invalid codepoints. + if (Str->getKind() == StringLiteral::Wide || + (Char >= 0xd800 && Char <= 0xdfff) || Char >= 0x110000) { + // FIXME: Is this the best way to print wchar_t? + OS << "\\x"; + int Shift = 28; + while ((Char >> Shift) == 0) + Shift -= 4; + for (/**/; Shift >= 0; Shift -= 4) + OS << Hex[(Char >> Shift) & 15]; + LastSlashX = I; + break; + } + + if (Char > 0xffff) + OS << "\\U00" + << Hex[(Char >> 20) & 15] + << Hex[(Char >> 16) & 15]; + else + OS << "\\u"; + OS << Hex[(Char >> 12) & 15] + << Hex[(Char >> 8) & 15] + << Hex[(Char >> 4) & 15] + << Hex[(Char >> 0) & 15]; + break; + } + + // If we used \x... for the previous character, and this character is a + // hexadecimal digit, prevent it being slurped as part of the \x. + if (LastSlashX + 1 == I) { + switch (Char) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + OS << "\"\""; + } + } + + if (Char <= 0xff && isprint(Char)) OS << (char)Char; else // Output anything hard as an octal escape. OS << '\\' - << (char)('0'+ ((Char >> 6) & 7)) - << (char)('0'+ ((Char >> 3) & 7)) - << (char)('0'+ ((Char >> 0) & 7)); + << (char)('0' + ((Char >> 6) & 7)) + << (char)('0' + ((Char >> 3) & 7)) + << (char)('0' + ((Char >> 0) & 7)); break; // Handle some common non-printable cases to make dumps prettier. case '\\': OS << "\\\\"; break; @@ -849,9 +939,9 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { OS << (Node->isArrow() ? "->" : "."); if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); - + if (Node->hasTemplateKeyword()) + OS << "template "; OS << Node->getMemberNameInfo(); - if (Node->hasExplicitTemplateArgs()) OS << TemplateSpecializationType::PrintTemplateArgumentList( Node->getTemplateArgs(), @@ -1011,52 +1101,42 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << ")"; } +void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) { + PrintExpr(Node->getSyntacticForm()); +} + void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { const char *Name = 0; switch (Node->getOp()) { - case AtomicExpr::Load: - Name = "__atomic_load("; - break; - case AtomicExpr::Store: - Name = "__atomic_store("; - break; - case AtomicExpr::CmpXchgStrong: - Name = "__atomic_compare_exchange_strong("; - break; - case AtomicExpr::CmpXchgWeak: - Name = "__atomic_compare_exchange_weak("; - break; - case AtomicExpr::Xchg: - Name = "__atomic_exchange("; - break; - case AtomicExpr::Add: - Name = "__atomic_fetch_add("; - break; - case AtomicExpr::Sub: - Name = "__atomic_fetch_sub("; - break; - case AtomicExpr::And: - Name = "__atomic_fetch_and("; - break; - case AtomicExpr::Or: - Name = "__atomic_fetch_or("; - break; - case AtomicExpr::Xor: - Name = "__atomic_fetch_xor("; - break; +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ + case AtomicExpr::AO ## ID: \ + Name = #ID "("; \ + break; +#include "clang/Basic/Builtins.def" } OS << Name; + + // AtomicExpr stores its subexpressions in a permuted order. PrintExpr(Node->getPtr()); OS << ", "; - if (Node->getOp() != AtomicExpr::Load) { + if (Node->getOp() != AtomicExpr::AO__c11_atomic_load && + Node->getOp() != AtomicExpr::AO__atomic_load_n) { PrintExpr(Node->getVal1()); OS << ", "; } - if (Node->isCmpXChg()) { + if (Node->getOp() == AtomicExpr::AO__atomic_exchange || + Node->isCmpXChg()) { PrintExpr(Node->getVal2()); OS << ", "; } - PrintExpr(Node->getOrder()); + if (Node->getOp() == AtomicExpr::AO__atomic_compare_exchange || + Node->getOp() == AtomicExpr::AO__atomic_compare_exchange_n) { + PrintExpr(Node->getWeak()); + OS << ", "; + } + if (Node->getOp() != AtomicExpr::AO__c11_atomic_init) + PrintExpr(Node->getOrder()); if (Node->isCmpXChg()) { OS << ", "; PrintExpr(Node->getOrderFail()); @@ -1165,6 +1245,39 @@ void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) { OS << ")"; } +void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { + switch (Node->getLiteralOperatorKind()) { + case UserDefinedLiteral::LOK_Raw: + OS << cast<StringLiteral>(Node->getArg(0)->IgnoreImpCasts())->getString(); + break; + case UserDefinedLiteral::LOK_Template: { + DeclRefExpr *DRE = cast<DeclRefExpr>(Node->getCallee()->IgnoreImpCasts()); + const TemplateArgumentList *Args = + cast<FunctionDecl>(DRE->getDecl())->getTemplateSpecializationArgs(); + assert(Args); + const TemplateArgument &Pack = Args->get(0); + for (TemplateArgument::pack_iterator I = Pack.pack_begin(), + E = Pack.pack_end(); I != E; ++I) { + char C = (char)I->getAsIntegral()->getZExtValue(); + OS << C; + } + break; + } + case UserDefinedLiteral::LOK_Integer: { + // Print integer literal without suffix. + IntegerLiteral *Int = cast<IntegerLiteral>(Node->getCookedLiteral()); + OS << Int->getValue().toString(10, /*isSigned*/false); + break; + } + case UserDefinedLiteral::LOK_Floating: + case UserDefinedLiteral::LOK_String: + case UserDefinedLiteral::LOK_Character: + PrintExpr(Node->getCookedLiteral()); + break; + } + OS << Node->getUDSuffix()->getName(); +} + void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { OS << (Node->getValue() ? "true" : "false"); } @@ -1214,6 +1327,98 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { OS << ")"; } +void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { + OS << '['; + bool NeedComma = false; + switch (Node->getCaptureDefault()) { + case LCD_None: + break; + + case LCD_ByCopy: + OS << '='; + NeedComma = true; + break; + + case LCD_ByRef: + OS << '&'; + NeedComma = true; + break; + } + for (LambdaExpr::capture_iterator C = Node->explicit_capture_begin(), + CEnd = Node->explicit_capture_end(); + C != CEnd; + ++C) { + if (NeedComma) + OS << ", "; + NeedComma = true; + + switch (C->getCaptureKind()) { + case LCK_This: + OS << "this"; + break; + + case LCK_ByRef: + if (Node->getCaptureDefault() != LCD_ByRef) + OS << '&'; + OS << C->getCapturedVar()->getName(); + break; + + case LCK_ByCopy: + if (Node->getCaptureDefault() != LCD_ByCopy) + OS << '='; + OS << C->getCapturedVar()->getName(); + break; + } + } + OS << ']'; + + if (Node->hasExplicitParameters()) { + OS << " ("; + CXXMethodDecl *Method = Node->getCallOperator(); + NeedComma = false; + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; ++P) { + if (NeedComma) { + OS << ", "; + } else { + NeedComma = true; + } + std::string ParamStr = (*P)->getNameAsString(); + (*P)->getOriginalType().getAsStringInternal(ParamStr, Policy); + OS << ParamStr; + } + if (Method->isVariadic()) { + if (NeedComma) + OS << ", "; + OS << "..."; + } + OS << ')'; + + if (Node->isMutable()) + OS << " mutable"; + + const FunctionProtoType *Proto + = Method->getType()->getAs<FunctionProtoType>(); + { + std::string ExceptionSpec; + Proto->printExceptionSpecification(ExceptionSpec, Policy); + OS << ExceptionSpec; + } + + // FIXME: Attributes + + // Print the trailing return type if it was specified in the source. + if (Node->hasExplicitResultType()) + OS << " -> " << Proto->getResultType().getAsString(Policy); + } + + // Print the body. + CompoundStmt *Body = Node->getBody(); + OS << ' '; + PrintStmt(Body); +} + void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo()) OS << TSInfo->getType().getAsString(Policy) << "()"; @@ -1249,17 +1454,13 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isParenTypeId()) OS << ")"; - if (E->hasInitializer()) { - OS << "("; - unsigned NumCons = E->getNumConstructorArgs(); - if (NumCons > 0) { - PrintExpr(E->getConstructorArg(0)); - for (unsigned i = 1; i < NumCons; ++i) { - OS << ", "; - PrintExpr(E->getConstructorArg(i)); - } - } - OS << ")"; + CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle(); + if (InitStyle) { + if (InitStyle == CXXNewExpr::CallInit) + OS << "("; + PrintExpr(E->getInitializer()); + if (InitStyle == CXXNewExpr::CallInit) + OS << ")"; } } @@ -1329,12 +1530,9 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr( } if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); - else if (Node->hasExplicitTemplateArgs()) - // FIXME: Track use of "template" keyword explicitly? + if (Node->hasTemplateKeyword()) OS << "template "; - OS << Node->getMemberNameInfo(); - if (Node->hasExplicitTemplateArgs()) { OS << TemplateSpecializationType::PrintTemplateArgumentList( Node->getTemplateArgs(), @@ -1350,11 +1548,9 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { } if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); - - // FIXME: this might originally have been written with 'template' - + if (Node->hasTemplateKeyword()) + OS << "template "; OS << Node->getMemberNameInfo(); - if (Node->hasExplicitTemplateArgs()) { OS << TemplateSpecializationType::PrintTemplateArgumentList( Node->getTemplateArgs(), @@ -1382,6 +1578,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { case UTT_IsConst: return "__is_const"; case UTT_IsEmpty: return "__is_empty"; case UTT_IsEnum: return "__is_enum"; + case UTT_IsFinal: return "__is_final"; case UTT_IsFloatingPoint: return "__is_floating_point"; case UTT_IsFunction: return "__is_function"; case UTT_IsFundamental: return "__is_fundamental"; @@ -1412,15 +1609,23 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) { static const char *getTypeTraitName(BinaryTypeTrait BTT) { switch (BTT) { - case BTT_IsBaseOf: return "__is_base_of"; - case BTT_IsConvertible: return "__is_convertible"; - case BTT_IsSame: return "__is_same"; - case BTT_TypeCompatible: return "__builtin_types_compatible_p"; - case BTT_IsConvertibleTo: return "__is_convertible_to"; + case BTT_IsBaseOf: return "__is_base_of"; + case BTT_IsConvertible: return "__is_convertible"; + case BTT_IsSame: return "__is_same"; + case BTT_TypeCompatible: return "__builtin_types_compatible_p"; + case BTT_IsConvertibleTo: return "__is_convertible_to"; + case BTT_IsTriviallyAssignable: return "__is_trivially_assignable"; } llvm_unreachable("Binary type trait not covered by switch"); } +static const char *getTypeTraitName(TypeTrait TT) { + switch (TT) { + case clang::TT_IsTriviallyConstructible:return "__is_trivially_constructible"; + } + llvm_unreachable("Type trait not covered by switch"); +} + static const char *getTypeTraitName(ArrayTypeTrait ATT) { switch (ATT) { case ATT_ArrayRank: return "__array_rank"; @@ -1448,6 +1653,16 @@ void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { << E->getRhsType().getAsString(Policy) << ")"; } +void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { + OS << getTypeTraitName(E->getTrait()) << "("; + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { + if (I > 0) + OS << ", "; + OS << E->getArg(I)->getType().getAsString(Policy); + } + OS << ")"; +} + void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { OS << getTypeTraitName(E->getTrait()) << "(" << E->getQueriedType().getAsString(Policy) << ")"; @@ -1471,12 +1686,12 @@ void StmtPrinter::VisitPackExpansionExpr(PackExpansionExpr *E) { } void StmtPrinter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { - OS << "sizeof...(" << E->getPack()->getNameAsString() << ")"; + OS << "sizeof...(" << *E->getPack() << ")"; } void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *Node) { - OS << Node->getParameterPack()->getNameAsString(); + OS << *Node->getParameterPack(); } void StmtPrinter::VisitSubstNonTypeTemplateParmExpr( @@ -1495,6 +1710,41 @@ void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) { VisitStringLiteral(Node->getString()); } +void StmtPrinter::VisitObjCNumericLiteral(ObjCNumericLiteral *E) { + OS << "@"; + Visit(E->getNumber()); +} + +void StmtPrinter::VisitObjCArrayLiteral(ObjCArrayLiteral *E) { + OS << "@[ "; + StmtRange ch = E->children(); + if (ch.first != ch.second) { + while (1) { + Visit(*ch.first); + ++ch.first; + if (ch.first == ch.second) break; + OS << ", "; + } + } + OS << " ]"; +} + +void StmtPrinter::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + OS << "@{ "; + for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { + if (I > 0) + OS << ", "; + + ObjCDictionaryElement Element = E->getKeyValueElement(I); + Visit(Element.Key); + OS << " : "; + Visit(Element.Value); + if (Element.isPackExpansion()) + OS << "..."; + } + OS << " }"; +} + void StmtPrinter::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { OS << "@encode(" << Node->getEncodedType().getAsString(Policy) << ')'; } @@ -1545,6 +1795,10 @@ void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) { OS << "]"; } +void StmtPrinter::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) { + OS << (Node->getValue() ? "__objc_yes" : "__objc_no"); +} + void StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) { PrintExpr(E->getSubExpr()); @@ -1585,12 +1839,10 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) { } } -void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) { - OS << *Node->getDecl(); +void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { + PrintExpr(Node->getSourceExpr()); } -void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {} - void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { OS << "__builtin_astype("; PrintExpr(Node->getSrcExpr()); @@ -1604,7 +1856,7 @@ void StmtPrinter::VisitAsTypeExpr(AsTypeExpr *Node) { void Stmt::dumpPretty(ASTContext& Context) const { printPretty(llvm::errs(), Context, 0, - PrintingPolicy(Context.getLangOptions())); + PrintingPolicy(Context.getLangOpts())); } void Stmt::printPretty(raw_ostream &OS, ASTContext& Context, diff --git a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp index 214378a..e5526ce 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtProfile.cpp @@ -69,8 +69,12 @@ namespace { void StmtProfiler::VisitStmt(const Stmt *S) { ID.AddInteger(S->getStmtClass()); - for (Stmt::const_child_range C = S->children(); C; ++C) - Visit(*C); + for (Stmt::const_child_range C = S->children(); C; ++C) { + if (*C) + Visit(*C); + else + ID.AddInteger(0); + } } void StmtProfiler::VisitDeclStmt(const DeclStmt *S) { @@ -182,6 +186,13 @@ void StmtProfiler::VisitCXXForRangeStmt(const CXXForRangeStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitMSDependentExistsStmt(const MSDependentExistsStmt *S) { + VisitStmt(S); + ID.AddBoolean(S->isIfExists()); + VisitNestedNameSpecifier(S->getQualifierLoc().getNestedNameSpecifier()); + VisitName(S->getNameInfo().getName()); +} + void StmtProfiler::VisitSEHTryStmt(const SEHTryStmt *S) { VisitStmt(S); } @@ -268,7 +279,7 @@ void StmtProfiler::VisitImaginaryLiteral(const ImaginaryLiteral *S) { void StmtProfiler::VisitStringLiteral(const StringLiteral *S) { VisitExpr(S); - ID.AddString(S->getString()); + ID.AddString(S->getBytes()); ID.AddInteger(S->getKind()); } @@ -449,13 +460,6 @@ void StmtProfiler::VisitBlockExpr(const BlockExpr *S) { VisitDecl(S->getBlockDecl()); } -void StmtProfiler::VisitBlockDeclRefExpr(const BlockDeclRefExpr *S) { - VisitExpr(S); - VisitDecl(S->getDecl()); - ID.AddBoolean(S->isByRef()); - ID.AddBoolean(S->isConstQualAdded()); -} - void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { VisitExpr(S); for (unsigned i = 0; i != S->getNumAssocs(); ++i) { @@ -468,6 +472,15 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { } } +void StmtProfiler::VisitPseudoObjectExpr(const PseudoObjectExpr *S) { + VisitExpr(S); + for (PseudoObjectExpr::const_semantics_iterator + i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) + // Normally, we would not profile the source expressions of OVEs. + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i)) + Visit(OVE->getSourceExpr()); +} + void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) { VisitExpr(S); ID.AddInteger(S->getOp()); @@ -487,7 +500,6 @@ static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, case OO_Conditional: case NUM_OVERLOADED_OPERATORS: llvm_unreachable("Invalid operator call kind"); - return Stmt::ArraySubscriptExprClass; case OO_Plus: if (S->getNumArgs() == 1) { @@ -719,6 +731,10 @@ void StmtProfiler::VisitCXXConstCastExpr(const CXXConstCastExpr *S) { VisitCXXNamedCastExpr(S); } +void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) { + VisitCallExpr(S); +} + void StmtProfiler::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) { VisitExpr(S); ID.AddBoolean(S->getValue()); @@ -775,6 +791,24 @@ StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { } void +StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { + VisitExpr(S); + for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), + CEnd = S->explicit_capture_end(); + C != CEnd; ++C) { + ID.AddInteger(C->getCaptureKind()); + if (C->capturesVariable()) { + VisitDecl(C->getCapturedVar()); + ID.AddBoolean(C->isPackExpansion()); + } + } + // Note: If we actually needed to be able to match lambda + // expressions, we would have to consider parameters and return type + // here, among other things. + VisitStmt(S->getBody()); +} + +void StmtProfiler::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *S) { VisitExpr(S); } @@ -792,13 +826,11 @@ void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) { VisitType(S->getAllocatedType()); VisitDecl(S->getOperatorNew()); VisitDecl(S->getOperatorDelete()); - VisitDecl(S->getConstructor()); ID.AddBoolean(S->isArray()); ID.AddInteger(S->getNumPlacementArgs()); ID.AddBoolean(S->isGlobalNew()); ID.AddBoolean(S->isParenTypeId()); - ID.AddBoolean(S->hasInitializer()); - ID.AddInteger(S->getNumConstructorArgs()); + ID.AddInteger(S->getInitializationStyle()); } void @@ -837,6 +869,14 @@ void StmtProfiler::VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *S) { VisitType(S->getRhsType()); } +void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) { + VisitExpr(S); + ID.AddInteger(S->getTrait()); + ID.AddInteger(S->getNumArgs()); + for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I) + VisitType(S->getArg(I)->getType()); +} + void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) { VisitExpr(S); ID.AddInteger(S->getTrait()); @@ -935,6 +975,18 @@ void StmtProfiler::VisitObjCStringLiteral(const ObjCStringLiteral *S) { VisitExpr(S); } +void StmtProfiler::VisitObjCNumericLiteral(const ObjCNumericLiteral *E) { + VisitExpr(E); +} + +void StmtProfiler::VisitObjCArrayLiteral(const ObjCArrayLiteral *E) { + VisitExpr(E); +} + +void StmtProfiler::VisitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E) { + VisitExpr(E); +} + void StmtProfiler::VisitObjCEncodeExpr(const ObjCEncodeExpr *S) { VisitExpr(S); VisitType(S->getEncodedType()); @@ -971,6 +1023,12 @@ void StmtProfiler::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *S) { } } +void StmtProfiler::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *S) { + VisitExpr(S); + VisitDecl(S->getAtIndexMethodDecl()); + VisitDecl(S->setAtIndexMethodDecl()); +} + void StmtProfiler::VisitObjCMessageExpr(const ObjCMessageExpr *S) { VisitExpr(S); VisitName(S->getSelector()); @@ -982,6 +1040,11 @@ void StmtProfiler::VisitObjCIsaExpr(const ObjCIsaExpr *S) { ID.AddBoolean(S->isArrow()); } +void StmtProfiler::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *S) { + VisitExpr(S); + ID.AddBoolean(S->getValue()); +} + void StmtProfiler::VisitObjCIndirectCopyRestoreExpr( const ObjCIndirectCopyRestoreExpr *S) { VisitExpr(S); @@ -1020,6 +1083,14 @@ void StmtProfiler::VisitDecl(const Decl *D) { return; } + if (const TemplateTypeParmDecl *TTP = + dyn_cast<TemplateTypeParmDecl>(D)) { + ID.AddInteger(TTP->getDepth()); + ID.AddInteger(TTP->getIndex()); + ID.AddBoolean(TTP->isParameterPack()); + return; + } + if (const TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { ID.AddInteger(TTP->getDepth()); diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 0c011a8..531e03e 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -22,6 +22,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallString.h" #include <algorithm> #include <cctype> @@ -40,10 +41,9 @@ static void printIntegral(const TemplateArgument &TemplArg, if (T->isBooleanType()) { Out << (Val->getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { - const unsigned char Ch = Val->getZExtValue(); - const std::string Str(1, Ch); + const char Ch = Val->getZExtValue(); Out << ((Ch == '\'') ? "'\\" : "'"); - Out.write_escaped(Str, /*UseHexEscapes=*/ true); + Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); Out << "'"; } else { Out << Val->toString(10); @@ -80,9 +80,13 @@ bool TemplateArgument::isDependent() const { return true; case Declaration: - if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) - return DC->isDependentContext(); - return getAsDecl()->getDeclContext()->isDependentContext(); + if (Decl *D = getAsDecl()) { + if (DeclContext *DC = dyn_cast<DeclContext>(D)) + return DC->isDependentContext(); + return D->getDeclContext()->isDependentContext(); + } + + return false; case Integral: // Never dependent @@ -100,7 +104,7 @@ bool TemplateArgument::isDependent() const { return false; } - return false; + llvm_unreachable("Invalid TemplateArgument Kind!"); } bool TemplateArgument::isInstantiationDependent() const { @@ -118,10 +122,13 @@ bool TemplateArgument::isInstantiationDependent() const { return true; case Declaration: - if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl())) - return DC->isDependentContext(); - return getAsDecl()->getDeclContext()->isDependentContext(); - + if (Decl *D = getAsDecl()) { + if (DeclContext *DC = dyn_cast<DeclContext>(D)) + return DC->isDependentContext(); + return D->getDeclContext()->isDependentContext(); + } + return false; + case Integral: // Never dependent return false; @@ -137,8 +144,8 @@ bool TemplateArgument::isInstantiationDependent() const { return false; } - - return false; + + llvm_unreachable("Invalid TemplateArgument Kind!"); } bool TemplateArgument::isPackExpansion() const { @@ -159,8 +166,8 @@ bool TemplateArgument::isPackExpansion() const { case Expression: return isa<PackExpansionExpr>(getAsExpr()); } - - return false; + + llvm_unreachable("Invalid TemplateArgument Kind!"); } bool TemplateArgument::containsUnexpandedParameterPack() const { @@ -278,8 +285,7 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { return true; } - // Suppress warnings. - return false; + llvm_unreachable("Invalid TemplateArgument Kind!"); } TemplateArgument TemplateArgument::getPackExpansionPattern() const { @@ -302,8 +308,8 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const { case Template: return TemplateArgument(); } - - return TemplateArgument(); + + llvm_unreachable("Invalid TemplateArgument Kind!"); } void TemplateArgument::print(const PrintingPolicy &Policy, @@ -323,16 +329,14 @@ void TemplateArgument::print(const PrintingPolicy &Policy, } case Declaration: { - bool Unnamed = true; if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) { if (ND->getDeclName()) { - Unnamed = false; - Out << ND->getNameAsString(); + Out << *ND; + } else { + Out << "<anonymous>"; } - } - - if (Unnamed) { - Out << "<anonymous>"; + } else { + Out << "nullptr"; } break; } @@ -412,8 +416,7 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return SourceRange(); } - // Silence bonus gcc warning. - return SourceRange(); + llvm_unreachable("Invalid TemplateArgument Kind!"); } TemplateArgumentLoc @@ -474,8 +477,8 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, case TemplateArgument::Null: return TemplateArgumentLoc(); } - - return TemplateArgumentLoc(); + + llvm_unreachable("Invalid TemplateArgument Kind!"); } const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, @@ -490,7 +493,9 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB << Arg.getAsType(); case TemplateArgument::Declaration: - return DB << Arg.getAsDecl(); + if (Decl *D = Arg.getAsDecl()) + return DB << D; + return DB << "nullptr"; case TemplateArgument::Integral: return DB << Arg.getAsIntegral()->toString(10); @@ -505,7 +510,7 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, // This shouldn't actually ever happen, so it's okay that we're // regurgitating an expression here. // FIXME: We're guessing at LangOptions! - llvm::SmallString<32> Str; + SmallString<32> Str; llvm::raw_svector_ostream OS(Str); LangOptions LangOpts; LangOpts.CPlusPlus = true; @@ -516,7 +521,7 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, case TemplateArgument::Pack: { // FIXME: We're guessing at LangOptions! - llvm::SmallString<32> Str; + SmallString<32> Str; llvm::raw_svector_ostream OS(Str); LangOptions LangOpts; LangOpts.CPlusPlus = true; @@ -525,15 +530,15 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB << OS.str(); } } - - return DB; + + llvm_unreachable("Invalid TemplateArgument Kind!"); } const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(ASTContext &C, const TemplateArgumentListInfo &List) { std::size_t size = sizeof(CXXDependentScopeMemberExpr) + - ASTTemplateArgumentListInfo::sizeFor(List); + ASTTemplateArgumentListInfo::sizeFor(List.size()); void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>()); ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo(); TAI->initializeFrom(List); @@ -586,7 +591,38 @@ std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) { sizeof(TemplateArgumentLoc) * NumTemplateArgs; } -std::size_t ASTTemplateArgumentListInfo::sizeFor( - const TemplateArgumentListInfo &Info) { - return sizeFor(Info.size()); +void +ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc, + const TemplateArgumentListInfo &Info) { + Base::initializeFrom(Info); + setTemplateKeywordLoc(TemplateKWLoc); +} + +void +ASTTemplateKWAndArgsInfo +::initializeFrom(SourceLocation TemplateKWLoc, + const TemplateArgumentListInfo &Info, + bool &Dependent, + bool &InstantiationDependent, + bool &ContainsUnexpandedParameterPack) { + Base::initializeFrom(Info, Dependent, InstantiationDependent, + ContainsUnexpandedParameterPack); + setTemplateKeywordLoc(TemplateKWLoc); +} + +void +ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { + // No explicit template arguments, but template keyword loc is valid. + assert(TemplateKWLoc.isValid()); + LAngleLoc = SourceLocation(); + RAngleLoc = SourceLocation(); + NumTemplateArgs = 0; + setTemplateKeywordLoc(TemplateKWLoc); +} + +std::size_t +ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) { + // Add space for the template keyword location. + return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation); } + diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp index a0487ba..e89ba53 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateName.cpp @@ -149,7 +149,7 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, subst->getReplacement().print(OS, Policy, SuppressNNS); } else if (SubstTemplateTemplateParmPackStorage *SubstPack = getAsSubstTemplateTemplateParmPack()) - OS << SubstPack->getParameterPack()->getNameAsString(); + OS << *SubstPack->getParameterPack(); else { OverloadedTemplateStorage *OTS = getAsOverloadedTemplate(); (*OTS->begin())->printName(OS); diff --git a/contrib/llvm/tools/clang/lib/AST/Type.cpp b/contrib/llvm/tools/clang/lib/AST/Type.cpp index 44eeec0..c82aeaa 100644 --- a/contrib/llvm/tools/clang/lib/AST/Type.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Type.cpp @@ -197,27 +197,28 @@ const Type *Type::getArrayElementTypeNoTypeQual() const { /// concrete. QualType QualType::getDesugaredType(QualType T, const ASTContext &Context) { SplitQualType split = getSplitDesugaredType(T); - return Context.getQualifiedType(split.first, split.second); + return Context.getQualifiedType(split.Ty, split.Quals); } -QualType QualType::getSingleStepDesugaredType(const ASTContext &Context) const { - QualifierCollector Qs; - - const Type *CurTy = Qs.strip(*this); - switch (CurTy->getTypeClass()) { +QualType QualType::getSingleStepDesugaredTypeImpl(QualType type, + const ASTContext &Context) { + SplitQualType split = type.split(); + QualType desugar = split.Ty->getLocallyUnqualifiedSingleStepDesugaredType(); + return Context.getQualifiedType(desugar, split.Quals); +} + +QualType Type::getLocallyUnqualifiedSingleStepDesugaredType() const { + switch (getTypeClass()) { #define ABSTRACT_TYPE(Class, Parent) #define TYPE(Class, Parent) \ case Type::Class: { \ - const Class##Type *Ty = cast<Class##Type>(CurTy); \ - if (!Ty->isSugared()) \ - return *this; \ - return Context.getQualifiedType(Ty->desugar(), Qs); \ - break; \ + const Class##Type *ty = cast<Class##Type>(this); \ + if (!ty->isSugared()) return QualType(ty, 0); \ + return ty->desugar(); \ } #include "clang/AST/TypeNodes.def" } - - return *this; + llvm_unreachable("bad type kind!"); } SplitQualType QualType::getSplitDesugaredType(QualType T) { @@ -245,21 +246,21 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) { SplitQualType split = type.split(); // All the qualifiers we've seen so far. - Qualifiers quals = split.second; + Qualifiers quals = split.Quals; // The last type node we saw with any nodes inside it. - const Type *lastTypeWithQuals = split.first; + const Type *lastTypeWithQuals = split.Ty; while (true) { QualType next; // Do a single-step desugar, aborting the loop if the type isn't // sugared. - switch (split.first->getTypeClass()) { + switch (split.Ty->getTypeClass()) { #define ABSTRACT_TYPE(Class, Parent) #define TYPE(Class, Parent) \ case Type::Class: { \ - const Class##Type *ty = cast<Class##Type>(split.first); \ + const Class##Type *ty = cast<Class##Type>(split.Ty); \ if (!ty->isSugared()) goto done; \ next = ty->desugar(); \ break; \ @@ -270,9 +271,9 @@ SplitQualType QualType::getSplitUnqualifiedTypeImpl(QualType type) { // Otherwise, split the underlying type. If that yields qualifiers, // update the information. split = next.split(); - if (!split.second.empty()) { - lastTypeWithQuals = split.first; - quals.addConsistentQualifiers(split.second); + if (!split.Quals.empty()) { + lastTypeWithQuals = split.Ty; + quals.addConsistentQualifiers(split.Quals); } } @@ -308,13 +309,6 @@ const Type *Type::getUnqualifiedDesugaredType() const { } } -/// isVoidType - Helper method to determine if this is the 'void' type. -bool Type::isVoidType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Void; - return false; -} - bool Type::isDerivedType() const { switch (CanonicalType->getTypeClass()) { case Pointer: @@ -555,17 +549,6 @@ AutoType *Type::getContainedAutoType() const { return GetContainedAutoVisitor().Visit(this); } -bool Type::isIntegerType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) - // Incomplete enum types are not treated as integer types. - // FIXME: In C++, enum types are never integer types. - return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); - return false; -} - bool Type::hasIntegerRepresentation() const { if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isIntegerType(); @@ -597,25 +580,13 @@ bool Type::isIntegralType(ASTContext &Ctx) const { return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; - if (!Ctx.getLangOptions().CPlusPlus) + if (!Ctx.getLangOpts().CPlusPlus) if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) return ET->getDecl()->isComplete(); // Complete enum types are integral in C. return false; } -bool Type::isIntegralOrEnumerationType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::Int128; - - // Check for a complete enum type; incomplete enum types are not properly an - // enumeration type in the sense required here. - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) - return ET->getDecl()->isComplete(); - - return false; -} bool Type::isIntegralOrUnscopedEnumerationType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) @@ -633,11 +604,6 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { } -bool Type::isBooleanType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Bool; - return false; -} bool Type::isCharType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) @@ -766,13 +732,6 @@ bool Type::hasUnsignedIntegerRepresentation() const { return isUnsignedIntegerType(); } -bool Type::isHalfType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() == BuiltinType::Half; - // FIXME: Should we allow complex __fp16? Probably not. - return false; -} - bool Type::isFloatingType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Half && @@ -819,21 +778,6 @@ bool Type::isArithmeticType() const { return isa<ComplexType>(CanonicalType); } -bool Type::isScalarType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() > BuiltinType::Void && - BT->getKind() <= BuiltinType::NullPtr; - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) - // Enums are scalar types, but only if they are defined. Incomplete enums - // are not treated as scalar types. - return ET->getDecl()->isComplete(); - return isa<PointerType>(CanonicalType) || - isa<BlockPointerType>(CanonicalType) || - isa<MemberPointerType>(CanonicalType) || - isa<ComplexType>(CanonicalType) || - isa<ObjCObjectPointerType>(CanonicalType); -} - Type::ScalarTypeKind Type::getScalarTypeKind() const { assert(isScalarType()); @@ -897,37 +841,56 @@ bool Type::isConstantSizeType() const { /// isIncompleteType - Return true if this is an incomplete type (C99 6.2.5p1) /// - a type that can describe objects, but which lacks information needed to /// determine its size. -bool Type::isIncompleteType() const { +bool Type::isIncompleteType(NamedDecl **Def) const { + if (Def) + *Def = 0; + switch (CanonicalType->getTypeClass()) { default: return false; case Builtin: // Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never // be completed. return isVoidType(); - case Enum: + case Enum: { + EnumDecl *EnumD = cast<EnumType>(CanonicalType)->getDecl(); + if (Def) + *Def = EnumD; + // An enumeration with fixed underlying type is complete (C++0x 7.2p3). - if (cast<EnumType>(CanonicalType)->getDecl()->isFixed()) - return false; - // Fall through. - case Record: + if (EnumD->isFixed()) + return false; + + return !EnumD->isCompleteDefinition(); + } + case Record: { // A tagged type (struct/union/enum/class) is incomplete if the decl is a // forward declaration, but not a full definition (C99 6.2.5p22). - return !cast<TagType>(CanonicalType)->getDecl()->isCompleteDefinition(); + RecordDecl *Rec = cast<RecordType>(CanonicalType)->getDecl(); + if (Def) + *Def = Rec; + return !Rec->isCompleteDefinition(); + } case ConstantArray: // An array is incomplete if its element type is incomplete // (C++ [dcl.array]p1). // We don't handle variable arrays (they're not allowed in C++) or // dependent-sized arrays (dependent types are never treated as incomplete). - return cast<ArrayType>(CanonicalType)->getElementType()->isIncompleteType(); + return cast<ArrayType>(CanonicalType)->getElementType() + ->isIncompleteType(Def); case IncompleteArray: // An array of unknown size is an incomplete type (C99 6.2.5p22). return true; case ObjCObject: return cast<ObjCObjectType>(CanonicalType)->getBaseType() - ->isIncompleteType(); - case ObjCInterface: + ->isIncompleteType(Def); + case ObjCInterface: { // ObjC interfaces are incomplete if they are @class, not @interface. - return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl(); + ObjCInterfaceDecl *Interface + = cast<ObjCInterfaceType>(CanonicalType)->getDecl(); + if (Def) + *Def = Interface; + return !Interface->hasDefinition(); + } } } @@ -944,7 +907,7 @@ bool QualType::isPODType(ASTContext &Context) const { if ((*this)->isIncompleteType()) return false; - if (Context.getLangOptions().ObjCAutoRefCount) { + if (Context.getLangOpts().ObjCAutoRefCount) { switch (getObjCLifetime()) { case Qualifiers::OCL_ExplicitNone: return true; @@ -1006,7 +969,7 @@ bool QualType::isTrivialType(ASTContext &Context) const { if ((*this)->isIncompleteType()) return false; - if (Context.getLangOptions().ObjCAutoRefCount) { + if (Context.getLangOpts().ObjCAutoRefCount) { switch (getObjCLifetime()) { case Qualifiers::OCL_ExplicitNone: return true; @@ -1056,7 +1019,7 @@ bool QualType::isTriviallyCopyableType(ASTContext &Context) const { if ((*this)->isArrayType()) return Context.getBaseElementType(*this).isTrivialType(Context); - if (Context.getLangOptions().ObjCAutoRefCount) { + if (Context.getLangOpts().ObjCAutoRefCount) { switch (getObjCLifetime()) { case Qualifiers::OCL_ExplicitNone: return true; @@ -1126,15 +1089,13 @@ bool Type::isLiteralType() const { if (BaseTy->isIncompleteType()) return false; - // Objective-C lifetime types are not literal types. - if (BaseTy->isObjCRetainableType()) - return false; - // C++0x [basic.types]p10: // A type is a literal type if it is: // -- a scalar type; or - // As an extension, Clang treats vector types as literal types. - if (BaseTy->isScalarType() || BaseTy->isVectorType()) + // As an extension, Clang treats vector types and complex types as + // literal types. + if (BaseTy->isScalarType() || BaseTy->isVectorType() || + BaseTy->isAnyComplexType()) return true; // -- a reference type; or if (BaseTy->isReferenceType()) @@ -1203,7 +1164,7 @@ bool QualType::isCXX11PODType(ASTContext &Context) const { if (ty->isDependentType()) return false; - if (Context.getLangOptions().ObjCAutoRefCount) { + if (Context.getLangOpts().ObjCAutoRefCount) { switch (getObjCLifetime()) { case Qualifiers::OCL_ExplicitNone: return true; @@ -1272,6 +1233,10 @@ bool Type::isPromotableIntegerType() const { case BuiltinType::UChar: case BuiltinType::Short: case BuiltinType::UShort: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + case BuiltinType::Char16: + case BuiltinType::Char32: return true; default: return false; @@ -1284,21 +1249,12 @@ bool Type::isPromotableIntegerType() const { || ET->getDecl()->isScoped()) return false; - const BuiltinType *BT - = ET->getDecl()->getPromotionType()->getAs<BuiltinType>(); - return BT->getKind() == BuiltinType::Int - || BT->getKind() == BuiltinType::UInt; + return true; } return false; } -bool Type::isNullPtrType() const { - if (const BuiltinType *BT = getAs<BuiltinType>()) - return BT->getKind() == BuiltinType::NullPtr; - return false; -} - bool Type::isSpecifierType() const { // Note that this intentionally does not use the canonical type. switch (getTypeClass()) { @@ -1346,7 +1302,6 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) { } llvm_unreachable("Type specifier is not a tag type kind."); - return TTK_Union; } ElaboratedTypeKeyword @@ -1401,7 +1356,6 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { } llvm_unreachable("Unknown elaborated type keyword."); - return ""; } DependentTemplateSpecializationType::DependentTemplateSpecializationType( @@ -1461,7 +1415,6 @@ const char *Type::getTypeClassName() const { } llvm_unreachable("Invalid type class."); - return 0; } const char *BuiltinType::getName(const PrintingPolicy &Policy) const { @@ -1475,13 +1428,13 @@ const char *BuiltinType::getName(const PrintingPolicy &Policy) const { case Int: return "int"; case Long: return "long"; case LongLong: return "long long"; - case Int128: return "__int128_t"; + case Int128: return "__int128"; case UChar: return "unsigned char"; case UShort: return "unsigned short"; case UInt: return "unsigned int"; case ULong: return "unsigned long"; case ULongLong: return "unsigned long long"; - case UInt128: return "__uint128_t"; + case UInt128: return "unsigned __int128"; case Half: return "half"; case Float: return "float"; case Double: return "double"; @@ -1493,15 +1446,16 @@ const char *BuiltinType::getName(const PrintingPolicy &Policy) const { case NullPtr: return "nullptr_t"; case Overload: return "<overloaded function type>"; case BoundMember: return "<bound member function type>"; + case PseudoObject: return "<pseudo-object type>"; case Dependent: return "<dependent type>"; case UnknownAny: return "<unknown type>"; + case ARCUnbridgedCast: return "<ARC unbridged cast type>"; case ObjCId: return "id"; case ObjCClass: return "Class"; case ObjCSel: return "SEL"; } llvm_unreachable("Invalid builtin type."); - return 0; } QualType QualType::getNonLValueExprType(ASTContext &Context) const { @@ -1513,7 +1467,7 @@ QualType QualType::getNonLValueExprType(ASTContext &Context) const { // have cv-unqualified types. // // See also C99 6.3.2.1p2. - if (!Context.getLangOptions().CPlusPlus || + if (!Context.getLangOpts().CPlusPlus || (!getTypePtr()->isDependentType() && !getTypePtr()->isRecordType())) return getUnqualifiedType(); @@ -1524,7 +1478,6 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { switch (CC) { case CC_Default: llvm_unreachable("no name for default cc"); - return ""; case CC_C: return "cdecl"; case CC_X86StdCall: return "stdcall"; @@ -1536,14 +1489,13 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { } llvm_unreachable("Invalid calling convention."); - return ""; } FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, QualType canonical, const ExtProtoInfo &epi) - : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals, - epi.RefQualifier, canonical, + : FunctionType(FunctionProto, result, epi.TypeQuals, epi.RefQualifier, + canonical, result->isDependentType(), result->isInstantiationDependentType(), result->isVariablyModifiedType(), @@ -1551,7 +1503,8 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, epi.ExtInfo), NumArgs(numArgs), NumExceptions(epi.NumExceptions), ExceptionSpecType(epi.ExceptionSpecType), - HasAnyConsumedArgs(epi.ConsumedArguments != 0) + HasAnyConsumedArgs(epi.ConsumedArguments != 0), + Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) { // Fill in the trailing argument array. QualType *argSlot = reinterpret_cast<QualType*>(this+1); @@ -1649,8 +1602,8 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, // This is followed by an optional "consumed argument" section of the // same length as the first type sequence: // bool* - // Finally, we have the ext info: - // int + // Finally, we have the ext info and trailing return type flag: + // int bool // // There is no ambiguity between the consumed arguments and an empty EH // spec because of the leading 'bool' which unambiguously indicates @@ -1682,6 +1635,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, ID.AddBoolean(epi.ConsumedArguments[i]); } epi.ExtInfo.Profile(ID); + ID.AddBoolean(epi.HasTrailingReturn); } void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, @@ -1719,7 +1673,10 @@ void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID, } DecltypeType::DecltypeType(Expr *E, QualType underlyingType, QualType can) - : Type(Decltype, can, E->isTypeDependent(), + // C++11 [temp.type]p2: "If an expression e involves a template parameter, + // decltype(e) denotes a unique dependent type." Hence a decltype type is + // type-dependent even if its expression is only instantiation-dependent. + : Type(Decltype, can, E->isInstantiationDependent(), E->isInstantiationDependent(), E->getType()->isVariablyModifiedType(), E->containsUnexpandedParameterPack()), @@ -1785,14 +1742,6 @@ CXXRecordDecl *InjectedClassNameType::getDecl() const { return cast<CXXRecordDecl>(getInterestingTagDecl(Decl)); } -bool RecordType::classof(const TagType *TT) { - return isa<RecordDecl>(TT->getDecl()); -} - -bool EnumType::classof(const TagType *TT) { - return isa<EnumDecl>(TT->getDecl()); -} - IdentifierInfo *TemplateTypeParmType::getIdentifier() const { return isCanonicalUnqualified() ? 0 : getDecl()->getIdentifier(); } @@ -1872,8 +1821,10 @@ TemplateSpecializationType(TemplateName T, Canon.isNull()? T.isDependent() : Canon->isDependentType(), Canon.isNull()? T.isDependent() : Canon->isInstantiationDependentType(), - false, T.containsUnexpandedParameterPack()), - Template(T), NumArgs(NumArgs) { + false, + Canon.isNull()? T.containsUnexpandedParameterPack() + : Canon->containsUnexpandedParameterPack()), + Template(T), NumArgs(NumArgs), TypeAlias(!AliasedType.isNull()) { assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); assert((T.getKind() == TemplateName::Template || @@ -1905,17 +1856,14 @@ TemplateSpecializationType(TemplateName T, if (Args[Arg].getKind() == TemplateArgument::Type && Args[Arg].getAsType()->isVariablyModifiedType()) setVariablyModified(); - if (Args[Arg].containsUnexpandedParameterPack()) + if (Canon.isNull() && Args[Arg].containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); } // Store the aliased type if this is a type alias template specialization. - bool IsTypeAlias = !AliasedType.isNull(); - assert(IsTypeAlias == isTypeAlias() && - "allocated wrong size for type alias"); - if (IsTypeAlias) { + if (TypeAlias) { TemplateArgument *Begin = reinterpret_cast<TemplateArgument *>(this + 1); *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType; } @@ -1932,11 +1880,6 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, Args[Idx].Profile(ID, Context); } -bool TemplateSpecializationType::isTypeAlias() const { - TemplateDecl *D = Template.getAsTemplateDecl(); - return D && isa<TypeAliasTemplateDecl>(D); -} - QualType QualifierCollector::apply(const ASTContext &Context, QualType QT) const { if (!hasNonFastQualifiers()) @@ -1970,21 +1913,22 @@ namespace { /// \brief The cached properties of a type. class CachedProperties { - char linkage; - char visibility; + NamedDecl::LinkageInfo LV; bool local; public: - CachedProperties(Linkage linkage, Visibility visibility, bool local) - : linkage(linkage), visibility(visibility), local(local) {} + CachedProperties(NamedDecl::LinkageInfo LV, bool local) + : LV(LV), local(local) {} - Linkage getLinkage() const { return (Linkage) linkage; } - Visibility getVisibility() const { return (Visibility) visibility; } + Linkage getLinkage() const { return LV.linkage(); } + Visibility getVisibility() const { return LV.visibility(); } + bool isVisibilityExplicit() const { return LV.visibilityExplicit(); } bool hasLocalOrUnnamedType() const { return local; } friend CachedProperties merge(CachedProperties L, CachedProperties R) { - return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()), - minVisibility(L.getVisibility(), R.getVisibility()), + NamedDecl::LinkageInfo MergedLV = L.LV; + MergedLV.merge(R.LV); + return CachedProperties(MergedLV, L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType()); } }; @@ -2004,9 +1948,10 @@ public: static CachedProperties get(const Type *T) { ensure(T); - return CachedProperties(T->TypeBits.getLinkage(), - T->TypeBits.getVisibility(), - T->TypeBits.hasLocalOrUnnamedType()); + NamedDecl::LinkageInfo LV(T->TypeBits.getLinkage(), + T->TypeBits.getVisibility(), + T->TypeBits.isVisibilityExplicit()); + return CachedProperties(LV, T->TypeBits.hasLocalOrUnnamedType()); } static void ensure(const Type *T) { @@ -2020,6 +1965,8 @@ public: ensure(CT); T->TypeBits.CacheValidAndVisibility = CT->TypeBits.CacheValidAndVisibility; + T->TypeBits.CachedExplicitVisibility = + CT->TypeBits.CachedExplicitVisibility; T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage; T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed; return; @@ -2028,6 +1975,7 @@ public: // Compute the cached properties and then set the cache. CachedProperties Result = computeCachedProperties(T); T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U; + T->TypeBits.CachedExplicitVisibility = Result.isVisibilityExplicit(); assert(T->TypeBits.isCacheValid() && T->TypeBits.getVisibility() == Result.getVisibility()); T->TypeBits.CachedLinkage = Result.getLinkage(); @@ -2055,13 +2003,13 @@ static CachedProperties computeCachedProperties(const Type *T) { #include "clang/AST/TypeNodes.def" // Treat instantiation-dependent types as external. assert(T->isInstantiationDependentType()); - return CachedProperties(ExternalLinkage, DefaultVisibility, false); + return CachedProperties(NamedDecl::LinkageInfo(), false); case Type::Builtin: // C++ [basic.link]p8: // A type is said to have linkage if and only if: // - it is a fundamental type (3.9.1); or - return CachedProperties(ExternalLinkage, DefaultVisibility, false); + return CachedProperties(NamedDecl::LinkageInfo(), false); case Type::Record: case Type::Enum: { @@ -2075,7 +2023,7 @@ static CachedProperties computeCachedProperties(const Type *T) { bool IsLocalOrUnnamed = Tag->getDeclContext()->isFunctionOrMethod() || (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()); - return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed); + return CachedProperties(LV, IsLocalOrUnnamed); } // C++ [basic.link]p8: @@ -2115,7 +2063,7 @@ static CachedProperties computeCachedProperties(const Type *T) { case Type::ObjCInterface: { NamedDecl::LinkageInfo LV = cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); - return CachedProperties(LV.linkage(), LV.visibility(), false); + return CachedProperties(LV, false); } case Type::ObjCObject: return Cache::get(cast<ObjCObjectType>(T)->getBaseType()); @@ -2126,10 +2074,6 @@ static CachedProperties computeCachedProperties(const Type *T) { } llvm_unreachable("unhandled type class"); - - // C++ [basic.link]p8: - // Names not covered by these rules have no linkage. - return CachedProperties(NoLinkage, DefaultVisibility, false); } /// \brief Determine the linkage of this type. @@ -2144,6 +2088,11 @@ Visibility Type::getVisibility() const { return TypeBits.getVisibility(); } +bool Type::isVisibilityExplicit() const { + Cache::ensure(this); + return TypeBits.isVisibilityExplicit(); +} + bool Type::hasUnnamedOrLocalType() const { Cache::ensure(this); return TypeBits.hasLocalOrUnnamedType(); @@ -2285,7 +2234,7 @@ bool QualType::hasTrivialAssignment(ASTContext &Context, bool Copying) const { case Qualifiers::OCL_Autoreleasing: case Qualifiers::OCL_Strong: case Qualifiers::OCL_Weak: - return !Context.getLangOptions().ObjCAutoRefCount; + return !Context.getLangOpts().ObjCAutoRefCount; } if (const CXXRecordDecl *Record diff --git a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp index 8e8b227..caa19b1 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp @@ -196,55 +196,54 @@ SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const { TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { if (needsExtraLocalData()) return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type); - else { - switch (getTypePtr()->getKind()) { - case BuiltinType::Void: - return TST_void; - case BuiltinType::Bool: - return TST_bool; - case BuiltinType::Char_U: - case BuiltinType::Char_S: - return TST_char; - case BuiltinType::Char16: - return TST_char16; - case BuiltinType::Char32: - return TST_char32; - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - return TST_wchar; - - case BuiltinType::UChar: - case BuiltinType::UShort: - case BuiltinType::UInt: - case BuiltinType::ULong: - case BuiltinType::ULongLong: - case BuiltinType::UInt128: - case BuiltinType::SChar: - case BuiltinType::Short: - case BuiltinType::Int: - case BuiltinType::Long: - case BuiltinType::LongLong: - case BuiltinType::Int128: - case BuiltinType::Half: - case BuiltinType::Float: - case BuiltinType::Double: - case BuiltinType::LongDouble: - llvm_unreachable("Builtin type needs extra local data!"); - // Fall through, if the impossible happens. - - case BuiltinType::NullPtr: - case BuiltinType::Overload: - case BuiltinType::Dependent: - case BuiltinType::BoundMember: - case BuiltinType::UnknownAny: - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - return TST_unspecified; - } + switch (getTypePtr()->getKind()) { + case BuiltinType::Void: + return TST_void; + case BuiltinType::Bool: + return TST_bool; + case BuiltinType::Char_U: + case BuiltinType::Char_S: + return TST_char; + case BuiltinType::Char16: + return TST_char16; + case BuiltinType::Char32: + return TST_char32; + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + return TST_wchar; + case BuiltinType::UChar: + case BuiltinType::UShort: + case BuiltinType::UInt: + case BuiltinType::ULong: + case BuiltinType::ULongLong: + case BuiltinType::UInt128: + case BuiltinType::SChar: + case BuiltinType::Short: + case BuiltinType::Int: + case BuiltinType::Long: + case BuiltinType::LongLong: + case BuiltinType::Int128: + case BuiltinType::Half: + case BuiltinType::Float: + case BuiltinType::Double: + case BuiltinType::LongDouble: + llvm_unreachable("Builtin type needs extra local data!"); + // Fall through, if the impossible happens. + + case BuiltinType::NullPtr: + case BuiltinType::Overload: + case BuiltinType::Dependent: + case BuiltinType::BoundMember: + case BuiltinType::UnknownAny: + case BuiltinType::ARCUnbridgedCast: + case BuiltinType::PseudoObject: + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return TST_unspecified; } - - return TST_unspecified; + + llvm_unreachable("Invalid BuiltinType Kind!"); } TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { @@ -255,7 +254,7 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) { void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); + setElaboratedKeywordLoc(Loc); NestedNameSpecifierLocBuilder Builder; Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); setQualifierLoc(Builder.getWithLocInContext(Context)); @@ -263,17 +262,17 @@ void ElaboratedTypeLoc::initializeLocal(ASTContext &Context, void DependentNameTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); + setElaboratedKeywordLoc(Loc); NestedNameSpecifierLocBuilder Builder; Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); setQualifierLoc(Builder.getWithLocInContext(Context)); setNameLoc(Loc); } -void -DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, +void +DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); + setElaboratedKeywordLoc(Loc); if (getTypePtr()->getQualifier()) { NestedNameSpecifierLocBuilder Builder; Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc); @@ -281,8 +280,8 @@ DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context, } else { setQualifierLoc(NestedNameSpecifierLoc()); } - - setNameLoc(Loc); + setTemplateKeywordLoc(Loc); + setTemplateNameLoc(Loc); setLAngleLoc(Loc); setRAngleLoc(Loc); TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), @@ -302,8 +301,7 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Expression: - // FIXME: Can we do better for declarations and integral values? - ArgInfos[i] = TemplateArgumentLocInfo(); + ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr()); break; case TemplateArgument::Type: @@ -332,4 +330,3 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context, } } } - diff --git a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp index fb7b918..3bf80e7 100644 --- a/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TypePrinter.cpp @@ -75,7 +75,7 @@ static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { void TypePrinter::print(QualType t, std::string &buffer) { SplitQualType split = t.split(); - print(split.first, split.second, buffer); + print(split.Ty, split.Quals, buffer); } void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { @@ -264,8 +264,9 @@ void TypePrinter::printRValueReference(const RValueReferenceType *T, void TypePrinter::printMemberPointer(const MemberPointerType *T, std::string &S) { - std::string C; - print(QualType(T->getClass(), 0), C); + PrintingPolicy InnerPolicy(Policy); + Policy.SuppressTag = true; + std::string C = QualType(T->getClass(), 0).getAsString(InnerPolicy); C += "::*"; S = C + S; @@ -397,6 +398,35 @@ void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) { print(T->getElementType(), S); } +void +FunctionProtoType::printExceptionSpecification(std::string &S, + PrintingPolicy Policy) const { + + if (hasDynamicExceptionSpec()) { + S += " throw("; + if (getExceptionSpecType() == EST_MSAny) + S += "..."; + else + for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) { + if (I) + S += ", "; + + S += getExceptionType(I).getAsString(Policy); + } + S += ")"; + } else if (isNoexceptExceptionSpec(getExceptionSpecType())) { + S += " noexcept"; + if (getExceptionSpecType() == EST_ComputedNoexcept) { + S += "("; + llvm::raw_string_ostream EOut(S); + getNoexceptExpr()->printPretty(EOut, 0, Policy); + EOut.flush(); + S += EOut.str(); + S += ")"; + } + } +} + void TypePrinter::printFunctionProto(const FunctionProtoType *T, std::string &S) { // If needed for precedence reasons, wrap the inner part in grouping parens. @@ -427,8 +457,7 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, FunctionType::ExtInfo Info = T->getExtInfo(); switch(Info.getCC()) { - case CC_Default: - default: break; + case CC_Default: break; case CC_C: S += " __attribute__((cdecl))"; break; @@ -471,34 +500,13 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, S += " &&"; break; } - - if (T->hasDynamicExceptionSpec()) { - S += " throw("; - if (T->getExceptionSpecType() == EST_MSAny) - S += "..."; - else - for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { - if (I) - S += ", "; - - std::string ExceptionType; - print(T->getExceptionType(I), ExceptionType); - S += ExceptionType; - } - S += ")"; - } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) { - S += " noexcept"; - if (T->getExceptionSpecType() == EST_ComputedNoexcept) { - S += "("; - llvm::raw_string_ostream EOut(S); - T->getNoexceptExpr()->printPretty(EOut, 0, Policy); - EOut.flush(); - S += EOut.str(); - S += ")"; - } - } - - print(T->getResultType(), S); + T->printExceptionSpecification(S, Policy); + if (T->hasTrailingReturn()) { + std::string ResultS; + print(T->getResultType(), ResultS); + S = "auto " + S + " -> " + ResultS; + } else + print(T->getResultType(), S); } void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T, @@ -600,6 +608,9 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { unsigned OldSize = Buffer.size(); if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { + if (Policy.SuppressUnwrittenScope && + (NS->isAnonymousNamespace() || NS->isInline())) + return; if (NS->getIdentifier()) Buffer += NS->getNameAsString(); else @@ -620,6 +631,8 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { Buffer += Typedef->getIdentifier()->getName(); else if (Tag->getIdentifier()) Buffer += Tag->getIdentifier()->getName(); + else + return; } if (Buffer.size() != OldSize) @@ -660,8 +673,14 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) { // Make an unambiguous representation for anonymous types, e.g. // <anonymous enum at /usr/include/string.h:120:9> llvm::raw_string_ostream OS(Buffer); - OS << "<anonymous"; - + + if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) { + OS << "<lambda"; + HasKindDecoration = true; + } else { + OS << "<anonymous"; + } + if (Policy.AnonymousTagLocations) { // Suppress the redundant tag keyword if we just printed one. // We don't have to worry about ElaboratedTypes here because you can't @@ -930,7 +949,7 @@ void TypePrinter::printAttributed(const AttributedType *T, case AttributedType::attr_objc_ownership: S += "objc_ownership("; switch (T->getEquivalentType().getObjCLifetime()) { - case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break; + case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); case Qualifiers::OCL_ExplicitNone: S += "none"; break; case Qualifiers::OCL_Strong: S += "strong"; break; case Qualifiers::OCL_Weak: S += "weak"; break; @@ -1157,9 +1176,21 @@ void Qualifiers::getAsStringInternal(std::string &S, AppendTypeQualList(S, getCVRQualifiers()); if (unsigned addrspace = getAddressSpace()) { if (!S.empty()) S += ' '; - S += "__attribute__((address_space("; - S += llvm::utostr_32(addrspace); - S += ")))"; + switch (addrspace) { + case LangAS::opencl_global: + S += "__global"; + break; + case LangAS::opencl_local: + S += "__local"; + break; + case LangAS::opencl_constant: + S += "__constant"; + break; + default: + S += "__attribute__((address_space("; + S += llvm::utostr_32(addrspace); + S += ")))"; + } } if (Qualifiers::GC gc = getObjCGCAttr()) { if (!S.empty()) S += ' '; diff --git a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp index 7765817..7a45972 100644 --- a/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp @@ -466,10 +466,10 @@ public: static bool HasSameVirtualSignature(const CXXMethodDecl *LHS, const CXXMethodDecl *RHS) { - ASTContext &C = LHS->getASTContext(); // TODO: thread this down - CanQual<FunctionProtoType> - LT = C.getCanonicalType(LHS->getType()).getAs<FunctionProtoType>(), - RT = C.getCanonicalType(RHS->getType()).getAs<FunctionProtoType>(); + const FunctionProtoType *LT = + cast<FunctionProtoType>(LHS->getType().getCanonicalType()); + const FunctionProtoType *RT = + cast<FunctionProtoType>(RHS->getType().getCanonicalType()); // Fast-path matches in the canonical types. if (LT == RT) return true; @@ -477,7 +477,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.getQualifiers() != RT.getQualifiers() || + if (LT->getTypeQuals() != RT->getTypeQuals() || LT->getNumArgs() != RT->getNumArgs()) return false; for (unsigned I = 0, E = LT->getNumArgs(); I != E; ++I) @@ -996,7 +996,7 @@ public: LayoutVTable(); - if (Context.getLangOptions().DumpVTableLayouts) + if (Context.getLangOpts().DumpVTableLayouts) dumpLayout(llvm::errs()); } @@ -1580,7 +1580,7 @@ void VTableBuilder::LayoutVTable() { LayoutVTablesForVirtualBases(MostDerivedClass, VBases); // -fapple-kext adds an extra entry at end of vtbl. - bool IsAppleKext = Context.getLangOptions().AppleKext; + bool IsAppleKext = Context.getLangOpts().AppleKext; if (IsAppleKext) Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero())); } @@ -2136,7 +2136,8 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) { uint64_t VTableIndex = I->first; const std::string &MethodName = I->second; - Out << llvm::format(" %4u | ", VTableIndex) << MethodName << '\n'; + Out << llvm::format(" %4" PRIu64 " | ", VTableIndex) << MethodName + << '\n'; } } |