diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 113 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 205 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 15 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 46 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 15 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 7 | ||||
-rw-r--r-- | lib/AST/DeclarationName.cpp | 44 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 212 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 244 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 62 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 259 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.h | 20 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 6 | ||||
-rw-r--r-- | lib/AST/StmtDumper.cpp | 3 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 52 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 46 | ||||
-rw-r--r-- | lib/AST/StmtViz.cpp | 5 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 14 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 10 |
20 files changed, 918 insertions, 466 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index dc13e7f..6c9ecf0 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -48,6 +48,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { ObjCIdRedefinitionType = QualType(); ObjCClassRedefinitionType = QualType(); + ObjCSelRedefinitionType = QualType(); if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); InitBuiltinTypes(); @@ -220,10 +221,12 @@ void ASTContext::InitBuiltinTypes() { // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope(). ObjCIdTypedefType = QualType(); ObjCClassTypedefType = QualType(); + ObjCSelTypedefType = QualType(); - // Builtin types for 'id' and 'Class'. + // Builtin types for 'id', 'Class', and 'SEL'. InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass); + InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel); ObjCConstantStringType = QualType(); @@ -517,18 +520,23 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { /// getDeclAlignInBytes - Return a conservative estimate of the alignment of the /// specified decl. Note that bitfields do not have a valid alignment, so /// this method will assert on them. -unsigned ASTContext::getDeclAlignInBytes(const Decl *D) { +/// If @p RefAsPointee, references are treated like their underlying type +/// (for alignof), else they're treated like pointers (for CodeGen). +unsigned ASTContext::getDeclAlignInBytes(const Decl *D, bool RefAsPointee) { unsigned Align = Target.getCharWidth(); if (const AlignedAttr* AA = D->getAttr<AlignedAttr>()) - Align = std::max(Align, AA->getAlignment()); + Align = std::max(Align, AA->getMaxAlignment()); if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); if (const ReferenceType* RT = T->getAs<ReferenceType>()) { - unsigned AS = RT->getPointeeType().getAddressSpace(); - Align = Target.getPointerAlign(AS); - } else if (!T->isIncompleteType() && !T->isFunctionType()) { + if (RefAsPointee) + T = RT->getPointeeType(); + else + T = getPointerType(RT->getPointeeType()); + } + if (!T->isIncompleteType() && !T->isFunctionType()) { // Incomplete or function types default to 1. while (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T)) T = cast<ArrayType>(T)->getElementType(); @@ -687,19 +695,21 @@ ASTContext::getTypeInfo(const Type *T) { Align = Target.getPointerAlign(AS); break; } + case Type::LValueReference: + case Type::RValueReference: { + // alignof and sizeof should never enter this code path here, so we go + // the pointer route. + unsigned AS = cast<ReferenceType>(T)->getPointeeType().getAddressSpace(); + Width = Target.getPointerWidth(AS); + Align = Target.getPointerAlign(AS); + break; + } case Type::Pointer: { unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace(); Width = Target.getPointerWidth(AS); Align = Target.getPointerAlign(AS); break; } - case Type::LValueReference: - case Type::RValueReference: - // "When applied to a reference or a reference type, the result is the size - // of the referenced type." C++98 5.3.3p2: expr.sizeof. - // FIXME: This is wrong for struct layout: a reference in a struct has - // pointer size. - return getTypeInfo(cast<ReferenceType>(T)->getPointeeType()); case Type::MemberPointer: { // FIXME: This is ABI dependent. We use the Itanium C++ ABI. // http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers @@ -761,7 +771,8 @@ ASTContext::getTypeInfo(const Type *T) { case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) { - Align = Aligned->getAlignment(); + Align = std::max(Aligned->getMaxAlignment(), + getTypeAlign(Typedef->getUnderlyingType().getTypePtr())); Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr()); } else return getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); @@ -1460,16 +1471,24 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy, ArrayType::ArraySizeModifier ASM, unsigned EltTypeQuals, SourceRange Brackets) { - assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) && + assert((!NumElts || NumElts->isTypeDependent() || + NumElts->isValueDependent()) && "Size must be type- or value-dependent!"); - llvm::FoldingSetNodeID ID; - DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM, - EltTypeQuals, NumElts); - void *InsertPos = 0; - DependentSizedArrayType *Canon - = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentSizedArrayType *Canon = 0; + + if (NumElts) { + // Dependently-sized array types that do not have a specified + // number of elements will have their sizes deduced from an + // initializer. + llvm::FoldingSetNodeID ID; + DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM, + EltTypeQuals, NumElts); + + Canon = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos); + } + DependentSizedArrayType *New; if (Canon) { // We already have a canonical version of this array type; use it as @@ -1483,7 +1502,9 @@ QualType ASTContext::getDependentSizedArrayType(QualType EltTy, New = new (*this, TypeAlignment) DependentSizedArrayType(*this, EltTy, QualType(), NumElts, ASM, EltTypeQuals, Brackets); - DependentSizedArrayTypes.InsertNode(New, InsertPos); + + if (NumElts) + DependentSizedArrayTypes.InsertNode(New, InsertPos); } else { QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts, ASM, EltTypeQuals, @@ -1818,9 +1839,10 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, - const TemplateArgumentLoc *Args, - unsigned NumArgs, + const TemplateArgumentListInfo &Args, QualType Canon) { + unsigned NumArgs = Args.size(); + llvm::SmallVector<TemplateArgument, 4> ArgVec; ArgVec.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) @@ -2320,6 +2342,22 @@ CanQualType ASTContext::getCanonicalType(QualType T) { VAT->getBracketsRange())); } +DeclarationName ASTContext::getNameForTemplate(TemplateName Name) { + if (TemplateDecl *TD = Name.getAsTemplateDecl()) + return TD->getDeclName(); + + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { + if (DTN->isIdentifier()) { + return DeclarationNames.getIdentifier(DTN->getIdentifier()); + } else { + return DeclarationNames.getCXXOperatorName(DTN->getOperator()); + } + } + + assert(Name.getAsOverloadedFunctionDecl()); + return Name.getAsOverloadedFunctionDecl()->getDeclName(); +} + TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { // If this template name refers to a template, the canonical // template name merely stores the template itself. @@ -3374,9 +3412,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, false); return; } - + if (const PointerType *PT = T->getAs<PointerType>()) { + if (PT->isObjCSelType()) { + S += ':'; + return; + } QualType PointeeTy = PT->getPointeeType(); + bool isReadOnly = false; // For historical/compatibility reasons, the read-only qualifier of the // pointee gets emitted _before_ the '^'. The read-only qualifier of @@ -3407,10 +3450,6 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S.replace(S.end()-2, S.end(), replace); } } - if (isObjCSelType(PointeeTy)) { - S += ':'; - return; - } if (PointeeTy->isCharType()) { // char pointer types should be encoded as '*' unless it is a @@ -3633,21 +3672,7 @@ void ASTContext::setObjCIdType(QualType T) { } void ASTContext::setObjCSelType(QualType T) { - ObjCSelType = T; - - const TypedefType *TT = T->getAs<TypedefType>(); - if (!TT) - return; - TypedefDecl *TD = TT->getDecl(); - - // typedef struct objc_selector *SEL; - const PointerType *ptr = TD->getUnderlyingType()->getAs<PointerType>(); - if (!ptr) - return; - const RecordType *rec = ptr->getPointeeType()->getAsStructureType(); - if (!rec) - return; - SelStructType = rec; + ObjCSelTypedefType = T; } void ASTContext::setObjCProtoType(QualType QT) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index bdc8047..572d76f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -211,6 +211,203 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, // NamedDecl Implementation //===----------------------------------------------------------------------===// +static NamedDecl::Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { + assert(D->getDeclContext()->getLookupContext()->isFileContext() && + "Not a name having namespace scope"); + ASTContext &Context = D->getASTContext(); + + // C++ [basic.link]p3: + // A name having namespace scope (3.3.6) has internal linkage if it + // is the name of + // - an object, reference, function or function template that is + // explicitly declared static; or, + // (This bullet corresponds to C99 6.2.2p3.) + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + // Explicitly declared static. + if (Var->getStorageClass() == VarDecl::Static) + return NamedDecl::InternalLinkage; + + // - an object or reference that is explicitly declared const + // and neither explicitly declared extern nor previously + // declared to have external linkage; or + // (there is no equivalent in C99) + if (Context.getLangOptions().CPlusPlus && + Var->getType().isConstant(Context) && + Var->getStorageClass() != VarDecl::Extern && + Var->getStorageClass() != VarDecl::PrivateExtern) { + bool FoundExtern = false; + for (const VarDecl *PrevVar = Var->getPreviousDeclaration(); + PrevVar && !FoundExtern; + PrevVar = PrevVar->getPreviousDeclaration()) + if (PrevVar->getLinkage() == NamedDecl::ExternalLinkage) + FoundExtern = true; + + if (!FoundExtern) + return NamedDecl::InternalLinkage; + } + } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { + const FunctionDecl *Function = 0; + if (const FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(D)) + Function = FunTmpl->getTemplatedDecl(); + else + Function = cast<FunctionDecl>(D); + + // Explicitly declared static. + if (Function->getStorageClass() == FunctionDecl::Static) + return NamedDecl::InternalLinkage; + } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) { + // - a data member of an anonymous union. + if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion()) + return NamedDecl::InternalLinkage; + } + + // C++ [basic.link]p4: + + // A name having namespace scope has external linkage if it is the + // name of + // + // - an object or reference, unless it has internal linkage; or + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (!Context.getLangOptions().CPlusPlus && + (Var->getStorageClass() == VarDecl::Extern || + Var->getStorageClass() == VarDecl::PrivateExtern)) { + // C99 6.2.2p4: + // For an identifier declared with the storage-class specifier + // extern in a scope in which a prior declaration of that + // identifier is visible, if the prior declaration specifies + // internal or external linkage, the linkage of the identifier + // at the later declaration is the same as the linkage + // 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 (NamedDecl::Linkage L = PrevVar->getLinkage()) + return L; + } + } + + // C99 6.2.2p5: + // If the declaration of an identifier for an object has file + // scope and no storage-class specifier, its linkage is + // external. + return NamedDecl::ExternalLinkage; + } + + // - a function, unless it has internal linkage; or + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + // C99 6.2.2p5: + // If the declaration of an identifier for a function has no + // storage-class specifier, its linkage is determined exactly + // as if it were declared with the storage-class specifier + // extern. + if (!Context.getLangOptions().CPlusPlus && + (Function->getStorageClass() == FunctionDecl::Extern || + Function->getStorageClass() == FunctionDecl::PrivateExtern || + Function->getStorageClass() == FunctionDecl::None)) { + // C99 6.2.2p4: + // For an identifier declared with the storage-class specifier + // extern in a scope in which a prior declaration of that + // identifier is visible, if the prior declaration specifies + // internal or external linkage, the linkage of the identifier + // at the later declaration is the same as the linkage + // 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 (NamedDecl::Linkage L = PrevFunc->getLinkage()) + return L; + } + } + + return NamedDecl::ExternalLinkage; + } + + // - a named class (Clause 9), or an unnamed class defined in a + // typedef declaration in which the class has the typedef name + // for linkage purposes (7.1.3); or + // - a named enumeration (7.2), or an unnamed enumeration + // defined in a typedef declaration in which the enumeration + // has the typedef name for linkage purposes (7.1.3); or + if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) + if (Tag->getDeclName() || Tag->getTypedefForAnonDecl()) + return NamedDecl::ExternalLinkage; + + // - an enumerator belonging to an enumeration with external linkage; + if (isa<EnumConstantDecl>(D)) + if (cast<NamedDecl>(D->getDeclContext())->getLinkage() + == NamedDecl::ExternalLinkage) + return NamedDecl::ExternalLinkage; + + // - a template, unless it is a function template that has + // internal linkage (Clause 14); + if (isa<TemplateDecl>(D)) + return NamedDecl::ExternalLinkage; + + // - a namespace (7.3), unless it is declared within an unnamed + // namespace. + if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) + return NamedDecl::ExternalLinkage; + + return NamedDecl::NoLinkage; +} + +NamedDecl::Linkage NamedDecl::getLinkage() const { + // Handle linkage for namespace-scope names. + if (getDeclContext()->getLookupContext()->isFileContext()) + if (Linkage L = getLinkageForNamespaceScopeDecl(this)) + return L; + + // C++ [basic.link]p5: + // In addition, a member function, static data member, a named + // class or enumeration of class scope, or an unnamed class or + // enumeration defined in a class-scope typedef declaration such + // that the class or enumeration has the typedef name for linkage + // purposes (7.1.3), has external linkage if the name of the class + // has external linkage. + if (getDeclContext()->isRecord() && + (isa<CXXMethodDecl>(this) || isa<VarDecl>(this) || + (isa<TagDecl>(this) && + (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl()))) && + cast<RecordDecl>(getDeclContext())->getLinkage() == ExternalLinkage) + return ExternalLinkage; + + // C++ [basic.link]p6: + // The name of a function declared in block scope and the name of + // an object declared by a block scope extern declaration have + // linkage. If there is a visible declaration of an entity with + // linkage having the same name and type, ignoring entities + // declared outside the innermost enclosing namespace scope, the + // block scope declaration declares that same entity and receives + // the linkage of the previous declaration. If there is more than + // one such matching entity, the program is ill-formed. Otherwise, + // if no matching entity is found, the block scope entity receives + // external linkage. + if (getLexicalDeclContext()->isFunctionOrMethod()) { + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) { + if (Function->getPreviousDeclaration()) + if (Linkage L = Function->getPreviousDeclaration()->getLinkage()) + return L; + + return ExternalLinkage; + } + + if (const VarDecl *Var = dyn_cast<VarDecl>(this)) + if (Var->getStorageClass() == VarDecl::Extern || + Var->getStorageClass() == VarDecl::PrivateExtern) { + if (Var->getPreviousDeclaration()) + if (Linkage L = Var->getPreviousDeclaration()->getLinkage()) + return L; + + return ExternalLinkage; + } + } + + // C++ [basic.link]p6: + // Names not covered by these rules have no linkage. + return NoLinkage; +} + std::string NamedDecl::getQualifiedNameAsString() const { return getQualifiedNameAsString(getASTContext().getLangOptions()); } @@ -300,13 +497,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { } bool NamedDecl::hasLinkage() const { - if (const VarDecl *VD = dyn_cast<VarDecl>(this)) - return VD->hasExternalStorage() || VD->isFileVarDecl(); - - if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this)) - return true; - - return false; + return getLinkage() != NoLinkage; } NamedDecl *NamedDecl::getUnderlyingDecl() { diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 831f552..2dcd80b 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -55,8 +55,7 @@ const char *DeclContext::getDeclKindName() const { } bool Decl::CollectingStats(bool Enable) { - if (Enable) - StatSwitch = true; + if (Enable) StatSwitch = true; return StatSwitch; } @@ -119,7 +118,7 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const { OS << Message; - if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) + if (const NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) OS << " '" << DN->getQualifiedNameAsString() << '\''; OS << '\n'; } @@ -130,9 +129,6 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const { // Out-of-line virtual method providing a home for Decl. Decl::~Decl() { - if (isOutOfSemaDC()) - delete getMultipleDC(); - assert(!HasAttrs && "attributes should have been freed by Destroy"); } @@ -148,7 +144,7 @@ void Decl::setLexicalDeclContext(DeclContext *DC) { return; if (isInSemaDC()) { - MultipleDC *MDC = new MultipleDC(); + MultipleDC *MDC = new (getASTContext()) MultipleDC(); MDC->SemanticDC = getDeclContext(); MDC->LexicalDC = DC; DeclCtx = MDC; @@ -343,9 +339,12 @@ void Decl::Destroy(ASTContext &C) { N = Tmp; } + if (isOutOfSemaDC()) + delete (C) getMultipleDC(); + this->~Decl(); C.Deallocate((void *)this); -#endif +#endif } Decl *Decl::castFromDeclContext (const DeclContext *D) { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index a21c93f..4001988 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -36,8 +36,6 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true), HasTrivialDestructor(true), ComputedVisibleConversions(false), Bases(0), NumBases(0), VBases(0), NumVBases(0), - Conversions(DC, DeclarationName()), - VisibleConversions(DC, DeclarationName()), TemplateOrInstantiation() { } CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, @@ -299,14 +297,11 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, void CXXRecordDecl::collectConversionFunctions( - llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) + llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const { - OverloadedFunctionDecl *TopConversions = getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator - TFunc = TopConversions->function_begin(), - TFuncEnd = TopConversions->function_end(); - TFunc != TFuncEnd; ++TFunc) { - NamedDecl *TopConv = TFunc->get(); + const UnresolvedSet *Cs = getConversionFunctions(); + for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) { + NamedDecl *TopConv = *I; CanQualType TConvType; if (FunctionTemplateDecl *TConversionTemplate = dyn_cast<FunctionTemplateDecl>(TopConv)) @@ -336,14 +331,11 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD, bool inTopClass = (RD == this); QualType ClassType = getASTContext().getTypeDeclType(this); if (const RecordType *Record = ClassType->getAs<RecordType>()) { - OverloadedFunctionDecl *Conversions + const UnresolvedSet *Cs = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions(); - for (OverloadedFunctionDecl::function_iterator - Func = Conversions->function_begin(), - FuncEnd = Conversions->function_end(); - Func != FuncEnd; ++Func) { - NamedDecl *Conv = Func->get(); + for (UnresolvedSet::iterator I = Cs->begin(), E = Cs->end(); I != E; ++I) { + NamedDecl *Conv = *I; // Only those conversions not exact match of conversions in current // class are candidateconversion routines. CanQualType ConvType; @@ -405,8 +397,7 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD, /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. -OverloadedFunctionDecl * -CXXRecordDecl::getVisibleConversionFunctions() { +const UnresolvedSet *CXXRecordDecl::getVisibleConversionFunctions() { // If root class, all conversions are visible. if (bases_begin() == bases_end()) return &Conversions; @@ -425,26 +416,26 @@ void CXXRecordDecl::addVisibleConversionFunction( CXXConversionDecl *ConvDecl) { assert(!ConvDecl->getDescribedFunctionTemplate() && "Conversion function templates should cast to FunctionTemplateDecl."); - VisibleConversions.addOverload(ConvDecl); + VisibleConversions.addDecl(ConvDecl); } void CXXRecordDecl::addVisibleConversionFunction( FunctionTemplateDecl *ConvDecl) { assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) && "Function template is not a conversion function template"); - VisibleConversions.addOverload(ConvDecl); + VisibleConversions.addDecl(ConvDecl); } void CXXRecordDecl::addConversionFunction(CXXConversionDecl *ConvDecl) { assert(!ConvDecl->getDescribedFunctionTemplate() && "Conversion function templates should cast to FunctionTemplateDecl."); - Conversions.addOverload(ConvDecl); + Conversions.addDecl(ConvDecl); } void CXXRecordDecl::addConversionFunction(FunctionTemplateDecl *ConvDecl) { assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) && "Function template is not a conversion function template"); - Conversions.addOverload(ConvDecl); + Conversions.addDecl(ConvDecl); } CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { @@ -895,12 +886,21 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, - NamespaceDecl *Used, + NamedDecl *Used, DeclContext *CommonAncestor) { + if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used)) + Used = NS->getOriginalNamespace(); return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange, Qualifier, IdentLoc, Used, CommonAncestor); } +NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { + if (NamespaceAliasDecl *NA = + dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace)) + return NA->getNamespace(); + return cast_or_null<NamespaceDecl>(NominatedNamespace); +} + NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation AliasLoc, @@ -909,6 +909,8 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace) { + if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace)) + Namespace = NS->getOriginalNamespace(); return new (C) NamespaceAliasDecl(DC, L, AliasLoc, Alias, QualifierRange, Qualifier, IdentLoc, Namespace); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 131de8b..a5982cf 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -18,19 +18,18 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/PrettyPrinter.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace clang; namespace { - class VISIBILITY_HIDDEN DeclPrinter : public DeclVisitor<DeclPrinter> { + class DeclPrinter : public DeclVisitor<DeclPrinter> { llvm::raw_ostream &Out; ASTContext &Context; PrintingPolicy Policy; unsigned Indentation; - llvm::raw_ostream& Indent(); + llvm::raw_ostream& Indent() { return Indent(Indentation); } + llvm::raw_ostream& Indent(unsigned Indentation); void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls); void Print(AccessSpecifier AS); @@ -154,8 +153,8 @@ void Decl::dump() const { print(llvm::errs()); } -llvm::raw_ostream& DeclPrinter::Indent() { - for (unsigned i = 0; i < Indentation; ++i) +llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) { + for (unsigned i = 0; i != Indentation; ++i) Out << " "; return Out; } @@ -205,6 +204,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { AccessSpecifier AS = D->getAccess(); if (AS != CurAS) { + if (Indent) + this->Indent(Indentation - Policy.Indentation); Print(AS); Out << ":\n"; CurAS = AS; @@ -502,7 +503,7 @@ void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { Out << "using namespace "; if (D->getQualifier()) D->getQualifier()->print(Out, Policy); - Out << D->getNominatedNamespace()->getNameAsString(); + Out << D->getNominatedNamespaceAsWritten()->getNameAsString(); } void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 0c14714..902339e 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -214,9 +214,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(), - NTTP->getLocation(), - NTTP->getType()->isDependentType(), - /*Value-dependent=*/true); + NTTP->getLocation()); TemplateArgs.push_back(TemplateArgument(E)); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); @@ -453,8 +451,9 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, - TemplateArgumentLoc *ArgInfos, unsigned N, + const TemplateArgumentListInfo &ArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl) { + unsigned N = ArgInfos.size(); TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N]; for (unsigned I = 0; I != N; ++I) ClonedArgs[I] = ArgInfos[I]; diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 1ff068c..3471657 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -50,6 +50,17 @@ public: void *FETokenInfo; }; +/// CXXLiberalOperatorName - Contains the actual identifier that makes up the +/// name. +/// +/// This identifier is stored here rather than directly in DeclarationName so as +/// to allow Objective-C selectors, which are about a million times more common, +/// to consume minimal memory. +class CXXLiteralOperatorIdName : public DeclarationNameExtra { +public: + IdentifierInfo *ID; +}; + bool operator<(DeclarationName LHS, DeclarationName RHS) { if (LHS.getNameKind() != RHS.getNameKind()) return LHS.getNameKind() < RHS.getNameKind(); @@ -89,6 +100,10 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) { case DeclarationName::CXXOperatorName: return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator(); + + case DeclarationName::CXXLiteralOperatorName: + return LHS.getCXXLiteralIdentifier()->getName() < + RHS.getCXXLiteralIdentifier()->getName(); case DeclarationName::CXXUsingDirective: return false; @@ -143,6 +158,9 @@ DeclarationName::NameKind DeclarationName::getNameKind() const { case DeclarationNameExtra::CXXConversionFunction: return CXXConversionFunctionName; + case DeclarationNameExtra::CXXLiteralOperator: + return CXXLiteralOperatorName; + case DeclarationNameExtra::CXXUsingDirective: return CXXUsingDirective; @@ -208,6 +226,10 @@ std::string DeclarationName::getAsString() const { return Result; } + case CXXLiteralOperatorName: { + return "operator \"\" " + std::string(getCXXLiteralIdentifier()->getName()); + } + case CXXConversionFunctionName: { std::string Result = "operator "; QualType Type = getCXXNameType(); @@ -242,6 +264,13 @@ OverloadedOperatorKind DeclarationName::getCXXOverloadedOperator() const { } } +IdentifierInfo *DeclarationName::getCXXLiteralIdentifier() const { + if (CXXLiteralOperatorIdName *CXXLit = getAsCXXLiteralOperatorIdName()) + return CXXLit->ID; + else + return 0; +} + Selector DeclarationName::getObjCSelector() const { switch (getNameKind()) { case ObjCZeroArgSelector: @@ -273,6 +302,9 @@ void *DeclarationName::getFETokenInfoAsVoid() const { case CXXOperatorName: return getAsCXXOperatorIdName()->FETokenInfo; + case CXXLiteralOperatorName: + return getCXXLiteralIdentifier()->getFETokenInfo<void>(); + default: assert(false && "Declaration name has no FETokenInfo"); } @@ -295,6 +327,10 @@ void DeclarationName::setFETokenInfo(void *T) { getAsCXXOperatorIdName()->FETokenInfo = T; break; + case CXXLiteralOperatorName: + getCXXLiteralIdentifier()->setFETokenInfo(T); + break; + default: assert(false && "Declaration name has no FETokenInfo"); } @@ -390,6 +426,14 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) { return DeclarationName(&CXXOperatorNames[(unsigned)Op]); } +DeclarationName +DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) { + CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName; + LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator; + LiteralName->ID = II; + return DeclarationName(LiteralName); +} + unsigned llvm::DenseMapInfo<clang::DeclarationName>:: getHashValue(clang::DeclarationName N) { diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 90b50c6..624a620 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -31,49 +31,104 @@ using namespace clang; // Primary Expressions. //===----------------------------------------------------------------------===// +void ExplicitTemplateArgumentList::initializeFrom( + const TemplateArgumentListInfo &Info) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); +} + +void ExplicitTemplateArgumentList::copyInto( + TemplateArgumentListInfo &Info) const { + Info.setLAngleLoc(LAngleLoc); + Info.setRAngleLoc(RAngleLoc); + for (unsigned I = 0; I != NumTemplateArgs; ++I) + Info.addArgument(getTemplateArgs()[I]); +} + +std::size_t ExplicitTemplateArgumentList::sizeFor( + const TemplateArgumentListInfo &Info) { + return sizeof(ExplicitTemplateArgumentList) + + sizeof(TemplateArgumentLoc) * Info.size(); +} + +void DeclRefExpr::computeDependence() { + TypeDependent = false; + ValueDependent = false; + + NamedDecl *D = getDecl(); + + // (TD) C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains: + // + // and + // + // (VD) C++ [temp.dep.constexpr]p2: + // An identifier is value-dependent if it is: + + // (TD) - an identifier that was declared with dependent type + // (VD) - a name declared with a dependent type, + if (getType()->isDependentType()) { + TypeDependent = true; + ValueDependent = true; + } + // (TD) - a conversion-function-id that specifies a dependent type + else if (D->getDeclName().getNameKind() + == DeclarationName::CXXConversionFunctionName && + D->getDeclName().getCXXNameType()->isDependentType()) { + TypeDependent = true; + ValueDependent = true; + } + // (TD) - a template-id that is dependent, + else if (hasExplicitTemplateArgumentList() && + TemplateSpecializationType::anyDependentTemplateArguments( + getTemplateArgs(), + getNumTemplateArgs())) { + TypeDependent = true; + ValueDependent = true; + } + // (VD) - the name of a non-type template parameter, + else if (isa<NonTypeTemplateParmDecl>(D)) + ValueDependent = true; + // (VD) - a constant with integral or enumeration type and is + // initialized with an expression that is value-dependent. + else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (Var->getType()->isIntegralType() && + Var->getType().getCVRQualifiers() == Qualifiers::Const && + Var->getInit() && + Var->getInit()->isValueDependent()) + ValueDependent = true; + } + // (TD) - a nested-name-specifier or a qualified-id that names a + // member of an unknown specialization. + // (handled by DependentScopeDeclRefExpr) +} + DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *D, SourceLocation NameLoc, - bool HasExplicitTemplateArgumentList, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, - QualType T, bool TD, bool VD) - : Expr(DeclRefExprClass, T, TD, VD), + const TemplateArgumentListInfo *TemplateArgs, + QualType T) + : Expr(DeclRefExprClass, T, false, false), DecoratedD(D, (Qualifier? HasQualifierFlag : 0) | - (HasExplicitTemplateArgumentList? - HasExplicitTemplateArgumentListFlag : 0)), + (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), Loc(NameLoc) { + assert(!isa<OverloadedFunctionDecl>(D)); if (Qualifier) { NameQualifier *NQ = getNameQualifier(); NQ->NNS = Qualifier; NQ->Range = QualifierRange; } - if (HasExplicitTemplateArgumentList) { - ExplicitTemplateArgumentList *ETemplateArgs - = getExplicitTemplateArgumentList(); - ETemplateArgs->LAngleLoc = LAngleLoc; - ETemplateArgs->RAngleLoc = RAngleLoc; - ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs; - - TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs(); - for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I) - new (TemplateArgs + I) TemplateArgumentLoc(ExplicitTemplateArgs[I]); - } -} + if (TemplateArgs) + getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs); -DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - NamedDecl *D, - SourceLocation NameLoc, - QualType T, bool TD, bool VD) { - return Create(Context, Qualifier, QualifierRange, D, NameLoc, - false, SourceLocation(), 0, 0, SourceLocation(), - T, TD, VD); + computeDependence(); } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, @@ -81,28 +136,18 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, SourceRange QualifierRange, NamedDecl *D, SourceLocation NameLoc, - bool HasExplicitTemplateArgumentList, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, - QualType T, bool TD, bool VD) { + QualType T, + const TemplateArgumentListInfo *TemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (Qualifier != 0) Size += sizeof(NameQualifier); - if (HasExplicitTemplateArgumentList) - Size += sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgumentLoc) * NumExplicitTemplateArgs; + if (TemplateArgs) + Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc, - HasExplicitTemplateArgumentList, - LAngleLoc, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - RAngleLoc, - T, TD, VD); + TemplateArgs, T); } SourceRange DeclRefExpr::getSourceRange() const { @@ -427,15 +472,13 @@ QualType CallExpr::getCallReturnType() const { MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, NamedDecl *memberdecl, - SourceLocation l, bool has_explicit, - SourceLocation langle, - const TemplateArgumentLoc *targs, unsigned numtargs, - SourceLocation rangle, QualType ty) + SourceLocation l, const TemplateArgumentListInfo *targs, + QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent() || (qual && qual->isDependent()), base->isValueDependent() || (qual && qual->isDependent())), Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), - HasQualifier(qual != 0), HasExplicitTemplateArgumentList(has_explicit) { + HasQualifier(qual != 0), HasExplicitTemplateArgumentList(targs) { // Initialize the qualifier, if any. if (HasQualifier) { NameQualifier *NQ = getMemberQualifier(); @@ -444,17 +487,8 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, } // Initialize the explicit template argument list, if any. - if (HasExplicitTemplateArgumentList) { - ExplicitTemplateArgumentList *ETemplateArgs - = getExplicitTemplateArgumentList(); - ETemplateArgs->LAngleLoc = langle; - ETemplateArgs->RAngleLoc = rangle; - ETemplateArgs->NumTemplateArgs = numtargs; - - TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs(); - for (unsigned I = 0; I < numtargs; ++I) - new (TemplateArgs + I) TemplateArgumentLoc(targs[I]); - } + if (targs) + getExplicitTemplateArgumentList()->initializeFrom(*targs); } MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, @@ -462,24 +496,18 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, - bool has_explicit, - SourceLocation langle, - const TemplateArgumentLoc *targs, - unsigned numtargs, - SourceLocation rangle, + const TemplateArgumentListInfo *targs, QualType ty) { std::size_t Size = sizeof(MemberExpr); if (qual != 0) Size += sizeof(NameQualifier); - if (has_explicit) - Size += sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgumentLoc) * numtargs; + if (targs) + Size += ExplicitTemplateArgumentList::sizeFor(*targs); void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>()); return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l, - has_explicit, langle, targs, numtargs, rangle, - ty); + targs, ty); } const char *CastExpr::getCastKindName() const { @@ -528,6 +556,8 @@ const char *CastExpr::getCastKindName() const { return "FloatingToIntegral"; case CastExpr::CK_FloatingCast: return "FloatingCast"; + case CastExpr::CK_MemberPointerToBoolean: + return "MemberPointerToBoolean"; } assert(0 && "Unhandled cast kind!"); @@ -640,12 +670,17 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { InitListExpr::InitListExpr(SourceLocation lbraceloc, Expr **initExprs, unsigned numInits, SourceLocation rbraceloc) - : Expr(InitListExprClass, QualType(), - hasAnyTypeDependentArguments(initExprs, numInits), - hasAnyValueDependentArguments(initExprs, numInits)), + : Expr(InitListExprClass, QualType(), false, false), LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), - UnionFieldInit(0), HadArrayRangeDesignator(false) { - + UnionFieldInit(0), HadArrayRangeDesignator(false) +{ + for (unsigned I = 0; I != numInits; ++I) { + if (initExprs[I]->isTypeDependent()) + TypeDependent = true; + if (initExprs[I]->isValueDependent()) + ValueDependent = true; + } + InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits); } @@ -1091,10 +1126,10 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; case PredefinedExprClass: return LV_Valid; + case UnresolvedLookupExprClass: + return LV_Valid; case CXXDefaultArgExprClass: return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx); - case CXXConditionDeclExprClass: - return LV_Valid; case CStyleCastExprClass: case CXXFunctionalCastExprClass: case CXXStaticCastExprClass: @@ -1141,18 +1176,6 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { return LV_Valid; } - case TemplateIdRefExprClass: { - const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this); - TemplateName Template = TID->getTemplateName(); - NamedDecl *ND = Template.getAsTemplateDecl(); - if (!ND) - ND = Template.getAsOverloadedFunctionDecl(); - if (ND && DeclCanBeLvalue(ND, Ctx)) - return LV_Valid; - - break; - } - default: break; } @@ -1491,19 +1514,18 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXNullPtrLiteralExprClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: - case Expr::CXXConditionDeclExprClass: // FIXME: is this correct? case Expr::CXXNewExprClass: case Expr::CXXDeleteExprClass: case Expr::CXXPseudoDestructorExprClass: - case Expr::UnresolvedFunctionNameExprClass: - case Expr::UnresolvedDeclRefExprClass: - case Expr::TemplateIdRefExprClass: + case Expr::UnresolvedLookupExprClass: + case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: case Expr::CXXBindTemporaryExprClass: case Expr::CXXExprWithTemporariesClass: case Expr::CXXTemporaryObjectExprClass: case Expr::CXXUnresolvedConstructExprClass: - case Expr::CXXUnresolvedMemberExprClass: + case Expr::CXXDependentScopeMemberExprClass: + case Expr::UnresolvedMemberExprClass: case Expr::ObjCStringLiteralClass: case Expr::ObjCEncodeExprClass: case Expr::ObjCMessageExprClass: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 0ba4608..d1a0390 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -72,14 +72,6 @@ Stmt::child_iterator CXXZeroInitValueExpr::child_end() { return child_iterator(); } -// CXXConditionDeclExpr -Stmt::child_iterator CXXConditionDeclExpr::child_begin() { - return getVarDecl(); -} -Stmt::child_iterator CXXConditionDeclExpr::child_end() { - return child_iterator(); -} - // CXXNewExpr CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs, unsigned numPlaceArgs, @@ -121,11 +113,45 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() { return &Base + 1; } -// UnresolvedFunctionNameExpr -Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() { +// UnresolvedLookupExpr +UnresolvedLookupExpr * +UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, DeclarationName Name, + SourceLocation NameLoc, bool ADL, + const TemplateArgumentListInfo &Args) +{ + void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + + ExplicitTemplateArgumentList::sizeFor(Args)); + UnresolvedLookupExpr *ULE + = new (Mem) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + Dependent, Qualifier, QualifierRange, + Name, NameLoc, ADL, + /*Overload*/ true, + /*ExplicitTemplateArgs*/ true); + + reinterpret_cast<ExplicitTemplateArgumentList*>(ULE+1)->initializeFrom(Args); + + return ULE; +} + +bool UnresolvedLookupExpr::ComputeDependence(NamedDecl * const *Begin, + NamedDecl * const *End, + const TemplateArgumentListInfo *Args) { + for (NamedDecl * const *I = Begin; I != End; ++I) + if ((*I)->getDeclContext()->isDependentContext()) + return true; + + if (Args && TemplateSpecializationType::anyDependentTemplateArguments(*Args)) + return true; + + return false; +} + +Stmt::child_iterator UnresolvedLookupExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() { +Stmt::child_iterator UnresolvedLookupExpr::child_end() { return child_iterator(); } // UnaryTypeTraitExpr @@ -136,72 +162,37 @@ Stmt::child_iterator UnaryTypeTraitExpr::child_end() { return child_iterator(); } -// UnresolvedDeclRefExpr -StmtIterator UnresolvedDeclRefExpr::child_begin() { - return child_iterator(); +// DependentScopeDeclRefExpr +DependentScopeDeclRefExpr * +DependentScopeDeclRefExpr::Create(ASTContext &C, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *Args) { + std::size_t size = sizeof(DependentScopeDeclRefExpr); + if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args); + void *Mem = C.Allocate(size); + + DependentScopeDeclRefExpr *DRE + = new (Mem) DependentScopeDeclRefExpr(C.DependentTy, + Qualifier, QualifierRange, + Name, NameLoc, + Args != 0); + + if (Args) + reinterpret_cast<ExplicitTemplateArgumentList*>(DRE+1) + ->initializeFrom(*Args); + + return DRE; } -StmtIterator UnresolvedDeclRefExpr::child_end() { +StmtIterator DependentScopeDeclRefExpr::child_begin() { return child_iterator(); } -TemplateIdRefExpr::TemplateIdRefExpr(QualType T, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) - : Expr(TemplateIdRefExprClass, T, - (Template.isDependent() || - TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, NumTemplateArgs)), - (Template.isDependent() || - TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, NumTemplateArgs))), - Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template), - TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc), - RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) { - TemplateArgumentLoc *StoredTemplateArgs - = reinterpret_cast<TemplateArgumentLoc *> (this+1); - for (unsigned I = 0; I != NumTemplateArgs; ++I) - new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]); -} - -TemplateIdRefExpr * -TemplateIdRefExpr::Create(ASTContext &Context, QualType T, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, SourceLocation RAngleLoc) { - void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) + - sizeof(TemplateArgumentLoc) * NumTemplateArgs); - return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template, - TemplateNameLoc, LAngleLoc, TemplateArgs, - NumTemplateArgs, RAngleLoc); -} - -void TemplateIdRefExpr::DoDestroy(ASTContext &Context) { - const TemplateArgumentLoc *TemplateArgs = getTemplateArgs(); - for (unsigned I = 0; I != NumTemplateArgs; ++I) - if (Expr *E = TemplateArgs[I].getArgument().getAsExpr()) - E->Destroy(Context); - this->~TemplateIdRefExpr(); - Context.Deallocate(this); -} - -Stmt::child_iterator TemplateIdRefExpr::child_begin() { - // FIXME: Walk the expressions in the template arguments (?) - return Stmt::child_iterator(); -} - -Stmt::child_iterator TemplateIdRefExpr::child_end() { - // FIXME: Walk the expressions in the template arguments (?) - return Stmt::child_iterator(); +StmtIterator DependentScopeDeclRefExpr::child_end() { + return child_iterator(); } bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const { @@ -526,7 +517,7 @@ Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() { return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs); } -CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C, +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, @@ -534,33 +525,20 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C, NamedDecl *FirstQualifierFoundInScope, DeclarationName Member, SourceLocation MemberLoc, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) - : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true), + const TemplateArgumentListInfo *TemplateArgs) + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), Base(Base), IsArrow(IsArrow), - HasExplicitTemplateArgumentList(HasExplicitTemplateArgs), + HasExplicitTemplateArgumentList(TemplateArgs), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), Member(Member), MemberLoc(MemberLoc) { - if (HasExplicitTemplateArgumentList) { - ExplicitTemplateArgumentList *ETemplateArgs - = getExplicitTemplateArgumentList(); - ETemplateArgs->LAngleLoc = LAngleLoc; - ETemplateArgs->RAngleLoc = RAngleLoc; - ETemplateArgs->NumTemplateArgs = NumTemplateArgs; - - TemplateArgumentLoc *SavedTemplateArgs = ETemplateArgs->getTemplateArgs(); - for (unsigned I = 0; I < NumTemplateArgs; ++I) - new (SavedTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]); - } + if (TemplateArgs) + getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs); } -CXXUnresolvedMemberExpr * -CXXUnresolvedMemberExpr::Create(ASTContext &C, +CXXDependentScopeMemberExpr * +CXXDependentScopeMemberExpr::Create(ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, @@ -568,37 +546,79 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C, NamedDecl *FirstQualifierFoundInScope, DeclarationName Member, SourceLocation MemberLoc, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { - if (!HasExplicitTemplateArgs) - return new (C) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc, + const TemplateArgumentListInfo *TemplateArgs) { + if (!TemplateArgs) + return new (C) CXXDependentScopeMemberExpr(C, Base, IsArrow, OperatorLoc, Qualifier, QualifierRange, FirstQualifierFoundInScope, Member, MemberLoc); - void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) + - sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgumentLoc) * NumTemplateArgs, - llvm::alignof<CXXUnresolvedMemberExpr>()); - return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc, + std::size_t size = sizeof(CXXDependentScopeMemberExpr); + if (TemplateArgs) + size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + + void *Mem = C.Allocate(size, llvm::alignof<CXXDependentScopeMemberExpr>()); + return new (Mem) CXXDependentScopeMemberExpr(C, Base, IsArrow, OperatorLoc, Qualifier, QualifierRange, FirstQualifierFoundInScope, Member, MemberLoc, - HasExplicitTemplateArgs, - LAngleLoc, - TemplateArgs, - NumTemplateArgs, - RAngleLoc); + TemplateArgs); +} + +Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { + return child_iterator(&Base); } -Stmt::child_iterator CXXUnresolvedMemberExpr::child_begin() { +Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() { + return child_iterator(&Base + 1); +} + +UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent, + bool HasUnresolvedUsing, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName MemberName, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs) + : Expr(UnresolvedMemberExprClass, T, Dependent, Dependent), + Base(Base), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), + HasExplicitTemplateArgs(TemplateArgs != 0), + OperatorLoc(OperatorLoc), + Qualifier(Qualifier), QualifierRange(QualifierRange), + MemberName(MemberName), MemberLoc(MemberLoc) { + if (TemplateArgs) + getExplicitTemplateArgs()->initializeFrom(*TemplateArgs); +} + +UnresolvedMemberExpr * +UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, + bool HasUnresolvedUsing, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs) { + std::size_t size = sizeof(UnresolvedMemberExpr); + if (TemplateArgs) + size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + + void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>()); + return new (Mem) UnresolvedMemberExpr( + Dependent ? C.DependentTy : C.OverloadTy, + Dependent, HasUnresolvedUsing, Base, IsArrow, + OperatorLoc, Qualifier, QualifierRange, + Member, MemberLoc, TemplateArgs); +} + +Stmt::child_iterator UnresolvedMemberExpr::child_begin() { return child_iterator(&Base); } -Stmt::child_iterator CXXUnresolvedMemberExpr::child_end() { +Stmt::child_iterator UnresolvedMemberExpr::child_end() { return child_iterator(&Base + 1); } diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 2689859..a20e1cc 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -19,7 +19,6 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/Compiler.h" #include <cstring> using namespace clang; @@ -153,7 +152,7 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, } namespace { -class VISIBILITY_HIDDEN HasSideEffect +class HasSideEffect : public StmtVisitor<HasSideEffect, bool> { EvalInfo &Info; public: @@ -210,7 +209,7 @@ public: // LValue Evaluation //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN LValueExprEvaluator +class LValueExprEvaluator : public StmtVisitor<LValueExprEvaluator, APValue> { EvalInfo &Info; public: @@ -353,7 +352,7 @@ APValue LValueExprEvaluator::VisitUnaryDeref(UnaryOperator *E) { //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN PointerExprEvaluator +class PointerExprEvaluator : public StmtVisitor<PointerExprEvaluator, APValue> { EvalInfo &Info; public: @@ -508,7 +507,7 @@ APValue PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { //===----------------------------------------------------------------------===// namespace { - class VISIBILITY_HIDDEN VectorExprEvaluator + class VectorExprEvaluator : public StmtVisitor<VectorExprEvaluator, APValue> { EvalInfo &Info; APValue GetZeroVector(QualType VecType); @@ -702,7 +701,7 @@ APValue VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN IntExprEvaluator +class IntExprEvaluator : public StmtVisitor<IntExprEvaluator, bool> { EvalInfo &Info; APValue &Result; @@ -776,7 +775,20 @@ public: T1.getUnqualifiedType()), E); } - bool VisitDeclRefExpr(const DeclRefExpr *E); + + bool CheckReferencedDecl(const Expr *E, const Decl *D); + bool VisitDeclRefExpr(const DeclRefExpr *E) { + return CheckReferencedDecl(E, E->getDecl()); + } + bool VisitMemberExpr(const MemberExpr *E) { + if (CheckReferencedDecl(E, E->getMemberDecl())) { + // Conservatively assume a MemberExpr will have side-effects + Info.EvalResult.HasSideEffects = true; + return true; + } + return false; + } + bool VisitCallExpr(const CallExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); @@ -834,12 +846,12 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) { return true; } -bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { +bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // Enums are integer constant exprs. - if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(E->getDecl())) { + if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { // FIXME: This is an ugly hack around the fact that enums don't set their // signedness consistently; see PR3173. - APSInt SI = D->getInitVal(); + APSInt SI = ECD->getInitVal(); SI.setIsUnsigned(!E->getType()->isSignedIntegerType()); // FIXME: This is an ugly hack around the fact that enums don't // set their width (!?!) consistently; see PR3173. @@ -851,15 +863,15 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { // In C, they can also be folded, although they are not ICEs. if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() == Qualifiers::Const) { - if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { const VarDecl *Def = 0; - if (const Expr *Init = D->getDefinition(Def)) { - if (APValue *V = D->getEvaluatedValue()) + if (const Expr *Init = VD->getDefinition(Def)) { + if (APValue *V = VD->getEvaluatedValue()) return Success(V->getInt(), E); if (Visit(const_cast<Expr*>(Init))) { // Cache the evaluated value in the variable declaration. - D->setEvaluatedValue(Info.Ctx, Result); + VD->setEvaluatedValue(Info.Ctx, Result); return true; } @@ -1244,6 +1256,13 @@ bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { } unsigned 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>()) + T = Ref->getPointeeType(); + // Get information about the alignment. unsigned CharSize = Info.Ctx.Target.getCharWidth(); @@ -1257,10 +1276,11 @@ unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) { // alignof decl is always accepted, even if it doesn't make sense: we default // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - return Info.Ctx.getDeclAlignInBytes(DRE->getDecl()); + return Info.Ctx.getDeclAlignInBytes(DRE->getDecl(), /*RefAsPointee*/true); if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) - return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl()); + return Info.Ctx.getDeclAlignInBytes(ME->getMemberDecl(), + /*RefAsPointee*/true); return GetAlignOfType(E->getType()); } @@ -1280,6 +1300,12 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { } 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. @@ -1460,7 +1486,7 @@ bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN FloatExprEvaluator +class FloatExprEvaluator : public StmtVisitor<FloatExprEvaluator, bool> { EvalInfo &Info; APFloat &Result; @@ -1652,7 +1678,7 @@ bool FloatExprEvaluator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN ComplexExprEvaluator +class ComplexExprEvaluator : public StmtVisitor<ComplexExprEvaluator, APValue> { EvalInfo &Info; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index b9cfcfe..326a1dc 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -14,7 +14,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" #include <llvm/ADT/SmallSet.h> #include <llvm/Support/MathExtras.h> @@ -22,9 +21,9 @@ using namespace clang; ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) - : Ctx(Ctx), Size(0), Alignment(8), Packed(false), MaxFieldAlignment(0), - DataSize(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8), - PrimaryBase(0), PrimaryBaseWasVirtual(false) {} + : Ctx(Ctx), Size(0), Alignment(8), Packed(false), UnfilledBitsInLastByte(0), + MaxFieldAlignment(0), DataSize(0), IsUnion(false), NonVirtualSize(0), + NonVirtualAlignment(8) { } /// LayoutVtable - Lay out the vtable and set PrimaryBase. void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) { @@ -34,7 +33,7 @@ void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) { } SelectPrimaryBase(RD); - if (PrimaryBase == 0) { + if (!PrimaryBase.getBase()) { int AS = 0; UpdateAlignment(Ctx.Target.getPointerAlign(AS)); Size += Ctx.Target.getPointerWidth(AS); @@ -52,7 +51,7 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); // Skip the PrimaryBase here, as it is laid down first. - if (Base != PrimaryBase || PrimaryBaseWasVirtual) + if (Base != PrimaryBase.getBase() || PrimaryBase.isVirtual()) LayoutBaseNonVirtually(Base, false); } } @@ -74,12 +73,13 @@ bool ASTRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const { } void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) { - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + const ASTRecordLayout::PrimaryBaseInfo &BaseInfo = + Ctx.getASTRecordLayout(RD).getPrimaryBaseInfo(); // If the record has a primary base class that is virtual, add it to the set // of primary bases. - if (Layout.getPrimaryBaseWasVirtual()) - IndirectPrimaryBases.insert(Layout.getPrimaryBase()); + if (BaseInfo.isVirtual()) + IndirectPrimaryBases.insert(BaseInfo.getBase()); // Now traverse all bases and find primary bases for them. for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), @@ -107,7 +107,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); if (!i->isVirtual()) { SelectPrimaryVBase(Base, FirstPrimary); - if (PrimaryBase) + if (PrimaryBase.getBase()) return; continue; } @@ -115,7 +115,7 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD, if (FirstPrimary==0) FirstPrimary = Base; if (!IndirectPrimaryBases.count(Base)) { - setPrimaryBase(Base, true); + setPrimaryBase(Base, /*IsVirtual=*/true); return; } } @@ -141,14 +141,17 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { // base class, if one exists. for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { - if (!i->isVirtual()) { - const CXXRecordDecl *Base = - cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (Base->isDynamicClass()) { - // We found it. - setPrimaryBase(Base, false); - return; - } + // Ignore virtual bases. + if (i->isVirtual()) + continue; + + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + + if (Base->isDynamicClass()) { + // We found it. + PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, /*IsVirtual=*/false); + return; } } @@ -166,8 +169,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { // Otherwise if is the first nearly empty virtual base, if one exists, // otherwise there is no primary base class. - if (!PrimaryBase) - setPrimaryBase(FirstPrimary, true); + if (!PrimaryBase.getBase()) + setPrimaryBase(FirstPrimary, /*IsVirtual=*/true); } void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) { @@ -232,9 +235,10 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class, } if (Base->getNumVBases()) { - const ASTRecordLayout &L = Ctx.getASTRecordLayout(Base); - const CXXRecordDecl *PB = L.getPrimaryBase(); - LayoutVirtualBases(Class, Base, PB, BaseOffset, mark, IndirectPrimary); + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Base); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBaseInfo().getBase(); + LayoutVirtualBases(Class, Base, PrimaryBase, BaseOffset, mark, + IndirectPrimary); } } } @@ -448,17 +452,17 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { MaxFieldAlignment = PPA->getAlignment(); if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - UpdateAlignment(AA->getAlignment()); + UpdateAlignment(AA->getMaxAlignment()); // If this is a C++ class, lay out the vtable and the non-virtual bases. const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D); if (RD) { LayoutVtable(RD); // PrimaryBase goes first. - if (PrimaryBase) { - if (PrimaryBaseWasVirtual) - IndirectPrimaryBases.insert(PrimaryBase); - LayoutBaseNonVirtually(PrimaryBase, PrimaryBaseWasVirtual); + if (PrimaryBase.getBase()) { + if (PrimaryBase.isVirtual()) + IndirectPrimaryBases.insert(PrimaryBase.getBase()); + LayoutBaseNonVirtually(PrimaryBase.getBase(), PrimaryBase.isVirtual()); } LayoutNonVirtualBases(RD); } @@ -470,7 +474,8 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { if (RD) { llvm::SmallSet<const CXXRecordDecl*, 32> mark; - LayoutVirtualBases(RD, RD, PrimaryBase, 0, mark, IndirectPrimaryBases); + LayoutVirtualBases(RD, RD, PrimaryBase.getBase(), + 0, mark, IndirectPrimaryBases); } // Finally, round the size of the total struct up to the alignment of the @@ -498,7 +503,7 @@ void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D, MaxFieldAlignment = PPA->getAlignment(); if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - UpdateAlignment(AA->getAlignment()); + UpdateAlignment(AA->getMaxAlignment()); // Layout each ivar sequentially. llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; @@ -519,84 +524,111 @@ void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { LayoutField(*Field); } +void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { + bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); + uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte); + uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Ctx).getZExtValue(); + + std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); + uint64_t TypeSize = FieldInfo.first; + unsigned FieldAlign = FieldInfo.second; + + if (FieldPacked) + FieldAlign = 1; + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) + FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); + + // The maximum field alignment overrides the aligned attribute. + if (MaxFieldAlignment) + FieldAlign = std::min(FieldAlign, MaxFieldAlignment); + + // Check if we need to add padding to give the field the correct + // alignment. + if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) + FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); + + // Padding members don't affect overall alignment + if (!D->getIdentifier()) + FieldAlign = 1; + + // Place this field at the current location. + FieldOffsets.push_back(FieldOffset); + + // Update DataSize to include the last byte containing (part of) the bitfield. + if (IsUnion) { + // FIXME: I think FieldSize should be TypeSize here. + DataSize = std::max(DataSize, FieldSize); + } else { + uint64_t NewSizeInBits = FieldOffset + FieldSize; + + DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8); + UnfilledBitsInLastByte = DataSize - NewSizeInBits; + } + + // Update the size. + Size = std::max(Size, DataSize); + + // Remember max struct/class alignment. + UpdateAlignment(FieldAlign); +} + void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { - bool FieldPacked = Packed; + if (D->isBitField()) { + LayoutBitField(D); + return; + } + + // Reset the unfilled bits. + UnfilledBitsInLastByte = 0; + + bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); uint64_t FieldOffset = IsUnion ? 0 : DataSize; uint64_t FieldSize; unsigned FieldAlign; - - FieldPacked |= D->hasAttr<PackedAttr>(); - - if (const Expr *BitWidthExpr = D->getBitWidth()) { - // TODO: Need to check this algorithm on other targets! - // (tested on Linux-X86) - FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue(); - + + if (D->getType()->isIncompleteArrayType()) { + // This is a flexible array member; we can't directly + // query getTypeInfo about these, so we figure it out here. + // Flexible array members don't have any size, but they + // have to be aligned appropriately for their element type. + FieldSize = 0; + const ArrayType* ATy = Ctx.getAsArrayType(D->getType()); + FieldAlign = Ctx.getTypeAlign(ATy->getElementType()); + } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) { + unsigned AS = RT->getPointeeType().getAddressSpace(); + FieldSize = Ctx.Target.getPointerWidth(AS); + FieldAlign = Ctx.Target.getPointerAlign(AS); + } else { std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); - uint64_t TypeSize = FieldInfo.first; - + FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; + } - if (FieldPacked) - FieldAlign = 1; - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - FieldAlign = std::max(FieldAlign, AA->getAlignment()); - // The maximum field alignment overrides the aligned attribute. - if (MaxFieldAlignment) - FieldAlign = std::min(FieldAlign, MaxFieldAlignment); - - // Check if we need to add padding to give the field the correct - // alignment. - if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) - FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1); - - // Padding members don't affect overall alignment - if (!D->getIdentifier()) - FieldAlign = 1; - } else { - if (D->getType()->isIncompleteArrayType()) { - // This is a flexible array member; we can't directly - // query getTypeInfo about these, so we figure it out here. - // Flexible array members don't have any size, but they - // have to be aligned appropriately for their element type. - FieldSize = 0; - const ArrayType* ATy = Ctx.getAsArrayType(D->getType()); - FieldAlign = Ctx.getTypeAlign(ATy->getElementType()); - } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) { - unsigned AS = RT->getPointeeType().getAddressSpace(); - FieldSize = Ctx.Target.getPointerWidth(AS); - FieldAlign = Ctx.Target.getPointerAlign(AS); - } else { - std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType()); - FieldSize = FieldInfo.first; - FieldAlign = FieldInfo.second; - } + if (FieldPacked) + FieldAlign = 8; + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) + FieldAlign = std::max(FieldAlign, AA->getMaxAlignment()); - if (FieldPacked) - FieldAlign = 8; - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) - FieldAlign = std::max(FieldAlign, AA->getAlignment()); - // The maximum field alignment overrides the aligned attribute. - if (MaxFieldAlignment) - FieldAlign = std::min(FieldAlign, MaxFieldAlignment); + // The maximum field alignment overrides the aligned attribute. + if (MaxFieldAlignment) + FieldAlign = std::min(FieldAlign, MaxFieldAlignment); - // Round up the current record size to the field's alignment boundary. - FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - - if (!IsUnion) { - while (true) { - // Check if we can place the field at this offset. - if (canPlaceFieldAtOffset(D, FieldOffset)) - break; - - // We couldn't place the field at the offset. Try again at a new offset. - FieldOffset += FieldAlign; - } + // Round up the current record size to the field's alignment boundary. + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); + + if (!IsUnion) { + while (true) { + // Check if we can place the field at this offset. + if (canPlaceFieldAtOffset(D, FieldOffset)) + break; - UpdateEmptyClassOffsets(D, FieldOffset); + // We couldn't place the field at the offset. Try again at a new offset. + FieldOffset += FieldAlign; } + + UpdateEmptyClassOffsets(D, FieldOffset); } - + // Place this field at the current location. FieldOffsets.push_back(FieldOffset); @@ -619,7 +651,7 @@ void ASTRecordLayoutBuilder::FinishLayout() { Size = 8; // Finally, round the size of the record up to the alignment of the // record itself. - Size = (Size + (Alignment-1)) & ~(Alignment-1); + Size = llvm::RoundUpToAlignment(Size, Alignment); } void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { @@ -631,6 +663,31 @@ void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { Alignment = NewAlignment; } +static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) { + if (!RD->isDynamicClass()) + return 0; + + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + if (MD->isPure()) + continue; + + const FunctionDecl *fn; + if (MD->getBody(fn) && !fn->isOutOfLine()) + continue; + + // We found it. + return MD; + } + + return 0; +} + const ASTRecordLayout * ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, const RecordDecl *D) { @@ -654,17 +711,19 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, uint64_t NonVirtualSize = IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; + const CXXMethodDecl *KeyFunction = GetKeyFunction(cast<CXXRecordDecl>(D)); + return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize, Builder.FieldOffsets.data(), Builder.FieldOffsets.size(), NonVirtualSize, Builder.NonVirtualAlignment, Builder.PrimaryBase, - Builder.PrimaryBaseWasVirtual, Builder.Bases.data(), Builder.Bases.size(), Builder.VBases.data(), - Builder.VBases.size()); + Builder.VBases.size(), + KeyFunction); } const ASTRecordLayout * diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index 0770723..69e0498 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H #define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H +#include "clang/AST/RecordLayout.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/System/DataTypes.h" @@ -27,12 +28,21 @@ namespace clang { class ASTRecordLayoutBuilder { ASTContext &Ctx; + /// Size - The current size of the record layout. uint64_t Size; + + /// Alignment - The current alignment of the record layout. unsigned Alignment; + llvm::SmallVector<uint64_t, 16> FieldOffsets; /// Packed - Whether the record is packed or not. bool Packed; + + /// UnfilledBitsInLastByte - If the last field laid out was a bitfield, + /// this contains the number of bits in the last byte that can be used for + /// an adjacent bitfield if necessary. + unsigned char UnfilledBitsInLastByte; /// MaxFieldAlignment - The maximum allowed field alignment. This is set by /// #pragma pack. @@ -45,8 +55,8 @@ class ASTRecordLayoutBuilder { uint64_t NonVirtualSize; unsigned NonVirtualAlignment; - const CXXRecordDecl *PrimaryBase; - bool PrimaryBaseWasVirtual; + + ASTRecordLayout::PrimaryBaseInfo PrimaryBase; typedef llvm::SmallVector<std::pair<const CXXRecordDecl *, uint64_t>, 4> BaseOffsetsTy; @@ -74,6 +84,7 @@ class ASTRecordLayoutBuilder { void LayoutFields(const RecordDecl *D); void LayoutField(const FieldDecl *D); + void LayoutBitField(const FieldDecl *D); void SelectPrimaryBase(const CXXRecordDecl *RD); void SelectPrimaryVBase(const CXXRecordDecl *RD, @@ -84,9 +95,8 @@ class ASTRecordLayoutBuilder { /// base class. void IdentifyPrimaryBases(const CXXRecordDecl *RD); - void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) { - PrimaryBase = PB; - PrimaryBaseWasVirtual = Virtual; + void setPrimaryBase(const CXXRecordDecl *Base, bool IsVirtual) { + PrimaryBase = ASTRecordLayout::PrimaryBaseInfo(Base, IsVirtual); } bool IsNearlyEmpty(const CXXRecordDecl *RD) const; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 6e0da47..fad80ec 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -88,8 +88,8 @@ void Stmt::addStmtClass(StmtClass s) { static bool StatSwitch = false; -bool Stmt::CollectingStats(bool enable) { - if (enable) StatSwitch = true; +bool Stmt::CollectingStats(bool Enable) { + if (Enable) StatSwitch = true; return StatSwitch; } @@ -559,7 +559,7 @@ Stmt::child_iterator CXXCatchStmt::child_end() { return &HandlerBlock + 1; } -QualType CXXCatchStmt::getCaughtType() { +QualType CXXCatchStmt::getCaughtType() const { if (ExceptionDecl) return ExceptionDecl->getType(); return QualType(); diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 93bf875..bbe6a71 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -17,7 +17,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/SourceManager.h" -#include "llvm/Support/Compiler.h" #include <cstdio> using namespace clang; @@ -26,7 +25,7 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace { - class VISIBILITY_HIDDEN StmtDumper : public StmtVisitor<StmtDumper> { + class StmtDumper : public StmtVisitor<StmtDumper> { SourceManager *SM; FILE *F; unsigned IndentLevel; diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 4bd7f96..205ea0d 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -16,7 +16,6 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/PrettyPrinter.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" using namespace clang; @@ -25,7 +24,7 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace { - class VISIBILITY_HIDDEN StmtPrinter : public StmtVisitor<StmtPrinter> { + class StmtPrinter : public StmtVisitor<StmtPrinter> { llvm::raw_ostream &OS; ASTContext &Context; unsigned IndentLevel; @@ -483,19 +482,26 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { Policy); } -void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) { +void StmtPrinter::VisitDependentScopeDeclRefExpr( + DependentScopeDeclRefExpr *Node) { Node->getQualifier()->print(OS, Policy); OS << Node->getDeclName().getAsString(); + if (Node->hasExplicitTemplateArgs()) + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), + Node->getNumTemplateArgs(), + Policy); } -void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) { +void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { if (Node->getQualifier()) Node->getQualifier()->print(OS, Policy); - Node->getTemplateName().print(OS, Policy, true); - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Node->getTemplateArgs(), + OS << Node->getName().getAsString(); + if (Node->hasExplicitTemplateArgs()) + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), Node->getNumTemplateArgs(), - Policy); + Policy); } void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { @@ -1048,11 +1054,6 @@ void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) { OS << Node->getType().getAsString() << "()"; } -void -StmtPrinter::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E) { - PrintRawDecl(E->getVarDecl()); -} - void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isGlobalNew()) OS << "::"; @@ -1118,10 +1119,6 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { OS << TypeS; } -void StmtPrinter::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *E) { - OS << E->getName().getAsString(); -} - void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { // Nothing to print. } @@ -1146,7 +1143,8 @@ StmtPrinter::VisitCXXUnresolvedConstructExpr( OS << ")"; } -void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) { +void StmtPrinter::VisitCXXDependentScopeMemberExpr( + CXXDependentScopeMemberExpr *Node) { PrintExpr(Node->getBase()); OS << (Node->isArrow() ? "->" : "."); if (NestedNameSpecifier *Qualifier = Node->getQualifier()) @@ -1165,6 +1163,24 @@ void StmtPrinter::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *Node) { } } +void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { + PrintExpr(Node->getBase()); + OS << (Node->isArrow() ? "->" : "."); + if (NestedNameSpecifier *Qualifier = Node->getQualifier()) + Qualifier->print(OS, Policy); + + // FIXME: this might originally have been written with 'template' + + OS << Node->getMemberName().getAsString(); + + if (Node->hasExplicitTemplateArgs()) { + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), + Node->getNumTemplateArgs(), + Policy); + } +} + static const char *getTypeTraitName(UnaryTypeTrait UTT) { switch (UTT) { default: assert(false && "Unknown type trait"); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 4458c2b..d832a46 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -20,11 +20,10 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtVisitor.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/Support/Compiler.h" using namespace clang; namespace { - class VISIBILITY_HIDDEN StmtProfiler : public StmtVisitor<StmtProfiler> { + class StmtProfiler : public StmtVisitor<StmtProfiler> { llvm::FoldingSetNodeID &ID; ASTContext &Context; bool Canonical; @@ -108,14 +107,17 @@ void StmtProfiler::VisitLabelStmt(LabelStmt *S) { void StmtProfiler::VisitIfStmt(IfStmt *S) { VisitStmt(S); + VisitDecl(S->getConditionVariable()); } void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) { VisitStmt(S); + VisitDecl(S->getConditionVariable()); } void StmtProfiler::VisitWhileStmt(WhileStmt *S) { VisitStmt(S); + VisitDecl(S->getConditionVariable()); } void StmtProfiler::VisitDoStmt(DoStmt *S) { @@ -481,10 +483,6 @@ void StmtProfiler::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *S) { VisitExpr(S); } -void StmtProfiler::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *S) { - VisitDeclRefExpr(S); -} - void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) { VisitExpr(S); ID.AddBoolean(S->isGlobalDelete()); @@ -515,9 +513,13 @@ void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) { } void -StmtProfiler::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *S) { +StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) { VisitExpr(S); + VisitNestedNameSpecifier(S->getQualifier()); VisitName(S->getName()); + ID.AddBoolean(S->hasExplicitTemplateArgs()); + if (S->hasExplicitTemplateArgs()) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) { @@ -526,18 +528,14 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) { VisitType(S->getQueriedType()); } -void StmtProfiler::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *S) { +void +StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) { VisitExpr(S); VisitName(S->getDeclName()); VisitNestedNameSpecifier(S->getQualifier()); - ID.AddBoolean(S->isAddressOfOperand()); -} - -void StmtProfiler::VisitTemplateIdRefExpr(TemplateIdRefExpr *S) { - VisitExpr(S); - VisitNestedNameSpecifier(S->getQualifier()); - VisitTemplateName(S->getTemplateName()); - VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); + ID.AddBoolean(S->hasExplicitTemplateArgs()); + if (S->hasExplicitTemplateArgs()) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *S) { @@ -554,11 +552,25 @@ StmtProfiler::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *S) { VisitType(S->getTypeAsWritten()); } -void StmtProfiler::VisitCXXUnresolvedMemberExpr(CXXUnresolvedMemberExpr *S) { +void +StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) { VisitExpr(S); ID.AddBoolean(S->isArrow()); VisitNestedNameSpecifier(S->getQualifier()); VisitName(S->getMember()); + ID.AddBoolean(S->hasExplicitTemplateArgumentList()); + if (S->hasExplicitTemplateArgumentList()) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); +} + +void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) { + VisitExpr(S); + ID.AddBoolean(S->isArrow()); + VisitNestedNameSpecifier(S->getQualifier()); + VisitName(S->getMemberName()); + ID.AddBoolean(S->hasExplicitTemplateArgs()); + if (S->hasExplicitTemplateArgs()) + VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs()); } void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) { diff --git a/lib/AST/StmtViz.cpp b/lib/AST/StmtViz.cpp index 61fd750..8be287e 100644 --- a/lib/AST/StmtViz.cpp +++ b/lib/AST/StmtViz.cpp @@ -30,8 +30,9 @@ void Stmt::viewAST() const { namespace llvm { template<> struct DOTGraphTraits<const Stmt*> : public DefaultDOTGraphTraits { - static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph, - bool ShortNames) { + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph) { #ifndef NDEBUG std::string OutSStr; diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index ff02f9a..f341b45 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/FoldingSet.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/TypeLoc.h" @@ -59,8 +60,17 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, break; case Template: - ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) - .getAsVoidPointer()); + if (TemplateTemplateParmDecl *TTP + = dyn_cast_or_null<TemplateTemplateParmDecl>( + getAsTemplate().getAsTemplateDecl())) { + ID.AddBoolean(true); + ID.AddInteger(TTP->getDepth()); + ID.AddInteger(TTP->getPosition()); + } else { + ID.AddBoolean(false); + ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) + .getAsVoidPointer()); + } break; case Integral: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 297534e..5a2434d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -725,6 +725,7 @@ const char *BuiltinType::getName(const LangOptions &LO) const { case UndeducedAuto: return "auto"; case ObjCId: return "id"; case ObjCClass: return "Class"; + case ObjCSel: return "SEL"; } } @@ -866,6 +867,11 @@ static bool isDependent(const TemplateArgument &Arg) { } bool TemplateSpecializationType:: +anyDependentTemplateArguments(const TemplateArgumentListInfo &Args) { + return anyDependentTemplateArguments(Args.getArgumentArray(), Args.size()); +} + +bool TemplateSpecializationType:: anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) { for (unsigned i = 0; i != N; ++i) if (isDependent(Args[i].getArgument())) diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index a482333..562e830 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -535,6 +535,8 @@ void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, ObjCQIString = "id"; else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) ObjCQIString = "Class"; + else if (T->isObjCSelType()) + ObjCQIString = "SEL"; else ObjCQIString = T->getInterfaceDecl()->getNameAsString(); @@ -599,6 +601,14 @@ static void PrintTemplateArgument(std::string &Buffer, } } +std::string TemplateSpecializationType:: + PrintTemplateArgumentList(const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy) { + return PrintTemplateArgumentList(Args.getArgumentArray(), + Args.size(), + Policy); +} + std::string TemplateSpecializationType::PrintTemplateArgumentList( const TemplateArgument *Args, |