diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 113 | ||||
-rw-r--r-- | lib/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/AST/CXXInheritance.cpp | 29 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 6 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 32 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 86 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 47 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 54 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 7 | ||||
-rw-r--r-- | lib/AST/DeclarationName.cpp | 5 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 19 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 8 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 29 | ||||
-rw-r--r-- | lib/AST/NestedNameSpecifier.cpp | 2 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 3 | ||||
-rw-r--r-- | lib/AST/StmtDumper.cpp | 7 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 14 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 710 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 728 |
20 files changed, 1098 insertions, 806 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 8562249479ca4..dc13e7f4688cc 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -35,7 +35,7 @@ enum FloatingRank { }; ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, - TargetInfo &t, + const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, bool FreeMem, unsigned size_reserve) : @@ -256,9 +256,9 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, = new (*this) MemberSpecializationInfo(Tmpl, TSK); } -UnresolvedUsingDecl * +NamedDecl * ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) { - llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>::iterator Pos + llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos = InstantiatedFromUnresolvedUsingDecl.find(UUD); if (Pos == InstantiatedFromUnresolvedUsingDecl.end()) return 0; @@ -268,7 +268,10 @@ ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) { void ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, - UnresolvedUsingDecl *UUD) { + NamedDecl *UUD) { + assert((isa<UnresolvedUsingValueDecl>(UUD) || + isa<UnresolvedUsingTypenameDecl>(UUD)) && + "original declaration is not an unresolved using decl"); assert(!InstantiatedFromUnresolvedUsingDecl[UD] && "Already noted what using decl what instantiated from"); InstantiatedFromUnresolvedUsingDecl[UD] = UUD; @@ -1186,7 +1189,7 @@ QualType ASTContext::getNoReturnType(QualType T) { } } - return getQualifiedType(ResultType, T.getQualifiers()); + return getQualifiedType(ResultType, T.getLocalQualifiers()); } /// getComplexType - Return the uniqued reference to the type for a complex @@ -2350,6 +2353,12 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { return DTN->CanonicalTemplateName; } +bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) { + X = getCanonicalTemplateName(X); + Y = getCanonicalTemplateName(Y); + return X.getAsVoidPointer() == Y.getAsVoidPointer(); +} + TemplateArgument ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { @@ -2357,12 +2366,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { return Arg; case TemplateArgument::Expression: - // FIXME: Build canonical expression? return Arg; case TemplateArgument::Declaration: return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl()); + case TemplateArgument::Template: + return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); + case TemplateArgument::Integral: return TemplateArgument(*Arg.getAsIntegral(), getCanonicalType(Arg.getIntegralType())); @@ -2427,7 +2438,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) { const ArrayType *ASTContext::getAsArrayType(QualType T) { // Handle the non-qualified case efficiently. - if (!T.hasQualifiers()) { + if (!T.hasLocalQualifiers()) { // Handle the common positive case fast. if (const ArrayType *AT = dyn_cast<ArrayType>(T)) return AT; @@ -2732,12 +2743,22 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) { return 1; } +static RecordDecl * +CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id) { + if (Ctx.getLangOptions().CPlusPlus) + return CXXRecordDecl::Create(Ctx, TK, DC, L, Id); + else + return RecordDecl::Create(Ctx, TK, DC, L, Id); +} + // getCFConstantStringType - Return the type used for constant CFStrings. QualType ASTContext::getCFConstantStringType() { if (!CFConstantStringTypeDecl) { CFConstantStringTypeDecl = - RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get("NSConstantString")); + CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("NSConstantString")); + QualType FieldTypes[4]; // const int *isa; @@ -2774,8 +2795,8 @@ void ASTContext::setCFConstantStringType(QualType T) { QualType ASTContext::getObjCFastEnumerationStateType() { if (!ObjCFastEnumerationStateTypeDecl) { ObjCFastEnumerationStateTypeDecl = - RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get("__objcFastEnumerationState")); + CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__objcFastEnumerationState")); QualType FieldTypes[] = { UnsignedLongTy, @@ -2807,8 +2828,8 @@ QualType ASTContext::getBlockDescriptorType() { RecordDecl *T; // FIXME: Needs the FlagAppleBlock bit. - T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get("__block_descriptor")); + T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__block_descriptor")); QualType FieldTypes[] = { UnsignedLongTy, @@ -2850,8 +2871,8 @@ QualType ASTContext::getBlockDescriptorExtendedType() { RecordDecl *T; // FIXME: Needs the FlagAppleBlock bit. - T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get("__block_descriptor_withcopydispose")); + T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__block_descriptor_withcopydispose")); QualType FieldTypes[] = { UnsignedLongTy, @@ -2920,8 +2941,8 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { llvm::raw_svector_ostream(Name) << "__Block_byref_" << ++UniqueBlockByRefTypeID << '_' << DeclName; RecordDecl *T; - T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get(Name.str())); + T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get(Name.str())); T->startDefinition(); QualType Int32Ty = IntTy; assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); @@ -2970,8 +2991,8 @@ QualType ASTContext::getBlockParmType( llvm::raw_svector_ostream(Name) << "__block_literal_" << ++UniqueBlockParmTypeID; RecordDecl *T; - T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get(Name.str())); + T = CreateRecordDecl(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get(Name.str())); QualType FieldTypes[] = { getPointerType(VoidPtrTy), IntTy, @@ -3053,6 +3074,54 @@ int ASTContext::getObjCEncodingTypeSize(QualType type) { return sz / getTypeSize(CharTy); } +/// getObjCEncodingForBlockDecl - Return the encoded type for this method +/// declaration. +void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr, + std::string& S) { + const BlockDecl *Decl = Expr->getBlockDecl(); + QualType BlockTy = + Expr->getType()->getAs<BlockPointerType>()->getPointeeType(); + // Encode result type. + getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S); + // 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! + SourceLocation Loc; + int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy); + int ParmOffset = PtrSize; + for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(), + E = Decl->param_end(); PI != E; ++PI) { + QualType PType = (*PI)->getType(); + int sz = getObjCEncodingTypeSize(PType); + assert (sz > 0 && "BlockExpr - Incomplete param type"); + ParmOffset += sz; + } + // Size of the argument frame + S += llvm::utostr(ParmOffset); + // Block pointer and offset. + S += "@?0"; + ParmOffset = PtrSize; + + // Argument types. + ParmOffset = PtrSize; + for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E = + Decl->param_end(); PI != E; ++PI) { + ParmVarDecl *PVDecl = *PI; + QualType PType = PVDecl->getOriginalType(); + if (const ArrayType *AT = + dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { + // Use array's original type only if it has known number of + // elements. + if (!isa<ConstantArrayType>(AT)) + PType = PVDecl->getType(); + } else if (PType->isFunctionType()) + PType = PVDecl->getType(); + getObjCEncodingForType(PType, S); + S += llvm::utostr(ParmOffset); + ParmOffset += getObjCEncodingTypeSize(PType); + } +} + /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, @@ -4186,8 +4255,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { return LHS; // If the qualifiers are different, the types aren't compatible... mostly. - Qualifiers LQuals = LHSCan.getQualifiers(); - Qualifiers RQuals = RHSCan.getQualifiers(); + Qualifiers LQuals = LHSCan.getLocalQualifiers(); + Qualifiers RQuals = RHSCan.getLocalQualifiers(); if (LQuals != RQuals) { // If any of these qualifiers are different, we have a type // mismatch. @@ -4394,7 +4463,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { //===----------------------------------------------------------------------===// unsigned ASTContext::getIntWidth(QualType T) { - if (T == BoolTy) + if (T->isBooleanType()) return 1; if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) { return FWIT->getWidth(); diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index e541406790a62..0f0b22d65f6f9 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangAST TemplateName.cpp Type.cpp TypeLoc.cpp + TypePrinter.cpp ) add_dependencies(clangAST ClangDiagnosticAST) diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index b59b45f6467e3..023bca436339c 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -76,31 +76,31 @@ void CXXBasePaths::swap(CXXBasePaths &Other) { std::swap(DetectedVirtual, Other.DetectedVirtual); } -bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) { +bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) const { CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, /*DetectVirtual=*/false); return isDerivedFrom(Base, Paths); } -bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) { +bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const { if (getCanonicalDecl() == Base->getCanonicalDecl()) return false; - Paths.setOrigin(this); + Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths); } bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, - CXXBasePaths &Paths) { + CXXBasePaths &Paths) const { bool FoundPath = false; ASTContext &Context = getASTContext(); - for (base_class_iterator BaseSpec = bases_begin(), BaseSpecEnd = bases_end(); - BaseSpec != BaseSpecEnd; ++BaseSpec) { + for (base_class_const_iterator BaseSpec = bases_begin(), + BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) { // Find the record of the base class subobjects for this type. - QualType BaseType = Context.getCanonicalType(BaseSpec->getType()); - BaseType = BaseType.getUnqualifiedType(); + QualType BaseType = Context.getCanonicalType(BaseSpec->getType()) + .getUnqualifiedType(); // C++ [temp.dep]p3: // In the definition of a class template or a member of a class template, @@ -183,7 +183,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, return FoundPath; } -bool CXXRecordDecl::FindBaseClass(CXXBaseSpecifier *Specifier, +bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *BaseRecord) { assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord && @@ -192,7 +192,7 @@ bool CXXRecordDecl::FindBaseClass(CXXBaseSpecifier *Specifier, ->getCanonicalDecl() == BaseRecord; } -bool CXXRecordDecl::FindTagMember(CXXBaseSpecifier *Specifier, +bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *Name) { RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); @@ -208,7 +208,7 @@ bool CXXRecordDecl::FindTagMember(CXXBaseSpecifier *Specifier, return false; } -bool CXXRecordDecl::FindOrdinaryMember(CXXBaseSpecifier *Specifier, +bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *Name) { RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); @@ -225,9 +225,10 @@ bool CXXRecordDecl::FindOrdinaryMember(CXXBaseSpecifier *Specifier, return false; } -bool CXXRecordDecl::FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - void *Name) { +bool CXXRecordDecl:: +FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *Name) { RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); DeclarationName N = DeclarationName::getFromOpaquePtr(Name); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a6996a4bfe5cc..bdc804722c417 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -289,6 +289,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD)) return true; + if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD)) + return cast<UsingShadowDecl>(this)->getTargetDecl() == + cast<UsingShadowDecl>(OldD)->getTargetDecl(); + // 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. @@ -308,7 +312,7 @@ bool NamedDecl::hasLinkage() const { NamedDecl *NamedDecl::getUnderlyingDecl() { NamedDecl *ND = this; while (true) { - if (UsingDecl *UD = dyn_cast<UsingDecl>(ND)) + if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND)) ND = UD->getTargetDecl(); else if (ObjCCompatibleAliasDecl *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 6cfdcdd3e50e1..831f552489f95 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -97,7 +97,7 @@ bool Decl::isTemplateParameterPack() const { } bool Decl::isFunctionOrFunctionTemplate() const { - if (const UsingDecl *UD = dyn_cast<UsingDecl>(this)) + if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this)) return UD->getTargetDecl()->isFunctionOrFunctionTemplate(); return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this); @@ -189,10 +189,11 @@ ASTContext &Decl::getASTContext() const { unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { switch (DeclKind) { - default: - if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast) - return IDNS_Ordinary; - assert(0 && "Unknown decl kind!"); + case Function: + case CXXMethod: + case CXXConstructor: + case CXXDestructor: + case CXXConversion: case OverloadedFunction: case Typedef: case EnumConstant: @@ -200,8 +201,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ImplicitParam: case ParmVar: case NonTypeTemplateParm: - case Using: - case UnresolvedUsing: case ObjCMethod: case ObjCContainer: case ObjCCategory: @@ -210,6 +209,16 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCCompatibleAlias: return IDNS_Ordinary; + case UsingShadow: + return 0; // we'll actually overwrite this later + + case UnresolvedUsingValue: + case UnresolvedUsingTypename: + return IDNS_Ordinary | IDNS_Using; + + case Using: + return IDNS_Using; + case ObjCProtocol: return IDNS_ObjCProtocol; @@ -256,6 +265,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ClassTemplatePartialSpecialization: return 0; } + + return 0; } void Decl::addAttr(Attr *NewAttr) { @@ -663,6 +674,13 @@ void DeclContext::buildLookup(DeclContext *DCtx) { if (D->getDeclContext() == DCtx) makeDeclVisibleInContextImpl(ND); + // Insert any forward-declared Objective-C interfaces into the lookup + // data structure. + if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) + for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end(); + I != IEnd; ++I) + makeDeclVisibleInContextImpl(I->getInterface()); + // If this declaration is itself a transparent declaration context, // add its members (recursively). if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index b4c0c59733e53..a21c93ffcdc97 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -211,7 +211,7 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context, if (!ArgType.isConstQualified()) AcceptsConst = false; } - if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType) + if (!Context.hasSameUnqualifiedType(ArgType, ClassType)) continue; MD = Method; // We have a single argument of type cv X or cv X&, i.e. we've found the @@ -276,10 +276,13 @@ void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( const_cast<CXXRecordDecl*>(this))); - if (ClassType != Context.getCanonicalType(ArgType)) + if (!Context.hasSameUnqualifiedType(ClassType, ArgType)) return; // This is a copy assignment operator. + // Note on the decl that it is a copy assignment operator. + OpDecl->setCopyAssignment(true); + // Suppress the implicit declaration of a copy constructor. UserDeclaredCopyAssignment = true; @@ -749,6 +752,33 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { (getNumParams() > 1 && getParamDecl(1)->hasDefaultArg()); } +bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { + if ((getNumParams() < 1) || + (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || + (getPrimaryTemplate() == 0) || + (getDescribedFunctionTemplate() != 0)) + return false; + + const ParmVarDecl *Param = getParamDecl(0); + + ASTContext &Context = getASTContext(); + CanQualType ParamType = Context.getCanonicalType(Param->getType()); + + // Strip off the lvalue reference, if any. + if (CanQual<LValueReferenceType> ParamRefType + = ParamType->getAs<LValueReferenceType>()) + ParamType = ParamRefType->getPointeeType(); + + + // Is it the same as our our class type? + CanQualType ClassTy + = Context.getCanonicalType(Context.getTagDeclType(getParent())); + if (ParamType.getUnqualifiedType() != ClassTy) + return false; + + return true; +} + CXXDestructorDecl * CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, @@ -761,12 +791,6 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, } void -CXXDestructorDecl::Destroy(ASTContext& C) { - C.Deallocate(BaseOrMemberDestructions); - CXXMethodDecl::Destroy(C); -} - -void CXXConstructorDecl::Destroy(ASTContext& C) { C.Deallocate(BaseOrMemberInitializers); CXXMethodDecl::Destroy(C); @@ -890,22 +914,36 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, } UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, SourceRange NNR, SourceLocation TargetNL, - SourceLocation UL, NamedDecl* Target, - NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) { - return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target, - TargetNNS, IsTypeNameArg); -} - -UnresolvedUsingDecl *UnresolvedUsingDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, - DeclarationName TargetName, - bool IsTypeNameArg) { - return new (C) UnresolvedUsingDecl(DC, UsingLoc, TargetNNR, TargetNNS, - TargetNameLoc, TargetName, IsTypeNameArg); + SourceLocation L, SourceRange NNR, SourceLocation UL, + NestedNameSpecifier* TargetNNS, DeclarationName Name, + bool IsTypeNameArg) { + return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg); +} + +UnresolvedUsingValueDecl * +UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingLoc, + SourceRange TargetNNR, + NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, + DeclarationName TargetName) { + return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, + TargetNNR, TargetNNS, + TargetNameLoc, TargetName); +} + +UnresolvedUsingTypenameDecl * +UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, + NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, + DeclarationName TargetName) { + return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc, + TargetNNR, TargetNNS, + TargetNameLoc, + TargetName.getAsIdentifierInfo()); } StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 7b48b724c0eb6..c33720f5633a9 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -571,34 +571,55 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, //===----------------------------------------------------------------------===// ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, unsigned nElts, + ObjCInterfaceDecl *const *Elts, + const SourceLocation *Locs, + unsigned nElts, ASTContext &C) : Decl(ObjCClass, DC, L) { - ForwardDecls.set(Elts, nElts, C); + setClassList(C, Elts, Locs, nElts); } +void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, + const SourceLocation *Locs, unsigned Num) { + ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num, + llvm::alignof<ObjCClassRef>()); + for (unsigned i = 0; i < Num; ++i) + new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]); + + NumDecls = Num; +} ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts, + const SourceLocation *Locs, unsigned nElts) { - return new (C) ObjCClassDecl(DC, L, Elts, nElts, C); + return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C); } void ObjCClassDecl::Destroy(ASTContext &C) { - - // FIXME: There is no clear ownership policy now for referenced - // ObjCInterfaceDecls. Some of them can be forward declarations that - // are never later defined (in which case the ObjCClassDecl owns them) - // or the ObjCInterfaceDecl later becomes a real definition later. Ideally - // we should have separate objects for forward declarations and definitions, - // obviating this problem. Because of this situation, referenced - // ObjCInterfaceDecls are destroyed in ~TranslationUnit. - - ForwardDecls.Destroy(C); + // ObjCInterfaceDecls registered with a DeclContext will get destroyed + // when the DeclContext is destroyed. For those created only by a forward + // declaration, the first @class that created the ObjCInterfaceDecl gets + // to destroy it. + // FIXME: Note that this ownership role is very brittle; a better + // polict is surely need in the future. + for (iterator I = begin(), E = end(); I !=E ; ++I) { + ObjCInterfaceDecl *ID = I->getInterface(); + if (ID->isForwardDecl() && ID->getLocStart() == getLocStart()) + ID->Destroy(C); + } + + C.Deallocate(ForwardDecls); Decl::Destroy(C); } +SourceRange ObjCClassDecl::getSourceRange() const { + // FIXME: We should include the semicolon + assert(NumDecls); + return SourceRange(getLocation(), ForwardDecls[NumDecls-1].getLocation()); +} + //===----------------------------------------------------------------------===// // ObjCForwardProtocolDecl //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index d9d195016bf30..131de8b2e11ba 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -71,8 +71,10 @@ namespace { void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); void VisitObjCPropertyDecl(ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); - void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); + void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); void VisitUsingDecl(UsingDecl *D); + void VisitUsingShadowDecl(UsingShadowDecl *D); }; } @@ -401,37 +403,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } } } - else if (CXXDestructorDecl *DDecl = dyn_cast<CXXDestructorDecl>(D)) { - if (DDecl->getNumBaseOrMemberDestructions() > 0) { - // List order of base/member destruction for visualization purposes. - assert (D->isThisDeclarationADefinition() && "Destructor with dtor-list"); - Proto += "/* : "; - for (CXXDestructorDecl::destr_const_iterator *B = DDecl->destr_begin(), - *E = DDecl->destr_end(); - B != E; ++B) { - uintptr_t BaseOrMember = (*B); - if (B != DDecl->destr_begin()) - Proto += ", "; - - if (DDecl->isMemberToDestroy(BaseOrMember)) { - FieldDecl *FD = DDecl->getMemberToDestroy(BaseOrMember); - Proto += "~"; - Proto += FD->getNameAsString(); - } - else // FIXME. skip dependent types for now. - if (const RecordType *RT = - DDecl->getAnyBaseClassToDestroy(BaseOrMember) - ->getAs<RecordType>()) { - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(RT->getDecl()); - Proto += "~"; - Proto += BaseDecl->getNameAsString(); - } - Proto += "()"; - } - Proto += " */"; - } - } else AFT->getResultType().getAsStringInternal(Proto, Policy); } else { @@ -654,7 +625,7 @@ void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I) { if (I != D->begin()) Out << ", "; - Out << (*I)->getNameAsString(); + Out << I->getInterface()->getNameAsString(); } } @@ -856,11 +827,22 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { void DeclPrinter::VisitUsingDecl(UsingDecl *D) { Out << "using "; D->getTargetNestedNameDecl()->print(Out, Policy); - Out << D->getTargetDecl()->getNameAsString(); + Out << D->getNameAsString(); +} + +void +DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { + Out << "using typename "; + D->getTargetNestedNameSpecifier()->print(Out, Policy); + Out << D->getDeclName().getAsString(); } -void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { +void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { Out << "using "; D->getTargetNestedNameSpecifier()->print(Out, Policy); - Out << D->getTargetName().getAsString(); + Out << D->getDeclName().getAsString(); +} + +void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { + // ignore } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 9ebc91afe1429..0c14714812f5a 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -220,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) { TemplateArgs.push_back(TemplateArgument(E)); } else { TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param); - TemplateArgs.push_back(TemplateArgument(TTP)); + TemplateArgs.push_back(TemplateArgument(TemplateName(TTP))); } } @@ -285,11 +285,6 @@ TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); } -SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { - return DefaultArgument? DefaultArgument->getSourceRange().getBegin() - : SourceLocation(); -} - //===----------------------------------------------------------------------===// // TemplateArgumentListBuilder Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 8664c508615fe..1ff068c9862c1 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include <cstdio> using namespace clang; namespace clang { @@ -310,6 +311,10 @@ DeclarationName DeclarationName::getUsingDirectiveName() { return DeclarationName(Ptr); } +void DeclarationName::dump() const { + fprintf(stderr, "%s\n", getAsString().c_str()); +} + DeclarationNameTable::DeclarationNameTable() { CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index a8ea752a4a7ea..90b50c61f989a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -490,6 +490,8 @@ const char *CastExpr::getCastKindName() const { return "BitCast"; case CastExpr::CK_NoOp: return "NoOp"; + case CastExpr::CK_BaseToDerived: + return "BaseToDerived"; case CastExpr::CK_DerivedToBase: return "DerivedToBase"; case CastExpr::CK_Dynamic: @@ -812,6 +814,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, } return false; } + + case CXXTemporaryObjectExprClass: + case CXXConstructExprClass: + return false; + case ObjCMessageExprClass: return false; @@ -853,15 +860,19 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, Loc = cast<CStyleCastExpr>(this)->getLParenLoc(); R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange(); return true; - case CXXFunctionalCastExprClass: - // If this is a cast to void, check the operand. Otherwise, the result of - // the cast is unused. - if (getType()->isVoidType()) + case CXXFunctionalCastExprClass: { + const CastExpr *CE = cast<CastExpr>(this); + + // If this is a cast to void or a constructor conversion, check the operand. + // Otherwise, the result of the cast is unused. + if (CE->getCastKind() == CastExpr::CK_ToVoid || + CE->getCastKind() == CastExpr::CK_ConstructorConversion) return (cast<CastExpr>(this)->getSubExpr() ->isUnusedResultAWarning(Loc, R1, R2, Ctx)); Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc(); R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange(); return true; + } case ImplicitCastExprClass: // Check the operand, since implicit casts are inserted by Sema diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 7c6fc41ef12ba..0ba4608ee198a 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -323,6 +323,14 @@ Expr *CXXMemberCallExpr::getImplicitObjectArgument() { return 0; } +SourceRange CXXMemberCallExpr::getSourceRange() const { + SourceLocation LocStart = getCallee()->getLocStart(); + if (LocStart.isInvalid() && getNumArgs() > 0) + LocStart = getArg(0)->getLocStart(); + return SourceRange(LocStart, getRParenLoc()); +} + + //===----------------------------------------------------------------------===// // Named casts //===----------------------------------------------------------------------===// diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7862c57c2d476..2689859e8e4aa 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -204,13 +204,6 @@ public: bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); } }; -bool HasSideEffects(const Expr* E, ASTContext &Ctx) { - Expr::EvalResult Result; - EvalInfo Info(Ctx, Result); - - return HasSideEffect(Info).Visit(const_cast<Expr*>(E)); -} - } // end anonymous namespace //===----------------------------------------------------------------------===// @@ -964,7 +957,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } } - if (HasSideEffects(E->getArg(0), Info.Ctx)) { + if (E->getArg(0)->HasSideEffects(Info.Ctx)) { if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2) return Success(-1ULL, E); return Success(0, E); @@ -1495,7 +1488,7 @@ public: // FIXME: Missing: __real__/__imag__, array subscript of vector, // member of vector, ImplicitValueInitExpr, - // conditional ?:, comma + // conditional ?: }; } // end anonymous namespace @@ -1584,6 +1577,18 @@ bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + if (E->getOpcode() == BinaryOperator::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; + } + // FIXME: Diagnostics? I really don't understand how the warnings // and errors are supposed to work. APFloat RHS(0.0); @@ -1947,6 +1952,12 @@ bool Expr::isEvaluatable(ASTContext &Ctx) const { return Evaluate(Result, Ctx) && !Result.HasSideEffects; } +bool Expr::HasSideEffects(ASTContext &Ctx) const { + Expr::EvalResult Result; + EvalInfo Info(Ctx, Result); + return HasSideEffect(Info).Visit(const_cast<Expr*>(this)); +} + APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const { EvalResult EvalResult; bool Result = Evaluate(EvalResult, Ctx); diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index d969776aa0ee7..e26c0bba49347 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -167,7 +167,7 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS, InnerPolicy); } else { // Print the type normally - T->getAsStringInternal(TypeStr, InnerPolicy); + TypeStr = QualType(T, 0).getAsString(InnerPolicy); } OS << TypeStr; break; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 021c53e9514f6..b9cfcfec74f07 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -226,8 +226,7 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *Class, if (RD == Class) BaseOffset = getBaseOffset(Base); else { - const ASTRecordLayout &Layout - = Ctx.getASTRecordLayout(RD); + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); BaseOffset = Offset + Layout.getBaseClassOffset(Base); } } diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index cf71d6b986a2b..93bf8755d5805 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -115,6 +115,7 @@ namespace { // Exprs void VisitExpr(Expr *Node); void VisitCastExpr(CastExpr *Node); + void VisitImplicitCastExpr(ImplicitCastExpr *Node); void VisitDeclRefExpr(DeclRefExpr *Node); void VisitPredefinedExpr(PredefinedExpr *Node); void VisitCharacterLiteral(CharacterLiteral *Node); @@ -301,6 +302,12 @@ void StmtDumper::VisitCastExpr(CastExpr *Node) { fprintf(F, " <%s>", Node->getCastKindName()); } +void StmtDumper::VisitImplicitCastExpr(ImplicitCastExpr *Node) { + VisitCastExpr(Node); + if (Node->isLvalueCast()) + fprintf(F, " lvalue"); +} + void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) { DumpExpr(Node); diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 02e0c74bb63a9..4458c2b9cd25f 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -695,6 +695,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) { VisitType(Arg.getAsType()); break; + case TemplateArgument::Template: + VisitTemplateName(Arg.getAsTemplate()); + break; + case TemplateArgument::Declaration: VisitDecl(Arg.getAsDecl()); break; diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index 94e1ca1e06e78..ff02f9a31cb29 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -58,6 +58,11 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0); break; + case Template: + ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate()) + .getAsVoidPointer()); + break; + case Integral: getAsIntegral()->Profile(ID); getIntegralType().Profile(ID); @@ -82,10 +87,19 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { switch (Argument.getKind()) { case TemplateArgument::Expression: return getSourceExpression()->getSourceRange(); + case TemplateArgument::Declaration: return getSourceDeclExpression()->getSourceRange(); + case TemplateArgument::Type: return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange(); + + case TemplateArgument::Template: + if (getTemplateQualifierRange().isValid()) + return SourceRange(getTemplateQualifierRange().getBegin(), + getTemplateNameLoc()); + return SourceRange(getTemplateNameLoc()); + case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 779f6808b6c18..297534eaf1fc9 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -98,6 +98,44 @@ const Type *Type::getArrayElementTypeNoTypeQual() const { ->getElementType().getTypePtr(); } +/// \brief Retrieve the unqualified variant of the given type, removing as +/// little sugar as possible. +/// +/// This routine looks through various kinds of sugar to find the +/// least-desuraged type that is unqualified. For example, given: +/// +/// \code +/// typedef int Integer; +/// typedef const Integer CInteger; +/// typedef CInteger DifferenceType; +/// \endcode +/// +/// Executing \c getUnqualifiedTypeSlow() on the type \c DifferenceType will +/// desugar until we hit the type \c Integer, which has no qualifiers on it. +QualType QualType::getUnqualifiedTypeSlow() const { + QualType Cur = *this; + while (true) { + if (!Cur.hasQualifiers()) + return Cur; + + const Type *CurTy = Cur.getTypePtr(); + switch (CurTy->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 Cur.getLocalUnqualifiedType(); \ + Cur = Ty->desugar(); \ + break; \ + } +#include "clang/AST/TypeNodes.def" + } + } + + return Cur.getUnqualifiedType(); +} + /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar @@ -425,7 +463,7 @@ bool Type::isSignedIntegerType() const { bool Type::isUnsignedIntegerType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) { return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::ULongLong; + BT->getKind() <= BuiltinType::UInt128; } if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) @@ -453,8 +491,7 @@ bool Type::isFloatingType() const { bool Type::isRealFloatingType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) - return BT->getKind() >= BuiltinType::Float && - BT->getKind() <= BuiltinType::LongDouble; + return BT->isFloatingPoint(); if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isRealFloatingType(); return false; @@ -808,6 +845,9 @@ static bool isDependent(const TemplateArgument &Arg) { case TemplateArgument::Type: return Arg.getAsType()->isDependentType(); + case TemplateArgument::Template: + return Arg.getAsTemplate().isDependent(); + case TemplateArgument::Declaration: case TemplateArgument::Integral: // Never dependent @@ -907,539 +947,6 @@ QualType QualifierCollector::apply(const Type *T) const { return Context->getQualifiedType(T, *this); } - -//===----------------------------------------------------------------------===// -// Type Printing -//===----------------------------------------------------------------------===// - -void QualType::dump(const char *msg) const { - std::string R = "identifier"; - LangOptions LO; - getAsStringInternal(R, PrintingPolicy(LO)); - if (msg) - fprintf(stderr, "%s: %s\n", msg, R.c_str()); - else - fprintf(stderr, "%s\n", R.c_str()); -} -void QualType::dump() const { - dump(""); -} - -void Type::dump() const { - std::string S = "identifier"; - LangOptions LO; - getAsStringInternal(S, PrintingPolicy(LO)); - fprintf(stderr, "%s\n", S.c_str()); -} - - - -static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { - if (TypeQuals & Qualifiers::Const) { - if (!S.empty()) S += ' '; - S += "const"; - } - if (TypeQuals & Qualifiers::Volatile) { - if (!S.empty()) S += ' '; - S += "volatile"; - } - if (TypeQuals & Qualifiers::Restrict) { - if (!S.empty()) S += ' '; - S += "restrict"; - } -} - -std::string Qualifiers::getAsString() const { - LangOptions LO; - return getAsString(PrintingPolicy(LO)); -} - -// Appends qualifiers to the given string, separated by spaces. Will -// prefix a space if the string is non-empty. Will not append a final -// space. -void Qualifiers::getAsStringInternal(std::string &S, - const PrintingPolicy&) const { - AppendTypeQualList(S, getCVRQualifiers()); - if (unsigned AddressSpace = getAddressSpace()) { - if (!S.empty()) S += ' '; - S += "__attribute__((address_space("; - S += llvm::utostr_32(AddressSpace); - S += ")))"; - } - if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { - if (!S.empty()) S += ' '; - S += "__attribute__((objc_gc("; - if (GCAttrType == Qualifiers::Weak) - S += "weak"; - else - S += "strong"; - S += ")))"; - } -} - -std::string QualType::getAsString() const { - std::string S; - LangOptions LO; - getAsStringInternal(S, PrintingPolicy(LO)); - return S; -} - -void -QualType::getAsStringInternal(std::string &S, - const PrintingPolicy &Policy) const { - if (isNull()) { - S += "NULL TYPE"; - return; - } - - if (Policy.SuppressSpecifiers && getTypePtr()->isSpecifierType()) - return; - - // Print qualifiers as appropriate. - Qualifiers Quals = getQualifiers(); - if (!Quals.empty()) { - std::string TQS; - Quals.getAsStringInternal(TQS, Policy); - - if (!S.empty()) { - TQS += ' '; - TQS += S; - } - std::swap(S, TQS); - } - - getTypePtr()->getAsStringInternal(S, Policy); -} - -void BuiltinType::getAsStringInternal(std::string &S, - const PrintingPolicy &Policy) const { - if (S.empty()) { - S = getName(Policy.LangOpts); - } else { - // Prefix the basic type, e.g. 'int X'. - S = ' ' + S; - S = getName(Policy.LangOpts) + S; - } -} - -void FixedWidthIntType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - // FIXME: Once we get bitwidth attribute, write as - // "int __attribute__((bitwidth(x)))". - std::string prefix = "__clang_fixedwidth"; - prefix += llvm::utostr_32(Width); - prefix += (char)(Signed ? 'S' : 'U'); - if (S.empty()) { - S = prefix; - } else { - // Prefix the basic type, e.g. 'int X'. - S = prefix + S; - } -} - - -void ComplexType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - ElementType->getAsStringInternal(S, Policy); - S = "_Complex " + S; -} - -void PointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S = '*' + S; - - // Handle things like 'int (*A)[4];' correctly. - // FIXME: this should include vectors, but vectors use attributes I guess. - if (isa<ArrayType>(getPointeeType())) - S = '(' + S + ')'; - - getPointeeType().getAsStringInternal(S, Policy); -} - -void BlockPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S = '^' + S; - PointeeType.getAsStringInternal(S, Policy); -} - -void LValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S = '&' + S; - - // Handle things like 'int (&A)[4];' correctly. - // FIXME: this should include vectors, but vectors use attributes I guess. - if (isa<ArrayType>(getPointeeTypeAsWritten())) - S = '(' + S + ')'; - - getPointeeTypeAsWritten().getAsStringInternal(S, Policy); -} - -void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S = "&&" + S; - - // Handle things like 'int (&&A)[4];' correctly. - // FIXME: this should include vectors, but vectors use attributes I guess. - if (isa<ArrayType>(getPointeeTypeAsWritten())) - S = '(' + S + ')'; - - getPointeeTypeAsWritten().getAsStringInternal(S, Policy); -} - -void MemberPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - std::string C; - Class->getAsStringInternal(C, Policy); - C += "::*"; - S = C + S; - - // Handle things like 'int (Cls::*A)[4];' correctly. - // FIXME: this should include vectors, but vectors use attributes I guess. - if (isa<ArrayType>(getPointeeType())) - S = '(' + S + ')'; - - getPointeeType().getAsStringInternal(S, Policy); -} - -void ConstantArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S += '['; - S += llvm::utostr(getSize().getZExtValue()); - S += ']'; - - getElementType().getAsStringInternal(S, Policy); -} - -void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S += "[]"; - - getElementType().getAsStringInternal(S, Policy); -} - -void VariableArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S += '['; - - if (getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(S, getIndexTypeCVRQualifiers()); - S += ' '; - } - - if (getSizeModifier() == Static) - S += "static"; - else if (getSizeModifier() == Star) - S += '*'; - - if (getSizeExpr()) { - std::string SStr; - llvm::raw_string_ostream s(SStr); - getSizeExpr()->printPretty(s, 0, Policy); - S += s.str(); - } - S += ']'; - - getElementType().getAsStringInternal(S, Policy); -} - -void DependentSizedArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S += '['; - - if (getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(S, getIndexTypeCVRQualifiers()); - S += ' '; - } - - if (getSizeModifier() == Static) - S += "static"; - else if (getSizeModifier() == Star) - S += '*'; - - if (getSizeExpr()) { - std::string SStr; - llvm::raw_string_ostream s(SStr); - getSizeExpr()->printPretty(s, 0, Policy); - S += s.str(); - } - S += ']'; - - getElementType().getAsStringInternal(S, Policy); -} - -void DependentSizedExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - getElementType().getAsStringInternal(S, Policy); - - S += " __attribute__((ext_vector_type("; - if (getSizeExpr()) { - std::string SStr; - llvm::raw_string_ostream s(SStr); - getSizeExpr()->printPretty(s, 0, Policy); - S += s.str(); - } - S += ")))"; -} - -void VectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - // FIXME: We prefer to print the size directly here, but have no way - // to get the size of the type. - S += " __attribute__((__vector_size__("; - S += llvm::utostr_32(NumElements); // convert back to bytes. - S += " * sizeof(" + ElementType.getAsString() + "))))"; - ElementType.getAsStringInternal(S, Policy); -} - -void ExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - S += " __attribute__((ext_vector_type("; - S += llvm::utostr_32(NumElements); - S += ")))"; - ElementType.getAsStringInternal(S, Policy); -} - -void TypeOfExprType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - if (!InnerString.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. - InnerString = ' ' + InnerString; - std::string Str; - llvm::raw_string_ostream s(Str); - getUnderlyingExpr()->printPretty(s, 0, Policy); - InnerString = "typeof " + s.str() + InnerString; -} - -void TypeOfType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - if (!InnerString.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. - InnerString = ' ' + InnerString; - std::string Tmp; - getUnderlyingType().getAsStringInternal(Tmp, Policy); - InnerString = "typeof(" + Tmp + ")" + InnerString; -} - -void DecltypeType::getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const { - if (!InnerString.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. - InnerString = ' ' + InnerString; - std::string Str; - llvm::raw_string_ostream s(Str); - getUnderlyingExpr()->printPretty(s, 0, Policy); - InnerString = "decltype(" + s.str() + ")" + InnerString; -} - -void FunctionNoProtoType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - // If needed for precedence reasons, wrap the inner part in grouping parens. - if (!S.empty()) - S = "(" + S + ")"; - - S += "()"; - if (getNoReturnAttr()) - S += " __attribute__((noreturn))"; - getResultType().getAsStringInternal(S, Policy); -} - -void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { - // If needed for precedence reasons, wrap the inner part in grouping parens. - if (!S.empty()) - S = "(" + S + ")"; - - S += "("; - std::string Tmp; - PrintingPolicy ParamPolicy(Policy); - ParamPolicy.SuppressSpecifiers = false; - for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { - if (i) S += ", "; - getArgType(i).getAsStringInternal(Tmp, ParamPolicy); - S += Tmp; - Tmp.clear(); - } - - if (isVariadic()) { - if (getNumArgs()) - S += ", "; - S += "..."; - } else if (getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { - // Do not emit int() if we have a proto, emit 'int(void)'. - S += "void"; - } - - S += ")"; - if (getNoReturnAttr()) - S += " __attribute__((noreturn))"; - getResultType().getAsStringInternal(S, Policy); -} - - -void TypedefType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. - InnerString = ' ' + InnerString; - InnerString = getDecl()->getIdentifier()->getName().str() + InnerString; -} - -void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - if (!InnerString.empty()) // Prefix the basic type, e.g. 'parmname X'. - InnerString = ' ' + InnerString; - - if (!Name) - InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' + - llvm::utostr_32(Index) + InnerString; - else - InnerString = Name->getName().str() + InnerString; -} - -void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - getReplacementType().getAsStringInternal(InnerString, Policy); -} - -static void PrintTemplateArgument(std::string &Buffer, - const TemplateArgument &Arg, - const PrintingPolicy &Policy) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - assert(false && "Null template argument"); - break; - - case TemplateArgument::Type: - Arg.getAsType().getAsStringInternal(Buffer, Policy); - break; - - case TemplateArgument::Declaration: - Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); - break; - - case TemplateArgument::Integral: - Buffer = Arg.getAsIntegral()->toString(10, true); - break; - - case TemplateArgument::Expression: { - llvm::raw_string_ostream s(Buffer); - Arg.getAsExpr()->printPretty(s, 0, Policy); - break; - } - - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } -} - -std::string -TemplateSpecializationType::PrintTemplateArgumentList( - const TemplateArgument *Args, - unsigned NumArgs, - const PrintingPolicy &Policy) { - std::string SpecString; - SpecString += '<'; - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (Arg) - SpecString += ", "; - - // Print the argument into a string. - std::string ArgString; - PrintTemplateArgument(ArgString, Args[Arg], Policy); - - // If this is the first argument and its string representation - // begins with the global scope specifier ('::foo'), add a space - // to avoid printing the diagraph '<:'. - if (!Arg && !ArgString.empty() && ArgString[0] == ':') - SpecString += ' '; - - SpecString += ArgString; - } - - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. - if (SpecString[SpecString.size() - 1] == '>') - SpecString += ' '; - - SpecString += '>'; - - return SpecString; -} - -// Sadly, repeat all that with TemplateArgLoc. -std::string TemplateSpecializationType:: -PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, - const PrintingPolicy &Policy) { - std::string SpecString; - SpecString += '<'; - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - if (Arg) - SpecString += ", "; - - // Print the argument into a string. - std::string ArgString; - PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); - - // If this is the first argument and its string representation - // begins with the global scope specifier ('::foo'), add a space - // to avoid printing the diagraph '<:'. - if (!Arg && !ArgString.empty() && ArgString[0] == ':') - SpecString += ' '; - - SpecString += ArgString; - } - - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. - if (SpecString[SpecString.size() - 1] == '>') - SpecString += ' '; - - SpecString += '>'; - - return SpecString; -} - -void -TemplateSpecializationType:: -getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - std::string SpecString; - - { - llvm::raw_string_ostream OS(SpecString); - Template.print(OS, Policy); - } - - SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs(), Policy); - if (InnerString.empty()) - InnerString.swap(SpecString); - else - InnerString = SpecString + ' ' + InnerString; -} - -void QualifiedNameType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - std::string MyString; - - { - llvm::raw_string_ostream OS(MyString); - NNS->print(OS, Policy); - } - - std::string TypeStr; - PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTagKind = true; - InnerPolicy.SuppressScope = true; - NamedType.getAsStringInternal(TypeStr, InnerPolicy); - - MyString += TypeStr; - if (InnerString.empty()) - InnerString.swap(MyString); - else - InnerString = MyString + ' ' + InnerString; -} - -void TypenameType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - std::string MyString; - - { - llvm::raw_string_ostream OS(MyString); - OS << "typename "; - NNS->print(OS, Policy); - - if (const IdentifierInfo *Ident = getIdentifier()) - OS << Ident->getName(); - else if (const TemplateSpecializationType *Spec = getTemplateId()) { - Spec->getTemplateName().print(OS, Policy, true); - OS << TemplateSpecializationType::PrintTemplateArgumentList( - Spec->getArgs(), - Spec->getNumArgs(), - Policy); - } - } - - if (InnerString.empty()) - InnerString.swap(MyString); - else - InnerString = MyString + ' ' + InnerString; -} - void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID, const ObjCInterfaceDecl *Decl, ObjCProtocolDecl **protocols, @@ -1455,134 +962,3 @@ void ObjCInterfaceType::Profile(llvm::FoldingSetNodeID &ID) { else Profile(ID, getDecl(), 0, 0); } - -void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const { - if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. - InnerString = ' ' + InnerString; - - std::string ObjCQIString = getDecl()->getNameAsString(); - if (getNumProtocols()) { - ObjCQIString += '<'; - bool isFirst = true; - for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) { - if (isFirst) - isFirst = false; - else - ObjCQIString += ','; - ObjCQIString += (*I)->getNameAsString(); - } - ObjCQIString += '>'; - } - InnerString = ObjCQIString + InnerString; -} - -void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const { - std::string ObjCQIString; - - if (isObjCIdType() || isObjCQualifiedIdType()) - ObjCQIString = "id"; - else if (isObjCClassType() || isObjCQualifiedClassType()) - ObjCQIString = "Class"; - else - ObjCQIString = getInterfaceDecl()->getNameAsString(); - - if (!qual_empty()) { - ObjCQIString += '<'; - for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) { - ObjCQIString += (*I)->getNameAsString(); - if (I+1 != E) - ObjCQIString += ','; - } - ObjCQIString += '>'; - } - - PointeeType.getQualifiers().getAsStringInternal(ObjCQIString, Policy); - - if (!isObjCIdType() && !isObjCQualifiedIdType()) - ObjCQIString += " *"; // Don't forget the implicit pointer. - else if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. - InnerString = ' ' + InnerString; - - InnerString = ObjCQIString + InnerString; -} - -void ElaboratedType::getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const { - std::string TypeStr; - PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTagKind = true; - UnderlyingType.getAsStringInternal(InnerString, InnerPolicy); - - InnerString = std::string(getNameForTagKind(getTagKind())) + ' ' + InnerString; -} - -void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { - if (Policy.SuppressTag) - return; - - if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. - InnerString = ' ' + InnerString; - - const char *Kind = Policy.SuppressTagKind? 0 : getDecl()->getKindName(); - const char *ID; - if (const IdentifierInfo *II = getDecl()->getIdentifier()) - ID = II->getNameStart(); - else if (TypedefDecl *Typedef = getDecl()->getTypedefForAnonDecl()) { - Kind = 0; - assert(Typedef->getIdentifier() && "Typedef without identifier?"); - ID = Typedef->getIdentifier()->getNameStart(); - } else - ID = "<anonymous>"; - - // If this is a class template specialization, print the template - // arguments. - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), - Policy); - InnerString = TemplateArgsStr + InnerString; - } - - if (!Policy.SuppressScope) { - // Compute the full nested-name-specifier for this type. In C, - // this will always be empty. - std::string ContextStr; - for (DeclContext *DC = getDecl()->getDeclContext(); - !DC->isTranslationUnit(); DC = DC->getParent()) { - std::string MyPart; - if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { - if (NS->getIdentifier()) - MyPart = NS->getNameAsString(); - } else if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), - Policy); - MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr; - } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { - if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) - MyPart = Typedef->getIdentifier()->getName(); - else if (Tag->getIdentifier()) - MyPart = Tag->getIdentifier()->getName(); - } - - if (!MyPart.empty()) - ContextStr = MyPart + "::" + ContextStr; - } - - if (Kind) - InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString; - else - InnerString = ContextStr + ID + InnerString; - } else - InnerString = ID + InnerString; -} diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp new file mode 100644 index 0000000000000..a482333782862 --- /dev/null +++ b/lib/AST/TypePrinter.cpp @@ -0,0 +1,728 @@ +//===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code to print types from Clang's type system. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +namespace { + class TypePrinter { + PrintingPolicy Policy; + + public: + explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } + + void Print(QualType T, std::string &S); + void PrintTag(const TagType *T, std::string &S); +#define ABSTRACT_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) \ + void Print##CLASS(const CLASS##Type *T, std::string &S); +#include "clang/AST/TypeNodes.def" + }; +} + +static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { + if (TypeQuals & Qualifiers::Const) { + if (!S.empty()) S += ' '; + S += "const"; + } + if (TypeQuals & Qualifiers::Volatile) { + if (!S.empty()) S += ' '; + S += "volatile"; + } + if (TypeQuals & Qualifiers::Restrict) { + if (!S.empty()) S += ' '; + S += "restrict"; + } +} + +void TypePrinter::Print(QualType T, std::string &S) { + if (T.isNull()) { + S += "NULL TYPE"; + return; + } + + if (Policy.SuppressSpecifiers && T->isSpecifierType()) + return; + + // Print qualifiers as appropriate. + Qualifiers Quals = T.getLocalQualifiers(); + if (!Quals.empty()) { + std::string TQS; + Quals.getAsStringInternal(TQS, Policy); + + if (!S.empty()) { + TQS += ' '; + TQS += S; + } + std::swap(S, TQS); + } + + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) case Type::CLASS: \ + Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \ + break; +#include "clang/AST/TypeNodes.def" + } +} + +void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) { + if (S.empty()) { + S = T->getName(Policy.LangOpts); + } else { + // Prefix the basic type, e.g. 'int X'. + S = ' ' + S; + S = T->getName(Policy.LangOpts) + S; + } +} + +void TypePrinter::PrintFixedWidthInt(const FixedWidthIntType *T, + std::string &S) { + // FIXME: Once we get bitwidth attribute, write as + // "int __attribute__((bitwidth(x)))". + std::string prefix = "__clang_fixedwidth"; + prefix += llvm::utostr_32(T->getWidth()); + prefix += (char)(T->isSigned() ? 'S' : 'U'); + if (S.empty()) { + S = prefix; + } else { + // Prefix the basic type, e.g. 'int X'. + S = prefix + S; + } +} + +void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) { + Print(T->getElementType(), S); + S = "_Complex " + S; +} + +void TypePrinter::PrintPointer(const PointerType *T, std::string &S) { + S = '*' + S; + + // Handle things like 'int (*A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeType())) + S = '(' + S + ')'; + + Print(T->getPointeeType(), S); +} + +void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) { + S = '^' + S; + Print(T->getPointeeType(), S); +} + +void TypePrinter::PrintLValueReference(const LValueReferenceType *T, + std::string &S) { + S = '&' + S; + + // Handle things like 'int (&A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeTypeAsWritten())) + S = '(' + S + ')'; + + Print(T->getPointeeTypeAsWritten(), S); +} + +void TypePrinter::PrintRValueReference(const RValueReferenceType *T, + std::string &S) { + S = "&&" + S; + + // Handle things like 'int (&&A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeTypeAsWritten())) + S = '(' + S + ')'; + + Print(T->getPointeeTypeAsWritten(), S); +} + +void TypePrinter::PrintMemberPointer(const MemberPointerType *T, + std::string &S) { + std::string C; + Print(QualType(T->getClass(), 0), C); + C += "::*"; + S = C + S; + + // Handle things like 'int (Cls::*A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeType())) + S = '(' + S + ')'; + + Print(T->getPointeeType(), S); +} + +void TypePrinter::PrintConstantArray(const ConstantArrayType *T, + std::string &S) { + S += '['; + S += llvm::utostr(T->getSize().getZExtValue()); + S += ']'; + + Print(T->getElementType(), S); +} + +void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T, + std::string &S) { + S += "[]"; + Print(T->getElementType(), S); +} + +void TypePrinter::PrintVariableArray(const VariableArrayType *T, + std::string &S) { + S += '['; + + if (T->getIndexTypeQualifiers().hasQualifiers()) { + AppendTypeQualList(S, T->getIndexTypeCVRQualifiers()); + S += ' '; + } + + if (T->getSizeModifier() == VariableArrayType::Static) + S += "static"; + else if (T->getSizeModifier() == VariableArrayType::Star) + S += '*'; + + if (T->getSizeExpr()) { + std::string SStr; + llvm::raw_string_ostream s(SStr); + T->getSizeExpr()->printPretty(s, 0, Policy); + S += s.str(); + } + S += ']'; + + Print(T->getElementType(), S); +} + +void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T, + std::string &S) { + S += '['; + + if (T->getSizeExpr()) { + std::string SStr; + llvm::raw_string_ostream s(SStr); + T->getSizeExpr()->printPretty(s, 0, Policy); + S += s.str(); + } + S += ']'; + + Print(T->getElementType(), S); +} + +void TypePrinter::PrintDependentSizedExtVector( + const DependentSizedExtVectorType *T, + std::string &S) { + Print(T->getElementType(), S); + + S += " __attribute__((ext_vector_type("; + if (T->getSizeExpr()) { + std::string SStr; + llvm::raw_string_ostream s(SStr); + T->getSizeExpr()->printPretty(s, 0, Policy); + S += s.str(); + } + S += ")))"; +} + +void TypePrinter::PrintVector(const VectorType *T, std::string &S) { + // FIXME: We prefer to print the size directly here, but have no way + // to get the size of the type. + S += " __attribute__((__vector_size__("; + S += llvm::utostr_32(T->getNumElements()); // convert back to bytes. + std::string ET; + Print(T->getElementType(), ET); + S += " * sizeof(" + ET + "))))"; + Print(T->getElementType(), S); +} + +void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { + S += " __attribute__((ext_vector_type("; + S += llvm::utostr_32(T->getNumElements()); + S += ")))"; + Print(T->getElementType(), S); +} + +void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, + std::string &S) { + // If needed for precedence reasons, wrap the inner part in grouping parens. + if (!S.empty()) + S = "(" + S + ")"; + + S += "("; + std::string Tmp; + PrintingPolicy ParamPolicy(Policy); + ParamPolicy.SuppressSpecifiers = false; + for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { + if (i) S += ", "; + Print(T->getArgType(i), Tmp); + S += Tmp; + Tmp.clear(); + } + + if (T->isVariadic()) { + if (T->getNumArgs()) + S += ", "; + S += "..."; + } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { + // Do not emit int() if we have a proto, emit 'int(void)'. + S += "void"; + } + + S += ")"; + if (T->getNoReturnAttr()) + S += " __attribute__((noreturn))"; + Print(T->getResultType(), S); + +} + +void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, + std::string &S) { + // If needed for precedence reasons, wrap the inner part in grouping parens. + if (!S.empty()) + S = "(" + S + ")"; + + S += "()"; + if (T->getNoReturnAttr()) + S += " __attribute__((noreturn))"; + Print(T->getResultType(), S); +} + +void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { + if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. + S = ' ' + S; + S = T->getDecl()->getIdentifier()->getName().str() + S; +} + +void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { + if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. + S = ' ' + S; + std::string Str; + llvm::raw_string_ostream s(Str); + T->getUnderlyingExpr()->printPretty(s, 0, Policy); + S = "typeof " + s.str() + S; +} + +void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) { + if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. + S = ' ' + S; + std::string Tmp; + Print(T->getUnderlyingType(), Tmp); + S = "typeof(" + Tmp + ")" + S; +} + +void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { + if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. + S = ' ' + S; + std::string Str; + llvm::raw_string_ostream s(Str); + T->getUnderlyingExpr()->printPretty(s, 0, Policy); + S = "decltype(" + s.str() + ")" + S; +} + +void TypePrinter::PrintTag(const TagType *T, std::string &InnerString) { + if (Policy.SuppressTag) + return; + + if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. + InnerString = ' ' + InnerString; + + const char *Kind = Policy.SuppressTagKind? 0 : T->getDecl()->getKindName(); + const char *ID; + if (const IdentifierInfo *II = T->getDecl()->getIdentifier()) + ID = II->getNameStart(); + else if (TypedefDecl *Typedef = T->getDecl()->getTypedefForAnonDecl()) { + Kind = 0; + assert(Typedef->getIdentifier() && "Typedef without identifier?"); + ID = Typedef->getIdentifier()->getNameStart(); + } else + ID = "<anonymous>"; + + // If this is a class template specialization, print the template + // arguments. + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + TemplateArgs.getFlatArgumentList(), + TemplateArgs.flat_size(), + Policy); + InnerString = TemplateArgsStr + InnerString; + } + + if (!Policy.SuppressScope) { + // Compute the full nested-name-specifier for this type. In C, + // this will always be empty. + std::string ContextStr; + for (DeclContext *DC = T->getDecl()->getDeclContext(); + !DC->isTranslationUnit(); DC = DC->getParent()) { + std::string MyPart; + if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { + if (NS->getIdentifier()) + MyPart = NS->getNameAsString(); + } else if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + TemplateArgs.getFlatArgumentList(), + TemplateArgs.flat_size(), + Policy); + MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr; + } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { + if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) + MyPart = Typedef->getIdentifier()->getName(); + else if (Tag->getIdentifier()) + MyPart = Tag->getIdentifier()->getName(); + } + + if (!MyPart.empty()) + ContextStr = MyPart + "::" + ContextStr; + } + + if (Kind) + InnerString = std::string(Kind) + ' ' + ContextStr + ID + InnerString; + else + InnerString = ContextStr + ID + InnerString; + } else + InnerString = ID + InnerString; +} + +void TypePrinter::PrintRecord(const RecordType *T, std::string &S) { + PrintTag(T, S); +} + +void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { + PrintTag(T, S); +} + +void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { + std::string TypeStr; + PrintingPolicy InnerPolicy(Policy); + InnerPolicy.SuppressTagKind = true; + TypePrinter(InnerPolicy).Print(T->getUnderlyingType(), S); + + S = std::string(T->getNameForTagKind(T->getTagKind())) + ' ' + S; +} + +void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, + std::string &S) { + if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. + S = ' ' + S; + + if (!T->getName()) + S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' + + llvm::utostr_32(T->getIndex()) + S; + else + S = T->getName()->getName().str() + S; +} + +void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, + std::string &S) { + Print(T->getReplacementType(), S); +} + +void TypePrinter::PrintTemplateSpecialization( + const TemplateSpecializationType *T, + std::string &S) { + std::string SpecString; + + { + llvm::raw_string_ostream OS(SpecString); + T->getTemplateName().print(OS, Policy); + } + + SpecString += TemplateSpecializationType::PrintTemplateArgumentList( + T->getArgs(), + T->getNumArgs(), + Policy); + if (S.empty()) + S.swap(SpecString); + else + S = SpecString + ' ' + S; +} + +void TypePrinter::PrintQualifiedName(const QualifiedNameType *T, + std::string &S) { + std::string MyString; + + { + llvm::raw_string_ostream OS(MyString); + T->getQualifier()->print(OS, Policy); + } + + std::string TypeStr; + PrintingPolicy InnerPolicy(Policy); + InnerPolicy.SuppressTagKind = true; + InnerPolicy.SuppressScope = true; + TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); + + MyString += TypeStr; + if (S.empty()) + S.swap(MyString); + else + S = MyString + ' ' + S; +} + +void TypePrinter::PrintTypename(const TypenameType *T, std::string &S) { + std::string MyString; + + { + llvm::raw_string_ostream OS(MyString); + OS << "typename "; + T->getQualifier()->print(OS, Policy); + + if (const IdentifierInfo *Ident = T->getIdentifier()) + OS << Ident->getName(); + else if (const TemplateSpecializationType *Spec = T->getTemplateId()) { + Spec->getTemplateName().print(OS, Policy, true); + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Spec->getArgs(), + Spec->getNumArgs(), + Policy); + } + } + + if (S.empty()) + S.swap(MyString); + else + S = MyString + ' ' + S; +} + +void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, + std::string &S) { + if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. + S = ' ' + S; + + std::string ObjCQIString = T->getDecl()->getNameAsString(); + if (T->getNumProtocols()) { + ObjCQIString += '<'; + bool isFirst = true; + for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), + E = T->qual_end(); + I != E; ++I) { + if (isFirst) + isFirst = false; + else + ObjCQIString += ','; + ObjCQIString += (*I)->getNameAsString(); + } + ObjCQIString += '>'; + } + S = ObjCQIString + S; +} + +void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, + std::string &S) { + std::string ObjCQIString; + + if (T->isObjCIdType() || T->isObjCQualifiedIdType()) + ObjCQIString = "id"; + else if (T->isObjCClassType() || T->isObjCQualifiedClassType()) + ObjCQIString = "Class"; + else + ObjCQIString = T->getInterfaceDecl()->getNameAsString(); + + if (!T->qual_empty()) { + ObjCQIString += '<'; + for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(), + E = T->qual_end(); + I != E; ++I) { + ObjCQIString += (*I)->getNameAsString(); + if (I+1 != E) + ObjCQIString += ','; + } + ObjCQIString += '>'; + } + + T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString, + Policy); + + if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) + ObjCQIString += " *"; // Don't forget the implicit pointer. + else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. + S = ' ' + S; + + S = ObjCQIString + S; +} + +static void PrintTemplateArgument(std::string &Buffer, + const TemplateArgument &Arg, + const PrintingPolicy &Policy) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + assert(false && "Null template argument"); + break; + + case TemplateArgument::Type: + Arg.getAsType().getAsStringInternal(Buffer, Policy); + break; + + case TemplateArgument::Declaration: + Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString(); + break; + + case TemplateArgument::Template: { + llvm::raw_string_ostream s(Buffer); + Arg.getAsTemplate().print(s, Policy); + break; + } + + case TemplateArgument::Integral: + Buffer = Arg.getAsIntegral()->toString(10, true); + break; + + case TemplateArgument::Expression: { + llvm::raw_string_ostream s(Buffer); + Arg.getAsExpr()->printPretty(s, 0, Policy); + break; + } + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; + } +} + +std::string +TemplateSpecializationType::PrintTemplateArgumentList( + const TemplateArgument *Args, + unsigned NumArgs, + const PrintingPolicy &Policy) { + std::string SpecString; + SpecString += '<'; + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + if (Arg) + SpecString += ", "; + + // Print the argument into a string. + std::string ArgString; + PrintTemplateArgument(ArgString, Args[Arg], Policy); + + // If this is the first argument and its string representation + // begins with the global scope specifier ('::foo'), add a space + // to avoid printing the diagraph '<:'. + if (!Arg && !ArgString.empty() && ArgString[0] == ':') + SpecString += ' '; + + SpecString += ArgString; + } + + // If the last character of our string is '>', add another space to + // keep the two '>''s separate tokens. We don't *have* to do this in + // C++0x, but it's still good hygiene. + if (SpecString[SpecString.size() - 1] == '>') + SpecString += ' '; + + SpecString += '>'; + + return SpecString; +} + +// Sadly, repeat all that with TemplateArgLoc. +std::string TemplateSpecializationType:: +PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, + const PrintingPolicy &Policy) { + std::string SpecString; + SpecString += '<'; + for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { + if (Arg) + SpecString += ", "; + + // Print the argument into a string. + std::string ArgString; + PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); + + // If this is the first argument and its string representation + // begins with the global scope specifier ('::foo'), add a space + // to avoid printing the diagraph '<:'. + if (!Arg && !ArgString.empty() && ArgString[0] == ':') + SpecString += ' '; + + SpecString += ArgString; + } + + // If the last character of our string is '>', add another space to + // keep the two '>''s separate tokens. We don't *have* to do this in + // C++0x, but it's still good hygiene. + if (SpecString[SpecString.size() - 1] == '>') + SpecString += ' '; + + SpecString += '>'; + + return SpecString; +} + +void QualType::dump(const char *msg) const { + std::string R = "identifier"; + LangOptions LO; + getAsStringInternal(R, PrintingPolicy(LO)); + if (msg) + fprintf(stderr, "%s: %s\n", msg, R.c_str()); + else + fprintf(stderr, "%s\n", R.c_str()); +} +void QualType::dump() const { + dump(""); +} + +void Type::dump() const { + QualType(this, 0).dump(); +} + +std::string Qualifiers::getAsString() const { + LangOptions LO; + return getAsString(PrintingPolicy(LO)); +} + +// Appends qualifiers to the given string, separated by spaces. Will +// prefix a space if the string is non-empty. Will not append a final +// space. +void Qualifiers::getAsStringInternal(std::string &S, + const PrintingPolicy&) const { + AppendTypeQualList(S, getCVRQualifiers()); + if (unsigned AddressSpace = getAddressSpace()) { + if (!S.empty()) S += ' '; + S += "__attribute__((address_space("; + S += llvm::utostr_32(AddressSpace); + S += ")))"; + } + if (Qualifiers::GC GCAttrType = getObjCGCAttr()) { + if (!S.empty()) S += ' '; + S += "__attribute__((objc_gc("; + if (GCAttrType == Qualifiers::Weak) + S += "weak"; + else + S += "strong"; + S += ")))"; + } +} + +std::string QualType::getAsString() const { + std::string S; + LangOptions LO; + getAsStringInternal(S, PrintingPolicy(LO)); + return S; +} + +void QualType::getAsStringInternal(std::string &S, + const PrintingPolicy &Policy) const { + TypePrinter Printer(Policy); + Printer.Print(*this, S); +} + |