This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

1
thirdparty/clang/copy.bat vendored Normal file
View File

@@ -0,0 +1 @@
python copy_includes\copy_includes.py

View File

@@ -0,0 +1,72 @@
import glob, sys, os, stat, shutil
g_nFilesCopied = 0
g_nFilesAdded = 0
g_nFilesSkipped = 0
def IsSame( a, b ):
return False
if a.st_size == b.st_size:
if a.st_mtime == b.st_mtime:
return True #perhaps we need to actually compare the files??
if abs( a.st_mtime - b.st_mtime ) < 1: # may not be runnable on all platforms, but runs fine on windows python 2.6+
return True
else:
return False
def Copy(fromDir, toDir, extensions):
global g_nFilesCopied
global g_nFilesAdded
global g_nFilesSkipped
if( toDir == "" ):
toDir = os.getcwd()
toDir = os.path.abspath( toDir )
fromDir = os.path.abspath( fromDir )
for root, subFolders, files in os.walk(fromDir):
for file in files:
if os.path.splitext(file)[1][1:].strip() in extensions and root[:len(fromDir)]==fromDir:
fromFile = os.path.join(root, file)
fromFileStat = os.stat( fromFile )
toFile = os.path.join(toDir,root[len(fromDir)+1:],file)
p4AddNeeded = True
if( os.path.isfile( toFile ) ): #file exists already, if it's the same file, there's no need to copy anything
p4AddNeeded = False
toFileStat = os.stat( toFile )
if( IsSame( toFileStat, fromFileStat ) ):
g_nFilesSkipped += 1
continue
if not( toFileStat.st_mode & stat.S_IWRITE ):
os.system( "p4 edit " + toFile )
if os.path.exists( os.path.dirname( toFile ) ):
if not os.path.isdir( os.path.dirname( toFile ) ):
print "This is not a dir. Expected a dir: " + os.path.dirname( toFile )
sys.exit(-1)
else:
os.makedirs( os.path.dirname( toFile ) )
#print fromFile + " -> " + toFile
shutil.copyfile( fromFile, toFile )
os.utime( toFile, ( fromFileStat.st_atime, fromFileStat.st_mtime ) )
if p4AddNeeded:
g_nFilesAdded += 1
os.system( "p4 add " + toFile )
g_nFilesCopied += 1
extInc = ["h","inc","inl","gen","def"]
extLib = ["lib","pdb","def"]
Copy( "f:/L/llvm.build64/tools/clang/include", "include/win64", extInc )
Copy( "f:/L/llvm.build64/include", "include/win64", extInc )
Copy( "f:/L/llvm.build/tools/clang/include", "include/win32", extInc )
Copy( "f:/L/llvm.build/include", "include/win32", extInc )
Copy( "f:/L/llvm/include", "include", extInc )
Copy( "f:/L/llvm/tools/clang/include", "include", extInc )
Copy( "f:/L/llvm.build64/lib/Debug", "lib/win64/Debug", extLib )
Copy( "f:/L/llvm.build64/lib/RelWithDebInfo", "lib/win64/Release", extLib )
Copy( "f:/L/llvm.build/lib/Debug", "lib/win32/Debug", extLib )
Copy( "f:/L/llvm.build/lib/RelWithDebInfo", "lib/win32/Release", extLib )
print "Files copied: %d, added: %d, skipped: %d" % ( g_nFilesCopied, g_nFilesAdded, g_nFilesSkipped )

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{715c6bff-399a-41b5-9ad8-14d4414cd5b6}</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>copy_includes.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>..</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>copy_includes</Name>
<RootNamespace>copy_includes</RootNamespace>
<IsWindowsApplication>False</IsWindowsApplication>
<InterpreterId>2af0f10d-7135-4994-9156-5d01c9c11b7e</InterpreterId>
<InterpreterVersion>2.6</InterpreterVersion>
<LaunchProvider>Standard Python launcher</LaunchProvider>
<CommandLineArguments>
</CommandLineArguments>
<InterpreterPath />
<InterpreterArguments />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="copy_includes.py" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
</Project>

View File

@@ -0,0 +1,995 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|*Attribute dumper *|
|* *|
|* Automatically generated file, do not edit! *|
|* *|
\*===----------------------------------------------------------------------===*/
switch (A->getKind()) {
default:
llvm_unreachable("Unknown attribute kind!");
break;
case attr::AcquiredAfter: {
const AcquiredAfterAttr *SA = cast<AcquiredAfterAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (AcquiredAfterAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::AcquiredBefore: {
const AcquiredBeforeAttr *SA = cast<AcquiredBeforeAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (AcquiredBeforeAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::Alias: {
const AliasAttr *SA = cast<AliasAttr>(A);
OS << " \"" << SA->getAliasee() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::AlignMac68k: {
break;
}
case attr::Aligned: {
const AlignedAttr *SA = cast<AlignedAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
if (SA->isAlignmentExpr()) {
lastChild();
dumpStmt(SA->getAlignmentExpr());
} else
dumpType(SA->getAlignmentType()->getType());
setMoreChildren(OldMoreChildren);
break;
}
case attr::AllocSize: {
const AllocSizeAttr *SA = cast<AllocSizeAttr>(A);
for (AllocSizeAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
OS << " " << *I;
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::AlwaysInline: {
break;
}
case attr::AnalyzerNoReturn: {
break;
}
case attr::Annotate: {
const AnnotateAttr *SA = cast<AnnotateAttr>(A);
OS << " \"" << SA->getAnnotation() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ArcWeakrefUnavailable: {
break;
}
case attr::ArgumentWithTypeTag: {
const ArgumentWithTypeTagAttr *SA = cast<ArgumentWithTypeTagAttr>(A);
OS << " " << SA->getArgumentKind()->getName();
OS << " " << SA->getArgumentIdx();
OS << " " << SA->getTypeTagIdx();
if (SA->getIsPointer()) OS << " IsPointer";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::AsmLabel: {
const AsmLabelAttr *SA = cast<AsmLabelAttr>(A);
OS << " \"" << SA->getLabel() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Availability: {
const AvailabilityAttr *SA = cast<AvailabilityAttr>(A);
OS << " " << SA->getPlatform()->getName();
OS << " " << SA->getIntroduced();
OS << " " << SA->getDeprecated();
OS << " " << SA->getObsoleted();
if (SA->getUnavailable()) OS << " Unavailable";
OS << " \"" << SA->getMessage() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false || false || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false || false || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Blocks: {
const BlocksAttr *SA = cast<BlocksAttr>(A);
switch(SA->getType()) {
case BlocksAttr::ByRef:
OS << " ByRef";
break;
}
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::C11NoReturn: {
break;
}
case attr::CDecl: {
break;
}
case attr::CFAuditedTransfer: {
break;
}
case attr::CFConsumed: {
break;
}
case attr::CFReturnsNotRetained: {
break;
}
case attr::CFReturnsRetained: {
break;
}
case attr::CFUnknownTransfer: {
break;
}
case attr::CUDAConstant: {
break;
}
case attr::CUDADevice: {
break;
}
case attr::CUDAGlobal: {
break;
}
case attr::CUDAHost: {
break;
}
case attr::CUDALaunchBounds: {
const CUDALaunchBoundsAttr *SA = cast<CUDALaunchBoundsAttr>(A);
OS << " " << SA->getMaxThreads();
OS << " " << SA->getMinBlocks();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::CUDAShared: {
break;
}
case attr::CXX11NoReturn: {
break;
}
case attr::CarriesDependency: {
break;
}
case attr::Cleanup: {
const CleanupAttr *SA = cast<CleanupAttr>(A);
OS << " ";
dumpBareDeclRef(SA->getFunctionDecl());
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Cold: {
break;
}
case attr::Common: {
break;
}
case attr::Const: {
break;
}
case attr::Constructor: {
const ConstructorAttr *SA = cast<ConstructorAttr>(A);
OS << " " << SA->getPriority();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::DLLExport: {
break;
}
case attr::DLLImport: {
break;
}
case attr::Deprecated: {
const DeprecatedAttr *SA = cast<DeprecatedAttr>(A);
OS << " \"" << SA->getMessage() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Destructor: {
const DestructorAttr *SA = cast<DestructorAttr>(A);
OS << " " << SA->getPriority();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Endian: {
const EndianAttr *SA = cast<EndianAttr>(A);
OS << " " << SA->getPlatform()->getName();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ExclusiveLockFunction: {
const ExclusiveLockFunctionAttr *SA = cast<ExclusiveLockFunctionAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (ExclusiveLockFunctionAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::ExclusiveLocksRequired: {
const ExclusiveLocksRequiredAttr *SA = cast<ExclusiveLocksRequiredAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (ExclusiveLocksRequiredAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::ExclusiveTrylockFunction: {
const ExclusiveTrylockFunctionAttr *SA = cast<ExclusiveTrylockFunctionAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || SA->args_begin() != SA->args_end();
setMoreChildren(MoreChildren);
lastChild();
dumpStmt(SA->getSuccessValue());
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (ExclusiveTrylockFunctionAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::FallThrough: {
break;
}
case attr::FastCall: {
break;
}
case attr::Final: {
break;
}
case attr::ForceInline: {
break;
}
case attr::Format: {
const FormatAttr *SA = cast<FormatAttr>(A);
OS << " \"" << SA->getType() << "\"";
OS << " " << SA->getFormatIdx();
OS << " " << SA->getFirstArg();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::FormatArg: {
const FormatArgAttr *SA = cast<FormatArgAttr>(A);
OS << " " << SA->getFormatIdx();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::GNUInline: {
break;
}
case attr::GuardedBy: {
const GuardedByAttr *SA = cast<GuardedByAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
lastChild();
dumpStmt(SA->getArg());
setMoreChildren(OldMoreChildren);
break;
}
case attr::GuardedVar: {
break;
}
case attr::Hot: {
break;
}
case attr::IBAction: {
break;
}
case attr::IBOutlet: {
break;
}
case attr::IBOutletCollection: {
const IBOutletCollectionAttr *SA = cast<IBOutletCollectionAttr>(A);
OS << " " << SA->getInterface().getAsString();
OS << " ";
SA->getInterfaceLoc().print(OS, *SM);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::InitPriority: {
const InitPriorityAttr *SA = cast<InitPriorityAttr>(A);
OS << " " << SA->getPriority();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::IntelOclBicc: {
break;
}
case attr::LockReturned: {
const LockReturnedAttr *SA = cast<LockReturnedAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
lastChild();
dumpStmt(SA->getArg());
setMoreChildren(OldMoreChildren);
break;
}
case attr::Lockable: {
break;
}
case attr::LocksExcluded: {
const LocksExcludedAttr *SA = cast<LocksExcludedAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (LocksExcludedAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::MBlazeInterruptHandler: {
break;
}
case attr::MBlazeSaveVolatiles: {
break;
}
case attr::MSP430Interrupt: {
const MSP430InterruptAttr *SA = cast<MSP430InterruptAttr>(A);
OS << " " << SA->getNumber();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Malloc: {
break;
}
case attr::MaxFieldAlignment: {
const MaxFieldAlignmentAttr *SA = cast<MaxFieldAlignmentAttr>(A);
OS << " " << SA->getAlignment();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::MayAlias: {
break;
}
case attr::MinSize: {
break;
}
case attr::Mips16: {
break;
}
case attr::MsProperty: {
break;
}
case attr::MsStruct: {
break;
}
case attr::MultipleInheritance: {
break;
}
case attr::NSBridged: {
const NSBridgedAttr *SA = cast<NSBridgedAttr>(A);
OS << " " << SA->getBridgedType()->getName();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::NSConsumed: {
break;
}
case attr::NSConsumesSelf: {
break;
}
case attr::NSReturnsAutoreleased: {
break;
}
case attr::NSReturnsNotRetained: {
break;
}
case attr::NSReturnsRetained: {
break;
}
case attr::Naked: {
break;
}
case attr::NoCommon: {
break;
}
case attr::NoDebug: {
break;
}
case attr::NoInline: {
break;
}
case attr::NoInstrumentFunction: {
break;
}
case attr::NoMips16: {
break;
}
case attr::NoReturn: {
break;
}
case attr::NoSanitizeAddress: {
break;
}
case attr::NoSanitizeMemory: {
break;
}
case attr::NoSanitizeThread: {
break;
}
case attr::NoThreadSafetyAnalysis: {
break;
}
case attr::NoThrow: {
break;
}
case attr::NonNull: {
const NonNullAttr *SA = cast<NonNullAttr>(A);
for (NonNullAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
OS << " " << *I;
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ObjCException: {
break;
}
case attr::ObjCMethodFamily: {
const ObjCMethodFamilyAttr *SA = cast<ObjCMethodFamilyAttr>(A);
switch(SA->getFamily()) {
case ObjCMethodFamilyAttr::OMF_None:
OS << " OMF_None";
break;
case ObjCMethodFamilyAttr::OMF_alloc:
OS << " OMF_alloc";
break;
case ObjCMethodFamilyAttr::OMF_copy:
OS << " OMF_copy";
break;
case ObjCMethodFamilyAttr::OMF_init:
OS << " OMF_init";
break;
case ObjCMethodFamilyAttr::OMF_mutableCopy:
OS << " OMF_mutableCopy";
break;
case ObjCMethodFamilyAttr::OMF_new:
OS << " OMF_new";
break;
}
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ObjCNSObject: {
break;
}
case attr::ObjCPreciseLifetime: {
break;
}
case attr::ObjCRequiresPropertyDefs: {
break;
}
case attr::ObjCRequiresSuper: {
break;
}
case attr::ObjCReturnsInnerPointer: {
break;
}
case attr::ObjCRootClass: {
break;
}
case attr::OpenCLImageAccess: {
const OpenCLImageAccessAttr *SA = cast<OpenCLImageAccessAttr>(A);
OS << " " << SA->getAccess();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::OpenCLKernel: {
break;
}
case attr::Overloadable: {
break;
}
case attr::Override: {
break;
}
case attr::Ownership: {
const OwnershipAttr *SA = cast<OwnershipAttr>(A);
switch(SA->getOwnKind()) {
case OwnershipAttr::Holds:
OS << " Holds";
break;
case OwnershipAttr::Returns:
OS << " Returns";
break;
case OwnershipAttr::Takes:
OS << " Takes";
break;
}
OS << " \"" << SA->getModule() << "\"";
for (OwnershipAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
OS << " " << *I;
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Packed: {
break;
}
case attr::Pascal: {
break;
}
case attr::Pcs: {
const PcsAttr *SA = cast<PcsAttr>(A);
switch(SA->getPCS()) {
case PcsAttr::AAPCS:
OS << " AAPCS";
break;
case PcsAttr::AAPCS_VFP:
OS << " AAPCS_VFP";
break;
}
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::PnaclCall: {
break;
}
case attr::PtGuardedBy: {
const PtGuardedByAttr *SA = cast<PtGuardedByAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
lastChild();
dumpStmt(SA->getArg());
setMoreChildren(OldMoreChildren);
break;
}
case attr::PtGuardedVar: {
break;
}
case attr::Ptr32: {
break;
}
case attr::Ptr64: {
break;
}
case attr::Pure: {
break;
}
case attr::Regparm: {
const RegparmAttr *SA = cast<RegparmAttr>(A);
OS << " " << SA->getNumParams();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ReqdWorkGroupSize: {
const ReqdWorkGroupSizeAttr *SA = cast<ReqdWorkGroupSizeAttr>(A);
OS << " " << SA->getXDim();
OS << " " << SA->getYDim();
OS << " " << SA->getZDim();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ReturnsTwice: {
break;
}
case attr::ScopedLockable: {
break;
}
case attr::Section: {
const SectionAttr *SA = cast<SectionAttr>(A);
OS << " \"" << SA->getName() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Sentinel: {
const SentinelAttr *SA = cast<SentinelAttr>(A);
OS << " " << SA->getSentinel();
OS << " " << SA->getNullPos();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::SharedLockFunction: {
const SharedLockFunctionAttr *SA = cast<SharedLockFunctionAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (SharedLockFunctionAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::SharedLocksRequired: {
const SharedLocksRequiredAttr *SA = cast<SharedLocksRequiredAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (SharedLocksRequiredAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::SharedTrylockFunction: {
const SharedTrylockFunctionAttr *SA = cast<SharedTrylockFunctionAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || SA->args_begin() != SA->args_end();
setMoreChildren(MoreChildren);
lastChild();
dumpStmt(SA->getSuccessValue());
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (SharedTrylockFunctionAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::SingleInheritance: {
break;
}
case attr::StdCall: {
break;
}
case attr::TLSModel: {
const TLSModelAttr *SA = cast<TLSModelAttr>(A);
OS << " \"" << SA->getModel() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::ThisCall: {
break;
}
case attr::TransparentUnion: {
break;
}
case attr::TypeTagForDatatype: {
const TypeTagForDatatypeAttr *SA = cast<TypeTagForDatatypeAttr>(A);
OS << " " << SA->getArgumentKind()->getName();
OS << " " << SA->getMatchingCType().getAsString();
if (SA->getLayoutCompatible()) OS << " LayoutCompatible";
if (SA->getMustBeNull()) OS << " MustBeNull";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::TypeVisibility: {
const TypeVisibilityAttr *SA = cast<TypeVisibilityAttr>(A);
switch(SA->getVisibility()) {
case TypeVisibilityAttr::Default:
OS << " Default";
break;
case TypeVisibilityAttr::Hidden:
OS << " Hidden";
break;
case TypeVisibilityAttr::Protected:
OS << " Protected";
break;
}
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::Unavailable: {
const UnavailableAttr *SA = cast<UnavailableAttr>(A);
OS << " \"" << SA->getMessage() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::UnlockFunction: {
const UnlockFunctionAttr *SA = cast<UnlockFunctionAttr>(A);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
for (UnlockFunctionAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I) {
if (I + 1 == E)
lastChild();
dumpStmt(*I);
}
setMoreChildren(OldMoreChildren);
break;
}
case attr::UnspecifiedInheritance: {
break;
}
case attr::Unused: {
break;
}
case attr::Used: {
break;
}
case attr::Uuid: {
const UuidAttr *SA = cast<UuidAttr>(A);
OS << " \"" << SA->getGuid() << "\"";
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::VecReturn: {
break;
}
case attr::VecTypeHint: {
const VecTypeHintAttr *SA = cast<VecTypeHintAttr>(A);
OS << " " << SA->getTypeHint().getAsString();
OS << " ";
SA->getTypeLoc().print(OS, *SM);
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::VirtualInheritance: {
break;
}
case attr::Visibility: {
const VisibilityAttr *SA = cast<VisibilityAttr>(A);
switch(SA->getVisibility()) {
case VisibilityAttr::Default:
OS << " Default";
break;
case VisibilityAttr::Hidden:
OS << " Hidden";
break;
case VisibilityAttr::Protected:
OS << " Protected";
break;
}
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::WarnUnusedResult: {
break;
}
case attr::Weak: {
break;
}
case attr::WeakImport: {
break;
}
case attr::WeakRef: {
break;
}
case attr::Win64: {
break;
}
case attr::WorkGroupSizeHint: {
const WorkGroupSizeHintAttr *SA = cast<WorkGroupSizeHintAttr>(A);
OS << " " << SA->getXDim();
OS << " " << SA->getYDim();
OS << " " << SA->getZDim();
bool OldMoreChildren = hasMoreChildren();
bool MoreChildren = OldMoreChildren;
MoreChildren = OldMoreChildren || false || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren || false;
setMoreChildren(MoreChildren);
MoreChildren = OldMoreChildren;
setMoreChildren(MoreChildren);
setMoreChildren(OldMoreChildren);
break;
}
case attr::X86ForceAlignArgPointer: {
break;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,730 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|*A list of commands useable in documentation comments *|
|* *|
|* Automatically generated file, do not edit! *|
|* *|
\*===----------------------------------------------------------------------===*/
namespace {
const CommandInfo Commands[] = {
{ "a", "", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "abstract", "", 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "addtogroup", "", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "arg", "", 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "attention", "", 4, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "author", "", 5, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "authors", "", 6, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "b", "", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "brief", "", 8, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "bug", "", 9, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "c", "", 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "callback", "", 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 },
{ "category", "", 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "class", "", 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 },
{ "classdesign", "", 14, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "coclass", "", 15, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "code", "endcode", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endcode", "", 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "const", "", 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "constant", "", 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "copyright", "", 20, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "date", "", 21, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "defgroup", "", 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "dependency", "", 23, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "deprecated", "", 24, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "details", "", 25, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "discussion", "", 26, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "dot", "enddot", 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "enddot", "", 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "e", "", 29, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "em", "", 30, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "enum", "", 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "f{", "f}", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "f}", "", 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "f[", "f]", 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "f]", "", 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "f$", "f$", 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "fn", "", 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "function", "", 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 },
{ "functiongroup", "", 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 },
{ "headerfile", "", 40, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "helper", "", 41, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "helperclass", "", 42, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "helps", "", 43, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "htmlonly", "endhtmlonly", 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endhtmlonly", "", 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "ingroup", "", 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "instancesize", "", 47, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "interface", "", 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 },
{ "invariant", "", 49, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "latexonly", "endlatexonly", 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endlatexonly", "", 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "li", "", 52, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "link", "/link", 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "/link", "", 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "mainpage", "", 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "manonly", "endmanonly", 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endmanonly", "", 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "method", "", 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 },
{ "methodgroup", "", 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 },
{ "msc", "endmsc", 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endmsc", "", 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "name", "", 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "namespace", "", 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "note", "", 64, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "overload", "", 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "ownership", "", 66, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "p", "", 67, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "paragraph", "", 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "param", "", 69, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "performance", "", 70, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "post", "", 71, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "pre", "", 72, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "property", "", 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "protocol", "", 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 },
{ "ref", "", 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "remark", "", 76, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "remarks", "", 77, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "result", "", 78, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "return", "", 79, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "returns", "", 80, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "rtfonly", "endrtfonly", 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endrtfonly", "", 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "sa", "", 83, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "section", "", 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "security", "", 85, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "see", "", 86, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "seealso", "", 87, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "short", "", 88, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "since", "", 89, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "struct", "", 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 },
{ "subpage", "", 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "subsection", "", 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "subsubsection", "", 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "superclass", "", 94, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ "template", "", 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "templatefield", "", 96, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "textblock", "/textblock", 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "/textblock", "", 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "todo", "", 99, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "tparam", "", 100, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "typedef", "", 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "union", "", 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 },
{ "var", "", 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ "verbatim", "endverbatim", 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endverbatim", "", 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ "version", "", 106, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "warning", "", 107, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ "weakgroup", "", 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ "xmlonly", "endxmlonly", 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ "endxmlonly", "", 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }
};
} // unnamed namespace
const CommandInfo *CommandTraits::getBuiltinCommandInfo(
StringRef Name) {
switch (Name.size()) {
default: break;
case 1: // 5 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
return &Commands[0]; // "a"
case 'b': // 1 string to match.
return &Commands[7]; // "b"
case 'c': // 1 string to match.
return &Commands[10]; // "c"
case 'e': // 1 string to match.
return &Commands[29]; // "e"
case 'p': // 1 string to match.
return &Commands[67]; // "p"
}
break;
case 2: // 9 strings to match.
switch (Name[0]) {
default: break;
case 'e': // 1 string to match.
if (Name[1] != 'm')
break;
return &Commands[30]; // "em"
case 'f': // 6 strings to match.
switch (Name[1]) {
default: break;
case '$': // 1 string to match.
return &Commands[36]; // "f$"
case '[': // 1 string to match.
return &Commands[34]; // "f["
case ']': // 1 string to match.
return &Commands[35]; // "f]"
case 'n': // 1 string to match.
return &Commands[37]; // "fn"
case '{': // 1 string to match.
return &Commands[32]; // "f{"
case '}': // 1 string to match.
return &Commands[33]; // "f}"
}
break;
case 'l': // 1 string to match.
if (Name[1] != 'i')
break;
return &Commands[52]; // "li"
case 's': // 1 string to match.
if (Name[1] != 'a')
break;
return &Commands[83]; // "sa"
}
break;
case 3: // 8 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "rg", 2))
break;
return &Commands[3]; // "arg"
case 'b': // 1 string to match.
if (memcmp(Name.data()+1, "ug", 2))
break;
return &Commands[9]; // "bug"
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "ot", 2))
break;
return &Commands[27]; // "dot"
case 'm': // 1 string to match.
if (memcmp(Name.data()+1, "sc", 2))
break;
return &Commands[60]; // "msc"
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "re", 2))
break;
return &Commands[72]; // "pre"
case 'r': // 1 string to match.
if (memcmp(Name.data()+1, "ef", 2))
break;
return &Commands[75]; // "ref"
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "ee", 2))
break;
return &Commands[86]; // "see"
case 'v': // 1 string to match.
if (memcmp(Name.data()+1, "ar", 2))
break;
return &Commands[103]; // "var"
}
break;
case 4: // 8 strings to match.
switch (Name[0]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "ode", 3))
break;
return &Commands[16]; // "code"
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "ate", 3))
break;
return &Commands[21]; // "date"
case 'e': // 1 string to match.
if (memcmp(Name.data()+1, "num", 3))
break;
return &Commands[31]; // "enum"
case 'l': // 1 string to match.
if (memcmp(Name.data()+1, "ink", 3))
break;
return &Commands[53]; // "link"
case 'n': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "me", 2))
break;
return &Commands[62]; // "name"
case 'o': // 1 string to match.
if (memcmp(Name.data()+2, "te", 2))
break;
return &Commands[64]; // "note"
}
break;
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "ost", 3))
break;
return &Commands[71]; // "post"
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "odo", 3))
break;
return &Commands[99]; // "todo"
}
break;
case 5: // 9 strings to match.
switch (Name[0]) {
default: break;
case '/': // 1 string to match.
if (memcmp(Name.data()+1, "link", 4))
break;
return &Commands[54]; // "/link"
case 'b': // 1 string to match.
if (memcmp(Name.data()+1, "rief", 4))
break;
return &Commands[8]; // "brief"
case 'c': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'l': // 1 string to match.
if (memcmp(Name.data()+2, "ass", 3))
break;
return &Commands[13]; // "class"
case 'o': // 1 string to match.
if (memcmp(Name.data()+2, "nst", 3))
break;
return &Commands[18]; // "const"
}
break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+1, "elps", 4))
break;
return &Commands[43]; // "helps"
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "aram", 4))
break;
return &Commands[69]; // "param"
case 's': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+2, "ort", 3))
break;
return &Commands[88]; // "short"
case 'i': // 1 string to match.
if (memcmp(Name.data()+2, "nce", 3))
break;
return &Commands[89]; // "since"
}
break;
case 'u': // 1 string to match.
if (memcmp(Name.data()+1, "nion", 4))
break;
return &Commands[102]; // "union"
}
break;
case 6: // 10 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "uthor", 5))
break;
return &Commands[5]; // "author"
case 'e': // 2 strings to match.
if (memcmp(Name.data()+1, "nd", 2))
break;
switch (Name[3]) {
default: break;
case 'd': // 1 string to match.
if (memcmp(Name.data()+4, "ot", 2))
break;
return &Commands[28]; // "enddot"
case 'm': // 1 string to match.
if (memcmp(Name.data()+4, "sc", 2))
break;
return &Commands[61]; // "endmsc"
}
break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+1, "elper", 5))
break;
return &Commands[41]; // "helper"
case 'm': // 1 string to match.
if (memcmp(Name.data()+1, "ethod", 5))
break;
return &Commands[58]; // "method"
case 'r': // 3 strings to match.
if (Name[1] != 'e')
break;
switch (Name[2]) {
default: break;
case 'm': // 1 string to match.
if (memcmp(Name.data()+3, "ark", 3))
break;
return &Commands[76]; // "remark"
case 's': // 1 string to match.
if (memcmp(Name.data()+3, "ult", 3))
break;
return &Commands[78]; // "result"
case 't': // 1 string to match.
if (memcmp(Name.data()+3, "urn", 3))
break;
return &Commands[79]; // "return"
}
break;
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "truct", 5))
break;
return &Commands[90]; // "struct"
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "param", 5))
break;
return &Commands[100]; // "tparam"
}
break;
case 7: // 16 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "uthors", 6))
break;
return &Commands[6]; // "authors"
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "oclass", 6))
break;
return &Commands[15]; // "coclass"
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "etails", 6))
break;
return &Commands[25]; // "details"
case 'e': // 1 string to match.
if (memcmp(Name.data()+1, "ndcode", 6))
break;
return &Commands[17]; // "endcode"
case 'i': // 1 string to match.
if (memcmp(Name.data()+1, "ngroup", 6))
break;
return &Commands[46]; // "ingroup"
case 'm': // 1 string to match.
if (memcmp(Name.data()+1, "anonly", 6))
break;
return &Commands[56]; // "manonly"
case 'r': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 2 strings to match.
switch (Name[2]) {
default: break;
case 'm': // 1 string to match.
if (memcmp(Name.data()+3, "arks", 4))
break;
return &Commands[77]; // "remarks"
case 't': // 1 string to match.
if (memcmp(Name.data()+3, "urns", 4))
break;
return &Commands[80]; // "returns"
}
break;
case 't': // 1 string to match.
if (memcmp(Name.data()+2, "fonly", 5))
break;
return &Commands[81]; // "rtfonly"
}
break;
case 's': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 2 strings to match.
switch (Name[2]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+3, "tion", 4))
break;
return &Commands[84]; // "section"
case 'e': // 1 string to match.
if (memcmp(Name.data()+3, "also", 4))
break;
return &Commands[87]; // "seealso"
}
break;
case 'u': // 1 string to match.
if (memcmp(Name.data()+2, "bpage", 5))
break;
return &Commands[91]; // "subpage"
}
break;
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "ypedef", 6))
break;
return &Commands[101]; // "typedef"
case 'v': // 1 string to match.
if (memcmp(Name.data()+1, "ersion", 6))
break;
return &Commands[106]; // "version"
case 'w': // 1 string to match.
if (memcmp(Name.data()+1, "arning", 6))
break;
return &Commands[107]; // "warning"
case 'x': // 1 string to match.
if (memcmp(Name.data()+1, "mlonly", 6))
break;
return &Commands[109]; // "xmlonly"
}
break;
case 8: // 14 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "bstract", 7))
break;
return &Commands[1]; // "abstract"
case 'c': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 2 strings to match.
switch (Name[2]) {
default: break;
case 'l': // 1 string to match.
if (memcmp(Name.data()+3, "lback", 5))
break;
return &Commands[11]; // "callback"
case 't': // 1 string to match.
if (memcmp(Name.data()+3, "egory", 5))
break;
return &Commands[12]; // "category"
}
break;
case 'o': // 1 string to match.
if (memcmp(Name.data()+2, "nstant", 6))
break;
return &Commands[19]; // "constant"
}
break;
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "efgroup", 7))
break;
return &Commands[22]; // "defgroup"
case 'f': // 1 string to match.
if (memcmp(Name.data()+1, "unction", 7))
break;
return &Commands[38]; // "function"
case 'h': // 1 string to match.
if (memcmp(Name.data()+1, "tmlonly", 7))
break;
return &Commands[44]; // "htmlonly"
case 'm': // 1 string to match.
if (memcmp(Name.data()+1, "ainpage", 7))
break;
return &Commands[55]; // "mainpage"
case 'o': // 1 string to match.
if (memcmp(Name.data()+1, "verload", 7))
break;
return &Commands[65]; // "overload"
case 'p': // 2 strings to match.
if (memcmp(Name.data()+1, "ro", 2))
break;
switch (Name[3]) {
default: break;
case 'p': // 1 string to match.
if (memcmp(Name.data()+4, "erty", 4))
break;
return &Commands[73]; // "property"
case 't': // 1 string to match.
if (memcmp(Name.data()+4, "ocol", 4))
break;
return &Commands[74]; // "protocol"
}
break;
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "ecurity", 7))
break;
return &Commands[85]; // "security"
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "emplate", 7))
break;
return &Commands[95]; // "template"
case 'v': // 1 string to match.
if (memcmp(Name.data()+1, "erbatim", 7))
break;
return &Commands[104]; // "verbatim"
}
break;
case 9: // 10 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "ttention", 8))
break;
return &Commands[4]; // "attention"
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "opyright", 8))
break;
return &Commands[20]; // "copyright"
case 'i': // 2 strings to match.
if (Name[1] != 'n')
break;
switch (Name[2]) {
default: break;
case 't': // 1 string to match.
if (memcmp(Name.data()+3, "erface", 6))
break;
return &Commands[48]; // "interface"
case 'v': // 1 string to match.
if (memcmp(Name.data()+3, "ariant", 6))
break;
return &Commands[49]; // "invariant"
}
break;
case 'l': // 1 string to match.
if (memcmp(Name.data()+1, "atexonly", 8))
break;
return &Commands[50]; // "latexonly"
case 'n': // 1 string to match.
if (memcmp(Name.data()+1, "amespace", 8))
break;
return &Commands[63]; // "namespace"
case 'o': // 1 string to match.
if (memcmp(Name.data()+1, "wnership", 8))
break;
return &Commands[66]; // "ownership"
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "aragraph", 8))
break;
return &Commands[68]; // "paragraph"
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "extblock", 8))
break;
return &Commands[97]; // "textblock"
case 'w': // 1 string to match.
if (memcmp(Name.data()+1, "eakgroup", 8))
break;
return &Commands[108]; // "weakgroup"
}
break;
case 10: // 11 strings to match.
switch (Name[0]) {
default: break;
case '/': // 1 string to match.
if (memcmp(Name.data()+1, "textblock", 9))
break;
return &Commands[98]; // "/textblock"
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "ddtogroup", 9))
break;
return &Commands[2]; // "addtogroup"
case 'd': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 2 strings to match.
if (Name[2] != 'p')
break;
switch (Name[3]) {
default: break;
case 'e': // 1 string to match.
if (memcmp(Name.data()+4, "ndency", 6))
break;
return &Commands[23]; // "dependency"
case 'r': // 1 string to match.
if (memcmp(Name.data()+4, "ecated", 6))
break;
return &Commands[24]; // "deprecated"
}
break;
case 'i': // 1 string to match.
if (memcmp(Name.data()+2, "scussion", 8))
break;
return &Commands[26]; // "discussion"
}
break;
case 'e': // 3 strings to match.
if (memcmp(Name.data()+1, "nd", 2))
break;
switch (Name[3]) {
default: break;
case 'm': // 1 string to match.
if (memcmp(Name.data()+4, "anonly", 6))
break;
return &Commands[57]; // "endmanonly"
case 'r': // 1 string to match.
if (memcmp(Name.data()+4, "tfonly", 6))
break;
return &Commands[82]; // "endrtfonly"
case 'x': // 1 string to match.
if (memcmp(Name.data()+4, "mlonly", 6))
break;
return &Commands[110]; // "endxmlonly"
}
break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+1, "eaderfile", 9))
break;
return &Commands[40]; // "headerfile"
case 's': // 2 strings to match.
if (Name[1] != 'u')
break;
switch (Name[2]) {
default: break;
case 'b': // 1 string to match.
if (memcmp(Name.data()+3, "section", 7))
break;
return &Commands[92]; // "subsection"
case 'p': // 1 string to match.
if (memcmp(Name.data()+3, "erclass", 7))
break;
return &Commands[94]; // "superclass"
}
break;
}
break;
case 11: // 6 strings to match.
switch (Name[0]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "lassdesign", 10))
break;
return &Commands[14]; // "classdesign"
case 'e': // 2 strings to match.
if (memcmp(Name.data()+1, "nd", 2))
break;
switch (Name[3]) {
default: break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+4, "tmlonly", 7))
break;
return &Commands[45]; // "endhtmlonly"
case 'v': // 1 string to match.
if (memcmp(Name.data()+4, "erbatim", 7))
break;
return &Commands[105]; // "endverbatim"
}
break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+1, "elperclass", 10))
break;
return &Commands[42]; // "helperclass"
case 'm': // 1 string to match.
if (memcmp(Name.data()+1, "ethodgroup", 10))
break;
return &Commands[59]; // "methodgroup"
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "erformance", 10))
break;
return &Commands[70]; // "performance"
}
break;
case 12: // 2 strings to match.
switch (Name[0]) {
default: break;
case 'e': // 1 string to match.
if (memcmp(Name.data()+1, "ndlatexonly", 11))
break;
return &Commands[51]; // "endlatexonly"
case 'i': // 1 string to match.
if (memcmp(Name.data()+1, "nstancesize", 11))
break;
return &Commands[47]; // "instancesize"
}
break;
case 13: // 3 strings to match.
switch (Name[0]) {
default: break;
case 'f': // 1 string to match.
if (memcmp(Name.data()+1, "unctiongroup", 12))
break;
return &Commands[39]; // "functiongroup"
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "ubsubsection", 12))
break;
return &Commands[93]; // "subsubsection"
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "emplatefield", 12))
break;
return &Commands[96]; // "templatefield"
}
break;
}
return NULL;
}

View File

@@ -0,0 +1,122 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|*A list of commands useable in documentation comments *|
|* *|
|* Automatically generated file, do not edit! *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef COMMENT_COMMAND
# define COMMENT_COMMAND(NAME)
#endif
COMMENT_COMMAND(a)
COMMENT_COMMAND(abstract)
COMMENT_COMMAND(addtogroup)
COMMENT_COMMAND(arg)
COMMENT_COMMAND(attention)
COMMENT_COMMAND(author)
COMMENT_COMMAND(authors)
COMMENT_COMMAND(b)
COMMENT_COMMAND(brief)
COMMENT_COMMAND(bug)
COMMENT_COMMAND(c)
COMMENT_COMMAND(callback)
COMMENT_COMMAND(category)
COMMENT_COMMAND(class)
COMMENT_COMMAND(classdesign)
COMMENT_COMMAND(coclass)
COMMENT_COMMAND(code)
COMMENT_COMMAND(endcode)
COMMENT_COMMAND(const)
COMMENT_COMMAND(constant)
COMMENT_COMMAND(copyright)
COMMENT_COMMAND(date)
COMMENT_COMMAND(defgroup)
COMMENT_COMMAND(dependency)
COMMENT_COMMAND(deprecated)
COMMENT_COMMAND(details)
COMMENT_COMMAND(discussion)
COMMENT_COMMAND(dot)
COMMENT_COMMAND(enddot)
COMMENT_COMMAND(e)
COMMENT_COMMAND(em)
COMMENT_COMMAND(enum)
COMMENT_COMMAND(flbrace)
COMMENT_COMMAND(frbrace)
COMMENT_COMMAND(flsquare)
COMMENT_COMMAND(frsquare)
COMMENT_COMMAND(fdollar)
COMMENT_COMMAND(fn)
COMMENT_COMMAND(function)
COMMENT_COMMAND(functiongroup)
COMMENT_COMMAND(headerfile)
COMMENT_COMMAND(helper)
COMMENT_COMMAND(helperclass)
COMMENT_COMMAND(helps)
COMMENT_COMMAND(htmlonly)
COMMENT_COMMAND(endhtmlonly)
COMMENT_COMMAND(ingroup)
COMMENT_COMMAND(instancesize)
COMMENT_COMMAND(interface)
COMMENT_COMMAND(invariant)
COMMENT_COMMAND(latexonly)
COMMENT_COMMAND(endlatexonly)
COMMENT_COMMAND(li)
COMMENT_COMMAND(link)
COMMENT_COMMAND(slashlink)
COMMENT_COMMAND(mainpage)
COMMENT_COMMAND(manonly)
COMMENT_COMMAND(endmanonly)
COMMENT_COMMAND(method)
COMMENT_COMMAND(methodgroup)
COMMENT_COMMAND(msc)
COMMENT_COMMAND(endmsc)
COMMENT_COMMAND(name)
COMMENT_COMMAND(namespace)
COMMENT_COMMAND(note)
COMMENT_COMMAND(overload)
COMMENT_COMMAND(ownership)
COMMENT_COMMAND(p)
COMMENT_COMMAND(paragraph)
COMMENT_COMMAND(param)
COMMENT_COMMAND(performance)
COMMENT_COMMAND(post)
COMMENT_COMMAND(pre)
COMMENT_COMMAND(property)
COMMENT_COMMAND(protocol)
COMMENT_COMMAND(ref)
COMMENT_COMMAND(remark)
COMMENT_COMMAND(remarks)
COMMENT_COMMAND(result)
COMMENT_COMMAND(return)
COMMENT_COMMAND(returns)
COMMENT_COMMAND(rtfonly)
COMMENT_COMMAND(endrtfonly)
COMMENT_COMMAND(sa)
COMMENT_COMMAND(section)
COMMENT_COMMAND(security)
COMMENT_COMMAND(see)
COMMENT_COMMAND(seealso)
COMMENT_COMMAND(short)
COMMENT_COMMAND(since)
COMMENT_COMMAND(struct)
COMMENT_COMMAND(subpage)
COMMENT_COMMAND(subsection)
COMMENT_COMMAND(subsubsection)
COMMENT_COMMAND(superclass)
COMMENT_COMMAND(template)
COMMENT_COMMAND(templatefield)
COMMENT_COMMAND(textblock)
COMMENT_COMMAND(slashtextblock)
COMMENT_COMMAND(todo)
COMMENT_COMMAND(tparam)
COMMENT_COMMAND(typedef)
COMMENT_COMMAND(union)
COMMENT_COMMAND(var)
COMMENT_COMMAND(verbatim)
COMMENT_COMMAND(endverbatim)
COMMENT_COMMAND(version)
COMMENT_COMMAND(warning)
COMMENT_COMMAND(weakgroup)
COMMENT_COMMAND(xmlonly)
COMMENT_COMMAND(endxmlonly)

View File

@@ -0,0 +1,152 @@
/*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides a public inferface to use CompilationDatabase without *|
|* the full Clang C++ API. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef CLANG_CXCOMPILATIONDATABASE_H
#define CLANG_CXCOMPILATIONDATABASE_H
#include "clang-c/Platform.h"
#include "clang-c/CXString.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup COMPILATIONDB CompilationDatabase functions
* \ingroup CINDEX
*
* @{
*/
/**
* A compilation database holds all information used to compile files in a
* project. For each file in the database, it can be queried for the working
* directory or the command line used for the compiler invocation.
*
* Must be freed by \c clang_CompilationDatabase_dispose
*/
typedef void * CXCompilationDatabase;
/**
* \brief Contains the results of a search in the compilation database
*
* When searching for the compile command for a file, the compilation db can
* return several commands, as the file may have been compiled with
* different options in different places of the project. This choice of compile
* commands is wrapped in this opaque data structure. It must be freed by
* \c clang_CompileCommands_dispose.
*/
typedef void * CXCompileCommands;
/**
* \brief Represents the command line invocation to compile a specific file.
*/
typedef void * CXCompileCommand;
/**
* \brief Error codes for Compilation Database
*/
typedef enum {
/*
* \brief No error occured
*/
CXCompilationDatabase_NoError = 0,
/*
* \brief Database can not be loaded
*/
CXCompilationDatabase_CanNotLoadDatabase = 1
} CXCompilationDatabase_Error;
/**
* \brief Creates a compilation database from the database found in directory
* buildDir. For example, CMake can output a compile_commands.json which can
* be used to build the database.
*
* It must be freed by \c clang_CompilationDatabase_dispose.
*/
CINDEX_LINKAGE CXCompilationDatabase
clang_CompilationDatabase_fromDirectory(const char *BuildDir,
CXCompilationDatabase_Error *ErrorCode);
/**
* \brief Free the given compilation database
*/
CINDEX_LINKAGE void
clang_CompilationDatabase_dispose(CXCompilationDatabase);
/**
* \brief Find the compile commands used for a file. The compile commands
* must be freed by \c clang_CompileCommands_dispose.
*/
CINDEX_LINKAGE CXCompileCommands
clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase,
const char *CompleteFileName);
/**
* \brief Get all the compile commands in the given compilation database.
*/
CINDEX_LINKAGE CXCompileCommands
clang_CompilationDatabase_getAllCompileCommands(CXCompilationDatabase);
/**
* \brief Free the given CompileCommands
*/
CINDEX_LINKAGE void clang_CompileCommands_dispose(CXCompileCommands);
/**
* \brief Get the number of CompileCommand we have for a file
*/
CINDEX_LINKAGE unsigned
clang_CompileCommands_getSize(CXCompileCommands);
/**
* \brief Get the I'th CompileCommand for a file
*
* Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands)
*/
CINDEX_LINKAGE CXCompileCommand
clang_CompileCommands_getCommand(CXCompileCommands, unsigned I);
/**
* \brief Get the working directory where the CompileCommand was executed from
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getDirectory(CXCompileCommand);
/**
* \brief Get the number of arguments in the compiler invocation.
*
*/
CINDEX_LINKAGE unsigned
clang_CompileCommand_getNumArgs(CXCompileCommand);
/**
* \brief Get the I'th argument value in the compiler invocations
*
* Invariant :
* - argument 0 is the compiler executable
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getArg(CXCompileCommand, unsigned I);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,61 @@
/*===-- clang-c/CXString.h - C Index strings --------------------*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides the interface to C Index strings. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef CLANG_CXSTRING_H
#define CLANG_CXSTRING_H
#include "clang-c/Platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup CINDEX_STRING String manipulation routines
* \ingroup CINDEX
*
* @{
*/
/**
* \brief A character string.
*
* The \c CXString type is used to return strings from the interface when
* the ownership of that string might different from one call to the next.
* Use \c clang_getCString() to retrieve the string data and, once finished
* with the string data, call \c clang_disposeString() to free the string.
*/
typedef struct {
const void *data;
unsigned private_flags;
} CXString;
/**
* \brief Retrieve the character data associated with the given string.
*/
CINDEX_LINKAGE const char *clang_getCString(CXString string);
/**
* \brief Free the given string,
*/
CINDEX_LINKAGE void clang_disposeString(CXString string);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

5784
thirdparty/clang/include/clang-c/Index.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/*===-- clang-c/Platform.h - C Index platform decls -------------*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header provides platform specific macros (dllimport, deprecated, ...) *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef CLANG_C_PLATFORM_H
#define CLANG_C_PLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
/* MSVC DLL import/export. */
#ifdef _MSC_VER
#ifdef _CINDEX_LIB_
#define CINDEX_LINKAGE __declspec(dllexport)
#else
#define CINDEX_LINKAGE __declspec(dllimport)
#endif
#else
#define CINDEX_LINKAGE
#endif
#ifdef __GNUC__
#define CINDEX_DEPRECATED __attribute__((deprecated))
#else
#ifdef _MSC_VER
#define CINDEX_DEPRECATED __declspec(deprecated)
#else
#define CINDEX_DEPRECATED
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,123 @@
//===-- ARCMT.h - ARC Migration Rewriter ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_H
#define LLVM_CLANG_ARCMIGRATE_ARCMT_H
#include "clang/ARCMigrate/FileRemapper.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/CompilerInvocation.h"
namespace clang {
class ASTContext;
class DiagnosticConsumer;
namespace arcmt {
class MigrationPass;
/// \brief Creates an AST with the provided CompilerInvocation but with these
/// changes:
/// -if a PCH/PTH is set, the original header is used instead
/// -Automatic Reference Counting mode is enabled
///
/// It then checks the AST and produces errors/warning for ARC migration issues
/// that the user needs to handle manually.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
/// even if the migrator can fix them, but the function will still return false
/// if all ARC errors can be fixed.
///
/// \param plistOut if non-empty, it is the file path to store the plist with
/// the pre-migration ARC diagnostics.
///
/// \returns false if no error is produced, true otherwise.
bool checkForManualIssues(CompilerInvocation &CI,
const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient,
bool emitPremigrationARCErrors = false,
StringRef plistOut = StringRef());
/// \brief Works similar to checkForManualIssues but instead of checking, it
/// applies automatic modifications to source files to conform to ARC.
///
/// \returns false if no error is produced, true otherwise.
bool applyTransformations(CompilerInvocation &origCI,
const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient);
/// \brief Applies automatic modifications and produces temporary files
/// and metadata into the \p outputDir path.
///
/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
/// even if the migrator can fix them, but the function will still return false
/// if all ARC errors can be fixed.
///
/// \param plistOut if non-empty, it is the file path to store the plist with
/// the pre-migration ARC diagnostics.
///
/// \returns false if no error is produced, true otherwise.
bool migrateWithTemporaryFiles(CompilerInvocation &origCI,
const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient,
StringRef outputDir,
bool emitPremigrationARCErrors,
StringRef plistOut);
/// \brief Get the set of file remappings from the \p outputDir path that
/// migrateWithTemporaryFiles produced.
///
/// \returns false if no error is produced, true otherwise.
bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
StringRef outputDir,
DiagnosticConsumer *DiagClient);
/// \brief Get the set of file remappings from a list of files with remapping
/// info.
///
/// \returns false if no error is produced, true otherwise.
bool getFileRemappingsFromFileList(
std::vector<std::pair<std::string,std::string> > &remap,
ArrayRef<StringRef> remapFiles,
DiagnosticConsumer *DiagClient);
typedef void (*TransformFn)(MigrationPass &pass);
std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode,
bool NoFinalizeRemoval);
class MigrationProcess {
CompilerInvocation OrigCI;
DiagnosticConsumer *DiagClient;
FileRemapper Remapper;
public:
MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient,
StringRef outputDir = StringRef());
class RewriteListener {
public:
virtual ~RewriteListener();
virtual void start(ASTContext &Ctx) { }
virtual void finish() { }
virtual void insert(SourceLocation loc, StringRef text) { }
virtual void remove(CharSourceRange range) { }
};
bool applyTransform(TransformFn trans, RewriteListener *listener = 0);
FileRemapper &getRemapper() { return Remapper; }
};
} // end namespace arcmt
} // end namespace clang
#endif

View File

@@ -0,0 +1,77 @@
//===--- ARCMTActions.h - ARC Migrate Tool Frontend Actions -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
#define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
#include "clang/ARCMigrate/FileRemapper.h"
#include "clang/Frontend/FrontendAction.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
namespace arcmt {
class CheckAction : public WrapperFrontendAction {
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
CheckAction(FrontendAction *WrappedAction);
};
class ModifyAction : public WrapperFrontendAction {
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
ModifyAction(FrontendAction *WrappedAction);
};
class MigrateSourceAction : public ASTFrontendAction {
FileRemapper Remapper;
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
StringRef InFile);
};
class MigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
std::string PlistOut;
bool EmitPremigrationARCErros;
protected:
virtual bool BeginInvocation(CompilerInstance &CI);
public:
MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
StringRef plistOut,
bool emitPremigrationARCErrors);
};
/// \brief Migrates to modern ObjC syntax.
class ObjCMigrateAction : public WrapperFrontendAction {
std::string MigrateDir;
bool MigrateLiterals;
bool MigrateSubscripting;
FileRemapper Remapper;
CompilerInstance *CompInst;
public:
ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
bool migrateLiterals,
bool migrateSubscripting);
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile);
virtual bool BeginInvocation(CompilerInstance &CI);
};
}
}
#endif

View File

@@ -0,0 +1,80 @@
//===-- FileRemapper.h - File Remapping Helper ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
#define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class FileManager;
class FileEntry;
class DiagnosticsEngine;
class PreprocessorOptions;
namespace arcmt {
class FileRemapper {
// FIXME: Reuse the same FileManager for multiple ASTContexts.
OwningPtr<FileManager> FileMgr;
typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target;
typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy;
MappingsTy FromToMappings;
llvm::DenseMap<const FileEntry *, const FileEntry *> ToFromMappings;
public:
FileRemapper();
~FileRemapper();
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged);
bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged);
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag);
bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag);
bool overwriteOriginal(DiagnosticsEngine &Diag,
StringRef outputDir = StringRef());
void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
void remap(StringRef filePath, StringRef newPath);
void applyMappings(PreprocessorOptions &PPOpts) const;
void transferMappingsAndClear(PreprocessorOptions &PPOpts);
void clear(StringRef outputDir = StringRef());
private:
void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf);
void remap(const FileEntry *file, const FileEntry *newfile);
const FileEntry *getOriginalFile(StringRef filePath);
void resetTarget(Target &targ);
bool report(const Twine &err, DiagnosticsEngine &Diag);
std::string getRemapInfoFile(StringRef outputDir);
};
} // end namespace arcmt
} // end namespace clang
#endif

View File

@@ -0,0 +1,446 @@
//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the APValue class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_APVALUE_H
#define LLVM_CLANG_AST_APVALUE_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
namespace clang {
class AddrLabelExpr;
class ASTContext;
class CharUnits;
class DiagnosticBuilder;
class Expr;
class FieldDecl;
class Decl;
class ValueDecl;
class CXXRecordDecl;
class QualType;
/// APValue - This class implements a discriminated union of [uninitialized]
/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
/// [Vector: N * APValue], [Array: N * APValue]
class APValue {
typedef llvm::APSInt APSInt;
typedef llvm::APFloat APFloat;
public:
enum ValueKind {
Uninitialized,
Int,
Float,
ComplexInt,
ComplexFloat,
LValue,
Vector,
Array,
Struct,
Union,
MemberPointer,
AddrLabelDiff
};
typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
union LValuePathEntry {
/// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
/// in the path. An opaque value of type BaseOrMemberType.
void *BaseOrMember;
/// ArrayIndex - The array index of the next item in the path.
uint64_t ArrayIndex;
};
struct NoLValuePath {};
struct UninitArray {};
struct UninitStruct {};
private:
ValueKind Kind;
struct ComplexAPSInt {
APSInt Real, Imag;
ComplexAPSInt() : Real(1), Imag(1) {}
};
struct ComplexAPFloat {
APFloat Real, Imag;
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
};
struct LV;
struct Vec {
APValue *Elts;
unsigned NumElts;
Vec() : Elts(0), NumElts(0) {}
~Vec() { delete[] Elts; }
};
struct Arr {
APValue *Elts;
unsigned NumElts, ArrSize;
Arr(unsigned NumElts, unsigned ArrSize);
~Arr();
};
struct StructData {
APValue *Elts;
unsigned NumBases;
unsigned NumFields;
StructData(unsigned NumBases, unsigned NumFields);
~StructData();
};
struct UnionData {
const FieldDecl *Field;
APValue *Value;
UnionData();
~UnionData();
};
struct AddrLabelDiffData {
const AddrLabelExpr* LHSExpr;
const AddrLabelExpr* RHSExpr;
};
struct MemberPointerData;
enum {
MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
};
union {
void *Aligner;
char Data[MaxSize];
};
public:
APValue() : Kind(Uninitialized) {}
explicit APValue(const APSInt &I) : Kind(Uninitialized) {
MakeInt(); setInt(I);
}
explicit APValue(const APFloat &F) : Kind(Uninitialized) {
MakeFloat(); setFloat(F);
}
explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
MakeVector(); setVector(E, N);
}
APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
MakeComplexInt(); setComplexInt(R, I);
}
APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
MakeComplexFloat(); setComplexFloat(R, I);
}
APValue(const APValue &RHS);
APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
: Kind(Uninitialized) {
MakeLValue(); setLValue(B, O, N, CallIndex);
}
APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
bool OnePastTheEnd, unsigned CallIndex)
: Kind(Uninitialized) {
MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex);
}
APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
MakeArray(InitElts, Size);
}
APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
MakeStruct(B, M);
}
explicit APValue(const FieldDecl *D, const APValue &V = APValue())
: Kind(Uninitialized) {
MakeUnion(); setUnion(D, V);
}
APValue(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
MakeMemberPointer(Member, IsDerivedMember, Path);
}
APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
: Kind(Uninitialized) {
MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
}
~APValue() {
MakeUninit();
}
/// \brief Swaps the contents of this and the given APValue.
void swap(APValue &RHS);
ValueKind getKind() const { return Kind; }
bool isUninit() const { return Kind == Uninitialized; }
bool isInt() const { return Kind == Int; }
bool isFloat() const { return Kind == Float; }
bool isComplexInt() const { return Kind == ComplexInt; }
bool isComplexFloat() const { return Kind == ComplexFloat; }
bool isLValue() const { return Kind == LValue; }
bool isVector() const { return Kind == Vector; }
bool isArray() const { return Kind == Array; }
bool isStruct() const { return Kind == Struct; }
bool isUnion() const { return Kind == Union; }
bool isMemberPointer() const { return Kind == MemberPointer; }
bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
void dump() const;
void dump(raw_ostream &OS) const;
void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
std::string getAsString(ASTContext &Ctx, QualType Ty) const;
APSInt &getInt() {
assert(isInt() && "Invalid accessor");
return *(APSInt*)(char*)Data;
}
const APSInt &getInt() const {
return const_cast<APValue*>(this)->getInt();
}
APFloat &getFloat() {
assert(isFloat() && "Invalid accessor");
return *(APFloat*)(char*)Data;
}
const APFloat &getFloat() const {
return const_cast<APValue*>(this)->getFloat();
}
APSInt &getComplexIntReal() {
assert(isComplexInt() && "Invalid accessor");
return ((ComplexAPSInt*)(char*)Data)->Real;
}
const APSInt &getComplexIntReal() const {
return const_cast<APValue*>(this)->getComplexIntReal();
}
APSInt &getComplexIntImag() {
assert(isComplexInt() && "Invalid accessor");
return ((ComplexAPSInt*)(char*)Data)->Imag;
}
const APSInt &getComplexIntImag() const {
return const_cast<APValue*>(this)->getComplexIntImag();
}
APFloat &getComplexFloatReal() {
assert(isComplexFloat() && "Invalid accessor");
return ((ComplexAPFloat*)(char*)Data)->Real;
}
const APFloat &getComplexFloatReal() const {
return const_cast<APValue*>(this)->getComplexFloatReal();
}
APFloat &getComplexFloatImag() {
assert(isComplexFloat() && "Invalid accessor");
return ((ComplexAPFloat*)(char*)Data)->Imag;
}
const APFloat &getComplexFloatImag() const {
return const_cast<APValue*>(this)->getComplexFloatImag();
}
const LValueBase getLValueBase() const;
CharUnits &getLValueOffset();
const CharUnits &getLValueOffset() const {
return const_cast<APValue*>(this)->getLValueOffset();
}
bool isLValueOnePastTheEnd() const;
bool hasLValuePath() const;
ArrayRef<LValuePathEntry> getLValuePath() const;
unsigned getLValueCallIndex() const;
APValue &getVectorElt(unsigned I) {
assert(isVector() && "Invalid accessor");
assert(I < getVectorLength() && "Index out of range");
return ((Vec*)(char*)Data)->Elts[I];
}
const APValue &getVectorElt(unsigned I) const {
return const_cast<APValue*>(this)->getVectorElt(I);
}
unsigned getVectorLength() const {
assert(isVector() && "Invalid accessor");
return ((const Vec*)(const void *)Data)->NumElts;
}
APValue &getArrayInitializedElt(unsigned I) {
assert(isArray() && "Invalid accessor");
assert(I < getArrayInitializedElts() && "Index out of range");
return ((Arr*)(char*)Data)->Elts[I];
}
const APValue &getArrayInitializedElt(unsigned I) const {
return const_cast<APValue*>(this)->getArrayInitializedElt(I);
}
bool hasArrayFiller() const {
return getArrayInitializedElts() != getArraySize();
}
APValue &getArrayFiller() {
assert(isArray() && "Invalid accessor");
assert(hasArrayFiller() && "No array filler");
return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()];
}
const APValue &getArrayFiller() const {
return const_cast<APValue*>(this)->getArrayFiller();
}
unsigned getArrayInitializedElts() const {
assert(isArray() && "Invalid accessor");
return ((const Arr*)(const void *)Data)->NumElts;
}
unsigned getArraySize() const {
assert(isArray() && "Invalid accessor");
return ((const Arr*)(const void *)Data)->ArrSize;
}
unsigned getStructNumBases() const {
assert(isStruct() && "Invalid accessor");
return ((const StructData*)(const char*)Data)->NumBases;
}
unsigned getStructNumFields() const {
assert(isStruct() && "Invalid accessor");
return ((const StructData*)(const char*)Data)->NumFields;
}
APValue &getStructBase(unsigned i) {
assert(isStruct() && "Invalid accessor");
return ((StructData*)(char*)Data)->Elts[i];
}
APValue &getStructField(unsigned i) {
assert(isStruct() && "Invalid accessor");
return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i];
}
const APValue &getStructBase(unsigned i) const {
return const_cast<APValue*>(this)->getStructBase(i);
}
const APValue &getStructField(unsigned i) const {
return const_cast<APValue*>(this)->getStructField(i);
}
const FieldDecl *getUnionField() const {
assert(isUnion() && "Invalid accessor");
return ((const UnionData*)(const char*)Data)->Field;
}
APValue &getUnionValue() {
assert(isUnion() && "Invalid accessor");
return *((UnionData*)(char*)Data)->Value;
}
const APValue &getUnionValue() const {
return const_cast<APValue*>(this)->getUnionValue();
}
const ValueDecl *getMemberPointerDecl() const;
bool isMemberPointerToDerivedMember() const;
ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
const AddrLabelExpr* getAddrLabelDiffLHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr;
}
const AddrLabelExpr* getAddrLabelDiffRHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr;
}
void setInt(const APSInt &I) {
assert(isInt() && "Invalid accessor");
*(APSInt*)(char*)Data = I;
}
void setFloat(const APFloat &F) {
assert(isFloat() && "Invalid accessor");
*(APFloat*)(char*)Data = F;
}
void setVector(const APValue *E, unsigned N) {
assert(isVector() && "Invalid accessor");
((Vec*)(char*)Data)->Elts = new APValue[N];
((Vec*)(char*)Data)->NumElts = N;
for (unsigned i = 0; i != N; ++i)
((Vec*)(char*)Data)->Elts[i] = E[i];
}
void setComplexInt(const APSInt &R, const APSInt &I) {
assert(R.getBitWidth() == I.getBitWidth() &&
"Invalid complex int (type mismatch).");
assert(isComplexInt() && "Invalid accessor");
((ComplexAPSInt*)(char*)Data)->Real = R;
((ComplexAPSInt*)(char*)Data)->Imag = I;
}
void setComplexFloat(const APFloat &R, const APFloat &I) {
assert(&R.getSemantics() == &I.getSemantics() &&
"Invalid complex float (type mismatch).");
assert(isComplexFloat() && "Invalid accessor");
((ComplexAPFloat*)(char*)Data)->Real = R;
((ComplexAPFloat*)(char*)Data)->Imag = I;
}
void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
unsigned CallIndex);
void setLValue(LValueBase B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
unsigned CallIndex);
void setUnion(const FieldDecl *Field, const APValue &Value) {
assert(isUnion() && "Invalid accessor");
((UnionData*)(char*)Data)->Field = Field;
*((UnionData*)(char*)Data)->Value = Value;
}
void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
const AddrLabelExpr* RHSExpr) {
((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr;
((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr;
}
/// Assign by swapping from a copy of the RHS.
APValue &operator=(APValue RHS) {
swap(RHS);
return *this;
}
private:
void DestroyDataAndMakeUninit();
void MakeUninit() {
if (Kind != Uninitialized)
DestroyDataAndMakeUninit();
}
void MakeInt() {
assert(isUninit() && "Bad state change");
new ((void*)Data) APSInt(1);
Kind = Int;
}
void MakeFloat() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) APFloat(0.0);
Kind = Float;
}
void MakeVector() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) Vec();
Kind = Vector;
}
void MakeComplexInt() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) ComplexAPSInt();
Kind = ComplexInt;
}
void MakeComplexFloat() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) ComplexAPFloat();
Kind = ComplexFloat;
}
void MakeLValue();
void MakeArray(unsigned InitElts, unsigned Size);
void MakeStruct(unsigned B, unsigned M) {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) StructData(B, M);
Kind = Struct;
}
void MakeUnion() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) UnionData();
Kind = Union;
}
void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl*> Path);
void MakeAddrLabelDiff() {
assert(isUninit() && "Bad state change");
new ((void*)(char*)Data) AddrLabelDiffData();
Kind = AddrLabelDiff;
}
};
} // end namespace clang.
#endif

View File

@@ -0,0 +1,28 @@
//===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface to the AST classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_AST_H
#define LLVM_CLANG_AST_AST_H
// This header exports all AST interfaces.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#endif

View File

@@ -0,0 +1,140 @@
//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTConsumer class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
namespace clang {
class ASTContext;
class CXXRecordDecl;
class Decl;
class DeclGroupRef;
class HandleTagDeclDefinition;
class ASTMutationListener;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
class VarDecl;
class FunctionDecl;
class ImportDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by
/// clients that read ASTs. This abstraction layer allows the client to be
/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
class ASTConsumer {
/// \brief Whether this AST consumer also requires information about
/// semantic analysis.
bool SemaConsumer;
friend class SemaConsumer;
public:
ASTConsumer() : SemaConsumer(false) { }
virtual ~ASTConsumer() {}
/// Initialize - This is called to initialize the consumer, providing the
/// ASTContext.
virtual void Initialize(ASTContext &Context) {}
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
/// called by the parser to process every top-level Decl*. Note that D can be
/// the head of a chain of Decls (e.g. for `int a, b` the chain will have two
/// elements). Use Decl::getNextDeclarator() to walk the chain.
///
/// \returns true to continue parsing, or false to abort parsing.
virtual bool HandleTopLevelDecl(DeclGroupRef D);
/// HandleInterestingDecl - Handle the specified interesting declaration. This
/// is called by the AST reader when deserializing things that might interest
/// the consumer. The default implementation forwards to HandleTopLevelDecl.
virtual void HandleInterestingDecl(DeclGroupRef D);
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
/// (e.g. struct, union, enum, class) is completed. This allows the client to
/// hack on the type, which can occur at any point in the file (because these
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
/// \brief Invoked when a function is implicitly instantiated.
/// Note that at this point point it does not have a body, its body is
/// instantiated at the end of the translation unit and passed to
/// HandleTopLevelDecl.
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
/// \brief Handle the specified top-level declaration that occurred inside
/// and ObjC container.
/// The default implementation ignored them.
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
/// \brief Handle an ImportDecl that was implicitly created due to an
/// inclusion directive.
/// The default implementation passes it to HandleTopLevelDecl.
virtual void HandleImplicitImportDecl(ImportDecl *D);
/// CompleteTentativeDefinition - Callback invoked at the end of a translation
/// unit to notify the consumer that the given tentative definition should be
/// completed.
///
/// The variable declaration itself will be a tentative
/// definition. If it had an incomplete array type, its type will
/// have already been changed to an array of size 1. However, the
/// declaration remains a tentative definition and has not been
/// modified by the introduction of an implicit zero initializer.
virtual void CompleteTentativeDefinition(VarDecl *D) {}
/// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this
// variable has been instantiated.
virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {}
/// \brief Callback involved at the end of a translation unit to
/// notify the consumer that a vtable for the given C++ class is
/// required.
///
/// \param RD The class whose vtable was used.
///
/// \param DefinitionRequired Whether a definition of this vtable is
/// required in this translation unit; otherwise, it is only needed if
/// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
/// \brief If the consumer is interested in entities getting modified after
/// their initial creation, it should return a pointer to
/// an ASTMutationListener here.
virtual ASTMutationListener *GetASTMutationListener() { return 0; }
/// \brief If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
virtual ASTDeserializationListener *GetASTDeserializationListener() {
return 0;
}
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {}
/// \brief This callback is called for each function if the Parser was
/// initialized with \c SkipFunctionBodies set to \c true.
///
/// \return \c true if the function's body should be skipped. The function
/// body may be parsed anyway if it is needed (for instance, if it contains
/// the code completion point or is constexpr).
virtual bool shouldSkipFunctionBody(Decl *D) { return true; }
};
} // end namespace clang.
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTICAST_H
#define LLVM_CLANG_DIAGNOSTICAST_H
#include "clang/Basic/Diagnostic.h"
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
#undef DIAG
NUM_BUILTIN_AST_DIAGNOSTICS
};
} // end namespace diag
/// \brief DiagnosticsEngine argument formatting function for diagnostics that
/// involve AST nodes.
///
/// This function formats diagnostic arguments for various AST nodes,
/// including types, declaration names, nested name specifiers, and
/// declaration contexts, into strings that can be printed as part of
/// diagnostics. It is meant to be used as the argument to
/// \c DiagnosticsEngine::SetArgToStringFn(), where the cookie is an \c
/// ASTContext pointer.
void FormatASTNodeDiagnosticArgument(
DiagnosticsEngine::ArgumentKind Kind,
intptr_t Val,
const char *Modifier,
unsigned ModLen,
const char *Argument,
unsigned ArgLen,
const DiagnosticsEngine::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
ArrayRef<intptr_t> QualTypeVals);
} // end namespace clang
#endif

View File

@@ -0,0 +1,282 @@
//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTImporter class which imports AST nodes from one
// context into another context.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
class ASTContext;
class Decl;
class DeclContext;
class DiagnosticsEngine;
class Expr;
class FileManager;
class IdentifierInfo;
class NestedNameSpecifier;
class Stmt;
class TypeSourceInfo;
/// \brief Imports selected nodes from one AST context into another context,
/// merging AST nodes where appropriate.
class ASTImporter {
public:
typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
private:
/// \brief The contexts we're importing to and from.
ASTContext &ToContext, &FromContext;
/// \brief The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
/// \brief Whether to perform a minimal import.
bool Minimal;
/// \brief Whether the last diagnostic came from the "from" context.
bool LastDiagFromFrom;
/// \brief Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
llvm::DenseMap<const Type *, const Type *> ImportedTypes;
/// \brief Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
llvm::DenseMap<Decl *, Decl *> ImportedDecls;
/// \brief Mapping from the already-imported statements in the "from"
/// context to the corresponding statements in the "to" context.
llvm::DenseMap<Stmt *, Stmt *> ImportedStmts;
/// \brief Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
llvm::DenseMap<FileID, FileID> ImportedFileIDs;
/// \brief Imported, anonymous tag declarations that are missing their
/// corresponding typedefs.
SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs;
/// \brief Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).
NonEquivalentDeclSet NonEquivalentDecls;
public:
/// \brief Create a new AST importer.
///
/// \param ToContext The context we'll be importing into.
///
/// \param ToFileManager The file manager we'll be importing into.
///
/// \param FromContext The context we'll be importing from.
///
/// \param FromFileManager The file manager we'll be importing into.
///
/// \param MinimalImport If true, the importer will attempt to import
/// as little as it can, e.g., by importing declarations as forward
/// declarations that can be completed at a later point.
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport);
virtual ~ASTImporter();
/// \brief Whether the importer will perform a minimal import, creating
/// to-be-completed forward declarations when possible.
bool isMinimalImport() const { return Minimal; }
/// \brief Import the given type from the "from" context into the "to"
/// context.
///
/// \returns the equivalent type in the "to" context, or a NULL type if
/// an error occurred.
QualType Import(QualType FromT);
/// \brief Import the given type source information from the
/// "from" context into the "to" context.
///
/// \returns the equivalent type source information in the "to"
/// context, or NULL if an error occurred.
TypeSourceInfo *Import(TypeSourceInfo *FromTSI);
/// \brief Import the given declaration from the "from" context into the
/// "to" context.
///
/// \returns the equivalent declaration in the "to" context, or a NULL type
/// if an error occurred.
Decl *Import(Decl *FromD);
/// \brief Import the given declaration context from the "from"
/// AST context into the "to" AST context.
///
/// \returns the equivalent declaration context in the "to"
/// context, or a NULL type if an error occurred.
DeclContext *ImportContext(DeclContext *FromDC);
/// \brief Import the given expression from the "from" context into the
/// "to" context.
///
/// \returns the equivalent expression in the "to" context, or NULL if
/// an error occurred.
Expr *Import(Expr *FromE);
/// \brief Import the given statement from the "from" context into the
/// "to" context.
///
/// \returns the equivalent statement in the "to" context, or NULL if
/// an error occurred.
Stmt *Import(Stmt *FromS);
/// \brief Import the given nested-name-specifier from the "from"
/// context into the "to" context.
///
/// \returns the equivalent nested-name-specifier in the "to"
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
/// \brief Import the given nested-name-specifier from the "from"
/// context into the "to" context.
///
/// \returns the equivalent nested-name-specifier in the "to"
/// context.
NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS);
/// \brief Import the goven template name from the "from" context into the
/// "to" context.
TemplateName Import(TemplateName From);
/// \brief Import the given source location from the "from" context into
/// the "to" context.
///
/// \returns the equivalent source location in the "to" context, or an
/// invalid source location if an error occurred.
SourceLocation Import(SourceLocation FromLoc);
/// \brief Import the given source range from the "from" context into
/// the "to" context.
///
/// \returns the equivalent source range in the "to" context, or an
/// invalid source location if an error occurred.
SourceRange Import(SourceRange FromRange);
/// \brief Import the given declaration name from the "from"
/// context into the "to" context.
///
/// \returns the equivalent declaration name in the "to" context,
/// or an empty declaration name if an error occurred.
DeclarationName Import(DeclarationName FromName);
/// \brief Import the given identifier from the "from" context
/// into the "to" context.
///
/// \returns the equivalent identifier in the "to" context.
IdentifierInfo *Import(const IdentifierInfo *FromId);
/// \brief Import the given Objective-C selector from the "from"
/// context into the "to" context.
///
/// \returns the equivalent selector in the "to" context.
Selector Import(Selector FromSel);
/// \brief Import the given file ID from the "from" context into the
/// "to" context.
///
/// \returns the equivalent file ID in the source manager of the "to"
/// context.
FileID Import(FileID);
/// \brief Import the definition of the given declaration, including all of
/// the declarations it contains.
///
/// This routine is intended to be used
void ImportDefinition(Decl *From);
/// \brief Cope with a name conflict when importing a declaration into the
/// given context.
///
/// This routine is invoked whenever there is a name conflict while
/// importing a declaration. The returned name will become the name of the
/// imported declaration. By default, the returned name is the same as the
/// original name, leaving the conflict unresolve such that name lookup
/// for this name is likely to find an ambiguity later.
///
/// Subclasses may override this routine to resolve the conflict, e.g., by
/// renaming the declaration being imported.
///
/// \param Name the name of the declaration being imported, which conflicts
/// with other declarations.
///
/// \param DC the declaration context (in the "to" AST context) in which
/// the name is being imported.
///
/// \param IDNS the identifier namespace in which the name will be found.
///
/// \param Decls the set of declarations with the same name as the
/// declaration being imported.
///
/// \param NumDecls the number of conflicting declarations in \p Decls.
///
/// \returns the name that the newly-imported declaration should have.
virtual DeclarationName HandleNameConflict(DeclarationName Name,
DeclContext *DC,
unsigned IDNS,
NamedDecl **Decls,
unsigned NumDecls);
/// \brief Retrieve the context that AST nodes are being imported into.
ASTContext &getToContext() const { return ToContext; }
/// \brief Retrieve the context that AST nodes are being imported from.
ASTContext &getFromContext() const { return FromContext; }
/// \brief Retrieve the file manager that AST nodes are being imported into.
FileManager &getToFileManager() const { return ToFileManager; }
/// \brief Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
/// \brief Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
/// \brief Report a diagnostic in the "from" context.
DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID);
/// \brief Return the set of declarations that we know are not equivalent.
NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
/// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl.
/// Mark the Decl as complete, filling it in as much as possible.
///
/// \param D A declaration in the "to" context.
virtual void CompleteDecl(Decl* D);
/// \brief Note that we have imported the "from" declaration by mapping it
/// to the (potentially-newly-created) "to" declaration.
///
/// Subclasses can override this function to observe all of the \c From ->
/// \c To declaration mappings as they are imported.
virtual Decl *Imported(Decl *From, Decl *To);
/// \brief Determine whether the given types are structurally
/// equivalent.
bool IsStructurallyEquivalent(QualType From, QualType To,
bool Complain = true);
};
}
#endif // LLVM_CLANG_AST_ASTIMPORTER_H

View File

@@ -0,0 +1,87 @@
//===--- ASTMutationListener.h - AST Mutation Interface --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTMutationListener interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
#include "clang/Basic/SourceLocation.h"
namespace clang {
class CXXRecordDecl;
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
class Decl;
class DeclContext;
class FunctionDecl;
class FunctionTemplateDecl;
class ObjCCategoryDecl;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCPropertyDecl;
class TagDecl;
class VarDecl;
/// \brief An abstract interface that should be implemented by listeners
/// that want to be notified when an AST entity gets modified after its
/// initial creation.
class ASTMutationListener {
public:
virtual ~ASTMutationListener();
/// \brief A new TagDecl definition was completed.
virtual void CompletedTagDefinition(const TagDecl *D) { }
/// \brief A new declaration with name has been added to a DeclContext.
virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
/// \brief An implicit member was added after the definition was completed.
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
/// \brief A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D) {}
/// \brief A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {}
/// \brief An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
/// \brief A static data member was implicitly instantiated.
virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
/// \brief A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
/// \brief A objc class extension redeclared or introduced a property.
///
/// \param Prop the property in the class extension
///
/// \param OrigProp the property from the original interface that was declared
/// or null if the property was introduced.
///
/// \param ClassExt the class extension.
virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
const ObjCPropertyDecl *OrigProp,
const ObjCCategoryDecl *ClassExt) {}
// NOTE: If new methods are added they should also be added to
// MultiplexASTMutationListener.
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,211 @@
//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Provides a dynamically typed node container that can be used to store
// an AST base node at runtime in the same storage in a type safe way.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H
#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TypeLoc.h"
#include "llvm/Support/AlignOf.h"
namespace clang {
namespace ast_type_traits {
/// \brief A dynamically typed AST node container.
///
/// Stores an AST node in a type safe way. This allows writing code that
/// works with different kinds of AST nodes, despite the fact that they don't
/// have a common base class.
///
/// Use \c create(Node) to create a \c DynTypedNode from an AST node,
/// and \c get<T>() to retrieve the node as type T if the types match.
///
/// See \c NodeTypeTag for which node base types are currently supported;
/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
/// the supported base types.
class DynTypedNode {
public:
/// \brief Creates a \c DynTypedNode from \c Node.
template <typename T>
static DynTypedNode create(const T &Node) {
return BaseConverter<T>::create(Node);
}
/// \brief Retrieve the stored node as type \c T.
///
/// Returns NULL if the stored node does not have a type that is
/// convertible to \c T.
///
/// For types that have identity via their pointer in the AST
/// (like \c Stmt and \c Decl) the returned pointer points to the
/// referenced AST node.
/// For other types (like \c QualType) the value is stored directly
/// in the \c DynTypedNode, and the returned pointer points at
/// the storage inside DynTypedNode. For those nodes, do not
/// use the pointer outside the scope of the DynTypedNode.
template <typename T>
const T *get() const {
return BaseConverter<T>::get(Tag, Storage.buffer);
}
/// \brief Returns a pointer that identifies the stored AST node.
///
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
/// method returns NULL.
const void *getMemoizationData() const;
private:
/// \brief Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
/// \brief Supported base node types.
enum NodeTypeTag {
NT_Decl,
NT_Stmt,
NT_NestedNameSpecifier,
NT_NestedNameSpecifierLoc,
NT_QualType,
NT_Type,
NT_TypeLoc
} Tag;
/// \brief Stores the data of the node.
///
/// Note that we can store \c Decls and \c Stmts by pointer as they are
/// guaranteed to be unique pointers pointing to dedicated storage in the
/// AST. \c QualTypes on the other hand do not have storage or unique
/// pointers and thus need to be stored by value.
llvm::AlignedCharArrayUnion<Decl *, Stmt *, NestedNameSpecifier,
NestedNameSpecifierLoc, QualType, Type,
TypeLoc> Storage;
};
// FIXME: Pull out abstraction for the following.
template<typename T> struct DynTypedNode::BaseConverter<T,
typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> {
static const T *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_Decl)
return dyn_cast<T>(*reinterpret_cast<Decl*const*>(Storage));
return NULL;
}
static DynTypedNode create(const Decl &Node) {
DynTypedNode Result;
Result.Tag = NT_Decl;
new (Result.Storage.buffer) const Decl*(&Node);
return Result;
}
};
template<typename T> struct DynTypedNode::BaseConverter<T,
typename llvm::enable_if<llvm::is_base_of<Stmt, T> >::type> {
static const T *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_Stmt)
return dyn_cast<T>(*reinterpret_cast<Stmt*const*>(Storage));
return NULL;
}
static DynTypedNode create(const Stmt &Node) {
DynTypedNode Result;
Result.Tag = NT_Stmt;
new (Result.Storage.buffer) const Stmt*(&Node);
return Result;
}
};
template<typename T> struct DynTypedNode::BaseConverter<T,
typename llvm::enable_if<llvm::is_base_of<Type, T> >::type> {
static const T *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_Type)
return dyn_cast<T>(*reinterpret_cast<Type*const*>(Storage));
return NULL;
}
static DynTypedNode create(const Type &Node) {
DynTypedNode Result;
Result.Tag = NT_Type;
new (Result.Storage.buffer) const Type*(&Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<NestedNameSpecifier, void> {
static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_NestedNameSpecifier)
return *reinterpret_cast<NestedNameSpecifier*const*>(Storage);
return NULL;
}
static DynTypedNode create(const NestedNameSpecifier &Node) {
DynTypedNode Result;
Result.Tag = NT_NestedNameSpecifier;
new (Result.Storage.buffer) const NestedNameSpecifier*(&Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<NestedNameSpecifierLoc, void> {
static const NestedNameSpecifierLoc *get(NodeTypeTag Tag,
const char Storage[]) {
if (Tag == NT_NestedNameSpecifierLoc)
return reinterpret_cast<const NestedNameSpecifierLoc*>(Storage);
return NULL;
}
static DynTypedNode create(const NestedNameSpecifierLoc &Node) {
DynTypedNode Result;
Result.Tag = NT_NestedNameSpecifierLoc;
new (Result.Storage.buffer) NestedNameSpecifierLoc(Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<QualType, void> {
static const QualType *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_QualType)
return reinterpret_cast<const QualType*>(Storage);
return NULL;
}
static DynTypedNode create(const QualType &Node) {
DynTypedNode Result;
Result.Tag = NT_QualType;
new (Result.Storage.buffer) QualType(Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<TypeLoc, void> {
static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_TypeLoc)
return reinterpret_cast<const TypeLoc*>(Storage);
return NULL;
}
static DynTypedNode create(const TypeLoc &Node) {
DynTypedNode Result;
Result.Tag = NT_TypeLoc;
new (Result.Storage.buffer) TypeLoc(Node);
return Result;
}
};
// The only operation we allow on unsupported types is \c get.
// This allows to conveniently use \c DynTypedNode when having an arbitrary
// AST node that is not supported, but prevents misuse - a user cannot create
// a DynTypedNode from arbitrary types.
template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; }
};
inline const void *DynTypedNode::getMemoizationData() const {
switch (Tag) {
case NT_Decl: return BaseConverter<Decl>::get(Tag, Storage.buffer);
case NT_Stmt: return BaseConverter<Stmt>::get(Tag, Storage.buffer);
default: return NULL;
};
}
} // end namespace ast_type_traits
} // end namespace clang
#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H

View File

@@ -0,0 +1,85 @@
//===-- ASTUnresolvedSet.h - Unresolved sets of declarations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides an UnresolvedSet-like class, whose contents are
// allocated using the allocator associated with an ASTContext.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
#include "clang/AST/ASTVector.h"
#include "clang/AST/UnresolvedSet.h"
namespace clang {
/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator.
class ASTUnresolvedSet {
typedef ASTVector<DeclAccessPair> DeclsTy;
DeclsTy Decls;
ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION;
void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION;
public:
ASTUnresolvedSet() {}
ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
typedef UnresolvedSetIterator iterator;
typedef UnresolvedSetIterator const_iterator;
iterator begin() { return iterator(Decls.begin()); }
iterator end() { return iterator(Decls.end()); }
const_iterator begin() const { return const_iterator(Decls.begin()); }
const_iterator end() const { return const_iterator(Decls.end()); }
void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) {
Decls.push_back(DeclAccessPair::make(D, AS), C);
}
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
bool replace(const NamedDecl* Old, NamedDecl *New, AccessSpecifier AS) {
for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
if (I->getDecl() == Old) {
I->set(New, AS);
return true;
}
}
return false;
}
void erase(unsigned I) {
Decls[I] = Decls.back();
Decls.pop_back();
}
void clear() { Decls.clear(); }
bool empty() const { return Decls.empty(); }
unsigned size() const { return Decls.size(); }
void reserve(ASTContext &C, unsigned N) {
Decls.reserve(C, N);
}
void append(ASTContext &C, iterator I, iterator E) {
Decls.append(C, I.ir, E.ir);
}
DeclAccessPair &operator[](unsigned I) { return Decls[I]; }
const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; }
};
} // namespace clang
#endif

View File

@@ -0,0 +1,401 @@
//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides ASTVector, a vector ADT whose contents are
// allocated using the allocator associated with an ASTContext..
//
//===----------------------------------------------------------------------===//
// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
// We can refactor this core logic into something common.
#ifndef LLVM_CLANG_AST_VECTOR
#define LLVM_CLANG_AST_VECTOR
#include "clang/AST/AttrIterator.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cstring>
#include <memory>
#ifdef _MSC_VER
namespace std {
#if _MSC_VER <= 1310
// Work around flawed VC++ implementation of std::uninitialized_copy. Define
// additional overloads so that elements with pointer types are recognized as
// scalars and not objects, causing bizarre type conversion errors.
template<class T1, class T2>
inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
_Scalar_ptr_iterator_tag _Cat;
return _Cat;
}
template<class T1, class T2>
inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
_Scalar_ptr_iterator_tag _Cat;
return _Cat;
}
#else
// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear
// is that the above hack won't work if it wasn't fixed.
#endif
}
#endif
namespace clang {
class ASTContext;
template<typename T>
class ASTVector {
T *Begin, *End, *Capacity;
void setEnd(T *P) { this->End = P; }
public:
// Default ctor - Initialize to empty.
ASTVector() : Begin(NULL), End(NULL), Capacity(NULL) { }
ASTVector(ASTContext &C, unsigned N)
: Begin(NULL), End(NULL), Capacity(NULL) {
reserve(C, N);
}
~ASTVector() {
if (llvm::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
}
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
// forward iterator creation methods.
iterator begin() { return Begin; }
const_iterator begin() const { return Begin; }
iterator end() { return End; }
const_iterator end() const { return End; }
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
bool empty() const { return Begin == End; }
size_type size() const { return End-Begin; }
reference operator[](unsigned idx) {
assert(Begin + idx < End);
return Begin[idx];
}
const_reference operator[](unsigned idx) const {
assert(Begin + idx < End);
return Begin[idx];
}
reference front() {
return begin()[0];
}
const_reference front() const {
return begin()[0];
}
reference back() {
return end()[-1];
}
const_reference back() const {
return end()[-1];
}
void pop_back() {
--End;
End->~T();
}
T pop_back_val() {
T Result = back();
pop_back();
return Result;
}
void clear() {
if (llvm::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
}
/// data - Return a pointer to the vector's buffer, even if empty().
pointer data() {
return pointer(Begin);
}
/// data - Return a pointer to the vector's buffer, even if empty().
const_pointer data() const {
return const_pointer(Begin);
}
void push_back(const_reference Elt, ASTContext &C) {
if (End < Capacity) {
Retry:
new (End) T(Elt);
++End;
return;
}
grow(C);
goto Retry;
}
void reserve(ASTContext &C, unsigned N) {
if (unsigned(Capacity-Begin) < N)
grow(C, N);
}
/// capacity - Return the total number of elements in the currently allocated
/// buffer.
size_t capacity() const { return Capacity - Begin; }
/// append - Add the specified range to the end of the SmallVector.
///
template<typename in_iter>
void append(ASTContext &C, in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
if (NumInputs == 0)
return;
// Grow allocated space if needed.
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
this->grow(C, this->size()+NumInputs);
// Copy the new elements over.
// TODO: NEED To compile time dispatch on whether in_iter is a random access
// iterator to use the fast uninitialized_copy.
std::uninitialized_copy(in_start, in_end, this->end());
this->setEnd(this->end() + NumInputs);
}
/// append - Add the specified range to the end of the SmallVector.
///
void append(ASTContext &C, size_type NumInputs, const T &Elt) {
// Grow allocated space if needed.
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
this->grow(C, this->size()+NumInputs);
// Copy the new elements over.
std::uninitialized_fill_n(this->end(), NumInputs, Elt);
this->setEnd(this->end() + NumInputs);
}
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename It1, typename It2>
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
std::uninitialized_copy(I, E, Dest);
}
iterator insert(ASTContext &C, iterator I, const T &Elt) {
if (I == this->end()) { // Important special case for empty vector.
push_back(Elt);
return this->end()-1;
}
if (this->EndX < this->CapacityX) {
Retry:
new (this->end()) T(this->back());
this->setEnd(this->end()+1);
// Push everything else over.
std::copy_backward(I, this->end()-1, this->end());
*I = Elt;
return I;
}
size_t EltNo = I-this->begin();
this->grow(C);
I = this->begin()+EltNo;
goto Retry;
}
iterator insert(ASTContext &C, iterator I, size_type NumToInsert,
const T &Elt) {
if (I == this->end()) { // Important special case for empty vector.
append(C, NumToInsert, Elt);
return this->end()-1;
}
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
// Ensure there is enough space.
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
// If there are more elements between the insertion point and the end of the
// range than there are being inserted, we can use a simple approach to
// insertion. Since we already reserved space, we know that this won't
// reallocate the vector.
if (size_t(this->end()-I) >= NumToInsert) {
T *OldEnd = this->end();
append(C, this->end()-NumToInsert, this->end());
// Copy the existing elements that get replaced.
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
std::fill_n(I, NumToInsert, Elt);
return I;
}
// Otherwise, we're inserting more elements than exist already, and we're
// not inserting at the end.
// Copy over the elements that we're about to overwrite.
T *OldEnd = this->end();
this->setEnd(this->end() + NumToInsert);
size_t NumOverwritten = OldEnd-I;
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
// Replace the overwritten part.
std::fill_n(I, NumOverwritten, Elt);
// Insert the non-overwritten middle part.
std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
return I;
}
template<typename ItTy>
iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) {
if (I == this->end()) { // Important special case for empty vector.
append(C, From, To);
return this->end()-1;
}
size_t NumToInsert = std::distance(From, To);
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
// Ensure there is enough space.
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
// If there are more elements between the insertion point and the end of the
// range than there are being inserted, we can use a simple approach to
// insertion. Since we already reserved space, we know that this won't
// reallocate the vector.
if (size_t(this->end()-I) >= NumToInsert) {
T *OldEnd = this->end();
append(C, this->end()-NumToInsert, this->end());
// Copy the existing elements that get replaced.
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
std::copy(From, To, I);
return I;
}
// Otherwise, we're inserting more elements than exist already, and we're
// not inserting at the end.
// Copy over the elements that we're about to overwrite.
T *OldEnd = this->end();
this->setEnd(this->end() + NumToInsert);
size_t NumOverwritten = OldEnd-I;
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
// Replace the overwritten part.
for (; NumOverwritten > 0; --NumOverwritten) {
*I = *From;
++I; ++From;
}
// Insert the non-overwritten middle part.
this->uninitialized_copy(From, To, OldEnd);
return I;
}
void resize(ASTContext &C, unsigned N, const T &NV) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->setEnd(this->begin()+N);
} else if (N > this->size()) {
if (this->capacity() < N)
this->grow(C, N);
construct_range(this->end(), this->begin()+N, NV);
this->setEnd(this->begin()+N);
}
}
private:
/// grow - double the size of the allocated memory, guaranteeing space for at
/// least one more element or MinSize if specified.
void grow(ASTContext &C, size_type MinSize = 1);
void construct_range(T *S, T *E, const T &Elt) {
for (; S != E; ++S)
new (S) T(Elt);
}
void destroy_range(T *S, T *E) {
while (S != E) {
--E;
E->~T();
}
}
protected:
iterator capacity_ptr() { return (iterator)this->Capacity; }
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T>
void ASTVector<T>::grow(ASTContext &C, size_t MinSize) {
size_t CurCapacity = Capacity-Begin;
size_t CurSize = size();
size_t NewCapacity = 2*CurCapacity;
if (NewCapacity < MinSize)
NewCapacity = MinSize;
// Allocate the memory from the ASTContext.
T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
// Copy the elements over.
if (llvm::is_class<T>::value) {
std::uninitialized_copy(Begin, End, NewElts);
// Destroy the original elements.
destroy_range(Begin, End);
}
else {
// Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
memcpy(NewElts, Begin, CurSize * sizeof(T));
}
// ASTContext never frees any memory.
Begin = NewElts;
End = NewElts+CurSize;
Capacity = Begin+NewCapacity;
}
} // end: clang namespace
#endif

View File

@@ -0,0 +1,157 @@
//===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Attr interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstring>
namespace clang {
class ASTContext;
class IdentifierInfo;
class ObjCInterfaceDecl;
class Expr;
class QualType;
class FunctionDecl;
class TypeSourceInfo;
/// Attr - This represents one attribute.
class Attr {
private:
SourceRange Range;
unsigned AttrKind : 16;
protected:
/// An index into the spelling list of an
/// attribute defined in Attr.td file.
unsigned SpellingListIndex : 4;
bool Inherited : 1;
bool IsPackExpansion : 1;
virtual ~Attr();
void* operator new(size_t bytes) throw() {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
}
void operator delete(void* data) throw() {
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
}
public:
// Forward so that the regular new and delete do not hide global ones.
void* operator new(size_t Bytes, ASTContext &C,
size_t Alignment = 16) throw() {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C,
size_t Alignment) throw() {
return ::operator delete(Ptr, C, Alignment);
}
protected:
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
Inherited(false), IsPackExpansion(false) {}
public:
attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
}
unsigned getSpellingListIndex() const { return SpellingListIndex; }
SourceLocation getLocation() const { return Range.getBegin(); }
SourceRange getRange() const { return Range; }
void setRange(SourceRange R) { Range = R; }
bool isInherited() const { return Inherited; }
void setPackExpansion(bool PE) { IsPackExpansion = PE; }
bool isPackExpansion() const { return IsPackExpansion; }
// Clone this attribute.
virtual Attr *clone(ASTContext &C) const = 0;
virtual bool isLateParsed() const { return false; }
// Pretty print this attribute.
virtual void printPretty(raw_ostream &OS,
const PrintingPolicy &Policy) const = 0;
};
class InheritableAttr : public Attr {
virtual void anchor();
protected:
InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
: Attr(AK, R, SpellingListIndex) {}
public:
void setInherited(bool I) { Inherited = I; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() <= attr::LAST_INHERITABLE;
}
};
class InheritableParamAttr : public InheritableAttr {
virtual void anchor();
protected:
InheritableParamAttr(attr::Kind AK, SourceRange R,
unsigned SpellingListIndex = 0)
: InheritableAttr(AK, R, SpellingListIndex) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
// Relies on relative order of enum emission with respect to MS inheritance
// attrs.
return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
}
};
class MSInheritanceAttr : public InheritableAttr {
virtual void anchor();
protected:
MSInheritanceAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
: InheritableAttr(AK, R, SpellingListIndex) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
// Relies on relative order of enum emission with respect to param attrs.
return (A->getKind() <= attr::LAST_MS_INHERITABLE &&
A->getKind() > attr::LAST_INHERITABLE_PARAM);
}
};
#include "clang/AST/Attrs.inc"
} // end namespace clang
#endif

View File

@@ -0,0 +1,142 @@
//===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Attr vector and specific_attr_iterator interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ATTRITERATOR_H
#define LLVM_CLANG_AST_ATTRITERATOR_H
#include "clang/Basic/LLVM.h"
#include <iterator>
namespace clang {
class ASTContext;
class Attr;
}
// Defined in ASTContext.h
void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 16);
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
void *operator new[](size_t Bytes, const clang::ASTContext &C,
size_t Alignment);
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, const clang::ASTContext &C, size_t);
void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
namespace clang {
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
typedef SmallVector<Attr*, 2> AttrVec;
typedef SmallVector<const Attr*, 2> ConstAttrVec;
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specifc type.
template <typename SpecificAttr, typename Container = AttrVec>
class specific_attr_iterator {
typedef typename Container::const_iterator Iterator;
/// Current - The current, underlying iterator.
/// In order to ensure we don't dereference an invalid iterator unless
/// specifically requested, we don't necessarily advance this all the
/// way. Instead, we advance it when an operation is requested; if the
/// operation is acting on what should be a past-the-end iterator,
/// then we offer no guarantees, but this way we do not dererence a
/// past-the-end iterator when we move to a past-the-end position.
mutable Iterator Current;
void AdvanceToNext() const {
while (!isa<SpecificAttr>(*Current))
++Current;
}
void AdvanceToNext(Iterator I) const {
while (Current != I && !isa<SpecificAttr>(*Current))
++Current;
}
public:
typedef SpecificAttr* value_type;
typedef SpecificAttr* reference;
typedef SpecificAttr* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
specific_attr_iterator() : Current() { }
explicit specific_attr_iterator(Iterator i) : Current(i) { }
reference operator*() const {
AdvanceToNext();
return cast<SpecificAttr>(*Current);
}
pointer operator->() const {
AdvanceToNext();
return cast<SpecificAttr>(*Current);
}
specific_attr_iterator& operator++() {
++Current;
return *this;
}
specific_attr_iterator operator++(int) {
specific_attr_iterator Tmp(*this);
++(*this);
return Tmp;
}
friend bool operator==(specific_attr_iterator Left,
specific_attr_iterator Right) {
assert((Left.Current == 0) == (Right.Current == 0));
if (Left.Current < Right.Current)
Left.AdvanceToNext(Right.Current);
else
Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
}
friend bool operator!=(specific_attr_iterator Left,
specific_attr_iterator Right) {
return !(Left == Right);
}
};
template <typename SpecificAttr, typename Container>
inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_begin(const Container& container) {
return specific_attr_iterator<SpecificAttr, Container>(container.begin());
}
template <typename SpecificAttr, typename Container>
inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_end(const Container& container) {
return specific_attr_iterator<SpecificAttr, Container>(container.end());
}
template <typename SpecificAttr, typename Container>
inline bool hasSpecificAttr(const Container& container) {
return specific_attr_begin<SpecificAttr>(container) !=
specific_attr_end<SpecificAttr>(container);
}
template <typename SpecificAttr, typename Container>
inline SpecificAttr *getSpecificAttr(const Container& container) {
specific_attr_iterator<SpecificAttr, Container> i =
specific_attr_begin<SpecificAttr>(container);
if (i != specific_attr_end<SpecificAttr>(container))
return *i;
else
return 0;
}
} // end namespace clang
#endif

View File

@@ -0,0 +1,87 @@
//===--- BaseSubobject.h - BaseSubobject class ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a definition of the BaseSubobject class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BASESUBOBJECT_H
#define LLVM_CLANG_AST_BASESUBOBJECT_H
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/type_traits.h"
namespace clang {
class CXXRecordDecl;
// BaseSubobject - Uniquely identifies a direct or indirect base class.
// Stores both the base class decl and the offset from the most derived class to
// the base class. Used for vtable and VTT generation.
class BaseSubobject {
/// Base - The base class declaration.
const CXXRecordDecl *Base;
/// BaseOffset - The offset from the most derived class to the base class.
CharUnits BaseOffset;
public:
BaseSubobject() { }
BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
: Base(Base), BaseOffset(BaseOffset) { }
/// getBase - Returns the base class declaration.
const CXXRecordDecl *getBase() const { return Base; }
/// getBaseOffset - Returns the base class offset.
CharUnits getBaseOffset() const { return BaseOffset; }
friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
}
};
} // end namespace clang
namespace llvm {
template<> struct DenseMapInfo<clang::BaseSubobject> {
static clang::BaseSubobject getEmptyKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getEmptyKey()));
}
static clang::BaseSubobject getTombstoneKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getTombstoneKey()));
}
static unsigned getHashValue(const clang::BaseSubobject &Base) {
typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy;
return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(),
Base.getBaseOffset()));
}
static bool isEqual(const clang::BaseSubobject &LHS,
const clang::BaseSubobject &RHS) {
return LHS == RHS;
}
};
// It's OK to treat BaseSubobject as a POD type.
template <> struct isPodLike<clang::BaseSubobject> {
static const bool value = true;
};
}
#endif

View File

@@ -0,0 +1,240 @@
//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the database about various builtin singleton types.
//
// BuiltinType::Id is the enumerator defining the type.
//
// Context.SingletonId is the global singleton of this type. Some global
// singletons are shared by multiple types.
//
// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been
// covered by any other #define. Defining this macro covers all
// the builtins.
//
// SIGNED_TYPE(Id, SingletonId) - A signed integral type.
//
// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type.
//
// FLOATING_TYPE(Id, SingletonId) - A floating-point type.
//
// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder
// types are used to perform context-sensitive checking of specific
// forms of expression.
//
// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds
// to a builtin which uses a shared singleton type.
//
//===----------------------------------------------------------------------===//
#ifndef SIGNED_TYPE
#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef UNSIGNED_TYPE
#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef FLOATING_TYPE
#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef PLACEHOLDER_TYPE
#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef SHARED_SINGLETON_TYPE
#define SHARED_SINGLETON_TYPE(Expansion) Expansion
#endif
//===- Builtin Types ------------------------------------------------------===//
// void
BUILTIN_TYPE(Void, VoidTy)
//===- Unsigned Types -----------------------------------------------------===//
// 'bool' in C++, '_Bool' in C99
UNSIGNED_TYPE(Bool, BoolTy)
// 'char' for targets where it's unsigned
SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy))
// 'unsigned char', explicitly qualified
UNSIGNED_TYPE(UChar, UnsignedCharTy)
// 'wchar_t' for targets where it's unsigned
SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy))
// 'char16_t' in C++
UNSIGNED_TYPE(Char16, Char16Ty)
// 'char32_t' in C++
UNSIGNED_TYPE(Char32, Char32Ty)
// 'unsigned short'
UNSIGNED_TYPE(UShort, UnsignedShortTy)
// 'unsigned int'
UNSIGNED_TYPE(UInt, UnsignedIntTy)
// 'unsigned long'
UNSIGNED_TYPE(ULong, UnsignedLongTy)
// 'unsigned long long'
UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy)
// '__uint128_t'
UNSIGNED_TYPE(UInt128, UnsignedInt128Ty)
//===- Signed Types -------------------------------------------------------===//
// 'char' for targets where it's signed
SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy))
// 'signed char', explicitly qualified
SIGNED_TYPE(SChar, SignedCharTy)
// 'wchar_t' for targets where it's signed
SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy))
// 'short' or 'signed short'
SIGNED_TYPE(Short, ShortTy)
// 'int' or 'signed int'
SIGNED_TYPE(Int, IntTy)
// 'long' or 'signed long'
SIGNED_TYPE(Long, LongTy)
// 'long long' or 'signed long long'
SIGNED_TYPE(LongLong, LongLongTy)
// '__int128_t'
SIGNED_TYPE(Int128, Int128Ty)
//===- Floating point types -----------------------------------------------===//
// 'half' in OpenCL, '__fp16' in ARM NEON.
FLOATING_TYPE(Half, HalfTy)
// 'float'
FLOATING_TYPE(Float, FloatTy)
// 'double'
FLOATING_TYPE(Double, DoubleTy)
// 'long double'
FLOATING_TYPE(LongDouble, LongDoubleTy)
//===- Language-specific types --------------------------------------------===//
// This is the type of C++0x 'nullptr'.
BUILTIN_TYPE(NullPtr, NullPtrTy)
// The primitive Objective C 'id' type. The user-visible 'id'
// type is a typedef of an ObjCObjectPointerType to an
// ObjCObjectType with this as its base. In fact, this only ever
// shows up in an AST as the base type of an ObjCObjectType.
BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy)
// The primitive Objective C 'Class' type. The user-visible
// 'Class' type is a typedef of an ObjCObjectPointerType to an
// ObjCObjectType with this as its base. In fact, this only ever
// shows up in an AST as the base type of an ObjCObjectType.
BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy)
// The primitive Objective C 'SEL' type. The user-visible 'SEL'
// type is a typedef of a PointerType to this.
BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy)
// OpenCL image types.
BUILTIN_TYPE(OCLImage1d, OCLImage1dTy)
BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)
BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)
BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)
BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
// OpenCL sampler_t.
BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
// OpenCL event_t.
BUILTIN_TYPE(OCLEvent, OCLEventTy)
// This represents the type of an expression whose type is
// totally unknown, e.g. 'T::foo'. It is permitted for this to
// appear in situations where the structure of the type is
// theoretically deducible.
BUILTIN_TYPE(Dependent, DependentTy)
// The type of an unresolved overload set. A placeholder type.
// Expressions with this type have one of the following basic
// forms, with parentheses generally permitted:
// foo # possibly qualified, not if an implicit access
// foo # possibly qualified, not if an implicit access
// &foo # possibly qualified, not if an implicit access
// x->foo # only if might be a static member function
// &x->foo # only if might be a static member function
// &Class::foo # when a pointer-to-member; sub-expr also has this type
// OverloadExpr::find can be used to analyze the expression.
//
// Overload should be the first placeholder type, or else change
// BuiltinType::isNonOverloadPlaceholderType()
PLACEHOLDER_TYPE(Overload, OverloadTy)
// The type of a bound C++ non-static member function.
// A placeholder type. Expressions with this type have one of the
// following basic forms:
// foo # if an implicit access
// x->foo # if only contains non-static members
PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)
// The type of an expression which refers to a pseudo-object,
// such as those introduced by Objective C's @property or
// VS.NET's __property declarations. A placeholder type. The
// pseudo-object is actually accessed by emitting a call to
// some sort of function or method; typically there is a pair
// of a setter and a getter, with the setter used if the
// pseudo-object reference is used syntactically as the
// left-hand-side of an assignment operator.
//
// A pseudo-object reference naming an Objective-C @property is
// always a dot access with a base of object-pointer type,
// e.g. 'x.foo'.
//
// In VS.NET, a __property declaration creates an implicit
// member with an associated name, which can then be named
// in any of the normal ways an ordinary member could be.
PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
// __builtin_any_type. A placeholder type. Useful for clients
// like debuggers that don't know what type to give something.
// Only a small number of operations are valid on expressions of
// unknown type, most notably explicit casts.
PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy)
PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
// The type of a cast which, in ARC, would normally require a
// __bridge, but which might be okay depending on the immediate
// context.
PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
#ifdef LAST_BUILTIN_TYPE
LAST_BUILTIN_TYPE(ARCUnbridgedCast)
#undef LAST_BUILTIN_TYPE
#endif
#undef SHARED_SINGLETON_TYPE
#undef PLACEHOLDER_TYPE
#undef FLOATING_TYPE
#undef SIGNED_TYPE
#undef UNSIGNED_TYPE
#undef BUILTIN_TYPE

View File

@@ -0,0 +1,368 @@
//===------ CXXInheritance.h - C++ Inheritance ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides routines that help analyzing C++ inheritance hierarchies.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H
#define LLVM_CLANG_AST_CXXINHERITANCE_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <list>
#include <map>
namespace clang {
class CXXBaseSpecifier;
class CXXMethodDecl;
class CXXRecordDecl;
class NamedDecl;
/// \brief Represents an element in a path from a derived class to a
/// base class.
///
/// Each step in the path references the link from a
/// derived class to one of its direct base classes, along with a
/// base "number" that identifies which base subobject of the
/// original derived class we are referencing.
struct CXXBasePathElement {
/// \brief The base specifier that states the link from a derived
/// class to a base class, which will be followed by this base
/// path element.
const CXXBaseSpecifier *Base;
/// \brief The record decl of the class that the base is a base of.
const CXXRecordDecl *Class;
/// \brief Identifies which base class subobject (of type
/// \c Base->getType()) this base path element refers to.
///
/// This value is only valid if \c !Base->isVirtual(), because there
/// is no base numbering for the zero or one virtual bases of a
/// given type.
int SubobjectNumber;
};
/// \brief Represents a path from a specific derived class
/// (which is not represented as part of the path) to a particular
/// (direct or indirect) base class subobject.
///
/// Individual elements in the path are described by the \c CXXBasePathElement
/// structure, which captures both the link from a derived class to one of its
/// direct bases and identification describing which base class
/// subobject is being used.
class CXXBasePath : public SmallVector<CXXBasePathElement, 4> {
public:
CXXBasePath() : Access(AS_public) {}
/// \brief The access along this inheritance path. This is only
/// calculated when recording paths. AS_none is a special value
/// used to indicate a path which permits no legal access.
AccessSpecifier Access;
/// \brief The set of declarations found inside this base class
/// subobject.
DeclContext::lookup_result Decls;
void clear() {
SmallVectorImpl<CXXBasePathElement>::clear();
Access = AS_public;
}
};
/// BasePaths - Represents the set of paths from a derived class to
/// one of its (direct or indirect) bases. For example, given the
/// following class hierarchy:
///
/// @code
/// class A { };
/// class B : public A { };
/// class C : public A { };
/// class D : public B, public C{ };
/// @endcode
///
/// There are two potential BasePaths to represent paths from D to a
/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0)
/// and another is (D,0)->(C,0)->(A,1). These two paths actually
/// refer to two different base class subobjects of the same type,
/// so the BasePaths object refers to an ambiguous path. On the
/// other hand, consider the following class hierarchy:
///
/// @code
/// class A { };
/// class B : public virtual A { };
/// class C : public virtual A { };
/// class D : public B, public C{ };
/// @endcode
///
/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0)
/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them
/// refer to the same base class subobject of type A (the virtual
/// one), there is no ambiguity.
class CXXBasePaths {
/// \brief The type from which this search originated.
CXXRecordDecl *Origin;
/// Paths - The actual set of paths that can be taken from the
/// derived class to the same base class.
std::list<CXXBasePath> Paths;
/// ClassSubobjects - Records the class subobjects for each class
/// type that we've seen. The first element in the pair says
/// whether we found a path to a virtual base for that class type,
/// while the element contains the number of non-virtual base
/// class subobjects for that class type. The key of the map is
/// the cv-unqualified canonical type of the base class subobject.
llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
/// ambiguous paths while it is looking for a path from a derived
/// type to a base type.
bool FindAmbiguities;
/// RecordPaths - Whether Sema::IsDerivedFrom should record paths
/// while it is determining whether there are paths from a derived
/// type to a base type.
bool RecordPaths;
/// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
/// if it finds a path that goes across a virtual base. The virtual class
/// is also recorded.
bool DetectVirtual;
/// ScratchPath - A BasePath that is used by Sema::lookupInBases
/// to help build the set of paths.
CXXBasePath ScratchPath;
/// DetectedVirtual - The base class that is virtual.
const RecordType *DetectedVirtual;
/// \brief Array of the declarations that have been found. This
/// array is constructed only if needed, e.g., to iterate over the
/// results within LookupResult.
NamedDecl **DeclsFound;
unsigned NumDeclsFound;
friend class CXXRecordDecl;
void ComputeDeclsFound();
bool lookupInBases(ASTContext &Context,
const CXXRecordDecl *Record,
CXXRecordDecl::BaseMatchesCallback *BaseMatches,
void *UserData);
public:
typedef std::list<CXXBasePath>::iterator paths_iterator;
typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
typedef NamedDecl **decl_iterator;
/// BasePaths - Construct a new BasePaths structure to record the
/// paths for a derived-to-base search.
explicit CXXBasePaths(bool FindAmbiguities = true,
bool RecordPaths = true,
bool DetectVirtual = true)
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
NumDeclsFound(0) { }
~CXXBasePaths() { delete [] DeclsFound; }
paths_iterator begin() { return Paths.begin(); }
paths_iterator end() { return Paths.end(); }
const_paths_iterator begin() const { return Paths.begin(); }
const_paths_iterator end() const { return Paths.end(); }
CXXBasePath& front() { return Paths.front(); }
const CXXBasePath& front() const { return Paths.front(); }
decl_iterator found_decls_begin();
decl_iterator found_decls_end();
/// \brief Determine whether the path from the most-derived type to the
/// given base type is ambiguous (i.e., it refers to multiple subobjects of
/// the same base type).
bool isAmbiguous(CanQualType BaseType);
/// \brief Whether we are finding multiple paths to detect ambiguities.
bool isFindingAmbiguities() const { return FindAmbiguities; }
/// \brief Whether we are recording paths.
bool isRecordingPaths() const { return RecordPaths; }
/// \brief Specify whether we should be recording paths or not.
void setRecordingPaths(bool RP) { RecordPaths = RP; }
/// \brief Whether we are detecting virtual bases.
bool isDetectingVirtual() const { return DetectVirtual; }
/// \brief The virtual base discovered on the path (if we are merely
/// detecting virtuals).
const RecordType* getDetectedVirtual() const {
return DetectedVirtual;
}
/// \brief Retrieve the type from which this base-paths search
/// began
CXXRecordDecl *getOrigin() const { return Origin; }
void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; }
/// \brief Clear the base-paths results.
void clear();
/// \brief Swap this data structure's contents with another CXXBasePaths
/// object.
void swap(CXXBasePaths &Other);
};
/// \brief Uniquely identifies a virtual method within a class
/// hierarchy by the method itself and a class subobject number.
struct UniqueVirtualMethod {
UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { }
UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
const CXXRecordDecl *InVirtualSubobject)
: Method(Method), Subobject(Subobject),
InVirtualSubobject(InVirtualSubobject) { }
/// \brief The overriding virtual method.
CXXMethodDecl *Method;
/// \brief The subobject in which the overriding virtual method
/// resides.
unsigned Subobject;
/// \brief The virtual base class subobject of which this overridden
/// virtual method is a part. Note that this records the closest
/// derived virtual base class subobject.
const CXXRecordDecl *InVirtualSubobject;
friend bool operator==(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
return X.Method == Y.Method && X.Subobject == Y.Subobject &&
X.InVirtualSubobject == Y.InVirtualSubobject;
}
friend bool operator!=(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
return !(X == Y);
}
};
/// \brief The set of methods that override a given virtual method in
/// each subobject where it occurs.
///
/// The first part of the pair is the subobject in which the
/// overridden virtual function occurs, while the second part of the
/// pair is the virtual method that overrides it (including the
/// subobject in which that virtual function occurs).
class OverridingMethods {
typedef SmallVector<UniqueVirtualMethod, 4> ValuesT;
typedef llvm::MapVector<unsigned, ValuesT> MapType;
MapType Overrides;
public:
// Iterate over the set of subobjects that have overriding methods.
typedef MapType::iterator iterator;
typedef MapType::const_iterator const_iterator;
iterator begin() { return Overrides.begin(); }
const_iterator begin() const { return Overrides.begin(); }
iterator end() { return Overrides.end(); }
const_iterator end() const { return Overrides.end(); }
unsigned size() const { return Overrides.size(); }
// Iterate over the set of overriding virtual methods in a given
// subobject.
typedef SmallVector<UniqueVirtualMethod, 4>::iterator
overriding_iterator;
typedef SmallVector<UniqueVirtualMethod, 4>::const_iterator
overriding_const_iterator;
// Add a new overriding method for a particular subobject.
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
// Add all of the overriding methods from "other" into overrides for
// this method. Used when merging the overrides from multiple base
// class subobjects.
void add(const OverridingMethods &Other);
// Replace all overriding virtual methods in all subobjects with the
// given virtual method.
void replaceAll(UniqueVirtualMethod Overriding);
};
/// \brief A mapping from each virtual member function to its set of
/// final overriders.
///
/// Within a class hierarchy for a given derived class, each virtual
/// member function in that hierarchy has one or more "final
/// overriders" (C++ [class.virtual]p2). A final overrider for a
/// virtual function "f" is the virtual function that will actually be
/// invoked when dispatching a call to "f" through the
/// vtable. Well-formed classes have a single final overrider for each
/// virtual function; in abstract classes, the final overrider for at
/// least one virtual function is a pure virtual function. Due to
/// multiple, virtual inheritance, it is possible for a class to have
/// more than one final overrider. Athough this is an error (per C++
/// [class.virtual]p2), it is not considered an error here: the final
/// overrider map can represent multiple final overriders for a
/// method, and it is up to the client to determine whether they are
/// problem. For example, the following class \c D has two final
/// overriders for the virtual function \c A::f(), one in \c C and one
/// in \c D:
///
/// \code
/// struct A { virtual void f(); };
/// struct B : virtual A { virtual void f(); };
/// struct C : virtual A { virtual void f(); };
/// struct D : B, C { };
/// \endcode
///
/// This data structure contaings a mapping from every virtual
/// function *that does not override an existing virtual function* and
/// in every subobject where that virtual function occurs to the set
/// of virtual functions that override it. Thus, the same virtual
/// function \c A::f can actually occur in multiple subobjects of type
/// \c A due to multiple inheritance, and may be overriden by
/// different virtual functions in each, as in the following example:
///
/// \code
/// struct A { virtual void f(); };
/// struct B : A { virtual void f(); };
/// struct C : A { virtual void f(); };
/// struct D : B, C { };
/// \endcode
///
/// Unlike in the previous example, where the virtual functions \c
/// B::f and \c C::f both overrode \c A::f in the same subobject of
/// type \c A, in this example the two virtual functions both override
/// \c A::f but in *different* subobjects of type A. This is
/// represented by numbering the subobjects in which the overridden
/// and the overriding virtual member functions are located. Subobject
/// 0 represents the virtua base class subobject of that type, while
/// subobject numbers greater than 0 refer to non-virtual base class
/// subobjects of that type.
class CXXFinalOverriderMap
: public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> { };
/// \brief A set of all the primary bases for a class.
class CXXIndirectPrimaryBaseSet
: public llvm::SmallSet<const CXXRecordDecl*, 32> { };
} // end namespace clang
#endif

View File

@@ -0,0 +1,740 @@
//===-- CanonicalType.h - C Language Family Type Representation -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the CanQual class template, which provides access to
// canonical types.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
#define LLVM_CLANG_AST_CANONICAL_TYPE_H
#include "clang/AST/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/type_traits.h"
#include <iterator>
namespace clang {
template<typename T> class CanProxy;
template<typename T> struct CanProxyAdaptor;
//----------------------------------------------------------------------------//
// Canonical, qualified type template
//----------------------------------------------------------------------------//
/// \brief Represents a canonical, potentially-qualified type.
///
/// The CanQual template is a lightweight smart pointer that provides access
/// to the canonical representation of a type, where all typedefs and other
/// syntactic sugar has been eliminated. A CanQualType may also have various
/// qualifiers (const, volatile, restrict) attached to it.
///
/// The template type parameter @p T is one of the Type classes (PointerType,
/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
/// type (or some subclass of that type). The typedef @c CanQualType is just
/// a shorthand for @c CanQual<Type>.
///
/// An instance of @c CanQual<T> can be implicitly converted to a
/// @c CanQual<U> when T is derived from U, which essentially provides an
/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
/// be implicitly converted to a QualType, but the reverse operation requires
/// a call to ASTContext::getCanonicalType().
///
///
template<typename T = Type>
class CanQual {
/// \brief The actual, canonical type.
QualType Stored;
public:
/// \brief Constructs a NULL canonical type.
CanQual() : Stored() { }
/// \brief Converting constructor that permits implicit upcasting of
/// canonical type pointers.
template<typename U>
CanQual(const CanQual<U>& Other,
typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type.
///
/// The underlying pointer must not be NULL.
const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
/// \brief Retrieve the underlying type pointer, which refers to a
/// canonical type, or NULL.
///
const T *getTypePtrOrNull() const {
return cast_or_null<T>(Stored.getTypePtrOrNull());
}
/// \brief Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
/// \brief Implicit conversion to bool.
operator bool() const { return !isNull(); }
bool isNull() const {
return Stored.isNull();
}
SplitQualType split() const { return Stored.split(); }
/// \brief Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
/// The getAs() function is typically used to try to downcast to a
/// more specific (canonical) type in the type system. For example:
///
/// @code
/// void f(CanQual<Type> T) {
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
/// // look at Ptr's pointee type
/// }
/// }
/// @endcode
///
/// \returns A proxy pointer to the same type, but with the specified
/// static type (@p U). If the dynamic type is not the specified static type
/// or a derived class thereof, a NULL canonical type.
template<typename U> CanProxy<U> getAs() const;
template<typename U> CanProxy<U> castAs() const;
/// \brief Overloaded arrow operator that produces a canonical type
/// proxy.
CanProxy<T> operator->() const;
/// \brief Retrieve all qualifiers.
Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
/// \brief Retrieve the const/volatile/restrict qualifiers.
unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
/// \brief Determines whether this type has any qualifiers
bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
bool isConstQualified() const {
return Stored.isLocalConstQualified();
}
bool isVolatileQualified() const {
return Stored.isLocalVolatileQualified();
}
bool isRestrictQualified() const {
return Stored.isLocalRestrictQualified();
}
/// \brief Determines if this canonical type is furthermore
/// canonical as a parameter. The parameter-canonicalization
/// process decays arrays to pointers and drops top-level qualifiers.
bool isCanonicalAsParam() const {
return Stored.isCanonicalAsParam();
}
/// \brief Retrieve the unqualified form of this type.
CanQual<T> getUnqualifiedType() const;
/// \brief Retrieves a version of this type with const applied.
/// Note that this does not always yield a canonical type.
QualType withConst() const {
return Stored.withConst();
}
/// \brief Determines whether this canonical type is more qualified than
/// the @p Other canonical type.
bool isMoreQualifiedThan(CanQual<T> Other) const {
return Stored.isMoreQualifiedThan(Other.Stored);
}
/// \brief Determines whether this canonical type is at least as qualified as
/// the @p Other canonical type.
bool isAtLeastAsQualifiedAs(CanQual<T> Other) const {
return Stored.isAtLeastAsQualifiedAs(Other.Stored);
}
/// \brief If the canonical type is a reference type, returns the type that
/// it refers to; otherwise, returns the type itself.
CanQual<Type> getNonReferenceType() const;
/// \brief Retrieve the internal representation of this canonical type.
void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
/// \brief Construct a canonical type from its internal representation.
static CanQual<T> getFromOpaquePtr(void *Ptr);
/// \brief Builds a canonical type from a QualType.
///
/// This routine is inherently unsafe, because it requires the user to
/// ensure that the given type is a canonical type with the correct
// (dynamic) type.
static CanQual<T> CreateUnsafe(QualType Other);
void dump() const { Stored.dump(); }
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getAsOpaquePtr());
}
};
template<typename T, typename U>
inline bool operator==(CanQual<T> x, CanQual<U> y) {
return x.getAsOpaquePtr() == y.getAsOpaquePtr();
}
template<typename T, typename U>
inline bool operator!=(CanQual<T> x, CanQual<U> y) {
return x.getAsOpaquePtr() != y.getAsOpaquePtr();
}
/// \brief Represents a canonical, potentially-qualified type.
typedef CanQual<Type> CanQualType;
inline CanQualType Type::getCanonicalTypeUnqualified() const {
return CanQualType::CreateUnsafe(getCanonicalTypeInternal());
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
CanQualType T) {
DB << static_cast<QualType>(T);
return DB;
}
//----------------------------------------------------------------------------//
// Internal proxy classes used by canonical types
//----------------------------------------------------------------------------//
#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \
CanQualType Accessor() const { \
return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
}
#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
Type Accessor() const { return this->getTypePtr()->Accessor(); }
/// \brief Base class of all canonical proxy types, which is responsible for
/// storing the underlying canonical type and providing basic conversions.
template<typename T>
class CanProxyBase {
protected:
CanQual<T> Stored;
public:
/// \brief Retrieve the pointer to the underlying Type
const T *getTypePtr() const { return Stored.getTypePtr(); }
/// \brief Implicit conversion to the underlying pointer.
///
/// Also provides the ability to use canonical type proxies in a Boolean
// context,e.g.,
/// @code
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
/// @endcode
operator const T*() const { return this->Stored.getTypePtrOrNull(); }
/// \brief Try to convert the given canonical type to a specific structural
/// type.
template<typename U> CanProxy<U> getAs() const {
return this->Stored.template getAs<U>();
}
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
// Type predicates
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
/// \brief Retrieve the proxy-adaptor type.
///
/// This arrow operator is used when CanProxyAdaptor has been specialized
/// for the given type T. In that case, we reference members of the
/// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
/// by the arrow operator in the primary CanProxyAdaptor template.
const CanProxyAdaptor<T> *operator->() const {
return static_cast<const CanProxyAdaptor<T> *>(this);
}
};
/// \brief Replacable canonical proxy adaptor class that provides the link
/// between a canonical type and the accessors of the type.
///
/// The CanProxyAdaptor is a replaceable class template that is instantiated
/// as part of each canonical proxy type. The primary template merely provides
/// redirection to the underlying type (T), e.g., @c PointerType. One can
/// provide specializations of this class template for each underlying type
/// that provide accessors returning canonical types (@c CanQualType) rather
/// than the more typical @c QualType, to propagate the notion of "canonical"
/// through the system.
template<typename T>
struct CanProxyAdaptor : CanProxyBase<T> { };
/// \brief Canonical proxy type returned when retrieving the members of a
/// canonical type or as the result of the @c CanQual<T>::getAs member
/// function.
///
/// The CanProxy type mainly exists as a proxy through which operator-> will
/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
/// type that provides canonical-type access to the fields of the type.
template<typename T>
class CanProxy : public CanProxyAdaptor<T> {
public:
/// \brief Build a NULL proxy.
CanProxy() { }
/// \brief Build a proxy to the given canonical type.
CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
/// \brief Implicit conversion to the stored canonical type.
operator CanQual<T>() const { return this->Stored; }
};
} // end namespace clang
namespace llvm {
/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
/// to return smart pointer (proxies?).
template<typename T>
struct simplify_type< ::clang::CanQual<T> > {
typedef const T *SimpleType;
static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) {
return Val.getTypePtr();
}
};
// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
template<typename T>
class PointerLikeTypeTraits<clang::CanQual<T> > {
public:
static inline void *getAsVoidPointer(clang::CanQual<T> P) {
return P.getAsOpaquePtr();
}
static inline clang::CanQual<T> getFromVoidPointer(void *P) {
return clang::CanQual<T>::getFromOpaquePtr(P);
}
// qualifier information is encoded in the low bits.
enum { NumLowBitsAvailable = 0 };
};
} // end namespace llvm
namespace clang {
//----------------------------------------------------------------------------//
// Canonical proxy adaptors for canonical type nodes.
//----------------------------------------------------------------------------//
/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
/// into an iterator over CanQualTypes.
template<typename InputIterator>
class CanTypeIterator {
InputIterator Iter;
public:
typedef CanQualType value_type;
typedef value_type reference;
typedef CanProxy<Type> pointer;
typedef typename std::iterator_traits<InputIterator>::difference_type
difference_type;
typedef typename std::iterator_traits<InputIterator>::iterator_category
iterator_category;
CanTypeIterator() : Iter() { }
explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
// Input iterator
reference operator*() const {
return CanQualType::CreateUnsafe(*Iter);
}
pointer operator->() const;
CanTypeIterator &operator++() {
++Iter;
return *this;
}
CanTypeIterator operator++(int) {
CanTypeIterator Tmp(*this);
++Iter;
return Tmp;
}
friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
return X.Iter == Y.Iter;
}
friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
return X.Iter != Y.Iter;
}
// Bidirectional iterator
CanTypeIterator &operator--() {
--Iter;
return *this;
}
CanTypeIterator operator--(int) {
CanTypeIterator Tmp(*this);
--Iter;
return Tmp;
}
// Random access iterator
reference operator[](difference_type n) const {
return CanQualType::CreateUnsafe(Iter[n]);
}
CanTypeIterator &operator+=(difference_type n) {
Iter += n;
return *this;
}
CanTypeIterator &operator-=(difference_type n) {
Iter -= n;
return *this;
}
friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
X += n;
return X;
}
friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
X += n;
return X;
}
friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
X -= n;
return X;
}
friend difference_type operator-(const CanTypeIterator &X,
const CanTypeIterator &Y) {
return X - Y;
}
};
template<>
struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
};
template<>
struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<BlockPointerType>
: public CanProxyBase<BlockPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<LValueReferenceType>
: public CanProxyBase<LValueReferenceType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<RValueReferenceType>
: public CanProxyBase<RValueReferenceType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<MemberPointerType>
: public CanProxyBase<MemberPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
};
// CanProxyAdaptors for arrays are intentionally unimplemented because
// they are not safe.
template<> struct CanProxyAdaptor<ArrayType>;
template<> struct CanProxyAdaptor<ConstantArrayType>;
template<> struct CanProxyAdaptor<IncompleteArrayType>;
template<> struct CanProxyAdaptor<VariableArrayType>;
template<> struct CanProxyAdaptor<DependentSizedArrayType>;
template<>
struct CanProxyAdaptor<DependentSizedExtVectorType>
: public CanProxyBase<DependentSizedExtVectorType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
};
template<>
struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
};
template<>
struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
};
template<>
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
};
template<>
struct CanProxyAdaptor<FunctionNoProtoType>
: public CanProxyBase<FunctionNoProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
};
template<>
struct CanProxyAdaptor<FunctionProtoType>
: public CanProxyBase<FunctionProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
CanQualType getArgType(unsigned i) const {
return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
}
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
typedef CanTypeIterator<FunctionProtoType::arg_type_iterator>
arg_type_iterator;
arg_type_iterator arg_type_begin() const {
return arg_type_iterator(this->getTypePtr()->arg_type_begin());
}
arg_type_iterator arg_type_end() const {
return arg_type_iterator(this->getTypePtr()->arg_type_end());
}
// Note: canonical function types never have exception specifications
};
template<>
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
};
template<>
struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
};
template <>
struct CanProxyAdaptor<UnaryTransformType>
: public CanProxyBase<UnaryTransformType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
};
template<>
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
};
template<>
struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
};
template<>
struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBeingDefined)
};
template<>
struct CanProxyAdaptor<TemplateTypeParmType>
: public CanProxyBase<TemplateTypeParmType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier)
};
template<>
struct CanProxyAdaptor<ObjCObjectType>
: public CanProxyBase<ObjCObjectType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *,
getInterface)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
typedef ObjCObjectPointerType::qual_iterator qual_iterator;
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
};
template<>
struct CanProxyAdaptor<ObjCObjectPointerType>
: public CanProxyBase<ObjCObjectPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
getInterfaceType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
typedef ObjCObjectPointerType::qual_iterator qual_iterator;
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
};
//----------------------------------------------------------------------------//
// Method and function definitions
//----------------------------------------------------------------------------//
template<typename T>
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
}
template<typename T>
inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
return RefType->getPointeeType();
else
return *this;
}
template<typename T>
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
CanQual<T> Result;
Result.Stored = QualType::getFromOpaquePtr(Ptr);
assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
Result.Stored.isCanonical()) && "Type is not canonical!");
return Result;
}
template<typename T>
CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
"Dynamic type does not meet the static type's requires");
CanQual<T> Result;
Result.Stored = Other;
return Result;
}
template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::getAs() const {
ArrayType_cannot_be_used_with_getAs<U> at;
(void)at;
if (Stored.isNull())
return CanProxy<U>();
if (isa<U>(Stored.getTypePtr()))
return CanQual<U>::CreateUnsafe(Stored);
return CanProxy<U>();
}
template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::castAs() const {
ArrayType_cannot_be_used_with_getAs<U> at;
(void)at;
assert(!Stored.isNull() && isa<U>(Stored.getTypePtr()));
return CanQual<U>::CreateUnsafe(Stored);
}
template<typename T>
CanProxy<T> CanQual<T>::operator->() const {
return CanProxy<T>(*this);
}
template<typename InputIterator>
typename CanTypeIterator<InputIterator>::pointer
CanTypeIterator<InputIterator>::operator->() const {
return CanProxy<Type>(*this);
}
}
#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H

View File

@@ -0,0 +1,228 @@
//===--- CharUnits.h - Character units for sizes and offsets ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the CharUnits class
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CHARUNITS_H
#define LLVM_CLANG_AST_CHARUNITS_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
namespace clang {
/// CharUnits - This is an opaque type for sizes expressed in character units.
/// Instances of this type represent a quantity as a multiple of the size
/// of the standard C type, char, on the target architecture. As an opaque
/// type, CharUnits protects you from accidentally combining operations on
/// quantities in bit units and character units.
///
/// It should be noted that characters and bytes are distinct concepts. Bytes
/// refer to addressable units of data storage on the target machine, and
/// characters are members of a set of elements used for the organization,
/// control, or representation of data. According to C99, bytes are allowed
/// to exceed characters in size, although currently, clang only supports
/// architectures where the two are the same size.
///
/// For portability, never assume that a target character is 8 bits wide. Use
/// CharUnit values wherever you calculate sizes, offsets, or alignments
/// in character units.
class CharUnits {
public:
typedef int64_t QuantityType;
private:
QuantityType Quantity;
explicit CharUnits(QuantityType C) : Quantity(C) {}
public:
/// CharUnits - A default constructor.
CharUnits() : Quantity(0) {}
/// Zero - Construct a CharUnits quantity of zero.
static CharUnits Zero() {
return CharUnits(0);
}
/// One - Construct a CharUnits quantity of one.
static CharUnits One() {
return CharUnits(1);
}
/// fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits fromQuantity(QuantityType Quantity) {
return CharUnits(Quantity);
}
// Compound assignment.
CharUnits& operator+= (const CharUnits &Other) {
Quantity += Other.Quantity;
return *this;
}
CharUnits& operator++ () {
++Quantity;
return *this;
}
CharUnits operator++ (int) {
return CharUnits(Quantity++);
}
CharUnits& operator-= (const CharUnits &Other) {
Quantity -= Other.Quantity;
return *this;
}
CharUnits& operator-- () {
--Quantity;
return *this;
}
CharUnits operator-- (int) {
return CharUnits(Quantity--);
}
// Comparison operators.
bool operator== (const CharUnits &Other) const {
return Quantity == Other.Quantity;
}
bool operator!= (const CharUnits &Other) const {
return Quantity != Other.Quantity;
}
// Relational operators.
bool operator< (const CharUnits &Other) const {
return Quantity < Other.Quantity;
}
bool operator<= (const CharUnits &Other) const {
return Quantity <= Other.Quantity;
}
bool operator> (const CharUnits &Other) const {
return Quantity > Other.Quantity;
}
bool operator>= (const CharUnits &Other) const {
return Quantity >= Other.Quantity;
}
// Other predicates.
/// isZero - Test whether the quantity equals zero.
bool isZero() const { return Quantity == 0; }
/// isOne - Test whether the quantity equals one.
bool isOne() const { return Quantity == 1; }
/// isPositive - Test whether the quantity is greater than zero.
bool isPositive() const { return Quantity > 0; }
/// isNegative - Test whether the quantity is less than zero.
bool isNegative() const { return Quantity < 0; }
/// isPowerOfTwo - Test whether the quantity is a power of two.
/// Zero is not a power of two.
bool isPowerOfTwo() const {
return (Quantity & -Quantity) == Quantity;
}
// Arithmetic operators.
CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);
}
CharUnits operator/ (QuantityType N) const {
return CharUnits(Quantity / N);
}
QuantityType operator/ (const CharUnits &Other) const {
return Quantity / Other.Quantity;
}
CharUnits operator% (QuantityType N) const {
return CharUnits(Quantity % N);
}
QuantityType operator% (const CharUnits &Other) const {
return Quantity % Other.Quantity;
}
CharUnits operator+ (const CharUnits &Other) const {
return CharUnits(Quantity + Other.Quantity);
}
CharUnits operator- (const CharUnits &Other) const {
return CharUnits(Quantity - Other.Quantity);
}
CharUnits operator- () const {
return CharUnits(-Quantity);
}
// Conversions.
/// getQuantity - Get the raw integer representation of this quantity.
QuantityType getQuantity() const { return Quantity; }
/// RoundUpToAlignment - Returns the next integer (mod 2**64) that is
/// greater than or equal to this quantity and is a multiple of \p Align.
/// Align must be non-zero.
CharUnits RoundUpToAlignment(const CharUnits &Align) {
return CharUnits(llvm::RoundUpToAlignment(Quantity,
Align.Quantity));
}
/// Given that this is a non-zero alignment value, what is the
/// alignment at the given offset?
CharUnits alignmentAtOffset(CharUnits offset) {
// alignment: 0010000
// offset: 1011100
// lowBits: 0001011
// result: 0000100
QuantityType lowBits = (Quantity-1) & (offset.Quantity-1);
return CharUnits((lowBits + 1) & ~lowBits);
}
}; // class CharUnit
} // namespace clang
inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
const clang::CharUnits &CU) {
return CU * Scale;
}
namespace llvm {
template<> struct DenseMapInfo<clang::CharUnits> {
static clang::CharUnits getEmptyKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
return clang::CharUnits::fromQuantity(Quantity);
}
static clang::CharUnits getTombstoneKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
return clang::CharUnits::fromQuantity(Quantity);
}
static unsigned getHashValue(const clang::CharUnits &CU) {
clang::CharUnits::QuantityType Quantity = CU.getQuantity();
return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
}
static bool isEqual(const clang::CharUnits &LHS,
const clang::CharUnits &RHS) {
return LHS == RHS;
}
};
template <> struct isPodLike<clang::CharUnits> {
static const bool value = true;
};
} // end namespace llvm
#endif // LLVM_CLANG_AST_CHARUNITS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
//===--- CommentBriefParser.h - Dumb comment parser -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a very simple Doxygen comment parser.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
#include "clang/AST/CommentLexer.h"
namespace clang {
namespace comments {
/// A very simple comment parser that extracts "a brief description".
///
/// Due to a variety of comment styles, it considers the following as "a brief
/// description", in order of priority:
/// \li a \\brief or \\short command,
/// \li the first paragraph,
/// \li a \\result or \\return or \\returns paragraph.
class BriefParser {
Lexer &L;
const CommandTraits &Traits;
/// Current lookahead token.
Token Tok;
SourceLocation ConsumeToken() {
SourceLocation Loc = Tok.getLocation();
L.lex(Tok);
return Loc;
}
public:
BriefParser(Lexer &L, const CommandTraits &Traits);
/// Return the best "brief description" we can find.
std::string Parse();
};
} // end namespace comments
} // end namespace clang
#endif

View File

@@ -0,0 +1,180 @@
//===--- CommentCommandTraits.h - Comment command properties ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the class that provides information about comment
// commands.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
/// \brief Information about a single command.
///
/// When reordering, adding or removing members please update the corresponding
/// TableGen backend.
struct CommandInfo {
unsigned getID() const {
return ID;
}
const char *Name;
/// Name of the command that ends the verbatim block.
const char *EndCommandName;
unsigned ID : 8;
/// Number of word-like arguments for a given block command, except for
/// \\param and \\tparam commands -- these have special argument parsers.
unsigned NumArgs : 4;
/// True if this command is a inline command (of any kind).
unsigned IsInlineCommand : 1;
/// True if this command is a block command (of any kind).
unsigned IsBlockCommand : 1;
/// True if this command is introducing a brief documentation
/// paragraph (\\brief or an alias).
unsigned IsBriefCommand : 1;
/// True if this command is \\returns or an alias.
unsigned IsReturnsCommand : 1;
/// True if this command is introducing documentation for a function
/// parameter (\\param or an alias).
unsigned IsParamCommand : 1;
/// True if this command is introducing documentation for
/// a template parameter (\\tparam or an alias).
unsigned IsTParamCommand : 1;
/// True if this command is \\deprecated or an alias.
unsigned IsDeprecatedCommand : 1;
/// \brief True if this is a \\headerfile-like command.
unsigned IsHeaderfileCommand : 1;
/// True if we don't want to warn about this command being passed an empty
/// paragraph. Meaningful only for block commands.
unsigned IsEmptyParagraphAllowed : 1;
/// \brief True if this command is a verbatim-like block command.
///
/// A verbatim-like block command eats every character (except line starting
/// decorations) until matching end command is seen or comment end is hit.
unsigned IsVerbatimBlockCommand : 1;
/// \brief True if this command is an end command for a verbatim-like block.
unsigned IsVerbatimBlockEndCommand : 1;
/// \brief True if this command is a verbatim line command.
///
/// A verbatim-like line command eats everything until a newline is seen or
/// comment end is hit.
unsigned IsVerbatimLineCommand : 1;
/// \brief True if this command contains a declaration for the entity being
/// documented.
///
/// For example:
/// \code
/// \fn void f(int a);
/// \endcode
unsigned IsDeclarationCommand : 1;
/// \brief True if verbatim-like line command is a function declaration.
unsigned IsFunctionDeclarationCommand : 1;
/// \brief True if block command is further describing a container API; such
/// as \@coclass, \@classdesign, etc.
unsigned IsRecordLikeDetailCommand : 1;
/// \brief True if block command is a container API; such as \@interface.
unsigned IsRecordLikeDeclarationCommand : 1;
/// \brief True if this command is unknown. This \c CommandInfo object was
/// created during parsing.
unsigned IsUnknownCommand : 1;
};
/// This class provides information about commands that can be used
/// in comments.
class CommandTraits {
public:
enum KnownCommandIDs {
#define COMMENT_COMMAND(NAME) KCI_##NAME,
#include "clang/AST/CommentCommandList.inc"
#undef COMMENT_COMMAND
KCI_Last
};
CommandTraits(llvm::BumpPtrAllocator &Allocator,
const CommentOptions &CommentOptions);
void registerCommentOptions(const CommentOptions &CommentOptions);
/// \returns a CommandInfo object for a given command name or
/// NULL if no CommandInfo object exists for this command.
const CommandInfo *getCommandInfoOrNULL(StringRef Name) const;
const CommandInfo *getCommandInfo(StringRef Name) const {
if (const CommandInfo *Info = getCommandInfoOrNULL(Name))
return Info;
llvm_unreachable("the command should be known");
}
const CommandInfo *getCommandInfo(unsigned CommandID) const;
const CommandInfo *registerUnknownCommand(StringRef CommandName);
const CommandInfo *registerBlockCommand(StringRef CommandName);
/// \returns a CommandInfo object for a given command name or
/// NULL if \c Name is not a builtin command.
static const CommandInfo *getBuiltinCommandInfo(StringRef Name);
/// \returns a CommandInfo object for a given command ID or
/// NULL if \c CommandID is not a builtin command.
static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID);
private:
CommandTraits(const CommandTraits &) LLVM_DELETED_FUNCTION;
void operator=(const CommandTraits &) LLVM_DELETED_FUNCTION;
const CommandInfo *getRegisteredCommandInfo(StringRef Name) const;
const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const;
CommandInfo *createCommandInfoWithName(StringRef CommandName);
unsigned NextID;
/// Allocator for CommandInfo objects.
llvm::BumpPtrAllocator &Allocator;
SmallVector<CommandInfo *, 4> RegisteredCommands;
};
} // end namespace comments
} // end namespace clang
#endif

View File

@@ -0,0 +1,29 @@
//===--- CommentDiagnostic.h - Diagnostics for the AST library --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H
#define LLVM_CLANG_COMMENTDIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
#define COMMENTSTART
#include "clang/Basic/DiagnosticCommentKinds.inc"
#undef DIAG
NUM_BUILTIN_COMMENT_DIAGNOSTICS
};
} // end namespace diag
} // end namespace clang
#endif

View File

@@ -0,0 +1,364 @@
//===--- CommentLexer.h - Lexer for structured comments ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines lexer for structured comments and supporting token class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H
#define LLVM_CLANG_AST_COMMENT_LEXER_H
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace comments {
class Lexer;
class TextTokenRetokenizer;
struct CommandInfo;
class CommandTraits;
namespace tok {
enum TokenKind {
eof,
newline,
text,
unknown_command, // Command that does not have an ID.
backslash_command, // Command with an ID, that used backslash marker.
at_command, // Command with an ID, that used 'at' marker.
verbatim_block_begin,
verbatim_block_line,
verbatim_block_end,
verbatim_line_name,
verbatim_line_text,
html_start_tag, // <tag
html_ident, // attr
html_equals, // =
html_quoted_string, // "blah\"blah" or 'blah\'blah'
html_greater, // >
html_slash_greater, // />
html_end_tag // </tag
};
} // end namespace tok
/// \brief Comment token.
class Token {
friend class Lexer;
friend class TextTokenRetokenizer;
/// The location of the token.
SourceLocation Loc;
/// The actual kind of the token.
tok::TokenKind Kind;
/// Length of the token spelling in comment. Can be 0 for synthenized
/// tokens.
unsigned Length;
/// Contains text value associated with a token.
const char *TextPtr;
/// Integer value associated with a token.
///
/// If the token is a konwn command, contains command ID and TextPtr is
/// unused (command spelling can be found with CommandTraits). Otherwise,
/// contains the length of the string that starts at TextPtr.
unsigned IntVal;
public:
SourceLocation getLocation() const LLVM_READONLY { return Loc; }
void setLocation(SourceLocation SL) { Loc = SL; }
SourceLocation getEndLocation() const LLVM_READONLY {
if (Length == 0 || Length == 1)
return Loc;
return Loc.getLocWithOffset(Length - 1);
}
tok::TokenKind getKind() const LLVM_READONLY { return Kind; }
void setKind(tok::TokenKind K) { Kind = K; }
bool is(tok::TokenKind K) const LLVM_READONLY { return Kind == K; }
bool isNot(tok::TokenKind K) const LLVM_READONLY { return Kind != K; }
unsigned getLength() const LLVM_READONLY { return Length; }
void setLength(unsigned L) { Length = L; }
StringRef getText() const LLVM_READONLY {
assert(is(tok::text));
return StringRef(TextPtr, IntVal);
}
void setText(StringRef Text) {
assert(is(tok::text));
TextPtr = Text.data();
IntVal = Text.size();
}
StringRef getUnknownCommandName() const LLVM_READONLY {
assert(is(tok::unknown_command));
return StringRef(TextPtr, IntVal);
}
void setUnknownCommandName(StringRef Name) {
assert(is(tok::unknown_command));
TextPtr = Name.data();
IntVal = Name.size();
}
unsigned getCommandID() const LLVM_READONLY {
assert(is(tok::backslash_command) || is(tok::at_command));
return IntVal;
}
void setCommandID(unsigned ID) {
assert(is(tok::backslash_command) || is(tok::at_command));
IntVal = ID;
}
unsigned getVerbatimBlockID() const LLVM_READONLY {
assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
return IntVal;
}
void setVerbatimBlockID(unsigned ID) {
assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
IntVal = ID;
}
StringRef getVerbatimBlockText() const LLVM_READONLY {
assert(is(tok::verbatim_block_line));
return StringRef(TextPtr, IntVal);
}
void setVerbatimBlockText(StringRef Text) {
assert(is(tok::verbatim_block_line));
TextPtr = Text.data();
IntVal = Text.size();
}
unsigned getVerbatimLineID() const LLVM_READONLY {
assert(is(tok::verbatim_line_name));
return IntVal;
}
void setVerbatimLineID(unsigned ID) {
assert(is(tok::verbatim_line_name));
IntVal = ID;
}
StringRef getVerbatimLineText() const LLVM_READONLY {
assert(is(tok::verbatim_line_text));
return StringRef(TextPtr, IntVal);
}
void setVerbatimLineText(StringRef Text) {
assert(is(tok::verbatim_line_text));
TextPtr = Text.data();
IntVal = Text.size();
}
StringRef getHTMLTagStartName() const LLVM_READONLY {
assert(is(tok::html_start_tag));
return StringRef(TextPtr, IntVal);
}
void setHTMLTagStartName(StringRef Name) {
assert(is(tok::html_start_tag));
TextPtr = Name.data();
IntVal = Name.size();
}
StringRef getHTMLIdent() const LLVM_READONLY {
assert(is(tok::html_ident));
return StringRef(TextPtr, IntVal);
}
void setHTMLIdent(StringRef Name) {
assert(is(tok::html_ident));
TextPtr = Name.data();
IntVal = Name.size();
}
StringRef getHTMLQuotedString() const LLVM_READONLY {
assert(is(tok::html_quoted_string));
return StringRef(TextPtr, IntVal);
}
void setHTMLQuotedString(StringRef Str) {
assert(is(tok::html_quoted_string));
TextPtr = Str.data();
IntVal = Str.size();
}
StringRef getHTMLTagEndName() const LLVM_READONLY {
assert(is(tok::html_end_tag));
return StringRef(TextPtr, IntVal);
}
void setHTMLTagEndName(StringRef Name) {
assert(is(tok::html_end_tag));
TextPtr = Name.data();
IntVal = Name.size();
}
void dump(const Lexer &L, const SourceManager &SM) const;
};
/// \brief Comment lexer.
class Lexer {
private:
Lexer(const Lexer &) LLVM_DELETED_FUNCTION;
void operator=(const Lexer &) LLVM_DELETED_FUNCTION;
/// Allocator for strings that are semantic values of tokens and have to be
/// computed (for example, resolved decimal character references).
llvm::BumpPtrAllocator &Allocator;
const CommandTraits &Traits;
const char *const BufferStart;
const char *const BufferEnd;
SourceLocation FileLoc;
const char *BufferPtr;
/// One past end pointer for the current comment. For BCPL comments points
/// to newline or BufferEnd, for C comments points to star in '*/'.
const char *CommentEnd;
enum LexerCommentState {
LCS_BeforeComment,
LCS_InsideBCPLComment,
LCS_InsideCComment,
LCS_BetweenComments
};
/// Low-level lexer state, track if we are inside or outside of comment.
LexerCommentState CommentState;
enum LexerState {
/// Lexing normal comment text
LS_Normal,
/// Finished lexing verbatim block beginning command, will lex first body
/// line.
LS_VerbatimBlockFirstLine,
/// Lexing verbatim block body line-by-line, skipping line-starting
/// decorations.
LS_VerbatimBlockBody,
/// Finished lexing verbatim line beginning command, will lex text (one
/// line).
LS_VerbatimLineText,
/// Finished lexing \verbatim <TAG \endverbatim part, lexing tag attributes.
LS_HTMLStartTag,
/// Finished lexing \verbatim </TAG \endverbatim part, lexing '>'.
LS_HTMLEndTag
};
/// Current lexing mode.
LexerState State;
/// If State is LS_VerbatimBlock, contains the name of verbatim end
/// command, including command marker.
SmallString<16> VerbatimBlockEndCommandName;
/// Given a character reference name (e.g., "lt"), return the character that
/// it stands for (e.g., "<").
StringRef resolveHTMLNamedCharacterReference(StringRef Name) const;
/// Given a Unicode codepoint as base-10 integer, return the character.
StringRef resolveHTMLDecimalCharacterReference(StringRef Name) const;
/// Given a Unicode codepoint as base-16 integer, return the character.
StringRef resolveHTMLHexCharacterReference(StringRef Name) const;
void formTokenWithChars(Token &Result, const char *TokEnd,
tok::TokenKind Kind) {
const unsigned TokLen = TokEnd - BufferPtr;
Result.setLocation(getSourceLocation(BufferPtr));
Result.setKind(Kind);
Result.setLength(TokLen);
#ifndef NDEBUG
Result.TextPtr = "<UNSET>";
Result.IntVal = 7;
#endif
BufferPtr = TokEnd;
}
void formTextToken(Token &Result, const char *TokEnd) {
StringRef Text(BufferPtr, TokEnd - BufferPtr);
formTokenWithChars(Result, TokEnd, tok::text);
Result.setText(Text);
}
SourceLocation getSourceLocation(const char *Loc) const {
assert(Loc >= BufferStart && Loc <= BufferEnd &&
"Location out of range for this buffer!");
const unsigned CharNo = Loc - BufferStart;
return FileLoc.getLocWithOffset(CharNo);
}
/// Eat string matching regexp \code \s*\* \endcode.
void skipLineStartingDecorations();
/// Lex stuff inside comments. CommentEnd should be set correctly.
void lexCommentText(Token &T);
void setupAndLexVerbatimBlock(Token &T,
const char *TextBegin,
char Marker, const CommandInfo *Info);
void lexVerbatimBlockFirstLine(Token &T);
void lexVerbatimBlockBody(Token &T);
void setupAndLexVerbatimLine(Token &T, const char *TextBegin,
const CommandInfo *Info);
void lexVerbatimLineText(Token &T);
void lexHTMLCharacterReference(Token &T);
void setupAndLexHTMLStartTag(Token &T);
void lexHTMLStartTag(Token &T);
void setupAndLexHTMLEndTag(Token &T);
void lexHTMLEndTag(Token &T);
public:
Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits,
SourceLocation FileLoc,
const char *BufferStart, const char *BufferEnd);
void lex(Token &T);
StringRef getSpelling(const Token &Tok,
const SourceManager &SourceMgr,
bool *Invalid = NULL) const;
};
} // end namespace comments
} // end namespace clang
#endif

View File

@@ -0,0 +1,129 @@
//===--- CommentParser.h - Doxygen comment parser ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Doxygen comment parser.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H
#define LLVM_CLANG_AST_COMMENT_PARSER_H
#include "clang/AST/Comment.h"
#include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentSema.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class SourceManager;
namespace comments {
class CommandTraits;
/// Doxygen comment parser.
class Parser {
Parser(const Parser &) LLVM_DELETED_FUNCTION;
void operator=(const Parser &) LLVM_DELETED_FUNCTION;
friend class TextTokenRetokenizer;
Lexer &L;
Sema &S;
/// Allocator for anything that goes into AST nodes.
llvm::BumpPtrAllocator &Allocator;
/// Source manager for the comment being parsed.
const SourceManager &SourceMgr;
DiagnosticsEngine &Diags;
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
const CommandTraits &Traits;
/// Current lookahead token. We can safely assume that all tokens are from
/// a single source file.
Token Tok;
/// A stack of additional lookahead tokens.
SmallVector<Token, 8> MoreLATokens;
void consumeToken() {
if (MoreLATokens.empty())
L.lex(Tok);
else {
Tok = MoreLATokens.back();
MoreLATokens.pop_back();
}
}
void putBack(const Token &OldTok) {
MoreLATokens.push_back(Tok);
Tok = OldTok;
}
void putBack(ArrayRef<Token> Toks) {
if (Toks.empty())
return;
MoreLATokens.push_back(Tok);
for (const Token *I = &Toks.back(),
*B = &Toks.front();
I != B; --I) {
MoreLATokens.push_back(*I);
}
Tok = Toks[0];
}
bool isTokBlockCommand() {
return (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) &&
Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand;
}
public:
Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const CommandTraits &Traits);
/// Parse arguments for \\param command.
void parseParamCommandArgs(ParamCommandComment *PC,
TextTokenRetokenizer &Retokenizer);
/// Parse arguments for \\tparam command.
void parseTParamCommandArgs(TParamCommandComment *TPC,
TextTokenRetokenizer &Retokenizer);
void parseBlockCommandArgs(BlockCommandComment *BC,
TextTokenRetokenizer &Retokenizer,
unsigned NumArgs);
BlockCommandComment *parseBlockCommand();
InlineCommandComment *parseInlineCommand();
HTMLStartTagComment *parseHTMLStartTag();
HTMLEndTagComment *parseHTMLEndTag();
BlockContentComment *parseParagraphOrBlockCommand();
VerbatimBlockComment *parseVerbatimBlock();
VerbatimLineComment *parseVerbatimLine();
BlockContentComment *parseBlockContent();
FullComment *parseFullComment();
};
} // end namespace comments
} // end namespace clang
#endif

View File

@@ -0,0 +1,255 @@
//===--- CommentSema.h - Doxygen comment semantic analysis ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the semantic analysis class for Doxygen comments.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H
#define LLVM_CLANG_AST_COMMENT_SEMA_H
#include "clang/AST/Comment.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class Decl;
class SourceMgr;
class Preprocessor;
namespace comments {
class CommandTraits;
class Sema {
Sema(const Sema &) LLVM_DELETED_FUNCTION;
void operator=(const Sema &) LLVM_DELETED_FUNCTION;
/// Allocator for AST nodes.
llvm::BumpPtrAllocator &Allocator;
/// Source manager for the comment being parsed.
const SourceManager &SourceMgr;
DiagnosticsEngine &Diags;
CommandTraits &Traits;
const Preprocessor *PP;
/// Information about the declaration this comment is attached to.
DeclInfo *ThisDeclInfo;
/// Comment AST nodes that correspond to parameter names in
/// \c TemplateParameters.
///
/// Contains a valid value if \c DeclInfo->IsFilled is true.
llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
/// AST node for the \\brief command and its aliases.
const BlockCommandComment *BriefCommand;
/// AST node for the \\returns command and its aliases.
const BlockCommandComment *ReturnsCommand;
/// AST node for the \\headerfile command.
const BlockCommandComment *HeaderfileCommand;
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
/// A stack of HTML tags that are currently open (not matched with closing
/// tags).
SmallVector<HTMLStartTagComment *, 8> HTMLOpenTags;
public:
Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
DiagnosticsEngine &Diags, CommandTraits &Traits,
const Preprocessor *PP);
void setDecl(const Decl *D);
/// Returns a copy of array, owned by Sema's allocator.
template<typename T>
ArrayRef<T> copyArray(ArrayRef<T> Source) {
size_t Size = Source.size();
if (Size != 0) {
T *Mem = Allocator.Allocate<T>(Size);
std::uninitialized_copy(Source.begin(), Source.end(), Mem);
return llvm::makeArrayRef(Mem, Size);
} else
return llvm::makeArrayRef(static_cast<T *>(NULL), 0);
}
ParagraphComment *actOnParagraphComment(
ArrayRef<InlineContentComment *> Content);
BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker);
void actOnBlockCommandArgs(BlockCommandComment *Command,
ArrayRef<BlockCommandComment::Argument> Args);
void actOnBlockCommandFinish(BlockCommandComment *Command,
ParagraphComment *Paragraph);
ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker);
void actOnParamCommandDirectionArg(ParamCommandComment *Command,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
void actOnParamCommandParamNameArg(ParamCommandComment *Command,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
void actOnParamCommandFinish(ParamCommandComment *Command,
ParagraphComment *Paragraph);
TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker);
void actOnTParamCommandParamNameArg(TParamCommandComment *Command,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
void actOnTParamCommandFinish(TParamCommandComment *Command,
ParagraphComment *Paragraph);
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
unsigned CommandID);
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
unsigned CommandID,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
SourceLocation LocEnd,
StringRef CommandName);
InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID);
TextComment *actOnText(SourceLocation LocBegin,
SourceLocation LocEnd,
StringRef Text);
VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc,
unsigned CommandID);
VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc,
StringRef Text);
void actOnVerbatimBlockFinish(VerbatimBlockComment *Block,
SourceLocation CloseNameLocBegin,
StringRef CloseName,
ArrayRef<VerbatimBlockLineComment *> Lines);
VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin,
unsigned CommandID,
SourceLocation TextBegin,
StringRef Text);
HTMLStartTagComment *actOnHTMLStartTagStart(SourceLocation LocBegin,
StringRef TagName);
void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag,
ArrayRef<HTMLStartTagComment::Attribute> Attrs,
SourceLocation GreaterLoc,
bool IsSelfClosing);
HTMLEndTagComment *actOnHTMLEndTag(SourceLocation LocBegin,
SourceLocation LocEnd,
StringRef TagName);
FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks);
void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
void checkReturnsCommand(const BlockCommandComment *Command);
/// Emit diagnostics about duplicate block commands that should be
/// used only once per comment, e.g., \\brief and \\returns.
void checkBlockCommandDuplicate(const BlockCommandComment *Command);
void checkDeprecatedCommand(const BlockCommandComment *Comment);
void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment);
void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment);
void checkContainerDecl(const BlockCommandComment *Comment);
/// Resolve parameter names to parameter indexes in function declaration.
/// Emit diagnostics about unknown parametrs.
void resolveParamCommandIndexes(const FullComment *FC);
bool isFunctionDecl();
bool isAnyFunctionDecl();
bool isFunctionPointerVarDecl();
bool isObjCMethodDecl();
bool isObjCPropertyDecl();
bool isTemplateOrSpecialization();
bool isRecordLikeDecl();
bool isClassOrStructDecl();
bool isUnionDecl();
bool isObjCInterfaceDecl();
bool isObjCProtocolDecl();
ArrayRef<const ParmVarDecl *> getParamVars();
/// Extract all important semantic information from
/// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members.
void inspectThisDecl();
/// Returns index of a function parameter with a given name.
unsigned resolveParmVarReference(StringRef Name,
ArrayRef<const ParmVarDecl *> ParamVars);
/// Returns index of a function parameter with the name closest to a given
/// typo.
unsigned correctTypoInParmVarReference(StringRef Typo,
ArrayRef<const ParmVarDecl *> ParamVars);
bool resolveTParamReference(StringRef Name,
const TemplateParameterList *TemplateParameters,
SmallVectorImpl<unsigned> *Position);
StringRef correctTypoInTParamReference(
StringRef Typo,
const TemplateParameterList *TemplateParameters);
InlineCommandComment::RenderKind
getInlineCommandRenderKind(StringRef Name) const;
};
} // end namespace comments
} // end namespace clang
#endif

View File

@@ -0,0 +1,70 @@
//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENTVISITOR_H
#define LLVM_CLANG_AST_COMMENTVISITOR_H
#include "clang/AST/Comment.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
template <typename T> struct make_ptr { typedef T *type; };
template <typename T> struct make_const_ptr { typedef const T *type; };
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class CommentVisitorBase {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->visit ## NAME(static_cast<PTR(CLASS)>(C))
RetTy visit(PTR(Comment) C) {
if (!C)
return RetTy();
switch (C->getCommentKind()) {
default: llvm_unreachable("Unknown comment kind!");
#define ABSTRACT_COMMENT(COMMENT)
#define COMMENT(CLASS, PARENT) \
case Comment::CLASS##Kind: DISPATCH(CLASS, CLASS);
#include "clang/AST/CommentNodes.inc"
#undef ABSTRACT_COMMENT
#undef COMMENT
}
}
// If the derived class does not implement a certain Visit* method, fall back
// on Visit* method for the superclass.
#define ABSTRACT_COMMENT(COMMENT) COMMENT
#define COMMENT(CLASS, PARENT) \
RetTy visit ## CLASS(PTR(CLASS) C) { DISPATCH(PARENT, PARENT); }
#include "clang/AST/CommentNodes.inc"
#undef ABSTRACT_COMMENT
#undef COMMENT
RetTy visitComment(PTR(Comment) C) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
template<typename ImplClass, typename RetTy=void>
class CommentVisitor :
public CommentVisitorBase<make_ptr, ImplClass, RetTy> {};
template<typename ImplClass, typename RetTy=void>
class ConstCommentVisitor :
public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {};
} // end namespace comments
} // end namespace clang
#endif

3337
thirdparty/clang/include/clang/AST/Decl.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
//===--- DeclAccessPair.h - A decl bundled with its path access -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DeclAccessPair class, which provides an
// efficient representation of a pair of a NamedDecl* and an
// AccessSpecifier. Generally the access specifier gives the
// natural access of a declaration when named in a class, as
// defined in C++ [class.access.base]p1.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H
#define LLVM_CLANG_AST_DECLACCESSPAIR_H
#include "clang/Basic/Specifiers.h"
#include "llvm/Support/DataTypes.h"
namespace clang {
class NamedDecl;
/// A POD class for pairing a NamedDecl* with an access specifier.
/// Can be put into unions.
class DeclAccessPair {
NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
enum { Mask = 0x3 };
public:
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
DeclAccessPair p;
p.set(D, AS);
return p;
}
NamedDecl *getDecl() const {
return (NamedDecl*) (~Mask & (uintptr_t) Ptr);
}
AccessSpecifier getAccess() const {
return AccessSpecifier(Mask & (uintptr_t) Ptr);
}
void setDecl(NamedDecl *D) {
set(D, getAccess());
}
void setAccess(AccessSpecifier AS) {
set(getDecl(), AS);
}
void set(NamedDecl *D, AccessSpecifier AS) {
Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) |
reinterpret_cast<uintptr_t>(D));
}
operator NamedDecl*() const { return getDecl(); }
NamedDecl *operator->() const { return getDecl(); }
};
}
// Take a moment to tell SmallVector that DeclAccessPair is POD.
namespace llvm {
template<typename> struct isPodLike;
template<> struct isPodLike<clang::DeclAccessPair> {
static const bool value = true;
};
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,239 @@
//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the data structures used in the implementation
// of DeclContext.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <algorithm>
namespace clang {
class DependentDiagnostic;
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
/// DeclsTy - When in vector form, this is what the Data pointer points to.
typedef SmallVector<NamedDecl *, 4> DeclsTy;
/// \brief The stored data, which will be either a pointer to a NamedDecl,
/// or a pointer to a vector.
llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
public:
StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (DeclsTy *RHSVec = RHS.getAsVector())
Data = new DeclsTy(*RHSVec);
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
if (DeclsTy *Vector = getAsVector())
delete Vector;
}
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
if (DeclsTy *Vector = getAsVector())
delete Vector;
Data = RHS.Data;
if (DeclsTy *RHSVec = RHS.getAsVector())
Data = new DeclsTy(*RHSVec);
return *this;
}
bool isNull() const { return Data.isNull(); }
NamedDecl *getAsDecl() const {
return Data.dyn_cast<NamedDecl *>();
}
DeclsTy *getAsVector() const {
return Data.dyn_cast<DeclsTy *>();
}
void setOnlyValue(NamedDecl *ND) {
assert(!getAsVector() && "Not inline");
Data = ND;
// Make sure that Data is a plain NamedDecl* so we can use its address
// at getLookupResult.
assert(*(NamedDecl **)&Data == ND &&
"PointerUnion mangles the NamedDecl pointer!");
}
void remove(NamedDecl *D) {
assert(!isNull() && "removing from empty list");
if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton");
(void)Singleton;
Data = (NamedDecl *)0;
return;
}
DeclsTy &Vec = *getAsVector();
DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
assert(I != Vec.end() && "list does not contain decl");
Vec.erase(I);
assert(std::find(Vec.begin(), Vec.end(), D)
== Vec.end() && "list still contains decl");
}
/// \brief Remove any declarations which were imported from an external
/// AST source.
void removeExternalDecls() {
if (isNull()) {
// Nothing to do.
} else if (NamedDecl *Singleton = getAsDecl()) {
if (Singleton->isFromASTFile())
*this = StoredDeclsList();
} else {
DeclsTy &Vec = *getAsVector();
Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
std::mem_fun(&Decl::isFromASTFile)),
Vec.end());
}
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
DeclContext::lookup_result getLookupResult() {
if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
DeclContext::lookup_iterator(0));
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
// Data is a raw pointer to a NamedDecl*, return it.
void *Ptr = &Data;
return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
}
assert(getAsVector() && "Must have a vector at this point");
DeclsTy &Vector = *getAsVector();
// Otherwise, we have a range result.
return DeclContext::lookup_result(Vector.begin(), Vector.end());
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(NamedDecl *D) {
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD))
return false;
setOnlyValue(D);
return true;
}
// Determine if this declaration is actually a redeclaration.
DeclsTy &Vec = *getAsVector();
for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) {
NamedDecl *OldD = *OD;
if (D->declarationReplaces(OldD)) {
*OD = D;
return true;
}
}
return false;
}
/// AddSubsequentDecl - This is called on the second and later decl when it is
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
// If this is the second decl added to the list, convert this to vector
// form.
if (NamedDecl *OldD = getAsDecl()) {
DeclsTy *VT = new DeclsTy();
VT->push_back(OldD);
Data = VT;
}
DeclsTy &Vec = *getAsVector();
// Using directives end up in a special entry which contains only
// other using directives, so all this logic is wasted for them.
// But avoiding the logic wastes time in the far-more-common case
// that we're *not* adding a new using directive.
// Tag declarations always go at the end of the list so that an
// iterator which points at the first tag will start a span of
// decls that only contains tags.
if (D->hasTagIdentifierNamespace())
Vec.push_back(D);
// Resolved using declarations go at the front of the list so that
// they won't show up in other lookup results. Unresolved using
// declarations (which are always in IDNS_Using | IDNS_Ordinary)
// follow that so that the using declarations will be contiguous.
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
DeclsTy::iterator I = Vec.begin();
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
while (I != Vec.end() &&
(*I)->getIdentifierNamespace() == Decl::IDNS_Using)
++I;
}
Vec.insert(I, D);
// All other declarations go at the end of the list, but before any
// tag declarations. But we can be clever about tag declarations
// because there can only ever be one in a scope.
} else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) {
NamedDecl *TagD = Vec.back();
Vec.back() = D;
Vec.push_back(TagD);
} else
Vec.push_back(D);
}
};
class StoredDeclsMap
: public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
public:
static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
private:
friend class ASTContext; // walks the chain deleting these
friend class DeclContext;
llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
};
class DependentStoredDeclsMap : public StoredDeclsMap {
public:
DependentStoredDeclsMap() : FirstDiagnostic(0) {}
private:
friend class DependentDiagnostic;
friend class DeclContext; // iterates over diagnostics
DependentDiagnostic *FirstDiagnostic;
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,238 @@
//===-- DeclFriend.h - Classes for C++ friend declarations -*- C++ -*------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the section of the AST representing C++ friend
// declarations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLFRIEND_H
#define LLVM_CLANG_AST_DECLFRIEND_H
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/Support/Compiler.h"
namespace clang {
/// FriendDecl - Represents the declaration of a friend entity,
/// which can be a function, a type, or a templated function or type.
// For example:
///
/// @code
/// template <typename T> class A {
/// friend int foo(T);
/// friend class B;
/// friend T; // only in C++0x
/// template <typename U> friend class C;
/// template <typename U> friend A& operator+=(A&, const U&) { ... }
/// };
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
class FriendDecl : public Decl {
virtual void anchor();
public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
private:
// The declaration that's a friend of this class.
FriendUnion Friend;
// A pointer to the next friend in the sequence.
LazyDeclPtr NextFriend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
/// True if this 'friend' declaration is unsupported. Eventually we
/// will support every possible friend declaration, but for now we
/// silently ignore some and set this flag to authorize all access.
bool UnsupportedFriend : 1;
// The number of "outer" template parameter lists in non-templatic
// (currently unsupported) friend type declarations, such as
// template <class T> friend class A<T>::B;
unsigned NumTPLists : 31;
// The tail-allocated friend type template parameter lists (if any).
TemplateParameterList* const *getTPLists() const {
return reinterpret_cast<TemplateParameterList* const *>(this + 1);
}
TemplateParameterList **getTPLists() {
return reinterpret_cast<TemplateParameterList**>(this + 1);
}
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL,
ArrayRef<TemplateParameterList*> FriendTypeTPLists)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
NextFriend(),
FriendLoc(FriendL),
UnsupportedFriend(false),
NumTPLists(FriendTypeTPLists.size()) {
for (unsigned i = 0; i < NumTPLists; ++i)
getTPLists()[i] = FriendTypeTPLists[i];
}
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
: Decl(Decl::Friend, Empty), NextFriend(),
NumTPLists(NumFriendTypeTPLists) { }
FriendDecl *getNextFriend() {
if (!NextFriend.isOffset())
return cast_or_null<FriendDecl>(NextFriend.get(0));
return getNextFriendSlowCase();
}
FriendDecl *getNextFriendSlowCase();
public:
static FriendDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL,
ArrayRef<TemplateParameterList*> FriendTypeTPLists
= ArrayRef<TemplateParameterList*>());
static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned FriendTypeNumTPLists);
/// If this friend declaration names an (untemplated but possibly
/// dependent) type, return the type; otherwise return null. This
/// is used for elaborated-type-specifiers and, in C++0x, for
/// arbitrary friend type declarations.
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
unsigned getFriendTypeNumTemplateParameterLists() const {
return NumTPLists;
}
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
assert(N < NumTPLists);
return getTPLists()[N];
}
/// If this friend declaration doesn't name a type, return the inner
/// declaration.
NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl*>();
}
/// Retrieves the location of the 'friend' keyword.
SourceLocation getFriendLoc() const {
return FriendLoc;
}
/// Retrieves the source range for the friend declaration.
SourceRange getSourceRange() const LLVM_READONLY {
if (NamedDecl *ND = getFriendDecl()) {
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
return FTD->getSourceRange();
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) {
if (DD->getOuterLocStart() != DD->getInnerLocStart())
return DD->getSourceRange();
}
return SourceRange(getFriendLoc(), ND->getLocEnd());
}
else if (TypeSourceInfo *TInfo = getFriendType()) {
SourceLocation StartL = (NumTPLists == 0)
? getFriendLoc()
: getTPLists()[0]->getTemplateLoc();
return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
}
else
return SourceRange(getFriendLoc(), getLocation());
}
/// Determines if this friend kind is unsupported.
bool isUnsupportedFriend() const {
return UnsupportedFriend;
}
void setUnsupportedFriend(bool Unsupported) {
UnsupportedFriend = Unsupported;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::Friend; }
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// An iterator over the friend declarations of a class.
class CXXRecordDecl::friend_iterator {
FriendDecl *Ptr;
friend class CXXRecordDecl;
explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
public:
friend_iterator() {}
typedef FriendDecl *value_type;
typedef FriendDecl *reference;
typedef FriendDecl *pointer;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
reference operator*() const { return Ptr; }
friend_iterator &operator++() {
assert(Ptr && "attempt to increment past end of friend list");
Ptr = Ptr->getNextFriend();
return *this;
}
friend_iterator operator++(int) {
friend_iterator tmp = *this;
++*this;
return tmp;
}
bool operator==(const friend_iterator &Other) const {
return Ptr == Other.Ptr;
}
bool operator!=(const friend_iterator &Other) const {
return Ptr != Other.Ptr;
}
friend_iterator &operator+=(difference_type N) {
assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
while (N--)
++*this;
return *this;
}
friend_iterator operator+(difference_type N) const {
friend_iterator tmp = *this;
tmp += N;
return tmp;
}
};
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
return friend_iterator(data().FirstFriend);
}
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
return friend_iterator(0);
}
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
assert(FD->NextFriend == 0 && "friend already has next friend?");
FD->NextFriend = data().FirstFriend;
data().FirstFriend = FD;
}
}
#endif

View File

@@ -0,0 +1,155 @@
//===--- DeclGroup.h - Classes for representing groups of Decls -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
#include "llvm/Support/DataTypes.h"
#include <cassert>
namespace clang {
class ASTContext;
class Decl;
class DeclGroup;
class DeclGroupIterator;
class DeclGroup {
// FIXME: Include a TypeSpecifier object.
union {
unsigned NumDecls;
Decl *Aligner;
};
private:
DeclGroup() : NumDecls(0) {}
DeclGroup(unsigned numdecls, Decl** decls);
public:
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
unsigned size() const { return NumDecls; }
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
return ((Decl**) (this+1))[i];
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
return ((Decl* const*) (this+1))[i];
}
};
class DeclGroupRef {
// Note this is not a PointerIntPair because we need the address of the
// non-group case to be valid as a Decl** for iteration.
enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
Decl* D;
Kind getKind() const {
return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
}
public:
DeclGroupRef() : D(0) {}
explicit DeclGroupRef(Decl* d) : D(d) {}
explicit DeclGroupRef(DeclGroup* dg)
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
if (NumDecls == 0)
return DeclGroupRef();
if (NumDecls == 1)
return DeclGroupRef(Decls[0]);
return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
}
typedef Decl** iterator;
typedef Decl* const * const_iterator;
bool isNull() const { return D == 0; }
bool isSingleDecl() const { return getKind() == SingleDeclKind; }
bool isDeclGroup() const { return getKind() == DeclGroupKind; }
Decl *getSingleDecl() {
assert(isSingleDecl() && "Isn't a declgroup");
return D;
}
const Decl *getSingleDecl() const {
return const_cast<DeclGroupRef*>(this)->getSingleDecl();
}
DeclGroup &getDeclGroup() {
assert(isDeclGroup() && "Isn't a declgroup");
return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
}
const DeclGroup &getDeclGroup() const {
return const_cast<DeclGroupRef*>(this)->getDeclGroup();
}
iterator begin() {
if (isSingleDecl())
return D ? &D : 0;
return &getDeclGroup()[0];
}
iterator end() {
if (isSingleDecl())
return D ? &D+1 : 0;
DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
const_iterator begin() const {
if (isSingleDecl())
return D ? &D : 0;
return &getDeclGroup()[0];
}
const_iterator end() const {
if (isSingleDecl())
return D ? &D+1 : 0;
const DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
void *getAsOpaquePtr() const { return D; }
static DeclGroupRef getFromOpaquePtr(void *Ptr) {
DeclGroupRef X;
X.D = static_cast<Decl*>(Ptr);
return X;
}
};
} // end clang namespace
namespace llvm {
// DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
template <typename T>
class PointerLikeTypeTraits;
template <>
class PointerLikeTypeTraits<clang::DeclGroupRef> {
public:
static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
return P.getAsOpaquePtr();
}
static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
return clang::DeclGroupRef::getFromOpaquePtr(P);
}
enum { NumLowBitsAvailable = 0 };
};
}
#endif

View File

@@ -0,0 +1,89 @@
//===-- DeclLookups.h - Low-level interface to all names in a DC-*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines DeclContext::all_lookups_iterator.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLLOOKUPS_H
#define LLVM_CLANG_AST_DECLLOOKUPS_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclarationName.h"
namespace clang {
/// all_lookups_iterator - An iterator that provides a view over the results
/// of looking up every possible name.
class DeclContext::all_lookups_iterator {
StoredDeclsMap::iterator It, End;
public:
typedef lookup_result value_type;
typedef lookup_result reference;
typedef lookup_result pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
all_lookups_iterator() {}
all_lookups_iterator(StoredDeclsMap::iterator It,
StoredDeclsMap::iterator End)
: It(It), End(End) {}
reference operator*() const { return It->second.getLookupResult(); }
pointer operator->() const { return It->second.getLookupResult(); }
all_lookups_iterator& operator++() {
// Filter out using directives. They don't belong as results from name
// lookup anyways, except as an implementation detail. Users of the API
// should not expect to get them (or worse, rely on it).
do {
++It;
} while (It != End &&
It->first == DeclarationName::getUsingDirectiveName());
return *this;
}
all_lookups_iterator operator++(int) {
all_lookups_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) {
return x.It == y.It;
}
friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) {
return x.It != y.It;
}
};
DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return all_lookups_iterator(Map->begin(), Map->end());
return all_lookups_iterator();
}
DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return all_lookups_iterator(Map->end(), Map->end());
return all_lookups_iterator();
}
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file defines OpenMP nodes.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_OPENMP_H
#define LLVM_CLANG_AST_OPENMP_H
#include "clang/AST/DeclBase.h"
#include "llvm/ADT/ArrayRef.h"
namespace clang {
class DeclRefExpr;
/// \brief This represents '#pragma omp threadprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are threadprivate:
///
/// \code
/// int a;
/// #pragma omp threadprivate(a)
/// struct A {
/// static int b;
/// #pragma omp threadprivate(b)
/// };
/// \endcode
///
class OMPThreadPrivateDecl : public Decl {
friend class ASTDeclReader;
unsigned NumVars;
virtual void anchor();
OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
Decl(DK, DC, L), NumVars(0) { }
ArrayRef<const DeclRefExpr *> getVars() const {
return ArrayRef<const DeclRefExpr *>(
reinterpret_cast<const DeclRefExpr * const *>(this + 1),
NumVars);
}
llvm::MutableArrayRef<DeclRefExpr *> getVars() {
return llvm::MutableArrayRef<DeclRefExpr *>(
reinterpret_cast<DeclRefExpr **>(this + 1),
NumVars);
}
void setVars(ArrayRef<DeclRefExpr *> VL);
public:
static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ArrayRef<DeclRefExpr *> VL);
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
unsigned ID, unsigned N);
typedef llvm::MutableArrayRef<DeclRefExpr *>::iterator varlist_iterator;
typedef ArrayRef<const DeclRefExpr *>::iterator varlist_const_iterator;
unsigned varlist_size() const { return NumVars; }
bool varlist_empty() const { return NumVars == 0; }
varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_iterator varlist_end() { return getVars().end(); }
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_const_iterator varlist_end() const { return getVars().end(); }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
};
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DeclVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLVISITOR_H
#define LLVM_CLANG_AST_DECLVISITOR_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
namespace clang {
namespace declvisitor {
template <typename T> struct make_ptr { typedef T *type; };
template <typename T> struct make_const_ptr { typedef const T *type; };
/// \brief A simple visitor class that helps create declaration visitors.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class Base {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D))
RetTy Visit(PTR(Decl) D) {
switch (D->getKind()) {
#define DECL(DERIVED, BASE) \
case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl);
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
}
llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
}
// If the implementation chooses not to implement a certain visit
// method, fall back to the parent.
#define DECL(DERIVED, BASE) \
RetTy Visit##DERIVED##Decl(PTR(DERIVED##Decl) D) { DISPATCH(BASE, BASE); }
#include "clang/AST/DeclNodes.inc"
RetTy VisitDecl(PTR(Decl) D) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
} // end namespace declvisitor
/// \brief A simple visitor class that helps create declaration visitors.
///
/// This class does not preserve constness of Decl pointers (see also
/// ConstDeclVisitor).
template<typename ImplClass, typename RetTy=void>
class DeclVisitor
: public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {};
/// \brief A simple visitor class that helps create declaration visitors.
///
/// This class preserves constness of Decl pointers (see also DeclVisitor).
template<typename ImplClass, typename RetTy=void>
class ConstDeclVisitor
: public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {};
} // end namespace clang
#endif // LLVM_CLANG_AST_DECLVISITOR_H

View File

@@ -0,0 +1,592 @@
//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the DeclarationName and DeclarationNameTable classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
#define LLVM_CLANG_AST_DECLARATIONNAME_H
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
template <typename T> struct DenseMapInfo;
}
namespace clang {
class ASTContext;
class CXXLiteralOperatorIdName;
class CXXOperatorIdName;
class CXXSpecialName;
class DeclarationNameExtra;
class IdentifierInfo;
class MultiKeywordSelector;
class QualType;
class Type;
class TypeSourceInfo;
class UsingDirectiveDecl;
template <typename> class CanQual;
typedef CanQual<Type> CanQualType;
/// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal
/// name. However, it also provides encodings for Objective-C
/// selectors (optimizing zero- and one-argument selectors, which make
/// up 78% percent of all selectors in Cocoa.h) and special C++ names
/// for constructors, destructors, and conversion functions.
class DeclarationName {
public:
/// NameKind - The kind of name this object contains.
enum NameKind {
Identifier,
ObjCZeroArgSelector,
ObjCOneArgSelector,
ObjCMultiArgSelector,
CXXConstructorName,
CXXDestructorName,
CXXConversionFunctionName,
CXXOperatorName,
CXXLiteralOperatorName,
CXXUsingDirective
};
private:
/// StoredNameKind - The kind of name that is actually stored in the
/// upper bits of the Ptr field. This is only used internally.
///
/// Note: The entries here are synchronized with the entries in Selector,
/// for efficient translation between the two.
enum StoredNameKind {
StoredIdentifier = 0,
StoredObjCZeroArgSelector = 0x01,
StoredObjCOneArgSelector = 0x02,
StoredDeclarationNameExtra = 0x03,
PtrMask = 0x03
};
/// Ptr - The lowest two bits are used to express what kind of name
/// we're actually storing, using the values of NameKind. Depending
/// on the kind of name this is, the upper bits of Ptr may have one
/// of several different meanings:
///
/// StoredIdentifier - The name is a normal identifier, and Ptr is
/// a normal IdentifierInfo pointer.
///
/// StoredObjCZeroArgSelector - The name is an Objective-C
/// selector with zero arguments, and Ptr is an IdentifierInfo
/// pointer pointing to the selector name.
///
/// StoredObjCOneArgSelector - The name is an Objective-C selector
/// with one argument, and Ptr is an IdentifierInfo pointer
/// pointing to the selector name.
///
/// StoredDeclarationNameExtra - Ptr is actually a pointer to a
/// DeclarationNameExtra structure, whose first value will tell us
/// whether this is an Objective-C selector, C++ operator-id name,
/// or special C++ name.
uintptr_t Ptr;
/// getStoredNameKind - Return the kind of object that is stored in
/// Ptr.
StoredNameKind getStoredNameKind() const {
return static_cast<StoredNameKind>(Ptr & PtrMask);
}
/// getExtra - Get the "extra" information associated with this
/// multi-argument selector or C++ special name.
DeclarationNameExtra *getExtra() const {
assert(getStoredNameKind() == StoredDeclarationNameExtra &&
"Declaration name does not store an Extra structure");
return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
}
/// getAsCXXSpecialName - If the stored pointer is actually a
/// CXXSpecialName, returns a pointer to it. Otherwise, returns
/// a NULL pointer.
CXXSpecialName *getAsCXXSpecialName() const {
NameKind Kind = getNameKind();
if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
return 0;
}
/// getAsCXXOperatorIdName
CXXOperatorIdName *getAsCXXOperatorIdName() const {
if (getNameKind() == CXXOperatorName)
return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
return 0;
}
CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
if (getNameKind() == CXXLiteralOperatorName)
return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
return 0;
}
// Construct a declaration name from the name of a C++ constructor,
// destructor, or conversion function.
DeclarationName(CXXSpecialName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
Ptr |= StoredDeclarationNameExtra;
}
// Construct a declaration name from the name of a C++ overloaded
// operator.
DeclarationName(CXXOperatorIdName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
Ptr |= StoredDeclarationNameExtra;
}
DeclarationName(CXXLiteralOperatorIdName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId");
Ptr |= StoredDeclarationNameExtra;
}
/// Construct a declaration name from a raw pointer.
DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
friend class DeclarationNameTable;
friend class NamedDecl;
/// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer
/// for this name as a void pointer if it's not an identifier.
void *getFETokenInfoAsVoidSlow() const;
public:
/// DeclarationName - Used to create an empty selector.
DeclarationName() : Ptr(0) { }
// Construct a declaration name from an IdentifierInfo *.
DeclarationName(const IdentifierInfo *II)
: Ptr(reinterpret_cast<uintptr_t>(II)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
}
// Construct a declaration name from an Objective-C selector.
DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) { }
/// getUsingDirectiveName - Return name for all using-directives.
static DeclarationName getUsingDirectiveName();
// operator bool() - Evaluates true when this declaration name is
// non-empty.
operator bool() const {
return ((Ptr & PtrMask) != 0) ||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
/// Predicate functions for querying what type of name this is.
bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; }
bool isObjCZeroArgSelector() const {
return getStoredNameKind() == StoredObjCZeroArgSelector;
}
bool isObjCOneArgSelector() const {
return getStoredNameKind() == StoredObjCOneArgSelector;
}
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
/// \brief Determines whether the name itself is dependent, e.g., because it
/// involves a C++ type that is itself dependent.
///
/// Note that this does not capture all of the notions of "dependent name",
/// because an identifier can be a dependent name if it is used as the
/// callee in a call expression with dependent arguments.
bool isDependentName() const;
/// getNameAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(raw_ostream &OS) const;
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
IdentifierInfo *getAsIdentifierInfo() const {
if (isIdentifier())
return reinterpret_cast<IdentifierInfo *>(Ptr);
return 0;
}
/// getAsOpaqueInteger - Get the representation of this declaration
/// name as an opaque integer.
uintptr_t getAsOpaqueInteger() const { return Ptr; }
/// getAsOpaquePtr - Get the representation of this declaration name as
/// an opaque pointer.
void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
static DeclarationName getFromOpaquePtr(void *P) {
DeclarationName N;
N.Ptr = reinterpret_cast<uintptr_t> (P);
return N;
}
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
return N;
}
/// getCXXNameType - If this name is one of the C++ names (of a
/// constructor, destructor, or conversion function), return the
/// type associated with that name.
QualType getCXXNameType() const;
/// getCXXOverloadedOperator - If this name is the name of an
/// overloadable operator in C++ (e.g., @c operator+), retrieve the
/// kind of overloaded operator.
OverloadedOperatorKind getCXXOverloadedOperator() const;
/// getCXXLiteralIdentifier - If this name is the name of a literal
/// operator, retrieve the identifier associated with it.
IdentifierInfo *getCXXLiteralIdentifier() const;
/// getObjCSelector - Get the Objective-C selector stored in this
/// declaration name.
Selector getObjCSelector() const {
assert((getNameKind() == ObjCZeroArgSelector ||
getNameKind() == ObjCOneArgSelector ||
getNameKind() == ObjCMultiArgSelector ||
Ptr == 0) && "Not a selector!");
return Selector(Ptr);
}
/// getFETokenInfo/setFETokenInfo - The language front-end is
/// allowed to associate arbitrary metadata with some kinds of
/// declaration names, including normal identifiers and C++
/// constructors, destructors, and conversion functions.
template<typename T>
T *getFETokenInfo() const {
if (const IdentifierInfo *Info = getAsIdentifierInfo())
return Info->getFETokenInfo<T>();
return static_cast<T*>(getFETokenInfoAsVoidSlow());
}
void setFETokenInfo(void *T);
/// operator== - Determine whether the specified names are identical..
friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr == RHS.Ptr;
}
/// operator!= - Determine whether the specified names are different.
friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr != RHS.Ptr;
}
static DeclarationName getEmptyMarker() {
return DeclarationName(uintptr_t(-1));
}
static DeclarationName getTombstoneMarker() {
return DeclarationName(uintptr_t(-2));
}
static int compare(DeclarationName LHS, DeclarationName RHS);
void dump() const;
};
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<(DeclarationName LHS, DeclarationName RHS) {
return DeclarationName::compare(LHS, RHS) < 0;
}
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
return DeclarationName::compare(LHS, RHS) > 0;
}
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
return DeclarationName::compare(LHS, RHS) <= 0;
}
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
return DeclarationName::compare(LHS, RHS) >= 0;
}
/// DeclarationNameTable - Used to store and retrieve DeclarationName
/// instances for the various kinds of declaration names, e.g., normal
/// identifiers, C++ constructor names, etc. This class contains
/// uniqued versions of each of the C++ special names, which can be
/// retrieved using its member functions (e.g.,
/// getCXXConstructorName).
class DeclarationNameTable {
const ASTContext &Ctx;
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
CXXOperatorIdName *CXXOperatorNames; // Operator names
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
DeclarationNameTable(const DeclarationNameTable&) LLVM_DELETED_FUNCTION;
void operator=(const DeclarationNameTable&) LLVM_DELETED_FUNCTION;
public:
DeclarationNameTable(const ASTContext &C);
~DeclarationNameTable();
/// getIdentifier - Create a declaration name that is a simple
/// identifier.
DeclarationName getIdentifier(const IdentifierInfo *ID) {
return DeclarationName(ID);
}
/// getCXXConstructorName - Returns the name of a C++ constructor
/// for the given Type.
DeclarationName getCXXConstructorName(CanQualType Ty);
/// getCXXDestructorName - Returns the name of a C++ destructor
/// for the given Type.
DeclarationName getCXXDestructorName(CanQualType Ty);
/// getCXXConversionFunctionName - Returns the name of a C++
/// conversion function for the given Type.
DeclarationName getCXXConversionFunctionName(CanQualType Ty);
/// getCXXSpecialName - Returns a declaration name for special kind
/// of C++ name, e.g., for a constructor, destructor, or conversion
/// function.
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
CanQualType Ty);
/// getCXXOperatorName - Get the name of the overloadable C++
/// operator corresponding to Op.
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
/// getCXXLiteralOperatorName - Get the name of the literal operator function
/// with II as the identifier.
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};
/// DeclarationNameLoc - Additional source/type location info
/// for a declaration name. Needs a DeclarationName in order
/// to be interpreted correctly.
struct DeclarationNameLoc {
// The source location for identifier stored elsewhere.
// struct {} Identifier;
// Type info for constructors, destructors and conversion functions.
// Locations (if any) for the tilde (destructor) or operator keyword
// (conversion) are stored elsewhere.
struct NT {
TypeSourceInfo* TInfo;
};
// The location (if any) of the operator keyword is stored elsewhere.
struct CXXOpName {
unsigned BeginOpNameLoc;
unsigned EndOpNameLoc;
};
// The location (if any) of the operator keyword is stored elsewhere.
struct CXXLitOpName {
unsigned OpNameLoc;
};
// struct {} CXXUsingDirective;
// struct {} ObjCZeroArgSelector;
// struct {} ObjCOneArgSelector;
// struct {} ObjCMultiArgSelector;
union {
struct NT NamedType;
struct CXXOpName CXXOperatorName;
struct CXXLitOpName CXXLiteralOperatorName;
};
DeclarationNameLoc(DeclarationName Name);
// FIXME: this should go away once all DNLocs are properly initialized.
DeclarationNameLoc() { memset((void*) this, 0, sizeof(*this)); }
}; // struct DeclarationNameLoc
/// DeclarationNameInfo - A collector data type for bundling together
/// a DeclarationName and the correspnding source/type location info.
struct DeclarationNameInfo {
private:
/// Name - The declaration name, also encoding name kind.
DeclarationName Name;
/// Loc - The main source location for the declaration name.
SourceLocation NameLoc;
/// Info - Further source/type location info for special kinds of names.
DeclarationNameLoc LocInfo;
public:
// FIXME: remove it.
DeclarationNameInfo() {}
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
: Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
DeclarationNameLoc LocInfo)
: Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
/// getName - Returns the embedded declaration name.
DeclarationName getName() const { return Name; }
/// setName - Sets the embedded declaration name.
void setName(DeclarationName N) { Name = N; }
/// getLoc - Returns the main location of the declaration name.
SourceLocation getLoc() const { return NameLoc; }
/// setLoc - Sets the main location of the declaration name.
void setLoc(SourceLocation L) { NameLoc = L; }
const DeclarationNameLoc &getInfo() const { return LocInfo; }
DeclarationNameLoc &getInfo() { return LocInfo; }
void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
/// getNamedTypeInfo - Returns the source type info associated to
/// the name. Assumes it is a constructor, destructor or conversion.
TypeSourceInfo *getNamedTypeInfo() const {
assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
return LocInfo.NamedType.TInfo;
}
/// setNamedTypeInfo - Sets the source type info associated to
/// the name. Assumes it is a constructor, destructor or conversion.
void setNamedTypeInfo(TypeSourceInfo *TInfo) {
assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
LocInfo.NamedType.TInfo = TInfo;
}
/// getCXXOperatorNameRange - Gets the range of the operator name
/// (without the operator keyword). Assumes it is a (non-literal) operator.
SourceRange getCXXOperatorNameRange() const {
assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
return SourceRange(
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
);
}
/// setCXXOperatorNameRange - Sets the range of the operator name
/// (without the operator keyword). Assumes it is a C++ operator.
void setCXXOperatorNameRange(SourceRange R) {
assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
}
/// getCXXLiteralOperatorNameLoc - Returns the location of the literal
/// operator name (not the operator keyword).
/// Assumes it is a literal operator.
SourceLocation getCXXLiteralOperatorNameLoc() const {
assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
return SourceLocation::
getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
}
/// setCXXLiteralOperatorNameLoc - Sets the location of the literal
/// operator name (not the operator keyword).
/// Assumes it is a literal operator.
void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
}
/// \brief Determine whether this name involves a template parameter.
bool isInstantiationDependent() const;
/// \brief Determine whether this name contains an unexpanded
/// parameter pack.
bool containsUnexpandedParameterPack() const;
/// getAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(raw_ostream &OS) const;
/// getBeginLoc - Retrieve the location of the first token.
SourceLocation getBeginLoc() const { return NameLoc; }
/// getEndLoc - Retrieve the location of the last token.
SourceLocation getEndLoc() const;
/// getSourceRange - The range of the declaration name.
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getLocStart(), getLocEnd());
}
SourceLocation getLocStart() const LLVM_READONLY {
return getBeginLoc();
}
SourceLocation getLocEnd() const LLVM_READONLY {
SourceLocation EndLoc = getEndLoc();
return EndLoc.isValid() ? EndLoc : getLocStart();
}
};
/// Insertion operator for diagnostics. This allows sending DeclarationName's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
DeclarationName N) {
DB.AddTaggedVal(N.getAsOpaqueInteger(),
DiagnosticsEngine::ak_declarationname);
return DB;
}
/// Insertion operator for partial diagnostics. This allows binding
/// DeclarationName's into a partial diagnostic with <<.
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
DeclarationName N) {
PD.AddTaggedVal(N.getAsOpaqueInteger(),
DiagnosticsEngine::ak_declarationname);
return PD;
}
inline raw_ostream &operator<<(raw_ostream &OS,
DeclarationNameInfo DNInfo) {
DNInfo.printName(OS);
return OS;
}
} // end namespace clang
namespace llvm {
/// Define DenseMapInfo so that DeclarationNames can be used as keys
/// in DenseMap and DenseSets.
template<>
struct DenseMapInfo<clang::DeclarationName> {
static inline clang::DeclarationName getEmptyKey() {
return clang::DeclarationName::getEmptyMarker();
}
static inline clang::DeclarationName getTombstoneKey() {
return clang::DeclarationName::getTombstoneMarker();
}
static unsigned getHashValue(clang::DeclarationName Name) {
return DenseMapInfo<void*>::getHashValue(Name.getAsOpaquePtr());
}
static inline bool
isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
return LHS == RHS;
}
};
template <>
struct isPodLike<clang::DeclarationName> { static const bool value = true; };
} // end namespace llvm
#endif

View File

@@ -0,0 +1,190 @@
//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces for diagnostics which may or may
// fire based on how a template is instantiated.
//
// At the moment, the only consumer of this interface is access
// control.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/Type.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
namespace clang {
class ASTContext;
class CXXRecordDecl;
class NamedDecl;
/// A dependently-generated diagnostic.
class DependentDiagnostic {
public:
enum AccessNonce { Access = 0 };
static DependentDiagnostic *Create(ASTContext &Context,
DeclContext *Parent,
AccessNonce _,
SourceLocation Loc,
bool IsMemberAccess,
AccessSpecifier AS,
NamedDecl *TargetDecl,
CXXRecordDecl *NamingClass,
QualType BaseObjectType,
const PartialDiagnostic &PDiag) {
DependentDiagnostic *DD = Create(Context, Parent, PDiag);
DD->AccessData.Loc = Loc.getRawEncoding();
DD->AccessData.IsMember = IsMemberAccess;
DD->AccessData.Access = AS;
DD->AccessData.TargetDecl = TargetDecl;
DD->AccessData.NamingClass = NamingClass;
DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
return DD;
}
unsigned getKind() const {
return Access;
}
bool isAccessToMember() const {
assert(getKind() == Access);
return AccessData.IsMember;
}
AccessSpecifier getAccess() const {
assert(getKind() == Access);
return AccessSpecifier(AccessData.Access);
}
SourceLocation getAccessLoc() const {
assert(getKind() == Access);
return SourceLocation::getFromRawEncoding(AccessData.Loc);
}
NamedDecl *getAccessTarget() const {
assert(getKind() == Access);
return AccessData.TargetDecl;
}
NamedDecl *getAccessNamingClass() const {
assert(getKind() == Access);
return AccessData.NamingClass;
}
QualType getAccessBaseObjectType() const {
assert(getKind() == Access);
return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
}
const PartialDiagnostic &getDiagnostic() const {
return Diag;
}
private:
DependentDiagnostic(const PartialDiagnostic &PDiag,
PartialDiagnostic::Storage *Storage)
: Diag(PDiag, Storage) {}
static DependentDiagnostic *Create(ASTContext &Context,
DeclContext *Parent,
const PartialDiagnostic &PDiag);
friend class DependentStoredDeclsMap;
friend class DeclContext::ddiag_iterator;
DependentDiagnostic *NextDiagnostic;
PartialDiagnostic Diag;
struct {
unsigned Loc;
unsigned Access : 2;
unsigned IsMember : 1;
NamedDecl *TargetDecl;
CXXRecordDecl *NamingClass;
void *BaseObjectType;
} AccessData;
};
///
/// An iterator over the dependent diagnostics in a dependent context.
class DeclContext::ddiag_iterator {
public:
ddiag_iterator() : Ptr(0) {}
explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
typedef DependentDiagnostic *value_type;
typedef DependentDiagnostic *reference;
typedef DependentDiagnostic *pointer;
typedef int difference_type;
typedef std::forward_iterator_tag iterator_category;
reference operator*() const { return Ptr; }
ddiag_iterator &operator++() {
assert(Ptr && "attempt to increment past end of diag list");
Ptr = Ptr->NextDiagnostic;
return *this;
}
ddiag_iterator operator++(int) {
ddiag_iterator tmp = *this;
++*this;
return tmp;
}
bool operator==(ddiag_iterator Other) const {
return Ptr == Other.Ptr;
}
bool operator!=(ddiag_iterator Other) const {
return Ptr != Other.Ptr;
}
ddiag_iterator &operator+=(difference_type N) {
assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
while (N--)
++*this;
return *this;
}
ddiag_iterator operator+(difference_type N) const {
ddiag_iterator tmp = *this;
tmp += N;
return tmp;
}
private:
DependentDiagnostic *Ptr;
};
inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
assert(isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
const DependentStoredDeclsMap *Map
= static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
if (!Map) return ddiag_iterator();
return ddiag_iterator(Map->FirstDiagnostic);
}
inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
return ddiag_iterator();
}
}
#endif

View File

@@ -0,0 +1,86 @@
//===--- EvaluatedExprVisitor.h - Evaluated expression visitor --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the EvaluatedExprVisitor class template, which visits
// the potentially-evaluated subexpressions of a potentially-evaluated
// expression.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
#define LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtVisitor.h"
namespace clang {
class ASTContext;
/// \brief Given a potentially-evaluated expression, this visitor visits all
/// of its potentially-evaluated subexpressions, recursively.
template<typename ImplClass>
class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
ASTContext &Context;
public:
explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
// Expressions that have no potentially-evaluated subexpressions (but may have
// other sub-expressions).
void VisitDeclRefExpr(DeclRefExpr *E) { }
void VisitOffsetOfExpr(OffsetOfExpr *E) { }
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { }
void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { }
void VisitBlockExpr(BlockExpr *E) { }
void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
void VisitMemberExpr(MemberExpr *E) {
// Only the base matters.
return this->Visit(E->getBase());
}
void VisitChooseExpr(ChooseExpr *E) {
// Don't visit either child expression if the condition is dependent.
if (E->getCond()->isValueDependent())
return;
// Only the selected subexpression matters; the other one is not evaluated.
return this->Visit(E->getChosenSubExpr(Context));
}
void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
// Only the actual initializer matters; the designators are all constant
// expressions.
return this->Visit(E->getInit());
}
void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
if (E->isPotentiallyEvaluated())
return this->Visit(E->getExprOperand());
}
void VisitCallExpr(CallExpr *CE) {
if (!CE->isUnevaluatedBuiltinCall(Context))
return static_cast<ImplClass*>(this)->VisitExpr(CE);
}
/// \brief The basis case walks all of the children of the statement or
/// expression, assuming they are all potentially evaluated.
void VisitStmt(Stmt *S) {
for (Stmt::child_range C = S->children(); C; ++C)
if (*C)
this->Visit(*C);
}
};
}
#endif // LLVM_CLANG_AST_EVALUATEDEXPRVISITOR_H

4715
thirdparty/clang/include/clang/AST/Expr.h vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,539 @@
//===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ExternalASTSource interface, which enables
// construction of AST nodes from some external source.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclBase.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class ASTConsumer;
class CXXBaseSpecifier;
class DeclarationName;
class ExternalSemaSource; // layering violation required for downcasting
class FieldDecl;
class Module;
class NamedDecl;
class RecordDecl;
class Selector;
class Stmt;
class TagDecl;
/// \brief Enumeration describing the result of loading information from
/// an external source.
enum ExternalLoadResult {
/// \brief Loading the external information has succeeded.
ELR_Success,
/// \brief Loading the external information has failed.
ELR_Failure,
/// \brief The external information has already been loaded, and therefore
/// no additional processing is required.
ELR_AlreadyLoaded
};
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
/// external source, such as a precompiled header. External AST
/// sources can resolve types and declarations from abstract IDs into
/// actual type and declaration nodes, and read parts of declaration
/// contexts.
class ExternalASTSource {
/// \brief Whether this AST source also provides information for
/// semantic analysis.
bool SemaSource;
friend class ExternalSemaSource;
public:
ExternalASTSource() : SemaSource(false) { }
virtual ~ExternalASTSource();
/// \brief RAII class for safely pairing a StartedDeserializing call
/// with FinishedDeserializing.
class Deserializing {
ExternalASTSource *Source;
public:
explicit Deserializing(ExternalASTSource *source) : Source(source) {
assert(Source);
Source->StartedDeserializing();
}
~Deserializing() {
Source->FinishedDeserializing();
}
};
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
///
/// This method only needs to be implemented if the AST source ever
/// passes back decl sets as VisibleDeclaration objects.
///
/// The default implementation of this method is a no-op.
virtual Decl *GetExternalDecl(uint32_t ID);
/// \brief Resolve a selector ID into a selector.
///
/// This operation only needs to be implemented if the AST source
/// returns non-zero for GetNumKnownSelectors().
///
/// The default implementation of this method is a no-op.
virtual Selector GetExternalSelector(uint32_t ID);
/// \brief Returns the number of selectors known to the external AST
/// source.
///
/// The default implementation of this method is a no-op.
virtual uint32_t GetNumExternalSelectors();
/// \brief Resolve the offset of a statement in the decl stream into
/// a statement.
///
/// This operation is meant to be used via a LazyOffsetPtr. It only
/// needs to be implemented if the AST source uses methods like
/// FunctionDecl::setLazyBody when building decls.
///
/// The default implementation of this method is a no-op.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
/// \brief Resolve the offset of a set of C++ base specifiers in the decl
/// stream into an array of specifiers.
///
/// The default implementation of this method is a no-op.
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
/// \brief Update an out-of-date identifier.
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { }
/// \brief Find all declarations with the given name in the given context,
/// and add them to the context by calling SetExternalVisibleDeclsForName
/// or SetNoExternalVisibleDeclsForName.
/// \return \c true if any declarations might have been found, \c false if
/// we definitely have no declarations with tbis name.
///
/// The default implementation of this method is a no-op returning \c false.
virtual bool
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
/// \brief Ensures that the table of all visible declarations inside this
/// context is up to date.
///
/// The default implementation of this function is a no-op.
virtual void completeVisibleDeclsMap(const DeclContext *DC);
/// \brief Retrieve the module that corresponds to the given module ID.
virtual Module *getModule(unsigned ID) { return 0; }
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
/// \param isKindWeWant a predicate function that returns true if the passed
/// declaration kind is one we are looking for. If NULL, all declarations
/// are returned.
///
/// \return an indication of whether the load succeeded or failed.
///
/// The default implementation of this method is a no-op.
virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Result);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
///
/// \return true if an error occurred
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, 0, Result);
}
template <typename DeclTy>
ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
}
/// \brief Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
/// a range.
virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
SmallVectorImpl<Decl *> &Decls) {}
/// \brief Gives the external AST source an opportunity to complete
/// an incomplete type.
virtual void CompleteType(TagDecl *Tag) {}
/// \brief Gives the external AST source an opportunity to complete an
/// incomplete Objective-C class.
///
/// This routine will only be invoked if the "externally completed" bit is
/// set on the ObjCInterfaceDecl via the function
/// \c ObjCInterfaceDecl::setExternallyCompleted().
virtual void CompleteType(ObjCInterfaceDecl *Class) { }
/// \brief Loads comment ranges.
virtual void ReadComments() { }
/// \brief Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void StartedDeserializing() { }
/// \brief Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void FinishedDeserializing() { }
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
/// The default implementation of this method is a no-op.
virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
/// \brief Print any statistics that have been gathered regarding
/// the external AST source.
///
/// The default implementation of this method is a no-op.
virtual void PrintStats();
/// \brief Perform layout on the given record.
///
/// This routine allows the external AST source to provide an specific
/// layout for a record, overriding the layout that would normally be
/// constructed. It is intended for clients who receive specific layout
/// details rather than source code (such as LLDB). The client is expected
/// to fill in the field offsets, base offsets, virtual base offsets, and
/// complete object size.
///
/// \param Record The record whose layout is being requested.
///
/// \param Size The final size of the record, in bits.
///
/// \param Alignment The final alignment of the record, in bits.
///
/// \param FieldOffsets The offset of each of the fields within the record,
/// expressed in bits. All of the fields must be provided with offsets.
///
/// \param BaseOffsets The offset of each of the direct, non-virtual base
/// classes. If any bases are not given offsets, the bases will be laid
/// out according to the ABI.
///
/// \param VirtualBaseOffsets The offset of each of the virtual base classes
/// (either direct or not). If any bases are not given offsets, the bases will be laid
/// out according to the ABI.
///
/// \returns true if the record layout was provided, false otherwise.
virtual bool
layoutRecordType(const RecordDecl *Record,
uint64_t &Size, uint64_t &Alignment,
llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)
{
return false;
}
//===--------------------------------------------------------------------===//
// Queries for performance analysis.
//===--------------------------------------------------------------------===//
struct MemoryBufferSizes {
size_t malloc_bytes;
size_t mmap_bytes;
MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
: malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
};
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
MemoryBufferSizes getMemoryBufferSizes() const {
MemoryBufferSizes sizes(0, 0);
getMemoryBufferSizes(sizes);
return sizes;
}
virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
protected:
static DeclContextLookupResult
SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
ArrayRef<NamedDecl*> Decls);
static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name);
};
/// \brief A lazy pointer to an AST node (of base type T) that resides
/// within an external AST source.
///
/// The AST node is identified within the external AST source by a
/// 63-bit offset, and can be retrieved via an operation on the
/// external AST source itself.
template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
struct LazyOffsetPtr {
/// \brief Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found.
///
/// If the low bit is clear, a pointer to the AST node. If the low
/// bit is set, the upper 63 bits are the offset.
mutable uint64_t Ptr;
public:
LazyOffsetPtr() : Ptr(0) { }
explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
if (Offset == 0)
Ptr = 0;
}
LazyOffsetPtr &operator=(T *Ptr) {
this->Ptr = reinterpret_cast<uint64_t>(Ptr);
return *this;
}
LazyOffsetPtr &operator=(uint64_t Offset) {
assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
if (Offset == 0)
Ptr = 0;
else
Ptr = (Offset << 1) | 0x01;
return *this;
}
/// \brief Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
operator bool() const { return Ptr != 0; }
/// \brief Whether this pointer is currently stored as an offset.
bool isOffset() const { return Ptr & 0x01; }
/// \brief Retrieve the pointer to the AST node that this lazy pointer
///
/// \param Source the external AST source.
///
/// \returns a pointer to the AST node.
T* get(ExternalASTSource *Source) const {
if (isOffset()) {
assert(Source &&
"Cannot deserialize a lazy pointer without an AST source");
Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
}
return reinterpret_cast<T*>(Ptr);
}
};
/// \brief Represents a lazily-loaded vector of data.
///
/// The lazily-loaded vector of data contains data that is partially loaded
/// from an external source and partially added by local translation. The
/// items loaded from the external source are loaded lazily, when needed for
/// iteration over the complete vector.
template<typename T, typename Source,
void (Source::*Loader)(SmallVectorImpl<T>&),
unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
class LazyVector {
SmallVector<T, LoadedStorage> Loaded;
SmallVector<T, LocalStorage> Local;
public:
// Iteration over the elements in the vector.
class iterator {
LazyVector *Self;
/// \brief Position within the vector..
///
/// In a complete iteration, the Position field walks the range [-M, N),
/// where negative values are used to indicate elements
/// loaded from the external source while non-negative values are used to
/// indicate elements added via \c push_back().
/// However, to provide iteration in source order (for, e.g., chained
/// precompiled headers), dereferencing the iterator flips the negative
/// values (corresponding to loaded entities), so that position -M
/// corresponds to element 0 in the loaded entities vector, position -M+1
/// corresponds to element 1 in the loaded entities vector, etc. This
/// gives us a reasonably efficient, source-order walk.
int Position;
friend class LazyVector;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef int difference_type;
iterator() : Self(0), Position(0) { }
iterator(LazyVector *Self, int Position)
: Self(Self), Position(Position) { }
reference operator*() const {
if (Position < 0)
return Self->Loaded.end()[Position];
return Self->Local[Position];
}
pointer operator->() const {
if (Position < 0)
return &Self->Loaded.end()[Position];
return &Self->Local[Position];
}
reference operator[](difference_type D) {
return *(*this + D);
}
iterator &operator++() {
++Position;
return *this;
}
iterator operator++(int) {
iterator Prev(*this);
++Position;
return Prev;
}
iterator &operator--() {
--Position;
return *this;
}
iterator operator--(int) {
iterator Prev(*this);
--Position;
return Prev;
}
friend bool operator==(const iterator &X, const iterator &Y) {
return X.Position == Y.Position;
}
friend bool operator!=(const iterator &X, const iterator &Y) {
return X.Position != Y.Position;
}
friend bool operator<(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend bool operator<=(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>=(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend iterator& operator+=(iterator &X, difference_type D) {
X.Position += D;
return X;
}
friend iterator& operator-=(iterator &X, difference_type D) {
X.Position -= D;
return X;
}
friend iterator operator+(iterator X, difference_type D) {
X.Position += D;
return X;
}
friend iterator operator+(difference_type D, iterator X) {
X.Position += D;
return X;
}
friend difference_type operator-(const iterator &X, const iterator &Y) {
return X.Position - Y.Position;
}
friend iterator operator-(iterator X, difference_type D) {
X.Position -= D;
return X;
}
};
friend class iterator;
iterator begin(Source *source, bool LocalOnly = false) {
if (LocalOnly)
return iterator(this, 0);
if (source)
(source->*Loader)(Loaded);
return iterator(this, -(int)Loaded.size());
}
iterator end() {
return iterator(this, Local.size());
}
void push_back(const T& LocalValue) {
Local.push_back(LocalValue);
}
void erase(iterator From, iterator To) {
if (From.Position < 0 && To.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position);
return;
}
if (From.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end());
From = begin(0, true);
}
Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
}
};
/// \brief A lazy pointer to a statement.
typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr;
/// \brief A lazy pointer to a declaration.
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
&ExternalASTSource::GetExternalCXXBaseSpecifiers>
LazyCXXBaseSpecifiersPtr;
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H

View File

@@ -0,0 +1,124 @@
//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor
// together with its type.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_GLOBALDECL_H
#define LLVM_CLANG_AST_GLOBALDECL_H
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/ABI.h"
namespace clang {
/// GlobalDecl - represents a global declaration. This can either be a
/// CXXConstructorDecl and the constructor type (Base, Complete).
/// a CXXDestructorDecl and the destructor type (Base, Complete) or
/// a VarDecl, a FunctionDecl or a BlockDecl.
class GlobalDecl {
llvm::PointerIntPair<const Decl*, 2> Value;
void Init(const Decl *D) {
assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
Value.setPointer(D);
}
public:
GlobalDecl() {}
GlobalDecl(const VarDecl *D) { Init(D);}
GlobalDecl(const FunctionDecl *D) { Init(D); }
GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
: Value(D, Type) {}
GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
: Value(D, Type) {}
GlobalDecl getCanonicalDecl() const {
GlobalDecl CanonGD;
CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
CanonGD.Value.setInt(Value.getInt());
return CanonGD;
}
const Decl *getDecl() const { return Value.getPointer(); }
CXXCtorType getCtorType() const {
assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
return static_cast<CXXCtorType>(Value.getInt());
}
CXXDtorType getDtorType() const {
assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
return static_cast<CXXDtorType>(Value.getInt());
}
friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
return LHS.Value == RHS.Value;
}
void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
static GlobalDecl getFromOpaquePtr(void *P) {
GlobalDecl GD;
GD.Value.setFromOpaqueValue(P);
return GD;
}
GlobalDecl getWithDecl(const Decl *D) {
GlobalDecl Result(*this);
Result.Value.setPointer(D);
return Result;
}
};
} // end namespace clang
namespace llvm {
template<class> struct DenseMapInfo;
template<> struct DenseMapInfo<clang::GlobalDecl> {
static inline clang::GlobalDecl getEmptyKey() {
return clang::GlobalDecl();
}
static inline clang::GlobalDecl getTombstoneKey() {
return clang::GlobalDecl::
getFromOpaquePtr(reinterpret_cast<void*>(-1));
}
static unsigned getHashValue(clang::GlobalDecl GD) {
return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
}
static bool isEqual(clang::GlobalDecl LHS,
clang::GlobalDecl RHS) {
return LHS == RHS;
}
};
// GlobalDecl isn't *technically* a POD type. However, its copy constructor,
// copy assignment operator, and destructor are all trivial.
template <>
struct isPodLike<clang::GlobalDecl> {
static const bool value = true;
};
} // end namespace llvm
#endif

View File

@@ -0,0 +1,38 @@
//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LambdaMangleContext interface, which keeps track of
// the Itanium C++ ABI mangling numbers for lambda expressions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H
#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
namespace clang {
class CXXMethodDecl;
class FunctionProtoType;
/// \brief Keeps track of the mangled names of lambda expressions within a
/// particular context.
class LambdaMangleContext : public RefCountedBase<LambdaMangleContext> {
llvm::DenseMap<const FunctionProtoType *, unsigned> ManglingNumbers;
public:
/// \brief Retrieve the mangling number of a new lambda expression with the
/// given call operator within this lambda context.
unsigned getManglingNumber(CXXMethodDecl *CallOperator);
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,164 @@
//===--- Mangle.h - Mangle C++ Names ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines the C++ name mangling interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MANGLE_H
#define LLVM_CLANG_AST_MANGLE_H
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
class ASTContext;
class BlockDecl;
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXMethodDecl;
class FunctionDecl;
class NamedDecl;
class ObjCMethodDecl;
class VarDecl;
struct ThisAdjustment;
struct ThunkInfo;
/// MangleBuffer - a convenient class for storing a name which is
/// either the result of a mangling or is a constant string with
/// external memory ownership.
class MangleBuffer {
public:
void setString(StringRef Ref) {
String = Ref;
}
SmallVectorImpl<char> &getBuffer() {
return Buffer;
}
StringRef getString() const {
if (!String.empty()) return String;
return Buffer.str();
}
operator StringRef() const {
return getString();
}
private:
StringRef String;
SmallString<256> Buffer;
};
/// MangleContext - Context for tracking state which persists across multiple
/// calls to the C++ name mangler.
class MangleContext {
virtual void anchor();
ASTContext &Context;
DiagnosticsEngine &Diags;
llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
public:
explicit MangleContext(ASTContext &Context,
DiagnosticsEngine &Diags)
: Context(Context), Diags(Diags) { }
virtual ~MangleContext() { }
ASTContext &getASTContext() const { return Context; }
DiagnosticsEngine &getDiags() const { return Diags; }
virtual void startNewFunction() { LocalBlockIds.clear(); }
unsigned getBlockId(const BlockDecl *BD, bool Local) {
llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
= Local? LocalBlockIds : GlobalBlockIds;
std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
Result = BlockIds.insert(std::make_pair(BD, BlockIds.size()));
return Result.first->second;
}
/// @name Mangler Entry Points
/// @{
virtual bool shouldMangleDeclName(const NamedDecl *D) = 0;
virtual void mangleName(const NamedDecl *D, raw_ostream &)=0;
virtual void mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &) = 0;
virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
raw_ostream &) = 0;
virtual void mangleReferenceTemporary(const VarDecl *D,
raw_ostream &) = 0;
virtual void mangleCXXVTable(const CXXRecordDecl *RD,
raw_ostream &) = 0;
virtual void mangleCXXVTT(const CXXRecordDecl *RD,
raw_ostream &) = 0;
virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
const CXXRecordDecl *Type,
raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
raw_ostream &) = 0;
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) = 0;
void mangleGlobalBlock(const BlockDecl *BD,
const NamedDecl *ID,
raw_ostream &Out);
void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
const BlockDecl *BD, raw_ostream &Out);
void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
const BlockDecl *BD, raw_ostream &Out);
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
raw_ostream &Out);
// Do the right thing.
void mangleBlock(const BlockDecl *BD, raw_ostream &Out,
const NamedDecl *ID=0);
void mangleObjCMethodName(const ObjCMethodDecl *MD,
raw_ostream &);
// This is pretty lame.
virtual void mangleItaniumGuardVariable(const VarDecl *D,
raw_ostream &) {
llvm_unreachable("Target does not support mangling guard variables");
}
// FIXME: Revisit this once we know what we need to do for MSVC compatibility.
virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
raw_ostream &) {
llvm_unreachable("Target does not support mangling thread_local variables");
}
virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) {
llvm_unreachable("Target does not support mangling thread_local variables");
}
/// @}
};
MangleContext *createItaniumMangleContext(ASTContext &Context,
DiagnosticsEngine &Diags);
MangleContext *createMicrosoftMangleContext(ASTContext &Context,
DiagnosticsEngine &Diags);
}
#endif

View File

@@ -0,0 +1,220 @@
//===--- NSAPI.h - NSFoundation APIs ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_NSAPI_H
#define LLVM_CLANG_AST_NSAPI_H
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
namespace clang {
class ASTContext;
class QualType;
class Expr;
// \brief Provides info and caches identifiers/selectors for NSFoundation API.
class NSAPI {
public:
explicit NSAPI(ASTContext &Ctx);
ASTContext &getASTContext() const { return Ctx; }
enum NSClassIdKindKind {
ClassId_NSObject,
ClassId_NSString,
ClassId_NSArray,
ClassId_NSMutableArray,
ClassId_NSDictionary,
ClassId_NSMutableDictionary,
ClassId_NSNumber
};
static const unsigned NumClassIds = 7;
enum NSStringMethodKind {
NSStr_stringWithString,
NSStr_stringWithUTF8String,
NSStr_stringWithCStringEncoding,
NSStr_stringWithCString,
NSStr_initWithString
};
static const unsigned NumNSStringMethods = 5;
IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
/// \brief The Objective-C NSString selectors.
Selector getNSStringSelector(NSStringMethodKind MK) const;
/// \brief Return NSStringMethodKind if \param Sel is such a selector.
Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
/// \brief Returns true if the expression \param E is a reference of
/// "NSUTF8StringEncoding" enum constant.
bool isNSUTF8StringEncodingConstant(const Expr *E) const {
return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
}
/// \brief Returns true if the expression \param E is a reference of
/// "NSASCIIStringEncoding" enum constant.
bool isNSASCIIStringEncodingConstant(const Expr *E) const {
return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
}
/// \brief Enumerates the NSArray methods used to generate literals.
enum NSArrayMethodKind {
NSArr_array,
NSArr_arrayWithArray,
NSArr_arrayWithObject,
NSArr_arrayWithObjects,
NSArr_arrayWithObjectsCount,
NSArr_initWithArray,
NSArr_initWithObjects,
NSArr_objectAtIndex,
NSMutableArr_replaceObjectAtIndex
};
static const unsigned NumNSArrayMethods = 9;
/// \brief The Objective-C NSArray selectors.
Selector getNSArraySelector(NSArrayMethodKind MK) const;
/// \brief Return NSArrayMethodKind if \p Sel is such a selector.
Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
/// \brief Enumerates the NSDictionary methods used to generate literals.
enum NSDictionaryMethodKind {
NSDict_dictionary,
NSDict_dictionaryWithDictionary,
NSDict_dictionaryWithObjectForKey,
NSDict_dictionaryWithObjectsForKeys,
NSDict_dictionaryWithObjectsForKeysCount,
NSDict_dictionaryWithObjectsAndKeys,
NSDict_initWithDictionary,
NSDict_initWithObjectsAndKeys,
NSDict_initWithObjectsForKeys,
NSDict_objectForKey,
NSMutableDict_setObjectForKey
};
static const unsigned NumNSDictionaryMethods = 11;
/// \brief The Objective-C NSDictionary selectors.
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
/// \brief Return NSDictionaryMethodKind if \p Sel is such a selector.
Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
/// \brief Returns selector for "objectForKeyedSubscript:".
Selector getObjectForKeyedSubscriptSelector() const {
return getOrInitSelector(StringRef("objectForKeyedSubscript"),
objectForKeyedSubscriptSel);
}
/// \brief Returns selector for "objectAtIndexedSubscript:".
Selector getObjectAtIndexedSubscriptSelector() const {
return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
objectAtIndexedSubscriptSel);
}
/// \brief Returns selector for "setObject:forKeyedSubscript".
Selector getSetObjectForKeyedSubscriptSelector() const {
StringRef Ids[] = { "setObject", "forKeyedSubscript" };
return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
}
/// \brief Returns selector for "setObject:atIndexedSubscript".
Selector getSetObjectAtIndexedSubscriptSelector() const {
StringRef Ids[] = { "setObject", "atIndexedSubscript" };
return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
}
/// \brief Returns selector for "isEqual:".
Selector getIsEqualSelector() const {
return getOrInitSelector(StringRef("isEqual"), isEqualSel);
}
/// \brief Enumerates the NSNumber methods used to generate literals.
enum NSNumberLiteralMethodKind {
NSNumberWithChar,
NSNumberWithUnsignedChar,
NSNumberWithShort,
NSNumberWithUnsignedShort,
NSNumberWithInt,
NSNumberWithUnsignedInt,
NSNumberWithLong,
NSNumberWithUnsignedLong,
NSNumberWithLongLong,
NSNumberWithUnsignedLongLong,
NSNumberWithFloat,
NSNumberWithDouble,
NSNumberWithBool,
NSNumberWithInteger,
NSNumberWithUnsignedInteger
};
static const unsigned NumNSNumberLiteralMethods = 15;
/// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
/// \param Instance if true it will return the selector for the init* method
/// otherwise it will return the selector for the number* method.
Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
bool Instance) const;
bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
Selector Sel) const {
return Sel == getNSNumberLiteralSelector(MK, false) ||
Sel == getNSNumberLiteralSelector(MK, true);
}
/// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector.
Optional<NSNumberLiteralMethodKind>
getNSNumberLiteralMethodKind(Selector Sel) const;
/// \brief Determine the appropriate NSNumber factory method kind for a
/// literal of the given type.
Optional<NSNumberLiteralMethodKind>
getNSNumberFactoryMethodKind(QualType T) const;
/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
bool isObjCBOOLType(QualType T) const;
/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
bool isObjCNSIntegerType(QualType T) const;
/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
bool isObjCNSUIntegerType(QualType T) const;
private:
bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
bool isObjCEnumerator(const Expr *E,
StringRef name, IdentifierInfo *&II) const;
Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
ASTContext &Ctx;
mutable IdentifierInfo *ClassIds[NumClassIds];
mutable Selector NSStringSelectors[NumNSStringMethods];
/// \brief The selectors for Objective-C NSArray methods.
mutable Selector NSArraySelectors[NumNSArrayMethods];
/// \brief The selectors for Objective-C NSDictionary methods.
mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
/// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
isEqualSel;
mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
};
} // end namespace clang
#endif // LLVM_CLANG_AST_NSAPI_H

View File

@@ -0,0 +1,481 @@
//===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the NestedNameSpecifier class, which represents
// a C++ nested-name-specifier.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Compiler.h"
namespace clang {
class ASTContext;
class NamespaceAliasDecl;
class NamespaceDecl;
class IdentifierInfo;
struct PrintingPolicy;
class Type;
class TypeLoc;
class LangOptions;
/// \brief Represents a C++ nested name specifier, such as
/// "\::std::vector<int>::".
///
/// C++ nested name specifiers are the prefixes to qualified
/// namespaces. For example, "foo::" in "foo::x" is a nested name
/// specifier. Nested name specifiers are made up of a sequence of
/// specifiers, each of which can be a namespace, type, identifier
/// (for dependent names), decltype specifier, or the global specifier ('::').
/// The last two specifiers can only appear at the start of a
/// nested-namespace-specifier.
class NestedNameSpecifier : public llvm::FoldingSetNode {
/// \brief Enumeration describing
enum StoredSpecifierKind {
StoredIdentifier = 0,
StoredNamespaceOrAlias = 1,
StoredTypeSpec = 2,
StoredTypeSpecWithTemplate = 3
};
/// \brief The nested name specifier that precedes this nested name
/// specifier.
///
/// The pointer is the nested-name-specifier that precedes this
/// one. The integer stores one of the first four values of type
/// SpecifierKind.
llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
/// \brief The last component in the nested name specifier, which
/// can be an identifier, a declaration, or a type.
///
/// When the pointer is NULL, this specifier represents the global
/// specifier '::'. Otherwise, the pointer is one of
/// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
/// specifier as encoded within the prefix.
void* Specifier;
public:
/// \brief The kind of specifier that completes this nested name
/// specifier.
enum SpecifierKind {
/// \brief An identifier, stored as an IdentifierInfo*.
Identifier,
/// \brief A namespace, stored as a NamespaceDecl*.
Namespace,
/// \brief A namespace alias, stored as a NamespaceAliasDecl*.
NamespaceAlias,
/// \brief A type, stored as a Type*.
TypeSpec,
/// \brief A type that was preceded by the 'template' keyword,
/// stored as a Type*.
TypeSpecWithTemplate,
/// \brief The global specifier '::'. There is no stored value.
Global
};
private:
/// \brief Builds the global specifier.
NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { }
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
NestedNameSpecifier(const NestedNameSpecifier &Other)
: llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
Specifier(Other.Specifier) {
}
void operator=(const NestedNameSpecifier &) LLVM_DELETED_FUNCTION;
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
const NestedNameSpecifier &Mockup);
public:
/// \brief Builds a specifier combining a prefix and an identifier.
///
/// The prefix must be dependent, since nested name specifiers
/// referencing an identifier are only permitted when the identifier
/// cannot be resolved.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
IdentifierInfo *II);
/// \brief Builds a nested name specifier that names a namespace.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
const NamespaceDecl *NS);
/// \brief Builds a nested name specifier that names a namespace alias.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceAliasDecl *Alias);
/// \brief Builds a nested name specifier that names a type.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
bool Template, const Type *T);
/// \brief Builds a specifier that consists of just an identifier.
///
/// The nested-name-specifier is assumed to be dependent, but has no
/// prefix because the prefix is implied by something outside of the
/// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
/// type.
static NestedNameSpecifier *Create(const ASTContext &Context,
IdentifierInfo *II);
/// \brief Returns the nested name specifier representing the global
/// scope.
static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
/// \brief Return the prefix of this nested name specifier.
///
/// The prefix contains all of the parts of the nested name
/// specifier that preced this current specifier. For example, for a
/// nested name specifier that represents "foo::bar::", the current
/// specifier will contain "bar::" and the prefix will contain
/// "foo::".
NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
/// \brief Determine what kind of nested name specifier is stored.
SpecifierKind getKind() const;
/// \brief Retrieve the identifier stored in this nested name
/// specifier.
IdentifierInfo *getAsIdentifier() const {
if (Prefix.getInt() == StoredIdentifier)
return (IdentifierInfo *)Specifier;
return 0;
}
/// \brief Retrieve the namespace stored in this nested name
/// specifier.
NamespaceDecl *getAsNamespace() const;
/// \brief Retrieve the namespace alias stored in this nested name
/// specifier.
NamespaceAliasDecl *getAsNamespaceAlias() const;
/// \brief Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
if (Prefix.getInt() == StoredTypeSpec ||
Prefix.getInt() == StoredTypeSpecWithTemplate)
return (const Type *)Specifier;
return 0;
}
/// \brief Whether this nested name specifier refers to a dependent
/// type or not.
bool isDependent() const;
/// \brief Whether this nested name specifier involves a template
/// parameter.
bool isInstantiationDependent() const;
/// \brief Whether this nested-name-specifier contains an unexpanded
/// parameter pack (for C++11 variadic templates).
bool containsUnexpandedParameterPack() const;
/// \brief Print this nested name specifier to the given output
/// stream.
void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(Prefix.getOpaqueValue());
ID.AddPointer(Specifier);
}
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
void dump(const LangOptions &LO);
};
/// \brief A C++ nested-name-specifier augmented with source location
/// information.
class NestedNameSpecifierLoc {
NestedNameSpecifier *Qualifier;
void *Data;
/// \brief Determines the data length for the last component in the
/// given nested-name-specifier.
static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
/// \brief Determines the data length for the entire
/// nested-name-specifier.
static unsigned getDataLength(NestedNameSpecifier *Qualifier);
public:
/// \brief Construct an empty nested-name-specifier.
NestedNameSpecifierLoc() : Qualifier(0), Data(0) { }
/// \brief Construct a nested-name-specifier with source location information
/// from
NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
: Qualifier(Qualifier), Data(Data) { }
/// \brief Evalutes true when this nested-name-specifier location is
/// non-empty.
operator bool() const { return Qualifier; }
/// \brief Retrieve the nested-name-specifier to which this instance
/// refers.
NestedNameSpecifier *getNestedNameSpecifier() const {
return Qualifier;
}
/// \brief Retrieve the opaque pointer that refers to source-location data.
void *getOpaqueData() const { return Data; }
/// \brief Retrieve the source range covering the entirety of this
/// nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c \::std::vector<int>::, the returned source range would cover
/// from the initial '::' to the last '::'.
SourceRange getSourceRange() const LLVM_READONLY;
/// \brief Retrieve the source range covering just the last part of
/// this nested-name-specifier, not including the prefix.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c \::std::vector<int>::, the returned source range would cover
/// from "vector" to the last '::'.
SourceRange getLocalSourceRange() const;
/// \brief Retrieve the location of the beginning of this
/// nested-name-specifier.
SourceLocation getBeginLoc() const {
return getSourceRange().getBegin();
}
/// \brief Retrieve the location of the end of this
/// nested-name-specifier.
SourceLocation getEndLoc() const {
return getSourceRange().getEnd();
}
/// \brief Retrieve the location of the beginning of this
/// component of the nested-name-specifier.
SourceLocation getLocalBeginLoc() const {
return getLocalSourceRange().getBegin();
}
/// \brief Retrieve the location of the end of this component of the
/// nested-name-specifier.
SourceLocation getLocalEndLoc() const {
return getLocalSourceRange().getEnd();
}
/// \brief Return the prefix of this nested-name-specifier.
///
/// For example, if this instance refers to a nested-name-specifier
/// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the
/// returned prefix may be empty, if this is the first component of
/// the nested-name-specifier.
NestedNameSpecifierLoc getPrefix() const {
if (!Qualifier)
return *this;
return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
}
/// \brief For a nested-name-specifier that refers to a type,
/// retrieve the type with source-location information.
TypeLoc getTypeLoc() const;
/// \brief Determines the data length for the entire
/// nested-name-specifier.
unsigned getDataLength() const { return getDataLength(Qualifier); }
friend bool operator==(NestedNameSpecifierLoc X,
NestedNameSpecifierLoc Y) {
return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
}
friend bool operator!=(NestedNameSpecifierLoc X,
NestedNameSpecifierLoc Y) {
return !(X == Y);
}
};
/// \brief Class that aids in the construction of nested-name-specifiers along
/// with source-location information for all of the components of the
/// nested-name-specifier.
class NestedNameSpecifierLocBuilder {
/// \brief The current representation of the nested-name-specifier we're
/// building.
NestedNameSpecifier *Representation;
/// \brief Buffer used to store source-location information for the
/// nested-name-specifier.
///
/// Note that we explicitly manage the buffer (rather than using a
/// SmallVector) because \c Declarator expects it to be possible to memcpy()
/// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
char *Buffer;
/// \brief The size of the buffer used to store source-location information
/// for the nested-name-specifier.
unsigned BufferSize;
/// \brief The capacity of the buffer used to store source-location
/// information for the nested-name-specifier.
unsigned BufferCapacity;
public:
NestedNameSpecifierLocBuilder()
: Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { }
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
NestedNameSpecifierLocBuilder &
operator=(const NestedNameSpecifierLocBuilder &Other);
~NestedNameSpecifierLocBuilder() {
if (BufferCapacity)
free(Buffer);
}
/// \brief Retrieve the representation of the nested-name-specifier.
NestedNameSpecifier *getRepresentation() const { return Representation; }
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'type::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param TemplateKWLoc The location of the 'template' keyword, if present.
///
/// \param TL The TypeLoc that describes the type preceding the '::'.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
SourceLocation ColonColonLoc);
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'identifier::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Identifier The identifier.
///
/// \param IdentifierLoc The location of the identifier.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, IdentifierInfo *Identifier,
SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Namespace The namespace.
///
/// \param NamespaceLoc The location of the namespace name.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, NamespaceDecl *Namespace,
SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
/// \brief Extend the current nested-name-specifier by another
/// nested-name-specifier component of the form 'namespace-alias::'.
///
/// \param Context The AST context in which this nested-name-specifier
/// resides.
///
/// \param Alias The namespace alias.
///
/// \param AliasLoc The location of the namespace alias
/// name.
///
/// \param ColonColonLoc The location of the trailing '::'.
void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
SourceLocation AliasLoc, SourceLocation ColonColonLoc);
/// \brief Turn this (empty) nested-name-specifier into the global
/// nested-name-specifier '::'.
void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
/// \brief Make a new nested-name-specifier from incomplete source-location
/// information.
///
/// This routine should be used very, very rarely, in cases where we
/// need to synthesize a nested-name-specifier. Most code should instead use
/// \c Adopt() with a proper \c NestedNameSpecifierLoc.
void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
SourceRange R);
/// \brief Adopt an existing nested-name-specifier (with source-range
/// information).
void Adopt(NestedNameSpecifierLoc Other);
/// \brief Retrieve the source range covered by this nested-name-specifier.
SourceRange getSourceRange() const LLVM_READONLY {
return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
}
/// \brief Retrieve a nested-name-specifier with location information,
/// copied into the given AST context.
///
/// \param Context The context into which this nested-name-specifier will be
/// copied.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
/// \brief Retrieve a nested-name-specifier with location
/// information based on the information in this builder.
///
/// This loc will contain references to the builder's internal data and may
/// be invalidated by any change to the builder.
NestedNameSpecifierLoc getTemporary() const {
return NestedNameSpecifierLoc(Representation, Buffer);
}
/// \brief Clear out this builder, and prepare it to build another
/// nested-name-specifier with source-location information.
void Clear() {
Representation = 0;
BufferSize = 0;
}
/// \brief Retrieve the underlying buffer.
///
/// \returns A pair containing a pointer to the buffer of source-location
/// data and the size of the source-location data that resides in that
/// buffer.
std::pair<char *, unsigned> getBuffer() const {
return std::make_pair(Buffer, BufferSize);
}
};
/// Insertion operator for diagnostics. This allows sending
/// NestedNameSpecifiers into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
NestedNameSpecifier *NNS) {
DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
DiagnosticsEngine::ak_nestednamespec);
return DB;
}
}
#endif

View File

@@ -0,0 +1,352 @@
//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file enumerates the different kinds of operations that can be
// performed by various expressions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
#define LLVM_CLANG_AST_OPERATION_KINDS_H
namespace clang {
/// CastKind - The kind of operation required for a conversion.
enum CastKind {
/// CK_Dependent - A conversion which cannot yet be analyzed because
/// either the expression or target type is dependent. These are
/// created only for explicit casts; dependent ASTs aren't required
/// to even approximately type-check.
/// (T*) malloc(sizeof(T))
/// reinterpret_cast<intptr_t>(A<T>::alloc());
CK_Dependent,
/// CK_BitCast - A conversion which causes a bit pattern of one type
/// to be reinterpreted as a bit pattern of another type. Generally
/// the operands must have equivalent size and unrelated types.
///
/// The pointer conversion char* -> int* is a bitcast. A conversion
/// from any pointer type to a C pointer type is a bitcast unless
/// it's actually BaseToDerived or DerivedToBase. A conversion to a
/// block pointer or ObjC pointer type is a bitcast only if the
/// operand has the same type kind; otherwise, it's one of the
/// specialized casts below.
///
/// Vector coercions are bitcasts.
CK_BitCast,
/// CK_LValueBitCast - A conversion which reinterprets the address of
/// an l-value as an l-value of a different kind. Used for
/// reinterpret_casts of l-value expressions to reference types.
/// bool b; reinterpret_cast<char&>(b) = 'a';
CK_LValueBitCast,
/// CK_LValueToRValue - A conversion which causes the extraction of
/// an r-value from the operand gl-value. The result of an r-value
/// conversion is always unqualified.
CK_LValueToRValue,
/// CK_NoOp - A conversion which does not affect the type other than
/// (possibly) adding qualifiers.
/// int -> int
/// char** -> const char * const *
CK_NoOp,
/// CK_BaseToDerived - A conversion from a C++ class pointer/reference
/// to a derived class pointer/reference.
/// B *b = static_cast<B*>(a);
CK_BaseToDerived,
/// CK_DerivedToBase - A conversion from a C++ class pointer
/// to a base class pointer.
/// A *a = new B();
CK_DerivedToBase,
/// CK_UncheckedDerivedToBase - A conversion from a C++ class
/// pointer/reference to a base class that can assume that the
/// derived pointer is not null.
/// const A &a = B();
/// b->method_from_a();
CK_UncheckedDerivedToBase,
/// CK_Dynamic - A C++ dynamic_cast.
CK_Dynamic,
/// CK_ToUnion - The GCC cast-to-union extension.
/// int -> union { int x; float y; }
/// float -> union { int x; float y; }
CK_ToUnion,
/// CK_ArrayToPointerDecay - Array to pointer decay.
/// int[10] -> int*
/// char[5][6] -> char(*)[6]
CK_ArrayToPointerDecay,
/// CK_FunctionToPointerDecay - Function to pointer decay.
/// void(int) -> void(*)(int)
CK_FunctionToPointerDecay,
/// CK_NullToPointer - Null pointer constant to pointer, ObjC
/// pointer, or block pointer.
/// (void*) 0
/// void (^block)() = 0;
CK_NullToPointer,
/// CK_NullToMemberPointer - Null pointer constant to member pointer.
/// int A::*mptr = 0;
/// int (A::*fptr)(int) = nullptr;
CK_NullToMemberPointer,
/// CK_BaseToDerivedMemberPointer - Member pointer in base class to
/// member pointer in derived class.
/// int B::*mptr = &A::member;
CK_BaseToDerivedMemberPointer,
/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
/// member pointer in base class.
/// int A::*mptr = static_cast<int A::*>(&B::member);
CK_DerivedToBaseMemberPointer,
/// CK_MemberPointerToBoolean - Member pointer to boolean. A check
/// against the null member pointer.
CK_MemberPointerToBoolean,
/// CK_ReinterpretMemberPointer - Reinterpret a member pointer as a
/// different kind of member pointer. C++ forbids this from
/// crossing between function and object types, but otherwise does
/// not restrict it. However, the only operation that is permitted
/// on a "punned" member pointer is casting it back to the original
/// type, which is required to be a lossless operation (although
/// many ABIs do not guarantee this on all possible intermediate types).
CK_ReinterpretMemberPointer,
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
/// struct A { operator int(); }; int i = int(A());
CK_UserDefinedConversion,
/// CK_ConstructorConversion - Conversion by constructor.
/// struct A { A(int); }; A a = A(10);
CK_ConstructorConversion,
/// CK_IntegralToPointer - Integral to pointer. A special kind of
/// reinterpreting conversion. Applies to normal, ObjC, and block
/// pointers.
/// (char*) 0x1001aab0
/// reinterpret_cast<int*>(0)
CK_IntegralToPointer,
/// CK_PointerToIntegral - Pointer to integral. A special kind of
/// reinterpreting conversion. Applies to normal, ObjC, and block
/// pointers.
/// (intptr_t) "help!"
CK_PointerToIntegral,
/// CK_PointerToBoolean - Pointer to boolean conversion. A check
/// against null. Applies to normal, ObjC, and block pointers.
CK_PointerToBoolean,
/// CK_ToVoid - Cast to void, discarding the computed value.
/// (void) malloc(2048)
CK_ToVoid,
/// CK_VectorSplat - A conversion from an arithmetic type to a
/// vector of that element type. Fills all elements ("splats") with
/// the source value.
/// __attribute__((ext_vector_type(4))) int v = 5;
CK_VectorSplat,
/// CK_IntegralCast - A cast between integral types (other than to
/// boolean). Variously a bitcast, a truncation, a sign-extension,
/// or a zero-extension.
/// long l = 5;
/// (unsigned) i
CK_IntegralCast,
/// CK_IntegralToBoolean - Integral to boolean. A check against zero.
/// (bool) i
CK_IntegralToBoolean,
/// CK_IntegralToFloating - Integral to floating point.
/// float f = i;
CK_IntegralToFloating,
/// CK_FloatingToIntegral - Floating point to integral. Rounds
/// towards zero, discarding any fractional component.
/// (int) f
CK_FloatingToIntegral,
/// CK_FloatingToBoolean - Floating point to boolean.
/// (bool) f
CK_FloatingToBoolean,
/// CK_FloatingCast - Casting between floating types of different size.
/// (double) f
/// (float) ld
CK_FloatingCast,
/// CK_CPointerToObjCPointerCast - Casting a C pointer kind to an
/// Objective-C pointer.
CK_CPointerToObjCPointerCast,
/// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an
/// ObjC pointer.
CK_BlockPointerToObjCPointerCast,
/// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer
/// to a block pointer. Block-to-block casts are bitcasts.
CK_AnyPointerToBlockPointerCast,
/// \brief Converting between two Objective-C object types, which
/// can occur when performing reference binding to an Objective-C
/// object.
CK_ObjCObjectLValueCast,
/// \brief A conversion of a floating point real to a floating point
/// complex of the original type. Injects the value as the real
/// component with a zero imaginary component.
/// float -> _Complex float
CK_FloatingRealToComplex,
/// \brief Converts a floating point complex to floating point real
/// of the source's element type. Just discards the imaginary
/// component.
/// _Complex long double -> long double
CK_FloatingComplexToReal,
/// \brief Converts a floating point complex to bool by comparing
/// against 0+0i.
CK_FloatingComplexToBoolean,
/// \brief Converts between different floating point complex types.
/// _Complex float -> _Complex double
CK_FloatingComplexCast,
/// \brief Converts from a floating complex to an integral complex.
/// _Complex float -> _Complex int
CK_FloatingComplexToIntegralComplex,
/// \brief Converts from an integral real to an integral complex
/// whose element type matches the source. Injects the value as
/// the real component with a zero imaginary component.
/// long -> _Complex long
CK_IntegralRealToComplex,
/// \brief Converts an integral complex to an integral real of the
/// source's element type by discarding the imaginary component.
/// _Complex short -> short
CK_IntegralComplexToReal,
/// \brief Converts an integral complex to bool by comparing against
/// 0+0i.
CK_IntegralComplexToBoolean,
/// \brief Converts between different integral complex types.
/// _Complex char -> _Complex long long
/// _Complex unsigned int -> _Complex signed int
CK_IntegralComplexCast,
/// \brief Converts from an integral complex to a floating complex.
/// _Complex unsigned -> _Complex float
CK_IntegralComplexToFloatingComplex,
/// \brief [ARC] Produces a retainable object pointer so that it may
/// be consumed, e.g. by being passed to a consuming parameter.
/// Calls objc_retain.
CK_ARCProduceObject,
/// \brief [ARC] Consumes a retainable object pointer that has just
/// been produced, e.g. as the return value of a retaining call.
/// Enters a cleanup to call objc_release at some indefinite time.
CK_ARCConsumeObject,
/// \brief [ARC] Reclaim a retainable object pointer object that may
/// have been produced and autoreleased as part of a function return
/// sequence.
CK_ARCReclaimReturnedObject,
/// \brief [ARC] Causes a value of block type to be copied to the
/// heap, if it is not already there. A number of other operations
/// in ARC cause blocks to be copied; this is for cases where that
/// would not otherwise be guaranteed, such as when casting to a
/// non-block pointer type.
CK_ARCExtendBlockObject,
/// \brief Converts from _Atomic(T) to T.
CK_AtomicToNonAtomic,
/// \brief Converts from T to _Atomic(T).
CK_NonAtomicToAtomic,
/// \brief Causes a block literal to by copied to the heap and then
/// autoreleased.
///
/// This particular cast kind is used for the conversion from a C++11
/// lambda expression to a block pointer.
CK_CopyAndAutoreleaseBlockObject,
// Convert a builtin function to a function pointer; only allowed in the
// callee of a call expression.
CK_BuiltinFnToFnPtr,
// Convert a zero value for OpenCL event_t initialization.
CK_ZeroToOCLEvent
};
static const CastKind CK_Invalid = static_cast<CastKind>(-1);
enum BinaryOperatorKind {
// Operators listed in order of precedence.
// Note that additions to this should also update the StmtVisitor class.
BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators.
BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators.
BO_Add, BO_Sub, // [C99 6.5.6] Additive operators.
BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators.
BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators.
BO_EQ, BO_NE, // [C99 6.5.9] Equality operators.
BO_And, // [C99 6.5.10] Bitwise AND operator.
BO_Xor, // [C99 6.5.11] Bitwise XOR operator.
BO_Or, // [C99 6.5.12] Bitwise OR operator.
BO_LAnd, // [C99 6.5.13] Logical AND operator.
BO_LOr, // [C99 6.5.14] Logical OR operator.
BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators.
BO_DivAssign, BO_RemAssign,
BO_AddAssign, BO_SubAssign,
BO_ShlAssign, BO_ShrAssign,
BO_AndAssign, BO_XorAssign,
BO_OrAssign,
BO_Comma // [C99 6.5.17] Comma operator.
};
enum UnaryOperatorKind {
// Note that additions to this should also update the StmtVisitor class.
UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement
UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement
UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection
UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
UO_Extension // __extension__ marker.
};
/// \brief The kind of bridging performed by the Objective-C bridge cast.
enum ObjCBridgeCastKind {
/// \brief Bridging via __bridge, which does nothing but reinterpret
/// the bits.
OBC_Bridge,
/// \brief Bridging via __bridge_transfer, which transfers ownership of an
/// Objective-C pointer into ARC.
OBC_BridgeTransfer,
/// \brief Bridging via __bridge_retain, which makes an ARC object available
/// as a +1 C pointer.
OBC_BridgeRetained
};
}
#endif

View File

@@ -0,0 +1,62 @@
//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ParentMap class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARENTMAP_H
#define LLVM_CLANG_PARENTMAP_H
namespace clang {
class Stmt;
class Expr;
class ParentMap {
void* Impl;
public:
ParentMap(Stmt* ASTRoot);
~ParentMap();
/// \brief Adds and/or updates the parent/child-relations of the complete
/// stmt tree of S. All children of S including indirect descendants are
/// visited and updated or inserted but not the parents of S.
void addStmt(Stmt* S);
Stmt *getParent(Stmt*) const;
Stmt *getParentIgnoreParens(Stmt *) const;
Stmt *getParentIgnoreParenCasts(Stmt *) const;
Stmt *getParentIgnoreParenImpCasts(Stmt *) const;
Stmt *getOuterParenParent(Stmt *) const;
const Stmt *getParent(const Stmt* S) const {
return getParent(const_cast<Stmt*>(S));
}
const Stmt *getParentIgnoreParens(const Stmt *S) const {
return getParentIgnoreParens(const_cast<Stmt*>(S));
}
const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
}
bool hasParent(Stmt* S) const {
return getParent(S) != 0;
}
bool isConsumedExpr(Expr *E) const;
bool isConsumedExpr(const Expr *E) const {
return isConsumedExpr(const_cast<Expr*>(E));
}
};
} // end clang namespace
#endif

View File

@@ -0,0 +1,153 @@
//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PrinterHelper interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
#define LLVM_CLANG_AST_PRETTY_PRINTER_H
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
namespace clang {
class LangOptions;
class SourceManager;
class Stmt;
class TagDecl;
class PrinterHelper {
public:
virtual ~PrinterHelper();
virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0;
};
/// \brief Describes how types, statements, expressions, and
/// declarations should be printed.
struct PrintingPolicy {
/// \brief Create a default printing policy for C.
PrintingPolicy(const LangOptions &LO)
: LangOpts(LO), Indentation(2), SuppressSpecifiers(false),
SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
SuppressUnwrittenScope(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), Bool(LO.Bool),
TerseOutput(false), PolishForDeclaration(false) { }
/// \brief What language we're printing.
LangOptions LangOpts;
/// \brief The number of spaces to use to indent each line.
unsigned Indentation : 8;
/// \brief Whether we should suppress printing of the actual specifiers for
/// the given type or declaration.
///
/// This flag is only used when we are printing declarators beyond
/// the first declarator within a declaration group. For example, given:
///
/// \code
/// const int *x, *y;
/// \endcode
///
/// SuppressSpecifiers will be false when printing the
/// declaration for "x", so that we will print "int *x"; it will be
/// \c true when we print "y", so that we suppress printing the
/// "const int" type specifier and instead only print the "*y".
bool SuppressSpecifiers : 1;
/// \brief Whether type printing should skip printing the tag keyword.
///
/// This is used when printing the inner type of elaborated types,
/// (as the tag keyword is part of the elaborated type):
///
/// \code
/// struct Geometry::Point;
/// \endcode
bool SuppressTagKeyword : 1;
/// \brief Whether type printing should skip printing the actual tag type.
///
/// This is used when the caller needs to print a tag definition in front
/// of the type, as in constructs like the following:
///
/// \code
/// typedef struct { int x, y; } Point;
/// \endcode
bool SuppressTag : 1;
/// \brief Suppresses printing of scope specifiers.
bool SuppressScope : 1;
/// \brief Suppress printing parts of scope specifiers that don't need
/// to be written, e.g., for inline or anonymous namespaces.
bool SuppressUnwrittenScope : 1;
/// \brief Suppress printing of variable initializers.
///
/// This flag is used when printing the loop variable in a for-range
/// statement. For example, given:
///
/// \code
/// for (auto x : coll)
/// \endcode
///
/// SuppressInitializers will be true when printing "auto x", so that the
/// internal initializer constructed for x will not be printed.
bool SuppressInitializers : 1;
/// \brief Whether we should print the sizes of constant array expressions
/// as written in the sources.
///
/// This flag is determines whether arrays types declared as
///
/// \code
/// int a[4+10*10];
/// char a[] = "A string";
/// \endcode
///
/// will be printed as written or as follows:
///
/// \code
/// int a[104];
/// char a[9] = "A string";
/// \endcode
bool ConstantArraySizeAsWritten : 1;
/// \brief When printing an anonymous tag name, also print the location of
/// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just
/// prints "<anonymous>" for the name.
bool AnonymousTagLocations : 1;
/// \brief When true, suppress printing of the __strong lifetime qualifier in
/// ARC.
unsigned SuppressStrongLifetime : 1;
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;
/// \brief Provide a 'terse' output.
///
/// For example, in this mode we don't print function bodies, class members,
/// declarations inside namespaces etc. Effectively, this should print
/// only the requested declaration.
unsigned TerseOutput : 1;
/// \brief When true, do certain refinement needed for producing proper
/// declaration tag; such as, do not print attributes attached to the declaration.
///
unsigned PolishForDeclaration : 1;
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,222 @@
//===--- RawCommentList.h - Classes for processing raw comments -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H
#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/ArrayRef.h"
namespace clang {
class ASTContext;
class ASTReader;
class Decl;
class Preprocessor;
namespace comments {
class FullComment;
} // end namespace comments
class RawComment {
public:
enum CommentKind {
RCK_Invalid, ///< Invalid comment
RCK_OrdinaryBCPL, ///< Any normal BCPL comments
RCK_OrdinaryC, ///< Any normal C comment
RCK_BCPLSlash, ///< \code /// stuff \endcode
RCK_BCPLExcl, ///< \code //! stuff \endcode
RCK_JavaDoc, ///< \code /** stuff */ \endcode
RCK_Qt, ///< \code /*! stuff */ \endcode, also used by HeaderDoc
RCK_Merged ///< Two or more documentation comments merged together
};
RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { }
RawComment(const SourceManager &SourceMgr, SourceRange SR,
bool Merged, bool ParseAllComments);
CommentKind getKind() const LLVM_READONLY {
return (CommentKind) Kind;
}
bool isInvalid() const LLVM_READONLY {
return Kind == RCK_Invalid;
}
bool isMerged() const LLVM_READONLY {
return Kind == RCK_Merged;
}
/// Is this comment attached to any declaration?
bool isAttached() const LLVM_READONLY {
return IsAttached;
}
void setAttached() {
IsAttached = true;
}
/// Returns true if it is a comment that should be put after a member:
/// \code ///< stuff \endcode
/// \code //!< stuff \endcode
/// \code /**< stuff */ \endcode
/// \code /*!< stuff */ \endcode
bool isTrailingComment() const LLVM_READONLY {
assert(isDocumentation());
return IsTrailingComment;
}
/// Returns true if it is a probable typo:
/// \code //< stuff \endcode
/// \code /*< stuff */ \endcode
bool isAlmostTrailingComment() const LLVM_READONLY {
return IsAlmostTrailingComment;
}
/// Returns true if this comment is not a documentation comment.
bool isOrdinary() const LLVM_READONLY {
return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)) &&
!ParseAllComments;
}
/// Returns true if this comment any kind of a documentation comment.
bool isDocumentation() const LLVM_READONLY {
return !isInvalid() && !isOrdinary();
}
/// Returns whether we are parsing all comments.
bool isParseAllComments() const LLVM_READONLY {
return ParseAllComments;
}
/// Returns raw comment text with comment markers.
StringRef getRawText(const SourceManager &SourceMgr) const {
if (RawTextValid)
return RawText;
RawText = getRawTextSlow(SourceMgr);
RawTextValid = true;
return RawText;
}
SourceRange getSourceRange() const LLVM_READONLY {
return Range;
}
unsigned getBeginLine(const SourceManager &SM) const;
unsigned getEndLine(const SourceManager &SM) const;
const char *getBriefText(const ASTContext &Context) const {
if (BriefTextValid)
return BriefText;
return extractBriefText(Context);
}
/// Parse the comment, assuming it is attached to decl \c D.
comments::FullComment *parse(const ASTContext &Context,
const Preprocessor *PP, const Decl *D) const;
private:
SourceRange Range;
mutable StringRef RawText;
mutable const char *BriefText;
mutable bool RawTextValid : 1; ///< True if RawText is valid
mutable bool BriefTextValid : 1; ///< True if BriefText is valid
unsigned Kind : 3;
/// True if comment is attached to a declaration in ASTContext.
bool IsAttached : 1;
bool IsTrailingComment : 1;
bool IsAlmostTrailingComment : 1;
/// When true, ordinary comments starting with "//" and "/*" will be
/// considered as documentation comments.
bool ParseAllComments : 1;
mutable bool BeginLineValid : 1; ///< True if BeginLine is valid
mutable bool EndLineValid : 1; ///< True if EndLine is valid
mutable unsigned BeginLine; ///< Cached line number
mutable unsigned EndLine; ///< Cached line number
/// \brief Constructor for AST deserialization.
RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
bool IsAlmostTrailingComment,
bool ParseAllComments) :
Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
IsAttached(false), IsTrailingComment(IsTrailingComment),
IsAlmostTrailingComment(IsAlmostTrailingComment),
ParseAllComments(ParseAllComments),
BeginLineValid(false), EndLineValid(false)
{ }
StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
const char *extractBriefText(const ASTContext &Context) const;
friend class ASTReader;
};
/// \brief Compare comments' source locations.
template<>
class BeforeThanCompare<RawComment> {
const SourceManager &SM;
public:
explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
bool operator()(const RawComment &LHS, const RawComment &RHS) {
return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(),
RHS.getSourceRange().getBegin());
}
bool operator()(const RawComment *LHS, const RawComment *RHS) {
return operator()(*LHS, *RHS);
}
};
/// \brief This class represents all comments included in the translation unit,
/// sorted in order of appearance in the translation unit.
class RawCommentList {
public:
RawCommentList(SourceManager &SourceMgr) :
SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { }
void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator);
ArrayRef<RawComment *> getComments() const {
return Comments;
}
private:
SourceManager &SourceMgr;
std::vector<RawComment *> Comments;
SourceLocation PrevCommentEndLoc;
bool OnlyWhitespaceSeen;
void addCommentsToFront(const std::vector<RawComment *> &C) {
size_t OldSize = Comments.size();
Comments.resize(C.size() + OldSize);
std::copy_backward(Comments.begin(), Comments.begin() + OldSize,
Comments.end());
std::copy(C.begin(), C.end(), Comments.begin());
}
friend class ASTReader;
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,244 @@
//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the RecordLayout interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class ASTContext;
class FieldDecl;
class RecordDecl;
class CXXRecordDecl;
/// ASTRecordLayout -
/// This class contains layout information for one RecordDecl,
/// which is a struct/union/class. The decl represented must be a definition,
/// not a forward declaration.
/// This class is also used to contain layout information for one
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
public:
struct VBaseInfo {
/// The offset to this virtual base in the complete-object layout
/// of this class.
CharUnits VBaseOffset;
private:
/// Whether this virtual base requires a vtordisp field in the
/// Microsoft ABI. These fields are required for certain operations
/// in constructors and destructors.
bool HasVtorDisp;
public:
bool hasVtorDisp() const { return HasVtorDisp; }
VBaseInfo() : HasVtorDisp(false) {}
VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) :
VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
};
typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
VBaseOffsetsMapTy;
private:
/// Size - Size of record in characters.
CharUnits Size;
/// DataSize - Size of record in characters without tail padding.
CharUnits DataSize;
// Alignment - Alignment of record in characters.
CharUnits Alignment;
/// FieldOffsets - Array of field offsets in bits.
uint64_t *FieldOffsets;
// FieldCount - Number of fields.
unsigned FieldCount;
/// CXXRecordLayoutInfo - Contains C++ specific layout information.
struct CXXRecordLayoutInfo {
/// NonVirtualSize - The non-virtual size (in chars) of an object, which is
/// the size of the object without virtual bases.
CharUnits NonVirtualSize;
/// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
CharUnits NonVirtualAlign;
/// SizeOfLargestEmptySubobject - The size of the largest empty subobject
/// (either a base or a member). Will be zero if the class doesn't contain
/// any empty subobjects.
CharUnits SizeOfLargestEmptySubobject;
/// VBPtrOffset - Virtual base table offset (Microsoft-only).
CharUnits VBPtrOffset;
/// HasOwnVFPtr - Does this class provide a virtual function table
/// (vtable in Itanium, vftbl in Microsoft) that is independent from
/// its base classes?
bool HasOwnVFPtr; // TODO: stash this somewhere more efficient
/// PrimaryBase - The primary base info for this record.
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
/// BaseOffsets - Contains a map from base classes to their offset.
BaseOffsetsMapTy BaseOffsets;
/// VBaseOffsets - Contains a map from vbase classes to their offset.
VBaseOffsetsMapTy VBaseOffsets;
};
/// CXXInfo - If the record layout is for a C++ record, this will have
/// C++ specific information about the record.
CXXRecordLayoutInfo *CXXInfo;
friend class ASTContext;
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
CharUnits datasize, const uint64_t *fieldoffsets,
unsigned fieldcount);
// Constructor for C++ records.
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
bool hasOwnVFPtr, CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
CharUnits nonvirtualsize, CharUnits nonvirtualalign,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets);
~ASTRecordLayout() {}
void Destroy(ASTContext &Ctx);
ASTRecordLayout(const ASTRecordLayout &) LLVM_DELETED_FUNCTION;
void operator=(const ASTRecordLayout &) LLVM_DELETED_FUNCTION;
public:
/// getAlignment - Get the record alignment in characters.
CharUnits getAlignment() const { return Alignment; }
/// getSize - Get the record size in characters.
CharUnits getSize() const { return Size; }
/// getFieldCount - Get the number of fields in the layout.
unsigned getFieldCount() const { return FieldCount; }
/// getFieldOffset - Get the offset of the given field index, in
/// bits.
uint64_t getFieldOffset(unsigned FieldNo) const {
assert (FieldNo < FieldCount && "Invalid Field No");
return FieldOffsets[FieldNo];
}
/// getDataSize() - Get the record data size, which is the record size
/// without tail padding, in characters.
CharUnits getDataSize() const {
return DataSize;
}
/// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
/// which is the size of the object without virtual bases.
CharUnits getNonVirtualSize() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->NonVirtualSize;
}
/// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
CharUnits getNonVirtualAlign() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->NonVirtualAlign;
}
/// getPrimaryBase - Get the primary base for this record.
const CXXRecordDecl *getPrimaryBase() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->PrimaryBase.getPointer();
}
/// isPrimaryBaseVirtual - Get whether the primary base for this record
/// is virtual or not.
bool isPrimaryBaseVirtual() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->PrimaryBase.getInt();
}
/// getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
return CXXInfo->BaseOffsets[Base];
}
/// getVBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
}
CharUnits getSizeOfLargestEmptySubobject() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->SizeOfLargestEmptySubobject;
}
/// hasOwnVFPtr - Does this class provide its own virtual-function
/// table pointer, rather than inheriting one from a primary base
/// class? If so, it is at offset zero.
///
/// This implies that the ABI has no primary base class, meaning
/// that it has no base classes that are suitable under the conditions
/// of the ABI.
bool hasOwnVFPtr() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->HasOwnVFPtr;
}
/// getVBPtrOffset - Get the offset for virtual base table pointer.
/// This is only meaningful with the Microsoft ABI.
CharUnits getVBPtrOffset() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->VBPtrOffset;
}
const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->VBaseOffsets;
}
};
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Redeclarable interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_REDECLARABLE_H
#define LLVM_CLANG_AST_REDECLARABLE_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Casting.h"
#include <iterator>
namespace clang {
/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
class Redeclarable {
protected:
class DeclLink {
llvm::PointerIntPair<decl_type *, 1, bool> NextAndIsPrevious;
public:
DeclLink(decl_type *D, bool isLatest)
: NextAndIsPrevious(D, isLatest) { }
bool NextIsPrevious() const { return !NextAndIsPrevious.getInt(); }
bool NextIsLatest() const { return NextAndIsPrevious.getInt(); }
decl_type *getNext() const { return NextAndIsPrevious.getPointer(); }
void setNext(decl_type *D) { NextAndIsPrevious.setPointer(D); }
};
static DeclLink PreviousDeclLink(decl_type *D) {
return DeclLink(D, false);
}
static DeclLink LatestDeclLink(decl_type *D) {
return DeclLink(D, true);
}
/// \brief Points to the next redeclaration in the chain.
///
/// If NextIsPrevious() is true, this is a link to the previous declaration
/// of this same Decl. If NextIsLatest() is true, this is the first
/// declaration and Link points to the latest declaration. For example:
///
/// #1 int f(int x, int y = 1); // <pointer to #3, true>
/// #2 int f(int x = 0, int y); // <pointer to #1, false>
/// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
///
/// If there is only one declaration, it is <pointer to self, true>
DeclLink RedeclLink;
public:
Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { }
/// \brief Return the previous declaration of this declaration or NULL if this
/// is the first declaration.
decl_type *getPreviousDecl() {
if (RedeclLink.NextIsPrevious())
return RedeclLink.getNext();
return 0;
}
const decl_type *getPreviousDecl() const {
return const_cast<decl_type *>(
static_cast<const decl_type*>(this))->getPreviousDecl();
}
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
decl_type *getFirstDeclaration() {
decl_type *D = static_cast<decl_type*>(this);
while (D->getPreviousDecl())
D = D->getPreviousDecl();
return D;
}
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
const decl_type *getFirstDeclaration() const {
const decl_type *D = static_cast<const decl_type*>(this);
while (D->getPreviousDecl())
D = D->getPreviousDecl();
return D;
}
/// \brief Returns true if this is the first declaration.
bool isFirstDeclaration() const {
return RedeclLink.NextIsLatest();
}
/// \brief Returns the most recent (re)declaration of this declaration.
decl_type *getMostRecentDecl() {
return getFirstDeclaration()->RedeclLink.getNext();
}
/// \brief Returns the most recent (re)declaration of this declaration.
const decl_type *getMostRecentDecl() const {
return getFirstDeclaration()->RedeclLink.getNext();
}
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
/// first and only declaration.
void setPreviousDeclaration(decl_type *PrevDecl);
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
/// Current - The current declaration.
decl_type *Current;
decl_type *Starter;
bool PassedFirst;
public:
typedef decl_type* value_type;
typedef decl_type* reference;
typedef decl_type* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
redecl_iterator() : Current(0) { }
explicit redecl_iterator(decl_type *C)
: Current(C), Starter(C), PassedFirst(false) { }
reference operator*() const { return Current; }
pointer operator->() const { return Current; }
redecl_iterator& operator++() {
assert(Current && "Advancing while iterator has reached end");
// Sanity check to avoid infinite loop on invalid redecl chain.
if (Current->isFirstDeclaration()) {
if (PassedFirst) {
assert(0 && "Passed first decl twice, invalid redecl chain!");
Current = 0;
return *this;
}
PassedFirst = true;
}
// Get either previous decl or latest decl.
decl_type *Next = Current->RedeclLink.getNext();
Current = (Next != Starter ? Next : 0);
return *this;
}
redecl_iterator operator++(int) {
redecl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(redecl_iterator x, redecl_iterator y) {
return x.Current == y.Current;
}
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
return x.Current != y.Current;
}
};
/// \brief Returns iterator for all the redeclarations of the same decl.
/// It will iterate at least once (when this decl is the only one).
redecl_iterator redecls_begin() const {
return redecl_iterator(const_cast<decl_type*>(
static_cast<const decl_type*>(this)));
}
redecl_iterator redecls_end() const { return redecl_iterator(); }
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
}
#endif

View File

@@ -0,0 +1,83 @@
//===--- SelectorLocationsKind.h - Kind of selector locations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Describes whether the identifier locations for a selector are "standard"
// or not.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
#define LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
#include "clang/Basic/LLVM.h"
namespace clang {
class Selector;
class SourceLocation;
class Expr;
class ParmVarDecl;
/// \brief Whether all locations of the selector identifiers are in a
/// "standard" position.
enum SelectorLocationsKind {
/// \brief Non-standard.
SelLoc_NonStandard = 0,
/// \brief For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or immediately before the arguments:
/// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y;
SelLoc_StandardNoSpace = 1,
/// \brief For nullary selectors, immediately before the end:
/// "[foo release]" / "-(void)release;"
/// Or with a space between the arguments:
/// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y;
SelLoc_StandardWithSpace = 2
};
/// \brief Returns true if all \p SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
/// \brief Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
/// before arguments: "[foo first: 1 second: 2]"
/// If false: "[foo first:1 second:2]"
SourceLocation getStandardSelectorLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
ArrayRef<Expr *> Args,
SourceLocation EndLoc);
/// \brief Returns true if all \p SelLocs are in a "standard" location.
SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
ArrayRef<SourceLocation> SelLocs,
ArrayRef<ParmVarDecl *> Args,
SourceLocation EndLoc);
/// \brief Get the "standard" location of a selector identifier, e.g:
/// For nullary selectors, immediately before ']': "[foo release]"
///
/// \param WithArgSpace if true the standard location is with a space apart
/// before arguments: "-(id)first: (int)x second: (int)y;"
/// If false: "-(id)first:(int)x second:(int)y;"
SourceLocation getStandardSelectorLoc(unsigned Index,
Selector Sel,
bool WithArgSpace,
ArrayRef<ParmVarDecl *> Args,
SourceLocation EndLoc);
} // end namespace clang
#endif

2053
thirdparty/clang/include/clang/AST/Stmt.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,292 @@
//===--- StmtCXX.h - Classes for representing C++ statements ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the C++ statement AST node classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMTCXX_H
#define LLVM_CLANG_AST_STMTCXX_H
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
#include "llvm/Support/Compiler.h"
namespace clang {
class VarDecl;
/// CXXCatchStmt - This represents a C++ catch block.
///
class CXXCatchStmt : public Stmt {
SourceLocation CatchLoc;
/// The exception-declaration of the type.
VarDecl *ExceptionDecl;
/// The handler block.
Stmt *HandlerBlock;
public:
CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
: Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
HandlerBlock(handlerBlock) {}
CXXCatchStmt(EmptyShell Empty)
: Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return HandlerBlock->getLocEnd();
}
SourceLocation getCatchLoc() const { return CatchLoc; }
VarDecl *getExceptionDecl() const { return ExceptionDecl; }
QualType getCaughtType() const;
Stmt *getHandlerBlock() const { return HandlerBlock; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXCatchStmtClass;
}
child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
friend class ASTStmtReader;
};
/// CXXTryStmt - A C++ try block, including all handlers.
///
class CXXTryStmt : public Stmt {
SourceLocation TryLoc;
unsigned NumHandlers;
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers);
CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
: Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
Stmt const * const *getStmts() const {
return reinterpret_cast<Stmt const * const*>(this + 1);
}
Stmt **getStmts() {
return reinterpret_cast<Stmt **>(this + 1);
}
public:
static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, ArrayRef<Stmt*> handlers);
static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
SourceLocation getTryLoc() const { return TryLoc; }
SourceLocation getEndLoc() const {
return getStmts()[NumHandlers]->getLocEnd();
}
CompoundStmt *getTryBlock() {
return cast<CompoundStmt>(getStmts()[0]);
}
const CompoundStmt *getTryBlock() const {
return cast<CompoundStmt>(getStmts()[0]);
}
unsigned getNumHandlers() const { return NumHandlers; }
CXXCatchStmt *getHandler(unsigned i) {
return cast<CXXCatchStmt>(getStmts()[i + 1]);
}
const CXXCatchStmt *getHandler(unsigned i) const {
return cast<CXXCatchStmt>(getStmts()[i + 1]);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTryStmtClass;
}
child_range children() {
return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
}
friend class ASTStmtReader;
};
/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
/// statement, represented as 'for (range-declarator : range-expression)'.
///
/// This is stored in a partially-desugared form to allow full semantic
/// analysis of the constituent components. The original syntactic components
/// can be extracted using getLoopVariable and getRangeInit.
class CXXForRangeStmt : public Stmt {
enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END };
// SubExprs[RANGE] is an expression or declstmt.
// SubExprs[COND] and SubExprs[INC] are expressions.
Stmt *SubExprs[END];
SourceLocation ForLoc;
SourceLocation ColonLoc;
SourceLocation RParenLoc;
public:
CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd,
Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
SourceLocation FL, SourceLocation CL, SourceLocation RPL);
CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
VarDecl *getLoopVariable();
Expr *getRangeInit();
const VarDecl *getLoopVariable() const;
const Expr *getRangeInit() const;
DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); }
DeclStmt *getBeginEndStmt() {
return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
}
Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); }
Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); }
DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
Stmt *getBody() { return SubExprs[BODY]; }
const DeclStmt *getRangeStmt() const {
return cast<DeclStmt>(SubExprs[RANGE]);
}
const DeclStmt *getBeginEndStmt() const {
return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
}
const Expr *getCond() const {
return cast_or_null<Expr>(SubExprs[COND]);
}
const Expr *getInc() const {
return cast_or_null<Expr>(SubExprs[INC]);
}
const DeclStmt *getLoopVarStmt() const {
return cast<DeclStmt>(SubExprs[LOOPVAR]);
}
const Stmt *getBody() const { return SubExprs[BODY]; }
void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); }
void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; }
void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; }
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
SourceLocation getForLoc() const { return ForLoc; }
void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return SubExprs[BODY]->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXForRangeStmtClass;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[END]);
}
};
/// \brief Representation of a Microsoft __if_exists or __if_not_exists
/// statement with a dependent name.
///
/// The __if_exists statement can be used to include a sequence of statements
/// in the program only when a particular dependent name does not exist. For
/// example:
///
/// \code
/// template<typename T>
/// void call_foo(T &t) {
/// __if_exists (T::foo) {
/// t.foo(); // okay: only called when T::foo exists.
/// }
/// }
/// \endcode
///
/// Similarly, the __if_not_exists statement can be used to include the
/// statements when a particular name does not exist.
///
/// Note that this statement only captures __if_exists and __if_not_exists
/// statements whose name is dependent. All non-dependent cases are handled
/// directly in the parser, so that they don't introduce a new scope. Clang
/// introduces scopes in the dependent case to keep names inside the compound
/// statement from leaking out into the surround statements, which would
/// compromise the template instantiation model. This behavior differs from
/// Visual C++ (which never introduces a scope), but is a fairly reasonable
/// approximation of the VC++ behavior.
class MSDependentExistsStmt : public Stmt {
SourceLocation KeywordLoc;
bool IsIfExists;
NestedNameSpecifierLoc QualifierLoc;
DeclarationNameInfo NameInfo;
Stmt *SubStmt;
friend class ASTReader;
friend class ASTStmtReader;
public:
MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists,
NestedNameSpecifierLoc QualifierLoc,
DeclarationNameInfo NameInfo,
CompoundStmt *SubStmt)
: Stmt(MSDependentExistsStmtClass),
KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
QualifierLoc(QualifierLoc), NameInfo(NameInfo),
SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
/// \brief Retrieve the location of the __if_exists or __if_not_exists
/// keyword.
SourceLocation getKeywordLoc() const { return KeywordLoc; }
/// \brief Determine whether this is an __if_exists statement.
bool isIfExists() const { return IsIfExists; }
/// \brief Determine whether this is an __if_exists statement.
bool isIfNotExists() const { return !IsIfExists; }
/// \brief Retrieve the nested-name-specifier that qualifies this name, if
/// any.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
/// \brief Retrieve the name of the entity we're testing for, along with
/// location information
DeclarationNameInfo getNameInfo() const { return NameInfo; }
/// \brief Retrieve the compound statement that will be included in the
/// program only if the existence of the symbol matches the initial keyword.
CompoundStmt *getSubStmt() const {
return reinterpret_cast<CompoundStmt *>(SubStmt);
}
SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
child_range children() {
return child_range(&SubStmt, &SubStmt+1);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == MSDependentExistsStmtClass;
}
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,83 @@
//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a template specialization of llvm::GraphTraits to
// treat ASTs (Stmt*) as graphs
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
#include "clang/AST/Stmt.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
namespace llvm {
//template <typename T> struct GraphTraits;
template <> struct GraphTraits<clang::Stmt*> {
typedef clang::Stmt NodeType;
typedef clang::Stmt::child_iterator ChildIteratorType;
typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
static NodeType* getEntryNode(clang::Stmt* S) { return S; }
static inline ChildIteratorType child_begin(NodeType* N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
static inline ChildIteratorType child_end(NodeType* N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
static nodes_iterator nodes_begin(clang::Stmt* S) {
return df_begin(S);
}
static nodes_iterator nodes_end(clang::Stmt* S) {
return df_end(S);
}
};
template <> struct GraphTraits<const clang::Stmt*> {
typedef const clang::Stmt NodeType;
typedef clang::Stmt::const_child_iterator ChildIteratorType;
typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
static inline ChildIteratorType child_begin(NodeType* N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
static inline ChildIteratorType child_end(NodeType* N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
static nodes_iterator nodes_begin(const clang::Stmt* S) {
return df_begin(S);
}
static nodes_iterator nodes_end(const clang::Stmt* S) {
return df_end(S);
}
};
} // end namespace llvm
#endif

View File

@@ -0,0 +1,230 @@
//===--- StmtIterator.h - Iterators for Statements --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the StmtIterator and ConstStmtIterator classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <utility>
namespace clang {
class Stmt;
class Decl;
class VariableArrayType;
class StmtIteratorBase {
protected:
enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
Flags = 0x3 };
Stmt **stmt;
union { Decl *decl; Decl **DGI; };
uintptr_t RawVAPtr;
Decl **DGE;
bool inDecl() const {
return (RawVAPtr & Flags) == DeclMode;
}
bool inDeclGroup() const {
return (RawVAPtr & Flags) == DeclGroupMode;
}
bool inSizeOfTypeVA() const {
return (RawVAPtr & Flags) == SizeOfTypeVAMode;
}
bool inStmt() const {
return (RawVAPtr & Flags) == 0;
}
const VariableArrayType *getVAPtr() const {
return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
}
void setVAPtr(const VariableArrayType *P) {
assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
void NextDecl(bool ImmediateAdvance = true);
bool HandleDecl(Decl* D);
void NextVA();
Stmt*& GetDeclExpr() const;
StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
StmtIteratorBase(Decl *d, Stmt **s);
StmtIteratorBase(const VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
};
template <typename DERIVED, typename REFERENCE>
class StmtIteratorImpl : public StmtIteratorBase,
public std::iterator<std::forward_iterator_tag,
REFERENCE, ptrdiff_t,
REFERENCE, REFERENCE> {
protected:
StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
public:
StmtIteratorImpl() {}
StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
if (inStmt())
++stmt;
else if (getVAPtr())
NextVA();
else
NextDecl();
return static_cast<DERIVED&>(*this);
}
DERIVED operator++(int) {
DERIVED tmp = static_cast<DERIVED&>(*this);
operator++();
return tmp;
}
bool operator==(const DERIVED& RHS) const {
return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr;
}
bool operator!=(const DERIVED& RHS) const {
return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr;
}
REFERENCE operator*() const {
return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr());
}
REFERENCE operator->() const { return operator*(); }
};
struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
StmtIterator(Decl** dgi, Decl** dge)
: StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
StmtIterator(const VariableArrayType *t)
: StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
StmtIterator(Decl* D, Stmt **s = 0)
: StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {}
};
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
const Stmt*> {
explicit ConstStmtIterator() :
StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
ConstStmtIterator(const StmtIterator& RHS) :
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
/// A range of statement iterators.
///
/// This class provides some extra functionality beyond std::pair
/// in order to allow the following idiom:
/// for (StmtRange range = stmt->children(); range; ++range)
struct StmtRange : std::pair<StmtIterator,StmtIterator> {
StmtRange() {}
StmtRange(const StmtIterator &begin, const StmtIterator &end)
: std::pair<StmtIterator,StmtIterator>(begin, end) {}
bool empty() const { return first == second; }
operator bool() const { return !empty(); }
Stmt *operator->() const { return first.operator->(); }
Stmt *&operator*() const { return first.operator*(); }
StmtRange &operator++() {
assert(!empty() && "incrementing on empty range");
++first;
return *this;
}
StmtRange operator++(int) {
assert(!empty() && "incrementing on empty range");
StmtRange copy = *this;
++first;
return copy;
}
friend const StmtIterator &begin(const StmtRange &range) {
return range.first;
}
friend const StmtIterator &end(const StmtRange &range) {
return range.second;
}
};
/// A range of const statement iterators.
///
/// This class provides some extra functionality beyond std::pair
/// in order to allow the following idiom:
/// for (ConstStmtRange range = stmt->children(); range; ++range)
struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
ConstStmtRange() {}
ConstStmtRange(const ConstStmtIterator &begin,
const ConstStmtIterator &end)
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
ConstStmtRange(const StmtRange &range)
: std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
{}
ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
bool empty() const { return first == second; }
operator bool() const { return !empty(); }
const Stmt *operator->() const { return first.operator->(); }
const Stmt *operator*() const { return first.operator*(); }
ConstStmtRange &operator++() {
assert(!empty() && "incrementing on empty range");
++first;
return *this;
}
ConstStmtRange operator++(int) {
assert(!empty() && "incrementing on empty range");
ConstStmtRange copy = *this;
++first;
return copy;
}
friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
return range.first;
}
friend const ConstStmtIterator &end(const ConstStmtRange &range) {
return range.second;
}
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,375 @@
//===--- StmtObjC.h - Classes for representing ObjC statements --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// \brief Defines the Objective-C statement AST node classes.
#ifndef LLVM_CLANG_AST_STMTOBJC_H
#define LLVM_CLANG_AST_STMTOBJC_H
#include "clang/AST/Stmt.h"
#include "llvm/Support/Compiler.h"
namespace clang {
/// \brief Represents Objective-C's collection statement.
///
/// This is represented as 'for (element 'in' collection-expression)' stmt.
class ObjCForCollectionStmt : public Stmt {
enum { ELEM, COLLECTION, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
SourceLocation ForLoc;
SourceLocation RParenLoc;
public:
ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body,
SourceLocation FCL, SourceLocation RPL);
explicit ObjCForCollectionStmt(EmptyShell Empty) :
Stmt(ObjCForCollectionStmtClass, Empty) { }
Stmt *getElement() { return SubExprs[ELEM]; }
Expr *getCollection() {
return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
}
Stmt *getBody() { return SubExprs[BODY]; }
const Stmt *getElement() const { return SubExprs[ELEM]; }
const Expr *getCollection() const {
return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
}
const Stmt *getBody() const { return SubExprs[BODY]; }
void setElement(Stmt *S) { SubExprs[ELEM] = S; }
void setCollection(Expr *E) {
SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(E);
}
void setBody(Stmt *S) { SubExprs[BODY] = S; }
SourceLocation getForLoc() const { return ForLoc; }
void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return SubExprs[BODY]->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCForCollectionStmtClass;
}
// Iterators
child_range children() {
return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
}
};
/// \brief Represents Objective-C's \@catch statement.
class ObjCAtCatchStmt : public Stmt {
private:
VarDecl *ExceptionDecl;
Stmt *Body;
SourceLocation AtCatchLoc, RParenLoc;
public:
ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
VarDecl *catchVarDecl,
Stmt *atCatchStmt)
: Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl),
Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { }
explicit ObjCAtCatchStmt(EmptyShell Empty) :
Stmt(ObjCAtCatchStmtClass, Empty) { }
const Stmt *getCatchBody() const { return Body; }
Stmt *getCatchBody() { return Body; }
void setCatchBody(Stmt *S) { Body = S; }
const VarDecl *getCatchParamDecl() const {
return ExceptionDecl;
}
VarDecl *getCatchParamDecl() {
return ExceptionDecl;
}
void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; }
SourceLocation getAtCatchLoc() const { return AtCatchLoc; }
void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); }
bool hasEllipsis() const { return getCatchParamDecl() == 0; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtCatchStmtClass;
}
child_range children() { return child_range(&Body, &Body + 1); }
};
/// \brief Represents Objective-C's \@finally statement
class ObjCAtFinallyStmt : public Stmt {
Stmt *AtFinallyStmt;
SourceLocation AtFinallyLoc;
public:
ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
: Stmt(ObjCAtFinallyStmtClass),
AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
explicit ObjCAtFinallyStmt(EmptyShell Empty) :
Stmt(ObjCAtFinallyStmtClass, Empty) { }
const Stmt *getFinallyBody() const { return AtFinallyStmt; }
Stmt *getFinallyBody() { return AtFinallyStmt; }
void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
SourceLocation getLocStart() const LLVM_READONLY { return AtFinallyLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return AtFinallyStmt->getLocEnd();
}
SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtFinallyStmtClass;
}
child_range children() {
return child_range(&AtFinallyStmt, &AtFinallyStmt+1);
}
};
/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement.
class ObjCAtTryStmt : public Stmt {
private:
// The location of the @ in the \@try.
SourceLocation AtTryLoc;
// The number of catch blocks in this statement.
unsigned NumCatchStmts : 16;
// Whether this statement has a \@finally statement.
bool HasFinally : 1;
/// \brief Retrieve the statements that are stored after this \@try statement.
///
/// The order of the statements in memory follows the order in the source,
/// with the \@try body first, followed by the \@catch statements (if any)
/// and, finally, the \@finally (if it exists).
Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); }
const Stmt* const *getStmts() const {
return reinterpret_cast<const Stmt * const*> (this + 1);
}
ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
Stmt **CatchStmts, unsigned NumCatchStmts,
Stmt *atFinallyStmt);
explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts,
bool HasFinally)
: Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts),
HasFinally(HasFinally) { }
public:
static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc,
Stmt *atTryStmt,
Stmt **CatchStmts, unsigned NumCatchStmts,
Stmt *atFinallyStmt);
static ObjCAtTryStmt *CreateEmpty(ASTContext &Context,
unsigned NumCatchStmts,
bool HasFinally);
/// \brief Retrieve the location of the @ in the \@try.
SourceLocation getAtTryLoc() const { return AtTryLoc; }
void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; }
/// \brief Retrieve the \@try body.
const Stmt *getTryBody() const { return getStmts()[0]; }
Stmt *getTryBody() { return getStmts()[0]; }
void setTryBody(Stmt *S) { getStmts()[0] = S; }
/// \brief Retrieve the number of \@catch statements in this try-catch-finally
/// block.
unsigned getNumCatchStmts() const { return NumCatchStmts; }
/// \brief Retrieve a \@catch statement.
const ObjCAtCatchStmt *getCatchStmt(unsigned I) const {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
}
/// \brief Retrieve a \@catch statement.
ObjCAtCatchStmt *getCatchStmt(unsigned I) {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]);
}
/// \brief Set a particular catch statement.
void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) {
assert(I < NumCatchStmts && "Out-of-bounds @catch index");
getStmts()[I + 1] = S;
}
/// \brief Retrieve the \@finally statement, if any.
const ObjCAtFinallyStmt *getFinallyStmt() const {
if (!HasFinally)
return 0;
return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
}
ObjCAtFinallyStmt *getFinallyStmt() {
if (!HasFinally)
return 0;
return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
}
void setFinallyStmt(Stmt *S) {
assert(HasFinally && "@try does not have a @finally slot!");
getStmts()[1 + NumCatchStmts] = S;
}
SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; }
SourceLocation getLocEnd() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtTryStmtClass;
}
child_range children() {
return child_range(getStmts(),
getStmts() + 1 + NumCatchStmts + HasFinally);
}
};
/// \brief Represents Objective-C's \@synchronized statement.
///
/// Example:
/// \code
/// @synchronized (sem) {
/// do-something;
/// }
/// \endcode
class ObjCAtSynchronizedStmt : public Stmt {
private:
enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
Stmt* SubStmts[END_EXPR];
SourceLocation AtSynchronizedLoc;
public:
ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
Stmt *synchBody)
: Stmt(ObjCAtSynchronizedStmtClass) {
SubStmts[SYNC_EXPR] = synchExpr;
SubStmts[SYNC_BODY] = synchBody;
AtSynchronizedLoc = atSynchronizedLoc;
}
explicit ObjCAtSynchronizedStmt(EmptyShell Empty) :
Stmt(ObjCAtSynchronizedStmtClass, Empty) { }
SourceLocation getAtSynchronizedLoc() const { return AtSynchronizedLoc; }
void setAtSynchronizedLoc(SourceLocation Loc) { AtSynchronizedLoc = Loc; }
const CompoundStmt *getSynchBody() const {
return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
}
CompoundStmt *getSynchBody() {
return reinterpret_cast<CompoundStmt*>(SubStmts[SYNC_BODY]);
}
void setSynchBody(Stmt *S) { SubStmts[SYNC_BODY] = S; }
const Expr *getSynchExpr() const {
return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
}
Expr *getSynchExpr() {
return reinterpret_cast<Expr*>(SubStmts[SYNC_EXPR]);
}
void setSynchExpr(Stmt *S) { SubStmts[SYNC_EXPR] = S; }
SourceLocation getLocStart() const LLVM_READONLY { return AtSynchronizedLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return getSynchBody()->getLocEnd();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
}
child_range children() {
return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
}
};
/// \brief Represents Objective-C's \@throw statement.
class ObjCAtThrowStmt : public Stmt {
Stmt *Throw;
SourceLocation AtThrowLoc;
public:
ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
: Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
AtThrowLoc = atThrowLoc;
}
explicit ObjCAtThrowStmt(EmptyShell Empty) :
Stmt(ObjCAtThrowStmtClass, Empty) { }
const Expr *getThrowExpr() const { return reinterpret_cast<Expr*>(Throw); }
Expr *getThrowExpr() { return reinterpret_cast<Expr*>(Throw); }
void setThrowExpr(Stmt *S) { Throw = S; }
SourceLocation getThrowLoc() { return AtThrowLoc; }
void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
return Throw ? Throw->getLocEnd() : AtThrowLoc;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtThrowStmtClass;
}
child_range children() { return child_range(&Throw, &Throw+1); }
};
/// \brief Represents Objective-C's \@autoreleasepool Statement
class ObjCAutoreleasePoolStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AtLoc;
public:
ObjCAutoreleasePoolStmt(SourceLocation atLoc,
Stmt *subStmt)
: Stmt(ObjCAutoreleasePoolStmtClass),
SubStmt(subStmt), AtLoc(atLoc) {}
explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
const Stmt *getSubStmt() const { return SubStmt; }
Stmt *getSubStmt() { return SubStmt; }
void setSubStmt(Stmt *S) { SubStmt = S; }
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAutoreleasePoolStmtClass;
}
child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,189 @@
//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the StmtVisitor and ConstStmtVisitor interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMTVISITOR_H
#define LLVM_CLANG_AST_STMTVISITOR_H
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
namespace clang {
template <typename T> struct make_ptr { typedef T *type; };
template <typename T> struct make_const_ptr { typedef const T *type; };
/// StmtVisitorBase - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class StmtVisitorBase {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<PTR(CLASS)>(S))
RetTy Visit(PTR(Stmt) S) {
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
// below.
if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
case BO_Mul: DISPATCH(BinMul, BinaryOperator);
case BO_Div: DISPATCH(BinDiv, BinaryOperator);
case BO_Rem: DISPATCH(BinRem, BinaryOperator);
case BO_Add: DISPATCH(BinAdd, BinaryOperator);
case BO_Sub: DISPATCH(BinSub, BinaryOperator);
case BO_Shl: DISPATCH(BinShl, BinaryOperator);
case BO_Shr: DISPATCH(BinShr, BinaryOperator);
case BO_LT: DISPATCH(BinLT, BinaryOperator);
case BO_GT: DISPATCH(BinGT, BinaryOperator);
case BO_LE: DISPATCH(BinLE, BinaryOperator);
case BO_GE: DISPATCH(BinGE, BinaryOperator);
case BO_EQ: DISPATCH(BinEQ, BinaryOperator);
case BO_NE: DISPATCH(BinNE, BinaryOperator);
case BO_And: DISPATCH(BinAnd, BinaryOperator);
case BO_Xor: DISPATCH(BinXor, BinaryOperator);
case BO_Or : DISPATCH(BinOr, BinaryOperator);
case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator);
case BO_LOr : DISPATCH(BinLOr, BinaryOperator);
case BO_Assign: DISPATCH(BinAssign, BinaryOperator);
case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator);
case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator);
case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator);
case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator);
case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator);
case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator);
case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator);
case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator);
case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator);
case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator);
case BO_Comma: DISPATCH(BinComma, BinaryOperator);
}
} else if (PTR(UnaryOperator) UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator);
case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator);
case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator);
case UO_Not: DISPATCH(UnaryNot, UnaryOperator);
case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator);
case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
}
}
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
switch (S->getStmtClass()) {
default: llvm_unreachable("Unknown stmt kind!");
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);
#include "clang/AST/StmtNodes.inc"
}
}
// If the implementation chooses not to implement a certain visit method, fall
// back on VisitExpr or whatever else is the superclass.
#define STMT(CLASS, PARENT) \
RetTy Visit ## CLASS(PTR(CLASS) S) { DISPATCH(PARENT, PARENT); }
#include "clang/AST/StmtNodes.inc"
// If the implementation doesn't implement binary operator methods, fall back
// on VisitBinaryOperator.
#define BINOP_FALLBACK(NAME) \
RetTy VisitBin ## NAME(PTR(BinaryOperator) S) { \
DISPATCH(BinaryOperator, BinaryOperator); \
}
BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI)
BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem)
BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl)
BINOP_FALLBACK(Shr)
BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE)
BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE)
BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or)
BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr)
BINOP_FALLBACK(Assign)
BINOP_FALLBACK(Comma)
#undef BINOP_FALLBACK
// If the implementation doesn't implement compound assignment operator
// methods, fall back on VisitCompoundAssignOperator.
#define CAO_FALLBACK(NAME) \
RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S) { \
DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \
}
CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign)
CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign)
CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign)
CAO_FALLBACK(XorAssign)
#undef CAO_FALLBACK
// If the implementation doesn't implement unary operator methods, fall back
// on VisitUnaryOperator.
#define UNARYOP_FALLBACK(NAME) \
RetTy VisitUnary ## NAME(PTR(UnaryOperator) S) { \
DISPATCH(UnaryOperator, UnaryOperator); \
}
UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec)
UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref)
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
UNARYOP_FALLBACK(Extension)
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
RetTy VisitStmt(PTR(Stmt) Node) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
///
/// This class does not preserve constness of Stmt pointers (see also
/// ConstStmtVisitor).
template<typename ImplClass, typename RetTy=void>
class StmtVisitor
: public StmtVisitorBase<make_ptr, ImplClass, RetTy> {};
/// ConstStmtVisitor - This class implements a simple visitor for Stmt
/// subclasses. Since Expr derives from Stmt, this also includes support for
/// visiting Exprs.
///
/// This class preserves constness of Stmt pointers (see also StmtVisitor).
template<typename ImplClass, typename RetTy=void>
class ConstStmtVisitor
: public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {};
} // end namespace clang
#endif

View File

@@ -0,0 +1,659 @@
//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides definitions which are common for all kinds of
// template representation.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
#define LLVM_CLANG_AST_TEMPLATEBASE_H
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
namespace llvm {
class FoldingSetNodeID;
}
namespace clang {
class DiagnosticBuilder;
class Expr;
struct PrintingPolicy;
class TypeSourceInfo;
class ValueDecl;
/// \brief Represents a template argument within a class template
/// specialization.
class TemplateArgument {
public:
/// \brief The kind of template argument we're storing.
enum ArgKind {
/// \brief Represents an empty template argument, e.g., one that has not
/// been deduced.
Null = 0,
/// The template argument is a type.
Type,
/// The template argument is a declaration that was provided for a pointer,
/// reference, or pointer to member non-type template parameter.
Declaration,
/// The template argument is a null pointer or null pointer to member that
/// was provided for a non-type template parameter.
NullPtr,
/// The template argument is an integral value stored in an llvm::APSInt
/// that was provided for an integral non-type template parameter.
Integral,
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
/// The template argument is a pack expansion of a template name that was
/// provided for a template template parameter.
TemplateExpansion,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression,
/// The template argument is actually a parameter pack. Arguments are stored
/// in the Args struct.
Pack
};
private:
/// \brief The kind of template argument we're storing.
unsigned Kind;
struct DA {
ValueDecl *D;
bool ForRefParam;
};
struct I {
// We store a decomposed APSInt with the data allocated by ASTContext if
// BitWidth > 64. The memory may be shared between multiple
// TemplateArgument instances.
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
const uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
unsigned BitWidth : 31;
unsigned IsUnsigned : 1;
void *Type;
};
struct A {
const TemplateArgument *Args;
unsigned NumArgs;
};
struct TA {
void *Name;
unsigned NumExpansions;
};
union {
struct DA DeclArg;
struct I Integer;
struct A Args;
struct TA TemplateArg;
uintptr_t TypeOrValue;
};
TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION;
public:
/// \brief Construct an empty, invalid template argument.
TemplateArgument() : Kind(Null), TypeOrValue(0) { }
/// \brief Construct a template type argument.
TemplateArgument(QualType T, bool isNullPtr = false)
: Kind(isNullPtr ? NullPtr : Type) {
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
}
/// \brief Construct a template argument that refers to a
/// declaration, which is either an external declaration or a
/// template declaration.
TemplateArgument(ValueDecl *D, bool ForRefParam) : Kind(Declaration) {
assert(D && "Expected decl");
DeclArg.D = D;
DeclArg.ForRefParam = ForRefParam;
}
/// \brief Construct an integral constant template argument. The memory to
/// store the value is allocated with Ctx.
TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
/// \brief Construct an integral constant template argument with the same
/// value as Other but a different type.
TemplateArgument(const TemplateArgument &Other, QualType Type)
: Kind(Integral) {
Integer = Other.Integer;
Integer.Type = Type.getAsOpaquePtr();
}
/// \brief Construct a template argument that is a template.
///
/// This form of template argument is generally used for template template
/// parameters. However, the template name could be a dependent template
/// name that ends up being instantiated to a function template whose address
/// is taken.
///
/// \param Name The template name.
TemplateArgument(TemplateName Name) : Kind(Template)
{
TemplateArg.Name = Name.getAsVoidPointer();
TemplateArg.NumExpansions = 0;
}
/// \brief Construct a template argument that is a template pack expansion.
///
/// This form of template argument is generally used for template template
/// parameters. However, the template name could be a dependent template
/// name that ends up being instantiated to a function template whose address
/// is taken.
///
/// \param Name The template name.
///
/// \param NumExpansions The number of expansions that will be generated by
/// instantiating
TemplateArgument(TemplateName Name, Optional<unsigned> NumExpansions)
: Kind(TemplateExpansion)
{
TemplateArg.Name = Name.getAsVoidPointer();
if (NumExpansions)
TemplateArg.NumExpansions = *NumExpansions + 1;
else
TemplateArg.NumExpansions = 0;
}
/// \brief Construct a template argument that is an expression.
///
/// This form of template argument only occurs in template argument
/// lists used for dependent types and for expression; it will not
/// occur in a non-dependent, canonical template argument list.
TemplateArgument(Expr *E) : Kind(Expression) {
TypeOrValue = reinterpret_cast<uintptr_t>(E);
}
/// \brief Construct a template argument that is a template argument pack.
///
/// We assume that storage for the template arguments provided
/// outlives the TemplateArgument itself.
TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){
this->Args.Args = Args;
this->Args.NumArgs = NumArgs;
}
static TemplateArgument getEmptyPack() {
return TemplateArgument((TemplateArgument*)0, 0);
}
/// \brief Create a new template argument pack by copying the given set of
/// template arguments.
static TemplateArgument CreatePackCopy(ASTContext &Context,
const TemplateArgument *Args,
unsigned NumArgs);
/// \brief Return the kind of stored template argument.
ArgKind getKind() const { return (ArgKind)Kind; }
/// \brief Determine whether this template argument has no value.
bool isNull() const { return Kind == Null; }
/// \brief Whether this template argument is dependent on a template
/// parameter such that its result can change from one instantiation to
/// another.
bool isDependent() const;
/// \brief Whether this template argument is dependent on a template
/// parameter.
bool isInstantiationDependent() const;
/// \brief Whether this template argument contains an unexpanded
/// parameter pack.
bool containsUnexpandedParameterPack() const;
/// \brief Determine whether this template argument is a pack expansion.
bool isPackExpansion() const;
/// \brief Retrieve the type for a type template argument.
QualType getAsType() const {
assert(Kind == Type && "Unexpected kind");
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
}
/// \brief Retrieve the declaration for a declaration non-type
/// template argument.
ValueDecl *getAsDecl() const {
assert(Kind == Declaration && "Unexpected kind");
return DeclArg.D;
}
/// \brief Retrieve whether a declaration is binding to a
/// reference parameter in a declaration non-type template argument.
bool isDeclForReferenceParam() const {
assert(Kind == Declaration && "Unexpected kind");
return DeclArg.ForRefParam;
}
/// \brief Retrieve the type for null non-type template argument.
QualType getNullPtrType() const {
assert(Kind == NullPtr && "Unexpected kind");
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
}
/// \brief Retrieve the template name for a template name argument.
TemplateName getAsTemplate() const {
assert(Kind == Template && "Unexpected kind");
return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
/// \brief Retrieve the template argument as a template name; if the argument
/// is a pack expansion, return the pattern as a template name.
TemplateName getAsTemplateOrTemplatePattern() const {
assert((Kind == Template || Kind == TemplateExpansion) &&
"Unexpected kind");
return TemplateName::getFromVoidPointer(TemplateArg.Name);
}
/// \brief Retrieve the number of expansions that a template template argument
/// expansion will produce, if known.
Optional<unsigned> getNumTemplateExpansions() const;
/// \brief Retrieve the template argument as an integral value.
// FIXME: Provide a way to read the integral data without copying the value.
llvm::APSInt getAsIntegral() const {
assert(Kind == Integral && "Unexpected kind");
using namespace llvm;
if (Integer.BitWidth <= 64)
return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
Integer.IsUnsigned);
}
/// \brief Retrieve the type of the integral value.
QualType getIntegralType() const {
assert(Kind == Integral && "Unexpected kind");
return QualType::getFromOpaquePtr(Integer.Type);
}
void setIntegralType(QualType T) {
assert(Kind == Integral && "Unexpected kind");
Integer.Type = T.getAsOpaquePtr();
}
/// \brief Retrieve the template argument as an expression.
Expr *getAsExpr() const {
assert(Kind == Expression && "Unexpected kind");
return reinterpret_cast<Expr *>(TypeOrValue);
}
/// \brief Iterator that traverses the elements of a template argument pack.
typedef const TemplateArgument * pack_iterator;
/// \brief Iterator referencing the first argument of a template argument
/// pack.
pack_iterator pack_begin() const {
assert(Kind == Pack);
return Args.Args;
}
/// \brief Iterator referencing one past the last argument of a template
/// argument pack.
pack_iterator pack_end() const {
assert(Kind == Pack);
return Args.Args + Args.NumArgs;
}
/// \brief The number of template arguments in the given template argument
/// pack.
unsigned pack_size() const {
assert(Kind == Pack);
return Args.NumArgs;
}
/// \brief Return the array of arguments in this template argument pack.
llvm::ArrayRef<TemplateArgument> getPackAsArray() const {
assert(Kind == Pack);
return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
}
/// \brief Determines whether two template arguments are superficially the
/// same.
bool structurallyEquals(const TemplateArgument &Other) const;
/// \brief When the template argument is a pack expansion, returns
/// the pattern of the pack expansion.
TemplateArgument getPackExpansionPattern() const;
/// \brief Print this template argument to the given output stream.
void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
/// \brief Used to insert TemplateArguments into FoldingSets.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
};
/// Location information for a TemplateArgument.
struct TemplateArgumentLocInfo {
private:
struct T {
// FIXME: We'd like to just use the qualifier in the TemplateName,
// but template arguments get canonicalized too quickly.
NestedNameSpecifier *Qualifier;
void *QualifierLocData;
unsigned TemplateNameLoc;
unsigned EllipsisLoc;
};
union {
struct T Template;
Expr *Expression;
TypeSourceInfo *Declarator;
};
public:
TemplateArgumentLocInfo();
TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
SourceLocation EllipsisLoc)
{
Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
Template.QualifierLocData = QualifierLoc.getOpaqueData();
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
}
TypeSourceInfo *getAsTypeSourceInfo() const {
return Declarator;
}
Expr *getAsExpr() const {
return Expression;
}
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
return NestedNameSpecifierLoc(Template.Qualifier,
Template.QualifierLocData);
}
SourceLocation getTemplateNameLoc() const {
return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
}
SourceLocation getTemplateEllipsisLoc() const {
return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
}
};
/// Location wrapper for a TemplateArgument. TemplateArgument is to
/// TemplateArgumentLoc as Type is to TypeLoc.
class TemplateArgumentLoc {
TemplateArgument Argument;
TemplateArgumentLocInfo LocInfo;
public:
TemplateArgumentLoc() {}
TemplateArgumentLoc(const TemplateArgument &Argument,
TemplateArgumentLocInfo Opaque)
: Argument(Argument), LocInfo(Opaque) {
}
TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
: Argument(Argument), LocInfo(TInfo) {
assert(Argument.getKind() == TemplateArgument::Type);
}
TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
: Argument(Argument), LocInfo(E) {
assert(Argument.getKind() == TemplateArgument::Expression);
}
TemplateArgumentLoc(const TemplateArgument &Argument,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc,
SourceLocation EllipsisLoc = SourceLocation())
: Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) {
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
}
/// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
if (Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion)
return getTemplateNameLoc();
return getSourceRange().getBegin();
}
/// \brief - Fetches the full source range of the argument.
SourceRange getSourceRange() const LLVM_READONLY;
const TemplateArgument &getArgument() const {
return Argument;
}
TemplateArgumentLocInfo getLocInfo() const {
return LocInfo;
}
TypeSourceInfo *getTypeSourceInfo() const {
assert(Argument.getKind() == TemplateArgument::Type);
return LocInfo.getAsTypeSourceInfo();
}
Expr *getSourceExpression() const {
assert(Argument.getKind() == TemplateArgument::Expression);
return LocInfo.getAsExpr();
}
Expr *getSourceDeclExpression() const {
assert(Argument.getKind() == TemplateArgument::Declaration);
return LocInfo.getAsExpr();
}
Expr *getSourceNullPtrExpression() const {
assert(Argument.getKind() == TemplateArgument::NullPtr);
return LocInfo.getAsExpr();
}
Expr *getSourceIntegralExpression() const {
assert(Argument.getKind() == TemplateArgument::Integral);
return LocInfo.getAsExpr();
}
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateQualifierLoc();
}
SourceLocation getTemplateNameLoc() const {
assert(Argument.getKind() == TemplateArgument::Template ||
Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateNameLoc();
}
SourceLocation getTemplateEllipsisLoc() const {
assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateEllipsisLoc();
}
/// \brief When the template argument is a pack expansion, returns
/// the pattern of the pack expansion.
///
/// \param Ellipsis Will be set to the location of the ellipsis.
///
/// \param NumExpansions Will be set to the number of expansions that will
/// be generated from this pack expansion, if known a priori.
TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis,
Optional<unsigned> &NumExpansions,
ASTContext &Context) const;
};
/// A convenient class for passing around template argument
/// information. Designed to be passed by reference.
class TemplateArgumentListInfo {
SmallVector<TemplateArgumentLoc, 8> Arguments;
SourceLocation LAngleLoc;
SourceLocation RAngleLoc;
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
// instead.
void* operator new(size_t bytes, ASTContext& C);
public:
TemplateArgumentListInfo() {}
TemplateArgumentListInfo(SourceLocation LAngleLoc,
SourceLocation RAngleLoc)
: LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
unsigned size() const { return Arguments.size(); }
const TemplateArgumentLoc *getArgumentArray() const {
return Arguments.data();
}
const TemplateArgumentLoc &operator[](unsigned I) const {
return Arguments[I];
}
void addArgument(const TemplateArgumentLoc &Loc) {
Arguments.push_back(Loc);
}
};
/// \brief Represents an explicit template argument list in C++, e.g.,
/// the "<int>" in "sort<int>".
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
struct ASTTemplateArgumentListInfo {
/// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
/// \brief The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;
union {
/// \brief The number of template arguments in TemplateArgs.
/// The actual template arguments (if any) are stored after the
/// ExplicitTemplateArgumentList structure.
unsigned NumTemplateArgs;
/// Force ASTTemplateArgumentListInfo to the right alignment
/// for the following array of TemplateArgumentLocs.
void *Aligner;
};
/// \brief Retrieve the template arguments
TemplateArgumentLoc *getTemplateArgs() {
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
}
/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
}
const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}
static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
const TemplateArgumentListInfo &List);
void initializeFrom(const TemplateArgumentListInfo &List);
void initializeFrom(const TemplateArgumentListInfo &List,
bool &Dependent, bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
};
/// \brief Extends ASTTemplateArgumentListInfo with the source location
/// information for the template keyword; this is used as part of the
/// representation of qualified identifiers, such as S<T>::template apply<T>.
struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
typedef ASTTemplateArgumentListInfo Base;
// NOTE: the source location of the (optional) template keyword is
// stored after all template arguments.
/// \brief Get the source location of the template keyword.
SourceLocation getTemplateKeywordLoc() const {
return *reinterpret_cast<const SourceLocation*>
(getTemplateArgs() + NumTemplateArgs);
}
/// \brief Sets the source location of the template keyword.
void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
*reinterpret_cast<SourceLocation*>
(getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
}
static const ASTTemplateKWAndArgsInfo*
Create(ASTContext &C, SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List);
void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List);
void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List,
bool &Dependent, bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void initializeFrom(SourceLocation TemplateKWLoc);
static std::size_t sizeFor(unsigned NumTemplateArgs);
};
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const TemplateArgument &Arg);
inline TemplateSpecializationType::iterator
TemplateSpecializationType::end() const {
return getArgs() + getNumArgs();
}
inline DependentTemplateSpecializationType::iterator
DependentTemplateSpecializationType::end() const {
return getArgs() + getNumArgs();
}
inline const TemplateArgument &
TemplateSpecializationType::getArg(unsigned Idx) const {
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
inline const TemplateArgument &
DependentTemplateSpecializationType::getArg(unsigned Idx) const {
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
} // end namespace clang
#endif

View File

@@ -0,0 +1,562 @@
//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TemplateName interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TEMPLATENAME_H
#define LLVM_CLANG_AST_TEMPLATENAME_H
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
namespace clang {
class ASTContext;
class DependentTemplateName;
class DiagnosticBuilder;
class IdentifierInfo;
class NestedNameSpecifier;
class OverloadedTemplateStorage;
struct PrintingPolicy;
class QualifiedTemplateName;
class NamedDecl;
class SubstTemplateTemplateParmStorage;
class SubstTemplateTemplateParmPackStorage;
class TemplateArgument;
class TemplateDecl;
class TemplateTemplateParmDecl;
/// \brief Implementation class used to describe either a set of overloaded
/// template names or an already-substituted template template parameter pack.
class UncommonTemplateNameStorage {
protected:
enum Kind {
Overloaded,
SubstTemplateTemplateParm,
SubstTemplateTemplateParmPack
};
struct BitsTag {
/// \brief A Kind.
unsigned Kind : 2;
/// \brief The number of stored templates or template arguments,
/// depending on which subclass we have.
unsigned Size : 30;
};
union {
struct BitsTag Bits;
void *PointerAlignment;
};
UncommonTemplateNameStorage(Kind kind, unsigned size) {
Bits.Kind = kind;
Bits.Size = size;
}
public:
unsigned size() const { return Bits.Size; }
OverloadedTemplateStorage *getAsOverloadedStorage() {
return Bits.Kind == Overloaded
? reinterpret_cast<OverloadedTemplateStorage *>(this)
: 0;
}
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
return Bits.Kind == SubstTemplateTemplateParm
? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
: 0;
}
SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
return Bits.Kind == SubstTemplateTemplateParmPack
? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this)
: 0;
}
};
/// \brief A structure for storing the information associated with an
/// overloaded template name.
class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
friend class ASTContext;
OverloadedTemplateStorage(unsigned size)
: UncommonTemplateNameStorage(Overloaded, size) { }
NamedDecl **getStorage() {
return reinterpret_cast<NamedDecl **>(this + 1);
}
NamedDecl * const *getStorage() const {
return reinterpret_cast<NamedDecl *const *>(this + 1);
}
public:
typedef NamedDecl *const *iterator;
iterator begin() const { return getStorage(); }
iterator end() const { return getStorage() + size(); }
};
/// \brief A structure for storing an already-substituted template template
/// parameter pack.
///
/// This kind of template names occurs when the parameter pack has been
/// provided with a template template argument pack in a context where its
/// enclosing pack expansion could not be fully expanded.
class SubstTemplateTemplateParmPackStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode
{
TemplateTemplateParmDecl *Parameter;
const TemplateArgument *Arguments;
public:
SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
unsigned Size,
const TemplateArgument *Arguments)
: UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
Parameter(Parameter), Arguments(Arguments) { }
/// \brief Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const {
return Parameter;
}
/// \brief Retrieve the template template argument pack with which this
/// parameter was substituted.
TemplateArgument getArgumentPack() const;
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
static void Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack);
};
/// \brief Represents a C++ template name within the type system.
///
/// A C++ template name refers to a template within the C++ type
/// system. In most cases, a template name is simply a reference to a
/// class template, e.g.
///
/// \code
/// template<typename T> class X { };
///
/// X<int> xi;
/// \endcode
///
/// Here, the 'X' in \c X<int> is a template name that refers to the
/// declaration of the class template X, above. Template names can
/// also refer to function templates, C++0x template aliases, etc.
///
/// Some template names are dependent. For example, consider:
///
/// \code
/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
/// typedef typename MetaFun::template apply<T1, T2>::type type;
/// };
/// \endcode
///
/// Here, "apply" is treated as a template name within the typename
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
class TemplateName {
typedef llvm::PointerUnion4<TemplateDecl *,
UncommonTemplateNameStorage *,
QualifiedTemplateName *,
DependentTemplateName *> StorageType;
StorageType Storage;
explicit TemplateName(void *Ptr) {
Storage = StorageType::getFromOpaqueValue(Ptr);
}
public:
// \brief Kind of name that is actually stored.
enum NameKind {
/// \brief A single template declaration.
Template,
/// \brief A set of overloaded template declarations.
OverloadedTemplate,
/// \brief A qualified template name, where the qualification is kept
/// to describe the source code as written.
QualifiedTemplate,
/// \brief A dependent template name that has not been resolved to a
/// template (or set of templates).
DependentTemplate,
/// \brief A template template parameter that has been substituted
/// for some other template name.
SubstTemplateTemplateParm,
/// \brief A template template parameter pack that has been substituted for
/// a template template argument pack, but has not yet been expanded into
/// individual arguments.
SubstTemplateTemplateParmPack
};
TemplateName() : Storage() { }
explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
explicit TemplateName(OverloadedTemplateStorage *Storage)
: Storage(Storage) { }
explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
: Storage(Storage) { }
explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
/// \brief Determine whether this template name is NULL.
bool isNull() const { return Storage.isNull(); }
// \brief Get the kind of name that is actually stored.
NameKind getKind() const;
/// \brief Retrieve the underlying template declaration that
/// this template name refers to, if known.
///
/// \returns The template declaration that this template name refers
/// to, if any. If the template name does not refer to a specific
/// declaration because it is a dependent name, or if it refers to a
/// set of function templates, returns NULL.
TemplateDecl *getAsTemplateDecl() const;
/// \brief Retrieve the underlying, overloaded function template
// declarations that this template name refers to, if known.
///
/// \returns The set of overloaded function templates that this template
/// name refers to, if known. If the template name does not refer to a
/// specific set of function templates because it is a dependent name or
/// refers to a single template, returns NULL.
OverloadedTemplateStorage *getAsOverloadedTemplate() const {
if (UncommonTemplateNameStorage *Uncommon =
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return Uncommon->getAsOverloadedStorage();
return 0;
}
/// \brief Retrieve the substituted template template parameter, if
/// known.
///
/// \returns The storage for the substituted template template parameter,
/// if known. Otherwise, returns NULL.
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const {
if (UncommonTemplateNameStorage *uncommon =
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return uncommon->getAsSubstTemplateTemplateParm();
return 0;
}
/// \brief Retrieve the substituted template template parameter pack, if
/// known.
///
/// \returns The storage for the substituted template template parameter pack,
/// if known. Otherwise, returns NULL.
SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const {
if (UncommonTemplateNameStorage *Uncommon =
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return Uncommon->getAsSubstTemplateTemplateParmPack();
return 0;
}
/// \brief Retrieve the underlying qualified template name
/// structure, if any.
QualifiedTemplateName *getAsQualifiedTemplateName() const {
return Storage.dyn_cast<QualifiedTemplateName *>();
}
/// \brief Retrieve the underlying dependent template name
/// structure, if any.
DependentTemplateName *getAsDependentTemplateName() const {
return Storage.dyn_cast<DependentTemplateName *>();
}
TemplateName getUnderlying() const;
/// \brief Determines whether this is a dependent template name.
bool isDependent() const;
/// \brief Determines whether this is a template name that somehow
/// depends on a template parameter.
bool isInstantiationDependent() const;
/// \brief Determines whether this template name contains an
/// unexpanded parameter pack (for C++0x variadic templates).
bool containsUnexpandedParameterPack() const;
/// \brief Print the template name.
///
/// \param OS the output stream to which the template name will be
/// printed.
///
/// \param SuppressNNS if true, don't print the
/// nested-name-specifier that precedes the template name (if it has
/// one).
void print(raw_ostream &OS, const PrintingPolicy &Policy,
bool SuppressNNS = false) const;
/// \brief Debugging aid that dumps the template name.
void dump(raw_ostream &OS) const;
/// \brief Debugging aid that dumps the template name to standard
/// error.
void dump() const;
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddPointer(Storage.getOpaqueValue());
}
/// \brief Retrieve the template name as a void pointer.
void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
/// \brief Build a template name from a void pointer.
static TemplateName getFromVoidPointer(void *Ptr) {
return TemplateName(Ptr);
}
};
/// Insertion operator for diagnostics. This allows sending TemplateName's
/// into a diagnostic with <<.
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
TemplateName N);
/// \brief A structure for storing the information associated with a
/// substituted template template parameter.
class SubstTemplateTemplateParmStorage
: public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
friend class ASTContext;
TemplateTemplateParmDecl *Parameter;
TemplateName Replacement;
SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
TemplateName replacement)
: UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
Parameter(parameter), Replacement(replacement) {}
public:
TemplateTemplateParmDecl *getParameter() const { return Parameter; }
TemplateName getReplacement() const { return Replacement; }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
TemplateTemplateParmDecl *parameter,
TemplateName replacement);
};
inline TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
: Storage(Storage) { }
inline TemplateName TemplateName::getUnderlying() const {
if (SubstTemplateTemplateParmStorage *subst
= getAsSubstTemplateTemplateParm())
return subst->getReplacement().getUnderlying();
return *this;
}
/// \brief Represents a template name that was expressed as a
/// qualified name.
///
/// This kind of template name refers to a template name that was
/// preceded by a nested name specifier, e.g., \c std::vector. Here,
/// the nested name specifier is "std::" and the template name is the
/// declaration for "vector". The QualifiedTemplateName class is only
/// used to provide "sugar" for template names that were expressed
/// with a qualified name, and has no semantic meaning. In this
/// manner, it is to TemplateName what ElaboratedType is to Type,
/// providing extra syntactic sugar for downstream clients.
class QualifiedTemplateName : public llvm::FoldingSetNode {
/// \brief The nested name specifier that qualifies the template name.
///
/// The bit is used to indicate whether the "template" keyword was
/// present before the template name itself. Note that the
/// "template" keyword is always redundant in this case (otherwise,
/// the template name would be a dependent name and we would express
/// this name with DependentTemplateName).
llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
/// \brief The template declaration or set of overloaded function templates
/// that this qualified name refers to.
TemplateDecl *Template;
friend class ASTContext;
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
TemplateDecl *Template)
: Qualifier(NNS, TemplateKeyword? 1 : 0),
Template(Template) { }
public:
/// \brief Return the nested name specifier that qualifies this name.
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
/// \brief Whether the template name was prefixed by the "template"
/// keyword.
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
/// \brief The template declaration that this qualified name refers
/// to.
TemplateDecl *getDecl() const { return Template; }
/// \brief The template declaration to which this qualified name
/// refers.
TemplateDecl *getTemplateDecl() const { return Template; }
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
bool TemplateKeyword, TemplateDecl *Template) {
ID.AddPointer(NNS);
ID.AddBoolean(TemplateKeyword);
ID.AddPointer(Template);
}
};
/// \brief Represents a dependent template name that cannot be
/// resolved prior to template instantiation.
///
/// This kind of template name refers to a dependent template name,
/// including its nested name specifier (if any). For example,
/// DependentTemplateName can refer to "MetaFun::template apply",
/// where "MetaFun::" is the nested name specifier and "apply" is the
/// template name referenced. The "template" keyword is implied.
class DependentTemplateName : public llvm::FoldingSetNode {
/// \brief The nested name specifier that qualifies the template
/// name.
///
/// The bit stored in this qualifier describes whether the \c Name field
/// is interpreted as an IdentifierInfo pointer (when clear) or as an
/// overloaded operator kind (when set).
llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
/// \brief The dependent template name.
union {
/// \brief The identifier template name.
///
/// Only valid when the bit on \c Qualifier is clear.
const IdentifierInfo *Identifier;
/// \brief The overloaded operator name.
///
/// Only valid when the bit on \c Qualifier is set.
OverloadedOperatorKind Operator;
};
/// \brief The canonical template name to which this dependent
/// template name refers.
///
/// The canonical template name for a dependent template name is
/// another dependent template name whose nested name specifier is
/// canonical.
TemplateName CanonicalTemplateName;
friend class ASTContext;
DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier)
: Qualifier(Qualifier, false), Identifier(Identifier),
CanonicalTemplateName(this) { }
DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier,
TemplateName Canon)
: Qualifier(Qualifier, false), Identifier(Identifier),
CanonicalTemplateName(Canon) { }
DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator)
: Qualifier(Qualifier, true), Operator(Operator),
CanonicalTemplateName(this) { }
DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator,
TemplateName Canon)
: Qualifier(Qualifier, true), Operator(Operator),
CanonicalTemplateName(Canon) { }
public:
/// \brief Return the nested name specifier that qualifies this name.
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
/// \brief Determine whether this template name refers to an identifier.
bool isIdentifier() const { return !Qualifier.getInt(); }
/// \brief Returns the identifier to which this template name refers.
const IdentifierInfo *getIdentifier() const {
assert(isIdentifier() && "Template name isn't an identifier?");
return Identifier;
}
/// \brief Determine whether this template name refers to an overloaded
/// operator.
bool isOverloadedOperator() const { return Qualifier.getInt(); }
/// \brief Return the overloaded operator to which this template name refers.
OverloadedOperatorKind getOperator() const {
assert(isOverloadedOperator() &&
"Template name isn't an overloaded operator?");
return Operator;
}
void Profile(llvm::FoldingSetNodeID &ID) {
if (isIdentifier())
Profile(ID, getQualifier(), getIdentifier());
else
Profile(ID, getQualifier(), getOperator());
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
const IdentifierInfo *Identifier) {
ID.AddPointer(NNS);
ID.AddBoolean(false);
ID.AddPointer(Identifier);
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) {
ID.AddPointer(NNS);
ID.AddBoolean(true);
ID.AddInteger(Operator);
}
};
} // end namespace clang.
namespace llvm {
/// \brief The clang::TemplateName class is effectively a pointer.
template<>
class PointerLikeTypeTraits<clang::TemplateName> {
public:
static inline void *getAsVoidPointer(clang::TemplateName TN) {
return TN.getAsVoidPointer();
}
static inline clang::TemplateName getFromVoidPointer(void *Ptr) {
return clang::TemplateName::getFromVoidPointer(Ptr);
}
// No bits are available!
enum { NumLowBitsAvailable = 0 };
};
} // end namespace llvm.
#endif

5126
thirdparty/clang/include/clang/AST/Type.h vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
//===-- TypeLocNodes.def - Metadata about TypeLoc wrappers ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeLoc info database. Each node is
// enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc")
// and base class (e.g., "DeclaratorLoc"). All nodes except QualifiedTypeLoc
// are associated
//
// TYPELOC(Class, Base) - A TypeLoc subclass. If UNQUAL_TYPELOC is
// provided, there will be exactly one of these, Qualified.
//
// UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass.
//
// ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc.
//
//===----------------------------------------------------------------------===//
#ifndef UNQUAL_TYPELOC
# define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base)
#endif
#ifndef ABSTRACT_TYPELOC
# define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base)
#endif
TYPELOC(Qualified, TypeLoc)
#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc)
#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc)
#include "clang/AST/TypeNodes.def"
#undef DECLARATOR_TYPELOC
#undef TYPESPEC_TYPELOC
#undef ABSTRACT_TYPELOC
#undef UNQUAL_TYPELOC
#undef TYPELOC

View File

@@ -0,0 +1,62 @@
//===--- TypeLocVisitor.h - Visitor for TypeLoc subclasses ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeLocVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPELOCVISITOR_H
#define LLVM_CLANG_AST_TYPELOCVISITOR_H
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
#define DISPATCH(CLASSNAME) \
return static_cast<ImplClass*>(this)-> \
Visit##CLASSNAME(TyLoc.castAs<CLASSNAME>())
template<typename ImplClass, typename RetTy=void>
class TypeLocVisitor {
public:
RetTy Visit(TypeLoc TyLoc) {
switch (TyLoc.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
#include "clang/AST/TypeLocNodes.def"
}
llvm_unreachable("unexpected type loc class!");
}
RetTy Visit(UnqualTypeLoc TyLoc) {
switch (TyLoc.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc);
#include "clang/AST/TypeLocNodes.def"
}
llvm_unreachable("unexpected type loc class!");
}
#define TYPELOC(CLASS, PARENT) \
RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
DISPATCH(PARENT); \
}
#include "clang/AST/TypeLocNodes.def"
RetTy VisitTypeLoc(TypeLoc TyLoc) { return RetTy(); }
};
#undef DISPATCH
} // end namespace clang
#endif // LLVM_CLANG_AST_TYPELOCVISITOR_H

View File

@@ -0,0 +1,127 @@
//===-- TypeNodes.def - Metadata about Type AST nodes -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AST type info database. Each type node is
// enumerated by providing its name (e.g., "Builtin" or "Enum") and
// base class (e.g., "Type" or "TagType"). Depending on where in the
// abstract syntax tree the type will show up, the enumeration uses
// one of four different macros:
//
// TYPE(Class, Base) - A type that can show up anywhere in the AST,
// and might be dependent, canonical, or non-canonical. All clients
// will need to understand these types.
//
// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
// the type hierarchy but has no concrete instances.
//
// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
// anywhere in the AST but will never be a part of a canonical
// type. Clients that only need to deal with canonical types
// (ignoring, e.g., typedefs and other type alises used for
// pretty-printing) can ignore these types.
//
// DEPENDENT_TYPE(Class, Base) - A type that will only show up
// within a C++ template that has not been instantiated, e.g., a
// type that is always dependent. Clients that do not need to deal
// with uninstantiated C++ templates can ignore these types.
//
// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
// is non-canonical unless it is dependent. Defaults to TYPE because
// it is neither reliably dependent nor reliably non-canonical.
//
// There is a sixth macro, independent of the others. Most clients
// will not need to use it.
//
// LEAF_TYPE(Class) - A type that never has inner types. Clients
// which can operate on such types more efficiently may wish to do so.
//
//===----------------------------------------------------------------------===//
#ifndef ABSTRACT_TYPE
# define ABSTRACT_TYPE(Class, Base) TYPE(Class, Base)
#endif
#ifndef NON_CANONICAL_TYPE
# define NON_CANONICAL_TYPE(Class, Base) TYPE(Class, Base)
#endif
#ifndef DEPENDENT_TYPE
# define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
#endif
#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
#endif
TYPE(Builtin, Type)
TYPE(Complex, Type)
TYPE(Pointer, Type)
TYPE(BlockPointer, Type)
ABSTRACT_TYPE(Reference, Type)
TYPE(LValueReference, ReferenceType)
TYPE(RValueReference, ReferenceType)
TYPE(MemberPointer, Type)
ABSTRACT_TYPE(Array, Type)
TYPE(ConstantArray, ArrayType)
TYPE(IncompleteArray, ArrayType)
TYPE(VariableArray, ArrayType)
DEPENDENT_TYPE(DependentSizedArray, ArrayType)
DEPENDENT_TYPE(DependentSizedExtVector, Type)
TYPE(Vector, Type)
TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
TYPE(FunctionProto, FunctionType)
TYPE(FunctionNoProto, FunctionType)
DEPENDENT_TYPE(UnresolvedUsing, Type)
NON_CANONICAL_TYPE(Paren, Type)
NON_CANONICAL_TYPE(Typedef, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type)
ABSTRACT_TYPE(Tag, Type)
TYPE(Record, TagType)
TYPE(Enum, TagType)
NON_CANONICAL_TYPE(Elaborated, Type)
NON_CANONICAL_TYPE(Attributed, Type)
DEPENDENT_TYPE(TemplateTypeParm, Type)
NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type)
DEPENDENT_TYPE(InjectedClassName, Type)
DEPENDENT_TYPE(DependentName, Type)
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
DEPENDENT_TYPE(PackExpansion, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
TYPE(Atomic, Type)
#ifdef LAST_TYPE
LAST_TYPE(Atomic)
#undef LAST_TYPE
#endif
// These types are always leaves in the type hierarchy.
#ifdef LEAF_TYPE
LEAF_TYPE(Enum)
LEAF_TYPE(Builtin)
LEAF_TYPE(Record)
LEAF_TYPE(InjectedClassName)
LEAF_TYPE(ObjCInterface)
LEAF_TYPE(TemplateTypeParm)
#undef LEAF_TYPE
#endif
#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
#undef DEPENDENT_TYPE
#undef NON_CANONICAL_TYPE
#undef ABSTRACT_TYPE
#undef TYPE

View File

@@ -0,0 +1,77 @@
//===-------------- TypeOrdering.h - Total ordering for types -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a function objects and specializations that
// allow QualType values to be sorted, used in std::maps, std::sets,
// llvm::DenseMaps, and llvm::DenseSets.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TYPE_ORDERING_H
#define LLVM_CLANG_TYPE_ORDERING_H
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Type.h"
#include <functional>
namespace clang {
/// QualTypeOrdering - Function object that provides a total ordering
/// on QualType values.
struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
bool operator()(QualType T1, QualType T2) const {
return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
}
};
}
namespace llvm {
template<class> struct DenseMapInfo;
template<> struct DenseMapInfo<clang::QualType> {
static inline clang::QualType getEmptyKey() { return clang::QualType(); }
static inline clang::QualType getTombstoneKey() {
using clang::QualType;
return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
}
static unsigned getHashValue(clang::QualType Val) {
return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
}
static bool isEqual(clang::QualType LHS, clang::QualType RHS) {
return LHS == RHS;
}
};
template<> struct DenseMapInfo<clang::CanQualType> {
static inline clang::CanQualType getEmptyKey() {
return clang::CanQualType();
}
static inline clang::CanQualType getTombstoneKey() {
using clang::CanQualType;
return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
}
static unsigned getHashValue(clang::CanQualType Val) {
return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
}
static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
return LHS == RHS;
}
};
}
#endif

View File

@@ -0,0 +1,53 @@
//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPEVISITOR_H
#define LLVM_CLANG_AST_TYPEVISITOR_H
#include "clang/AST/Type.h"
namespace clang {
#define DISPATCH(CLASS) \
return static_cast<ImplClass*>(this)-> \
Visit##CLASS(static_cast<const CLASS*>(T))
template<typename ImplClass, typename RetTy=void>
class TypeVisitor {
public:
RetTy Visit(const Type *T) {
// Top switch stmt: dispatch to VisitFooType for each FooType.
switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
#include "clang/AST/TypeNodes.def"
}
llvm_unreachable("Unknown type class!");
}
// If the implementation chooses not to implement a certain visit method, fall
// back on superclass.
#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
DISPATCH(PARENT); \
}
#include "clang/AST/TypeNodes.def"
// Base case, ignore it. :)
RetTy VisitType(const Type*) { return RetTy(); }
};
#undef DISPATCH
} // end namespace clang
#endif

View File

@@ -0,0 +1,189 @@
//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the UnresolvedSet class, which is used to store
// collections of declarations in the AST.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H
#define LLVM_CLANG_AST_UNRESOLVEDSET_H
#include "clang/AST/DeclAccessPair.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include <iterator>
namespace clang {
/// The iterator over UnresolvedSets. Serves as both the const and
/// non-const iterator.
class UnresolvedSetIterator {
private:
typedef llvm::MutableArrayRef<DeclAccessPair> DeclsTy;
typedef DeclsTy::iterator IteratorTy;
IteratorTy ir;
friend class UnresolvedSetImpl;
friend class ASTUnresolvedSet;
friend class OverloadExpr;
explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {}
explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) :
ir(const_cast<DeclsTy::iterator>(ir)) {}
IteratorTy getIterator() const { return ir; }
public:
UnresolvedSetIterator() {}
typedef std::iterator_traits<IteratorTy>::difference_type difference_type;
typedef NamedDecl *value_type;
typedef NamedDecl **pointer;
typedef NamedDecl *reference;
typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
NamedDecl *getDecl() const { return ir->getDecl(); }
AccessSpecifier getAccess() const { return ir->getAccess(); }
void setAccess(AccessSpecifier AS) { ir->setAccess(AS); }
DeclAccessPair getPair() const { return *ir; }
NamedDecl *operator*() const { return getDecl(); }
UnresolvedSetIterator &operator++() { ++ir; return *this; }
UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); }
UnresolvedSetIterator &operator--() { --ir; return *this; }
UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); }
UnresolvedSetIterator &operator+=(difference_type d) {
ir += d; return *this;
}
UnresolvedSetIterator operator+(difference_type d) const {
return UnresolvedSetIterator(ir + d);
}
UnresolvedSetIterator &operator-=(difference_type d) {
ir -= d; return *this;
}
UnresolvedSetIterator operator-(difference_type d) const {
return UnresolvedSetIterator(ir - d);
}
value_type operator[](difference_type d) const { return *(*this + d); }
difference_type operator-(const UnresolvedSetIterator &o) const {
return ir - o.ir;
}
bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; }
bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; }
bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; }
bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; }
bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; }
bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
};
/// UnresolvedSet - A set of unresolved declarations.
class UnresolvedSetImpl {
typedef SmallVectorImpl<DeclAccessPair> DeclsTy;
// Don't allow direct construction, and only permit subclassing by
// UnresolvedSet.
private:
template <unsigned N> friend class UnresolvedSet;
UnresolvedSetImpl() {}
UnresolvedSetImpl(const UnresolvedSetImpl &) LLVM_DELETED_FUNCTION;
public:
// We don't currently support assignment through this iterator, so we might
// as well use the same implementation twice.
typedef UnresolvedSetIterator iterator;
typedef UnresolvedSetIterator const_iterator;
iterator begin() { return iterator(decls().begin()); }
iterator end() { return iterator(decls().end()); }
const_iterator begin() const { return const_iterator(decls().begin()); }
const_iterator end() const { return const_iterator(decls().end()); }
void addDecl(NamedDecl *D) {
addDecl(D, AS_none);
}
void addDecl(NamedDecl *D, AccessSpecifier AS) {
decls().push_back(DeclAccessPair::make(D, AS));
}
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
bool replace(const NamedDecl* Old, NamedDecl *New) {
for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I)
if (I->getDecl() == Old)
return (I->setDecl(New), true);
return false;
}
/// Replaces the declaration at the given iterator with the new one,
/// preserving the original access bits.
void replace(iterator I, NamedDecl *New) {
I.ir->setDecl(New);
}
void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
I.ir->set(New, AS);
}
void erase(unsigned I) {
decls()[I] = decls().back();
decls().pop_back();
}
void erase(iterator I) {
*I.ir = decls().back();
decls().pop_back();
}
void setAccess(iterator I, AccessSpecifier AS) {
I.ir->setAccess(AS);
}
void clear() { decls().clear(); }
void set_size(unsigned N) { decls().set_size(N); }
bool empty() const { return decls().empty(); }
unsigned size() const { return decls().size(); }
void append(iterator I, iterator E) {
decls().append(I.ir, E.ir);
}
DeclAccessPair &operator[](unsigned I) { return decls()[I]; }
const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; }
private:
// These work because the only permitted subclass is UnresolvedSetImpl
DeclsTy &decls() {
return *reinterpret_cast<DeclsTy*>(this);
}
const DeclsTy &decls() const {
return *reinterpret_cast<const DeclsTy*>(this);
}
};
/// A set of unresolved declarations
template <unsigned InlineCapacity> class UnresolvedSet :
public UnresolvedSetImpl {
SmallVector<DeclAccessPair, InlineCapacity> Decls;
};
} // namespace clang
#endif

View File

@@ -0,0 +1,167 @@
//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with generation of the layout of virtual table
// tables (VTT).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_VTTBUILDER_H
#define LLVM_CLANG_AST_VTTBUILDER_H
#include "clang/AST/BaseSubobject.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/SetVector.h"
#include <utility>
namespace clang {
class VTTVTable {
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual;
CharUnits BaseOffset;
public:
VTTVTable() {}
VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual)
: BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
VTTVTable(BaseSubobject Base, bool BaseIsVirtual)
: BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
BaseOffset(Base.getBaseOffset()) {}
const CXXRecordDecl *getBase() const {
return BaseAndIsVirtual.getPointer();
}
CharUnits getBaseOffset() const {
return BaseOffset;
}
bool isVirtual() const {
return BaseAndIsVirtual.getInt();
}
BaseSubobject getBaseSubobject() const {
return BaseSubobject(getBase(), getBaseOffset());
}
};
struct VTTComponent {
uint64_t VTableIndex;
BaseSubobject VTableBase;
VTTComponent() {}
VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase)
: VTableIndex(VTableIndex), VTableBase(VTableBase) {}
};
/// VTT builder - Class for building VTT layout information.
class VTTBuilder {
ASTContext &Ctx;
/// MostDerivedClass - The most derived class for which we're building this
/// vtable.
const CXXRecordDecl *MostDerivedClass;
typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy;
/// VTTVTables - The VTT vtables.
VTTVTablesVectorTy VTTVTables;
typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy;
/// VTTComponents - The VTT components.
VTTComponentsVectorTy VTTComponents;
/// MostDerivedClassLayout - the AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
/// SubVTTIndicies - The sub-VTT indices for the bases of the most derived
/// class.
llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
/// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of
/// all subobjects of the most derived class.
llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
/// GenerateDefinition - Whether the VTT builder should generate LLVM IR for
/// the VTT.
bool GenerateDefinition;
/// AddVTablePointer - Add a vtable pointer to the VTT currently being built.
void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
const CXXRecordDecl *VTableClass);
/// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base
/// subobject.
void LayoutSecondaryVTTs(BaseSubobject Base);
/// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
/// for the given base subobject.
///
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
/// or a direct or indirect base of a virtual base.
void LayoutSecondaryVirtualPointers(BaseSubobject Base,
bool BaseIsMorallyVirtual,
uint64_t VTableIndex,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy &VBases);
/// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers
/// for the given base subobject.
void LayoutSecondaryVirtualPointers(BaseSubobject Base,
uint64_t VTableIndex);
/// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the
/// given record decl.
void LayoutVirtualVTTs(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases);
/// LayoutVTT - Will lay out the VTT for the given subobject, including any
/// secondary VTTs, secondary virtual pointers and virtual VTTs.
void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual);
public:
VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
bool GenerateDefinition);
// getVTTComponents - Returns a reference to the VTT components.
const VTTComponentsVectorTy &getVTTComponents() const {
return VTTComponents;
}
// getVTTVTables - Returns a reference to the VTT vtables.
const VTTVTablesVectorTy &getVTTVTables() const {
return VTTVTables;
}
/// getSubVTTIndicies - Returns a reference to the sub-VTT indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
return SubVTTIndicies;
}
/// getSecondaryVirtualPointerIndices - Returns a reference to the secondary
/// virtual pointer indices.
const llvm::DenseMap<BaseSubobject, uint64_t> &
getSecondaryVirtualPointerIndices() const {
return SecondaryVirtualPointerIndices;
}
};
}
#endif

View File

@@ -0,0 +1,375 @@
//===--- VTableBuilder.h - C++ vtable layout builder --------------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with generation of the layout of virtual tables.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_VTABLEBUILDER_H
#define LLVM_CLANG_AST_VTABLEBUILDER_H
#include "clang/AST/BaseSubobject.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/SetVector.h"
#include <utility>
namespace clang {
class CXXRecordDecl;
/// VTableComponent - Represents a single component in a vtable.
class VTableComponent {
public:
enum Kind {
CK_VCallOffset,
CK_VBaseOffset,
CK_OffsetToTop,
CK_RTTI,
CK_FunctionPointer,
/// CK_CompleteDtorPointer - A pointer to the complete destructor.
CK_CompleteDtorPointer,
/// CK_DeletingDtorPointer - A pointer to the deleting destructor.
CK_DeletingDtorPointer,
/// CK_UnusedFunctionPointer - In some cases, a vtable function pointer
/// will end up never being called. Such vtable function pointers are
/// represented as a CK_UnusedFunctionPointer.
CK_UnusedFunctionPointer
};
VTableComponent() { }
static VTableComponent MakeVCallOffset(CharUnits Offset) {
return VTableComponent(CK_VCallOffset, Offset);
}
static VTableComponent MakeVBaseOffset(CharUnits Offset) {
return VTableComponent(CK_VBaseOffset, Offset);
}
static VTableComponent MakeOffsetToTop(CharUnits Offset) {
return VTableComponent(CK_OffsetToTop, Offset);
}
static VTableComponent MakeRTTI(const CXXRecordDecl *RD) {
return VTableComponent(CK_RTTI, reinterpret_cast<uintptr_t>(RD));
}
static VTableComponent MakeFunction(const CXXMethodDecl *MD) {
assert(!isa<CXXDestructorDecl>(MD) &&
"Don't use MakeFunction with destructors!");
return VTableComponent(CK_FunctionPointer,
reinterpret_cast<uintptr_t>(MD));
}
static VTableComponent MakeCompleteDtor(const CXXDestructorDecl *DD) {
return VTableComponent(CK_CompleteDtorPointer,
reinterpret_cast<uintptr_t>(DD));
}
static VTableComponent MakeDeletingDtor(const CXXDestructorDecl *DD) {
return VTableComponent(CK_DeletingDtorPointer,
reinterpret_cast<uintptr_t>(DD));
}
static VTableComponent MakeUnusedFunction(const CXXMethodDecl *MD) {
assert(!isa<CXXDestructorDecl>(MD) &&
"Don't use MakeUnusedFunction with destructors!");
return VTableComponent(CK_UnusedFunctionPointer,
reinterpret_cast<uintptr_t>(MD));
}
static VTableComponent getFromOpaqueInteger(uint64_t I) {
return VTableComponent(I);
}
/// getKind - Get the kind of this vtable component.
Kind getKind() const {
return (Kind)(Value & 0x7);
}
CharUnits getVCallOffset() const {
assert(getKind() == CK_VCallOffset && "Invalid component kind!");
return getOffset();
}
CharUnits getVBaseOffset() const {
assert(getKind() == CK_VBaseOffset && "Invalid component kind!");
return getOffset();
}
CharUnits getOffsetToTop() const {
assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
return getOffset();
}
const CXXRecordDecl *getRTTIDecl() const {
assert(getKind() == CK_RTTI && "Invalid component kind!");
return reinterpret_cast<CXXRecordDecl *>(getPointer());
}
const CXXMethodDecl *getFunctionDecl() const {
assert(getKind() == CK_FunctionPointer);
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
const CXXDestructorDecl *getDestructorDecl() const {
assert((getKind() == CK_CompleteDtorPointer ||
getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
}
const CXXMethodDecl *getUnusedFunctionDecl() const {
assert(getKind() == CK_UnusedFunctionPointer);
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
private:
VTableComponent(Kind ComponentKind, CharUnits Offset) {
assert((ComponentKind == CK_VCallOffset ||
ComponentKind == CK_VBaseOffset ||
ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!");
assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!");
Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind;
}
VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
assert((ComponentKind == CK_RTTI ||
ComponentKind == CK_FunctionPointer ||
ComponentKind == CK_CompleteDtorPointer ||
ComponentKind == CK_DeletingDtorPointer ||
ComponentKind == CK_UnusedFunctionPointer) &&
"Invalid component kind!");
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
Value = Ptr | ComponentKind;
}
CharUnits getOffset() const {
assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
getKind() == CK_OffsetToTop) && "Invalid component kind!");
return CharUnits::fromQuantity(Value >> 3);
}
uintptr_t getPointer() const {
assert((getKind() == CK_RTTI ||
getKind() == CK_FunctionPointer ||
getKind() == CK_CompleteDtorPointer ||
getKind() == CK_DeletingDtorPointer ||
getKind() == CK_UnusedFunctionPointer) &&
"Invalid component kind!");
return static_cast<uintptr_t>(Value & ~7ULL);
}
explicit VTableComponent(uint64_t Value)
: Value(Value) { }
/// The kind is stored in the lower 3 bits of the value. For offsets, we
/// make use of the facts that classes can't be larger than 2^55 bytes,
/// so we store the offset in the lower part of the 61 bytes that remain.
/// (The reason that we're not simply using a PointerIntPair here is that we
/// need the offsets to be 64-bit, even when on a 32-bit machine).
int64_t Value;
};
class VTableLayout {
public:
typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
typedef const VTableComponent *vtable_component_iterator;
typedef const VTableThunkTy *vtable_thunk_iterator;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
private:
uint64_t NumVTableComponents;
llvm::OwningArrayPtr<VTableComponent> VTableComponents;
/// VTableThunks - Contains thunks needed by vtables.
uint64_t NumVTableThunks;
llvm::OwningArrayPtr<VTableThunkTy> VTableThunks;
/// Address points - Address points for all vtables.
AddressPointsMapTy AddressPoints;
bool IsMicrosoftABI;
public:
VTableLayout(uint64_t NumVTableComponents,
const VTableComponent *VTableComponents,
uint64_t NumVTableThunks,
const VTableThunkTy *VTableThunks,
const AddressPointsMapTy &AddressPoints,
bool IsMicrosoftABI);
~VTableLayout();
uint64_t getNumVTableComponents() const {
return NumVTableComponents;
}
vtable_component_iterator vtable_component_begin() const {
return VTableComponents.get();
}
vtable_component_iterator vtable_component_end() const {
return VTableComponents.get()+NumVTableComponents;
}
uint64_t getNumVTableThunks() const {
return NumVTableThunks;
}
vtable_thunk_iterator vtable_thunk_begin() const {
return VTableThunks.get();
}
vtable_thunk_iterator vtable_thunk_end() const {
return VTableThunks.get()+NumVTableThunks;
}
uint64_t getAddressPoint(BaseSubobject Base) const {
assert(AddressPoints.count(Base) &&
"Did not find address point!");
uint64_t AddressPoint = AddressPoints.lookup(Base);
assert(AddressPoint != 0 || IsMicrosoftABI);
(void)IsMicrosoftABI;
return AddressPoint;
}
const AddressPointsMapTy &getAddressPoints() const {
return AddressPoints;
}
};
class VTableContext {
ASTContext &Context;
public:
typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1>
VTableThunksTy;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
private:
bool IsMicrosoftABI;
/// MethodVTableIndices - Contains the index (relative to the vtable address
/// point) where the function pointer for a virtual function is stored.
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
MethodVTableIndicesTy MethodVTableIndices;
typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *>
VTableLayoutMapTy;
VTableLayoutMapTy VTableLayouts;
/// NumVirtualFunctionPointers - Contains the number of virtual function
/// pointers in the vtable for a given record decl.
llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
typedef std::pair<const CXXRecordDecl *,
const CXXRecordDecl *> ClassPairTy;
/// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to
/// the address point) in chars where the offsets for virtual bases of a class
/// are stored.
typedef llvm::DenseMap<ClassPairTy, CharUnits>
VirtualBaseClassOffsetOffsetsMapTy;
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
/// Thunks - Contains all thunks that a given method decl will need.
ThunksMapTy Thunks;
void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
/// ComputeVTableRelatedInformation - Compute and store all vtable related
/// information (vtable layout, vbase offset offsets, thunks etc) for the
/// given record decl.
void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
/// ErrorUnsupported - Print out an error that the v-table layout code
/// doesn't support the particular C++ feature yet.
void ErrorUnsupported(StringRef Feature, SourceLocation Location);
public:
VTableContext(ASTContext &Context);
~VTableContext();
bool isMicrosoftABI() const {
// FIXME: Currently, this method is only used in the VTableContext and
// VTableBuilder code which is ABI-specific. Probably we can remove it
// when we add a layer of abstraction for vtable generation.
return IsMicrosoftABI;
}
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
ComputeVTableRelatedInformation(RD);
assert(VTableLayouts.count(RD) && "No layout for this record decl!");
return *VTableLayouts[RD];
}
VTableLayout *
createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
bool MostDerivedClassIsVirtual,
const CXXRecordDecl *LayoutClass);
const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) {
ComputeVTableRelatedInformation(MD->getParent());
ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) {
// We did not find a thunk for this method.
return 0;
}
return &I->second;
}
/// getNumVirtualFunctionPointers - Return the number of virtual function
/// pointers in the vtable for a given record decl.
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
/// getMethodVTableIndex - Return the index (relative to the vtable address
/// point) where the function pointer for the given virtual function is
/// stored.
uint64_t getMethodVTableIndex(GlobalDecl GD);
/// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the
/// vtable address point) where the offset of the virtual base that contains
/// the given base is stored, otherwise, if no virtual base contains the given
/// class, return 0. Base must be a virtual base class or an unambigious
/// base.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase);
};
}
#endif

View File

@@ -0,0 +1,239 @@
//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Provides a way to construct an ASTConsumer that runs given matchers
// over the AST and invokes a given callback on every match.
//
// The general idea is to construct a matcher expression that describes a
// subtree match on the AST. Next, a callback that is executed every time the
// expression matches is registered, and the matcher is run over the AST of
// some code. Matched subexpressions can be bound to string IDs and easily
// be accessed from the registered callback. The callback can than use the
// AST nodes that the subexpressions matched on to output information about
// the match or construct changes that can be applied to the code.
//
// Example:
// class HandleMatch : public MatchFinder::MatchCallback {
// public:
// virtual void Run(const MatchFinder::MatchResult &Result) {
// const CXXRecordDecl *Class =
// Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
// ...
// }
// };
//
// int main(int argc, char **argv) {
// ClangTool Tool(argc, argv);
// MatchFinder finder;
// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
// new HandleMatch);
// return Tool.Run(newFrontendActionFactory(&finder));
// }
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
#include "clang/ASTMatchers/ASTMatchers.h"
namespace clang {
namespace ast_matchers {
/// \brief A class to allow finding matches over the Clang AST.
///
/// After creation, you can add multiple matchers to the MatchFinder via
/// calls to addMatcher(...).
///
/// Once all matchers are added, newASTConsumer() returns an ASTConsumer
/// that will trigger the callbacks specified via addMatcher(...) when a match
/// is found.
///
/// The order of matches is guaranteed to be equivalent to doing a pre-order
/// traversal on the AST, and applying the matchers in the order in which they
/// were added to the MatchFinder.
///
/// See ASTMatchers.h for more information about how to create matchers.
///
/// Not intended to be subclassed.
class MatchFinder {
public:
/// \brief Contains all information for a given match.
///
/// Every time a match is found, the MatchFinder will invoke the registered
/// MatchCallback with a MatchResult containing information about the match.
struct MatchResult {
MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
/// \brief Contains the nodes bound on the current match.
///
/// This allows user code to easily extract matched AST nodes.
const BoundNodes Nodes;
/// \brief Utilities for interpreting the matched AST structures.
/// @{
clang::ASTContext * const Context;
clang::SourceManager * const SourceManager;
/// @}
};
/// \brief Called when the Match registered for it was successfully found
/// in the AST.
class MatchCallback {
public:
virtual ~MatchCallback();
/// \brief Called on every match by the \c MatchFinder.
virtual void run(const MatchResult &Result) = 0;
/// \brief Called at the start of each translation unit.
///
/// Optionally override to do per translation unit tasks.
virtual void onStartOfTranslationUnit() {}
};
/// \brief Called when parsing is finished. Intended for testing only.
class ParsingDoneTestCallback {
public:
virtual ~ParsingDoneTestCallback();
virtual void run() = 0;
};
MatchFinder();
~MatchFinder();
/// \brief Adds a matcher to execute when running over the AST.
///
/// Calls 'Action' with the BoundNodes on every match.
/// Adding more than one 'NodeMatch' allows finding different matches in a
/// single pass over the AST.
///
/// Does not take ownership of 'Action'.
/// @{
void addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const TypeMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action);
/// @}
/// \brief Creates a clang ASTConsumer that finds all matches.
clang::ASTConsumer *newASTConsumer();
/// \brief Calls the registered callbacks on all matches on the given \p Node.
///
/// Note that there can be multiple matches on a single node, for
/// example when using decl(forEachDescendant(stmt())).
///
/// @{
template <typename T> void match(const T &Node, ASTContext &Context) {
match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
}
void match(const clang::ast_type_traits::DynTypedNode &Node,
ASTContext &Context);
/// @}
/// \brief Registers a callback to notify the end of parsing.
///
/// The provided closure is called after parsing is done, before the AST is
/// traversed. Useful for benchmarking.
/// Each call to FindAll(...) will call the closure once.
void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
private:
/// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
/// when it matches.
std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
MatcherCallbackPairs;
/// \brief Called when parsing is done.
ParsingDoneTestCallback *ParsingDone;
};
/// \brief Returns the results of matching \p Matcher on \p Node.
///
/// Collects the \c BoundNodes of all callback invocations when matching
/// \p Matcher on \p Node and returns the collected results.
///
/// Multiple results occur when using matchers like \c forEachDescendant,
/// which generate a result for each sub-match.
///
/// \see selectFirst
/// @{
template <typename MatcherT, typename NodeT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
template <typename MatcherT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
ASTContext &Context);
/// @}
/// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
///
/// Returns \c NULL if there is no match, or if the matching node cannot be
/// casted to \c NodeT.
///
/// This is useful in combanation with \c match():
/// \code
/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
/// Node, Context));
/// \endcode
template <typename NodeT>
NodeT *
selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(),
E = Results.end();
I != E; ++I) {
if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo))
return Node;
}
return NULL;
}
namespace internal {
class CollectMatchesCallback : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result) {
Nodes.push_back(Result.Nodes);
}
SmallVector<BoundNodes, 1> Nodes;
};
}
template <typename MatcherT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
ASTContext &Context) {
internal::CollectMatchesCallback Callback;
MatchFinder Finder;
Finder.addMatcher(Matcher, &Callback);
Finder.match(Node, Context);
return Callback.Nodes;
}
template <typename MatcherT, typename NodeT>
SmallVector<BoundNodes, 1>
match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
}
} // end namespace ast_matchers
} // end namespace clang
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,345 @@
//===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines macros that enable us to define new matchers in a single place.
// Since a matcher is a function which returns a Matcher<T> object, where
// T is the type of the actual implementation of the matcher, the macros allow
// us to write matchers like functions and take care of the definition of the
// class boilerplate.
//
// Note that when you define a matcher with an AST_MATCHER* macro, only the
// function which creates the matcher goes into the current namespace - the
// class that implements the actual matcher, which gets returned by the
// generator function, is put into the 'internal' namespace. This allows us
// to only have the functions (which is all the user cares about) in the
// 'ast_matchers' namespace and hide the boilerplate.
//
// To define a matcher in user code, always put it into the clang::ast_matchers
// namespace and refer to the internal types via the 'internal::':
//
// namespace clang {
// namespace ast_matchers {
// AST_MATCHER_P(MemberExpr, Member,
// internal::Matcher<ValueDecl>, InnerMatcher) {
// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
// }
// } // end namespace ast_matchers
// } // end namespace clang
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
/// \brief AST_MATCHER(Type, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// Matcher<Type> object.
///
/// The code between the curly braces has access to the following variables:
///
/// Node: the AST node being matched; its type is Type.
/// Finder: an ASTMatchFinder*.
/// Builder: a BoundNodesTreeBuilder*.
///
/// The code should return true if 'Node' matches.
#define AST_MATCHER(Type, DefineMatcher) \
AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0)
#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId) \
namespace internal { \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher() {} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher() { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher()); \
} \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that returns a
/// Matcher<Type> object.
///
/// The code between the curly braces has access to the following variables:
///
/// Node: the AST node being matched; its type is Type.
/// Param: the parameter passed to the function; its type
/// is ParamType.
/// Finder: an ASTMatchFinder*.
/// Builder: a BoundNodesTreeBuilder*.
///
/// The code should return true if 'Node' matches.
#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \
AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0)
#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \
OverloadId) \
namespace internal { \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
const ParamType &A##Param) \
: Param(A##Param) { \
} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType Param; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
} \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief AST_MATCHER_P2(
/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
/// defines a two-parameter function named DefineMatcher() that returns a
/// Matcher<Type> object.
///
/// The code between the curly braces has access to the following variables:
///
/// Node: the AST node being matched; its type is Type.
/// Param1, Param2: the parameters passed to the function; their types
/// are ParamType1 and ParamType2.
/// Finder: an ASTMatchFinder*.
/// Builder: a BoundNodesTreeBuilder*.
///
/// The code should return true if 'Node' matches.
#define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
Param2) \
AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
Param2, 0)
#define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, \
ParamType2, Param2, OverloadId) \
namespace internal { \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<Type> { \
public: \
matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
const ParamType2 &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) { \
} \
virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
}; \
} \
inline internal::Matcher<Type> \
DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
Param2)); \
} \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
/// from the calling context.
#define AST_POLYMORPHIC_MATCHER(DefineMatcher) \
AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0)
#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \
namespace internal { \
template <typename NodeType> \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<NodeType> { \
public: \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
}; \
} \
inline internal::PolymorphicMatcherWithParam0< \
internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\
return internal::PolymorphicMatcherWithParam0< \
internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \
} \
template <typename NodeType> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that is
/// polymorphic in the return type.
///
/// The variables are the same as for
/// AST_MATCHER_P, with the addition of NodeType, which specifies the node type
/// of the matcher Matcher<NodeType> returned by the function matcher().
///
/// FIXME: Pull out common code with above macro?
#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0)
#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \
OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT> \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<NodeType> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
const ParamType &A##Param) \
: Param(A##Param) { \
} \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType Param; \
}; \
} \
inline internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType> \
DefineMatcher(const ParamType &Param) { \
return internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \
Param); \
} \
template <typename NodeType, typename ParamT> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief AST_POLYMORPHIC_MATCHER_P2(
/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
/// defines a two-parameter function named matcher() that is polymorphic in
/// the return type.
///
/// The variables are the same as for AST_MATCHER_P2, with the
/// addition of NodeType, which specifies the node type of the matcher
/// Matcher<NodeType> returned by the function DefineMatcher().
#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \
ParamType2, Param2) \
AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
ParamType2, Param2, 0)
#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \
ParamType2, Param2, OverloadId) \
namespace internal { \
template <typename NodeType, typename ParamT1, typename ParamT2> \
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<NodeType> { \
public: \
matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
const ParamType2 &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) { \
} \
virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const; \
private: \
const ParamType1 Param1; \
const ParamType2 Param2; \
}; \
} \
inline internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2> \
DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \
return internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2>(Param1, Param2); \
} \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT1, ParamT2>::matches( \
const NodeType &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
/// \brief Creates a variadic matcher for both a specific \c Type as well as
/// the corresponding \c TypeLoc.
#define AST_TYPE_MATCHER(NodeType, MatcherName) \
const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName
// FIXME: add a matcher for TypeLoc derived classes using its custom casting
// API (no longer dyn_cast) if/when we need such matching
/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
/// the matcher \c MatcherName that can be used to traverse from one \c Type
/// to another.
///
/// For a specific \c SpecificType, the traversal is done using
/// \c SpecificType::FunctionName. The existance of such a function determines
/// whether a corresponding matcher can be used on \c SpecificType.
#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \
class Polymorphic##MatcherName##TypeMatcher { \
public: \
Polymorphic##MatcherName##TypeMatcher( \
const internal::Matcher<QualType> &InnerMatcher) \
: InnerMatcher(InnerMatcher) { \
} \
template <typename T> operator internal:: Matcher< T>() { \
return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \
InnerMatcher, &T::FunctionName)); \
} \
private: \
const internal::Matcher<QualType> InnerMatcher; \
} \
; \
class Variadic##MatcherName##TypeTraverseMatcher \
: public llvm::VariadicFunction< \
Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>, \
internal::makeTypeAllOfComposite< \
Polymorphic##MatcherName##TypeMatcher, QualType> > { \
public: \
Variadic##MatcherName##TypeTraverseMatcher() { \
} \
} \
; \
const Variadic##MatcherName##TypeTraverseMatcher MatcherName
/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \
class Polymorphic##MatcherName##TypeLocMatcher { \
public: \
Polymorphic##MatcherName##TypeLocMatcher( \
const internal::Matcher<TypeLoc> &InnerMatcher) \
: InnerMatcher(InnerMatcher) { \
} \
template <typename T> operator internal:: Matcher< T>() { \
return internal::Matcher<T>( \
new internal::TypeLocTraverseMatcher<T>(InnerMatcher, \
&T::FunctionName##Loc)); \
} \
private: \
const internal::Matcher<TypeLoc> InnerMatcher; \
} \
; \
class Variadic##MatcherName##TypeLocTraverseMatcher \
: public llvm::VariadicFunction< \
Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\
internal::makeTypeAllOfComposite< \
Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \
public: \
Variadic##MatcherName##TypeLocTraverseMatcher() { \
} \
} \
; \
const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type)
#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H

View File

@@ -0,0 +1,177 @@
//===--- ASTMatchersTypeTraits.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Provides a dynamically typed node container that can be used to store
// an AST base node at runtime in the same storage in a type safe way.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H
#define LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
#include "llvm/Support/AlignOf.h"
namespace clang {
namespace ast_type_traits {
/// \brief A dynamically typed AST node container.
///
/// Stores an AST node in a type safe way. This allows writing code that
/// works with different kinds of AST nodes, despite the fact that they don't
/// have a common base class.
///
/// Use \c create(Node) to create a \c DynTypedNode from an AST node,
/// and \c get<T>() to retrieve the node as type T if the types match.
///
/// See \c NodeTypeTag for which node base types are currently supported;
/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
/// the supported base types.
class DynTypedNode {
public:
/// \brief Creates a \c DynTypedNode from \c Node.
template <typename T>
static DynTypedNode create(const T &Node) {
return BaseConverter<T>::create(Node);
}
/// \brief Retrieve the stored node as type \c T.
///
/// Returns NULL if the stored node does not have a type that is
/// convertible to \c T.
///
/// For types that have identity via their pointer in the AST
/// (like \c Stmt and \c Decl) the returned pointer points to the
/// referenced AST node.
/// For other types (like \c QualType) the value is stored directly
/// in the \c DynTypedNode, and the returned pointer points at
/// the storage inside DynTypedNode. For those nodes, do not
/// use the pointer outside the scope of the DynTypedNode.
template <typename T>
const T *get() const {
return BaseConverter<T>::get(Tag, Storage.buffer);
}
/// \brief Returns a pointer that identifies the stored AST node.
///
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
/// method returns NULL.
const void *getMemoizationData() const;
private:
/// \brief Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
/// \brief Supported base node types.
enum NodeTypeTag {
NT_Decl,
NT_Stmt,
NT_NestedNameSpecifier,
NT_NestedNameSpecifierLoc,
NT_QualType
} Tag;
/// \brief Stores the data of the node.
///
/// Note that we can store \c Decls and \c Stmts by pointer as they are
/// guaranteed to be unique pointers pointing to dedicated storage in the
/// AST. \c QualTypes on the other hand do not have storage or unique
/// pointers and thus need to be stored by value.
llvm::AlignedCharArrayUnion<Decl*, Stmt*, NestedNameSpecifierLoc, QualType> Storage;
};
template<typename T> struct DynTypedNode::BaseConverter<T,
typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> {
static const T *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_Decl)
return dyn_cast<T>(*reinterpret_cast<Decl*const*>(Storage));
return NULL;
}
static DynTypedNode create(const Decl &Node) {
DynTypedNode Result;
Result.Tag = NT_Decl;
new (Result.Storage.buffer) const Decl*(&Node);
return Result;
}
};
template<typename T> struct DynTypedNode::BaseConverter<T,
typename llvm::enable_if<llvm::is_base_of<Stmt, T> >::type> {
static const T *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_Stmt)
return dyn_cast<T>(*reinterpret_cast<Stmt*const*>(Storage));
return NULL;
}
static DynTypedNode create(const Stmt &Node) {
DynTypedNode Result;
Result.Tag = NT_Stmt;
new (Result.Storage.buffer) const Stmt*(&Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<NestedNameSpecifier, void> {
static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_NestedNameSpecifier)
return *reinterpret_cast<NestedNameSpecifier*const*>(Storage);
return NULL;
}
static DynTypedNode create(const NestedNameSpecifier &Node) {
DynTypedNode Result;
Result.Tag = NT_NestedNameSpecifier;
new (Result.Storage.buffer) const NestedNameSpecifier*(&Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<NestedNameSpecifierLoc, void> {
static const NestedNameSpecifierLoc *get(NodeTypeTag Tag,
const char Storage[]) {
if (Tag == NT_NestedNameSpecifierLoc)
return reinterpret_cast<const NestedNameSpecifierLoc*>(Storage);
return NULL;
}
static DynTypedNode create(const NestedNameSpecifierLoc &Node) {
DynTypedNode Result;
Result.Tag = NT_NestedNameSpecifierLoc;
new (Result.Storage.buffer) NestedNameSpecifierLoc(Node);
return Result;
}
};
template<> struct DynTypedNode::BaseConverter<QualType, void> {
static const QualType *get(NodeTypeTag Tag, const char Storage[]) {
if (Tag == NT_QualType)
return reinterpret_cast<const QualType*>(Storage);
return NULL;
}
static DynTypedNode create(const QualType &Node) {
DynTypedNode Result;
Result.Tag = NT_QualType;
new (Result.Storage.buffer) QualType(Node);
return Result;
}
};
// The only operation we allow on unsupported types is \c get.
// This allows to conveniently use \c DynTypedNode when having an arbitrary
// AST node that is not supported, but prevents misuse - a user cannot create
// a DynTypedNode from arbitrary types.
template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; }
};
inline const void *DynTypedNode::getMemoizationData() const {
switch (Tag) {
case NT_Decl: return BaseConverter<Decl>::get(Tag, Storage.buffer);
case NT_Stmt: return BaseConverter<Stmt>::get(Tag, Storage.buffer);
default: return NULL;
};
}
} // end namespace ast_type_traits
} // end namespace clang
#endif // LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H

View File

@@ -0,0 +1,49 @@
//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a flow-sensitive, (mostly) path-insensitive reachability
// analysis based on Clang's CFGs. Clients can query if a given basic block
// is reachable within the CFG.
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_ANALYSIS_CFG_REACHABILITY
#define CLANG_ANALYSIS_CFG_REACHABILITY
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class CFG;
class CFGBlock;
// A class that performs reachability queries for CFGBlocks. Several internal
// checks in this checker require reachability information. The requests all
// tend to have a common destination, so we lazily do a predecessor search
// from the destination node and cache the results to prevent work
// duplication.
class CFGReverseBlockReachabilityAnalysis {
typedef llvm::BitVector ReachableSet;
typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
ReachableSet analyzed;
ReachableMap reachable;
public:
CFGReverseBlockReachabilityAnalysis(const CFG &cfg);
/// Returns true if the block 'Dst' can be reached from block 'Src'.
bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
private:
void mapReachability(const CFGBlock *Dst);
};
}
#endif

View File

@@ -0,0 +1,211 @@
//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the dominators tree functionality for Clang CFGs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DOMINATORS_H
#define LLVM_CLANG_DOMINATORS_H
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/Analysis/DominatorInternals.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/IR/Module.h"
namespace clang {
class CFGBlock;
typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode;
/// \brief Concrete subclass of DominatorTreeBase for Clang
/// This class implements the dominators tree functionality given a Clang CFG.
///
class DominatorTree : public ManagedAnalysis {
virtual void anchor();
public:
llvm::DominatorTreeBase<CFGBlock>* DT;
DominatorTree() {
DT = new llvm::DominatorTreeBase<CFGBlock>(false);
}
~DominatorTree() {
delete DT;
}
llvm::DominatorTreeBase<CFGBlock>& getBase() { return *DT; }
/// \brief This method returns the root CFGBlock of the dominators tree.
///
inline CFGBlock *getRoot() const {
return DT->getRoot();
}
/// \brief This method returns the root DomTreeNode, which is the wrapper
/// for CFGBlock.
inline DomTreeNode *getRootNode() const {
return DT->getRootNode();
}
/// \brief This method compares two dominator trees.
/// The method returns false if the other dominator tree matches this
/// dominator tree, otherwise returns true.
///
inline bool compare(DominatorTree &Other) const {
DomTreeNode *R = getRootNode();
DomTreeNode *OtherR = Other.getRootNode();
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
return true;
if (DT->compare(Other.getBase()))
return true;
return false;
}
/// \brief This method builds the dominator tree for a given CFG
/// The CFG information is passed via AnalysisDeclContext
///
void buildDominatorTree(AnalysisDeclContext &AC) {
cfg = AC.getCFG();
DT->recalculate(*cfg);
}
/// \brief This method dumps immediate dominators for each block,
/// mainly used for debug purposes.
///
void dump() {
llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n";
for (CFG::const_iterator I = cfg->begin(),
E = cfg->end(); I != E; ++I) {
if(DT->getNode(*I)->getIDom())
llvm::errs() << "(" << (*I)->getBlockID()
<< ","
<< DT->getNode(*I)->getIDom()->getBlock()->getBlockID()
<< ")\n";
else llvm::errs() << "(" << (*I)->getBlockID()
<< "," << (*I)->getBlockID() << ")\n";
}
}
/// \brief This method tests if one CFGBlock dominates the other.
/// The method return true if A dominates B, false otherwise.
/// Note a block always dominates itself.
///
inline bool dominates(const CFGBlock* A, const CFGBlock* B) const {
return DT->dominates(A, B);
}
/// \brief This method tests if one CFGBlock properly dominates the other.
/// The method return true if A properly dominates B, false otherwise.
///
bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const {
return DT->properlyDominates(A, B);
}
/// \brief This method finds the nearest common dominator CFG block
/// for CFG block A and B. If there is no such block then return NULL.
///
inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
const CFGBlock *B) {
return DT->findNearestCommonDominator(A, B);
}
/// \brief This method is used to update the dominator
/// tree information when a node's immediate dominator changes.
///
inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
DT->changeImmediateDominator(N, NewIDom);
}
/// \brief This method tests if the given CFGBlock can be reachable from root.
/// Returns true if reachable, false otherwise.
///
bool isReachableFromEntry(const CFGBlock *A) {
return DT->isReachableFromEntry(A);
}
/// \brief This method releases the memory held by the dominator tree.
///
virtual void releaseMemory() {
DT->releaseMemory();
}
/// \brief This method converts the dominator tree to human readable form.
///
virtual void print(raw_ostream &OS, const llvm::Module* M= 0) const {
DT->print(OS);
}
private:
CFG *cfg;
};
inline void WriteAsOperand(raw_ostream &OS, const CFGBlock *BB,
bool t) {
OS << "BB#" << BB->getBlockID();
}
} // end namespace clang
//===-------------------------------------
/// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators.
///
namespace llvm {
template <> struct GraphTraits< ::clang::DomTreeNode* > {
typedef ::clang::DomTreeNode NodeType;
typedef NodeType::iterator ChildIteratorType;
static NodeType *getEntryNode(NodeType *N) {
return N;
}
static inline ChildIteratorType child_begin(NodeType *N) {
return N->begin();
}
static inline ChildIteratorType child_end(NodeType *N) {
return N->end();
}
typedef df_iterator< ::clang::DomTreeNode* > nodes_iterator;
static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
return df_begin(getEntryNode(N));
}
static nodes_iterator nodes_end(::clang::DomTreeNode *N) {
return df_end(getEntryNode(N));
}
};
template <> struct GraphTraits< ::clang::DominatorTree* >
: public GraphTraits< ::clang::DomTreeNode* > {
static NodeType *getEntryNode(::clang::DominatorTree *DT) {
return DT->getRootNode();
}
static nodes_iterator nodes_begin(::clang::DominatorTree *N) {
return df_begin(getEntryNode(N));
}
static nodes_iterator nodes_end(::clang::DominatorTree *N) {
return df_end(getEntryNode(N));
}
};
} // end namespace llvm
#endif

View File

@@ -0,0 +1,645 @@
//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines APIs for analyzing the format strings of printf, fscanf,
// and friends.
//
// The structure of format strings for fprintf are described in C99 7.19.6.1.
//
// The structure of format strings for fscanf are described in C99 7.19.6.2.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FORMAT_H
#define LLVM_CLANG_FORMAT_H
#include "clang/AST/CanonicalType.h"
namespace clang {
class TargetInfo;
//===----------------------------------------------------------------------===//
/// Common components of both fprintf and fscanf format strings.
namespace analyze_format_string {
/// Class representing optional flags with location and representation
/// information.
class OptionalFlag {
public:
OptionalFlag(const char *Representation)
: representation(Representation), flag(false) {}
bool isSet() { return flag; }
void set() { flag = true; }
void clear() { flag = false; }
void setPosition(const char *position) {
assert(position);
this->position = position;
}
const char *getPosition() const {
assert(position);
return position;
}
const char *toString() const { return representation; }
// Overloaded operators for bool like qualities
operator bool() const { return flag; }
OptionalFlag& operator=(const bool &rhs) {
flag = rhs;
return *this; // Return a reference to myself.
}
private:
const char *representation;
const char *position;
bool flag;
};
/// Represents the length modifier in a format string in scanf/printf.
class LengthModifier {
public:
enum Kind {
None,
AsChar, // 'hh'
AsShort, // 'h'
AsLong, // 'l'
AsLongLong, // 'll'
AsQuad, // 'q' (BSD, deprecated, for 64-bit integer types)
AsIntMax, // 'j'
AsSizeT, // 'z'
AsPtrDiff, // 't'
AsLongDouble, // 'L'
AsAllocate, // for '%as', GNU extension to C90 scanf
AsMAllocate, // for '%ms', GNU extension to scanf
AsWideChar = AsLong // for '%ls', only makes sense for printf
};
LengthModifier()
: Position(0), kind(None) {}
LengthModifier(const char *pos, Kind k)
: Position(pos), kind(k) {}
const char *getStart() const {
return Position;
}
unsigned getLength() const {
switch (kind) {
default:
return 1;
case AsLongLong:
case AsChar:
return 2;
case None:
return 0;
}
}
Kind getKind() const { return kind; }
void setKind(Kind k) { kind = k; }
const char *toString() const;
private:
const char *Position;
Kind kind;
};
class ConversionSpecifier {
public:
enum Kind {
InvalidSpecifier = 0,
// C99 conversion specifiers.
cArg,
dArg,
DArg, // Apple extension
iArg,
IntArgBeg = dArg, IntArgEnd = iArg,
oArg,
OArg, // Apple extension
uArg,
UArg, // Apple extension
xArg,
XArg,
UIntArgBeg = oArg, UIntArgEnd = XArg,
fArg,
FArg,
eArg,
EArg,
gArg,
GArg,
aArg,
AArg,
DoubleArgBeg = fArg, DoubleArgEnd = AArg,
sArg,
pArg,
nArg,
PercentArg,
CArg,
SArg,
// ** Printf-specific **
// Objective-C specific specifiers.
ObjCObjArg, // '@'
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
// GlibC specific specifiers.
PrintErrno, // 'm'
PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
// ** Scanf-specific **
ScanListArg, // '['
ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
};
ConversionSpecifier(bool isPrintf = true)
: IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
: IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
const char *getStart() const {
return Position;
}
StringRef getCharacters() const {
return StringRef(getStart(), getLength());
}
bool consumesDataArgument() const {
switch (kind) {
case PrintErrno:
assert(IsPrintf);
return false;
case PercentArg:
return false;
default:
return true;
}
}
Kind getKind() const { return kind; }
void setKind(Kind k) { kind = k; }
unsigned getLength() const {
return EndScanList ? EndScanList - Position : 1;
}
bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }
const char *toString() const;
bool isPrintfKind() const { return IsPrintf; }
Optional<ConversionSpecifier> getStandardSpecifier() const;
protected:
bool IsPrintf;
const char *Position;
const char *EndScanList;
Kind kind;
};
class ArgType {
public:
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
AnyCharTy, CStrTy, WCStrTy, WIntTy };
private:
const Kind K;
QualType T;
const char *Name;
bool Ptr;
public:
ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {}
ArgType(QualType t, const char *n = 0)
: K(SpecificTy), T(t), Name(n), Ptr(false) {}
ArgType(CanQualType t) : K(SpecificTy), T(t), Name(0), Ptr(false) {}
static ArgType Invalid() { return ArgType(InvalidTy); }
bool isValid() const { return K != InvalidTy; }
/// Create an ArgType which corresponds to the type pointer to A.
static ArgType PtrTo(const ArgType& A) {
assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
ArgType Res = A;
Res.Ptr = true;
return Res;
}
bool matchesType(ASTContext &C, QualType argTy) const;
QualType getRepresentativeType(ASTContext &C) const;
std::string getRepresentativeTypeName(ASTContext &C) const;
};
class OptionalAmount {
public:
enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
OptionalAmount(HowSpecified howSpecified,
unsigned amount,
const char *amountStart,
unsigned amountLength,
bool usesPositionalArg)
: start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
OptionalAmount(bool valid = true)
: start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
UsesPositionalArg(0), UsesDotPrefix(0) {}
bool isInvalid() const {
return hs == Invalid;
}
HowSpecified getHowSpecified() const { return hs; }
void setHowSpecified(HowSpecified h) { hs = h; }
bool hasDataArgument() const { return hs == Arg; }
unsigned getArgIndex() const {
assert(hasDataArgument());
return amt;
}
unsigned getConstantAmount() const {
assert(hs == Constant);
return amt;
}
const char *getStart() const {
// We include the . character if it is given.
return start - UsesDotPrefix;
}
unsigned getConstantLength() const {
assert(hs == Constant);
return length + UsesDotPrefix;
}
ArgType getArgType(ASTContext &Ctx) const;
void toString(raw_ostream &os) const;
bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
unsigned getPositionalArgIndex() const {
assert(hasDataArgument());
return amt + 1;
}
bool usesDotPrefix() const { return UsesDotPrefix; }
void setUsesDotPrefix() { UsesDotPrefix = true; }
private:
const char *start;
unsigned length;
HowSpecified hs;
unsigned amt;
bool UsesPositionalArg : 1;
bool UsesDotPrefix;
};
class FormatSpecifier {
protected:
LengthModifier LM;
OptionalAmount FieldWidth;
ConversionSpecifier CS;
/// Positional arguments, an IEEE extension:
/// IEEE Std 1003.1, 2004 Edition
/// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
bool UsesPositionalArg;
unsigned argIndex;
public:
FormatSpecifier(bool isPrintf)
: CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
void setLengthModifier(LengthModifier lm) {
LM = lm;
}
void setUsesPositionalArg() { UsesPositionalArg = true; }
void setArgIndex(unsigned i) {
argIndex = i;
}
unsigned getArgIndex() const {
return argIndex;
}
unsigned getPositionalArgIndex() const {
return argIndex + 1;
}
const LengthModifier &getLengthModifier() const {
return LM;
}
const OptionalAmount &getFieldWidth() const {
return FieldWidth;
}
void setFieldWidth(const OptionalAmount &Amt) {
FieldWidth = Amt;
}
bool usesPositionalArg() const { return UsesPositionalArg; }
bool hasValidLengthModifier(const TargetInfo &Target) const;
bool hasStandardLengthModifier() const;
Optional<LengthModifier> getCorrectedLengthModifier() const;
bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
bool hasStandardLengthConversionCombination() const;
/// For a TypedefType QT, if it is a named integer type such as size_t,
/// assign the appropriate value to LM and return true.
static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
};
} // end analyze_format_string namespace
//===----------------------------------------------------------------------===//
/// Pieces specific to fprintf format strings.
namespace analyze_printf {
class PrintfConversionSpecifier :
public analyze_format_string::ConversionSpecifier {
public:
PrintfConversionSpecifier()
: ConversionSpecifier(true, 0, InvalidSpecifier) {}
PrintfConversionSpecifier(const char *pos, Kind k)
: ConversionSpecifier(true, pos, k) {}
bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
bool isDoubleArg() const { return kind >= DoubleArgBeg &&
kind <= DoubleArgEnd; }
unsigned getLength() const {
// Conversion specifiers currently only are represented by
// single characters, but we be flexible.
return 1;
}
static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
return CS->isPrintfKind();
}
};
using analyze_format_string::ArgType;
using analyze_format_string::LengthModifier;
using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
OptionalFlag IsLeftJustified; // '-'
OptionalFlag HasPlusPrefix; // '+'
OptionalFlag HasSpacePrefix; // ' '
OptionalFlag HasAlternativeForm; // '#'
OptionalFlag HasLeadingZeroes; // '0'
OptionalAmount Precision;
public:
PrintfSpecifier() :
FormatSpecifier(/* isPrintf = */ true),
HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0") {}
static PrintfSpecifier Parse(const char *beg, const char *end);
// Methods for incrementally constructing the PrintfSpecifier.
void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
CS = cs;
}
void setHasThousandsGrouping(const char *position) {
HasThousandsGrouping = true;
HasThousandsGrouping.setPosition(position);
}
void setIsLeftJustified(const char *position) {
IsLeftJustified = true;
IsLeftJustified.setPosition(position);
}
void setHasPlusPrefix(const char *position) {
HasPlusPrefix = true;
HasPlusPrefix.setPosition(position);
}
void setHasSpacePrefix(const char *position) {
HasSpacePrefix = true;
HasSpacePrefix.setPosition(position);
}
void setHasAlternativeForm(const char *position) {
HasAlternativeForm = true;
HasAlternativeForm.setPosition(position);
}
void setHasLeadingZeros(const char *position) {
HasLeadingZeroes = true;
HasLeadingZeroes.setPosition(position);
}
void setUsesPositionalArg() { UsesPositionalArg = true; }
// Methods for querying the format specifier.
const PrintfConversionSpecifier &getConversionSpecifier() const {
return cast<PrintfConversionSpecifier>(CS);
}
void setPrecision(const OptionalAmount &Amt) {
Precision = Amt;
Precision.setUsesDotPrefix();
}
const OptionalAmount &getPrecision() const {
return Precision;
}
bool consumesDataArgument() const {
return getConversionSpecifier().consumesDataArgument();
}
/// \brief Returns the builtin type that a data argument
/// paired with this format specifier should have. This method
/// will return null if the format specifier does not have
/// a matching data argument or the matching argument matches
/// more than one type.
ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
const OptionalFlag &hasThousandsGrouping() const {
return HasThousandsGrouping;
}
const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
bool usesPositionalArg() const { return UsesPositionalArg; }
/// Changes the specifier and length according to a QualType, retaining any
/// flags or options. Returns true on success, or false when a conversion
/// was not successful.
bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,
bool IsObjCLiteral);
void toString(raw_ostream &os) const;
// Validation methods - to check if any element results in undefined behavior
bool hasValidPlusPrefix() const;
bool hasValidAlternativeForm() const;
bool hasValidLeadingZeros() const;
bool hasValidSpacePrefix() const;
bool hasValidLeftJustified() const;
bool hasValidThousandsGroupingPrefix() const;
bool hasValidPrecision() const;
bool hasValidFieldWidth() const;
};
} // end analyze_printf namespace
//===----------------------------------------------------------------------===//
/// Pieces specific to fscanf format strings.
namespace analyze_scanf {
class ScanfConversionSpecifier :
public analyze_format_string::ConversionSpecifier {
public:
ScanfConversionSpecifier()
: ConversionSpecifier(false, 0, InvalidSpecifier) {}
ScanfConversionSpecifier(const char *pos, Kind k)
: ConversionSpecifier(false, pos, k) {}
void setEndScanList(const char *pos) { EndScanList = pos; }
static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
return !CS->isPrintfKind();
}
};
using analyze_format_string::ArgType;
using analyze_format_string::LengthModifier;
using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag SuppressAssignment; // '*'
public:
ScanfSpecifier() :
FormatSpecifier(/* isPrintf = */ false),
SuppressAssignment("*") {}
void setSuppressAssignment(const char *position) {
SuppressAssignment = true;
SuppressAssignment.setPosition(position);
}
const OptionalFlag &getSuppressAssignment() const {
return SuppressAssignment;
}
void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
CS = cs;
}
const ScanfConversionSpecifier &getConversionSpecifier() const {
return cast<ScanfConversionSpecifier>(CS);
}
bool consumesDataArgument() const {
return CS.consumesDataArgument() && !SuppressAssignment;
}
ArgType getArgType(ASTContext &Ctx) const;
bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx);
void toString(raw_ostream &os) const;
static ScanfSpecifier Parse(const char *beg, const char *end);
};
} // end analyze_scanf namespace
//===----------------------------------------------------------------------===//
// Parsing and processing of format strings (both fprintf and fscanf).
namespace analyze_format_string {
enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
class FormatStringHandler {
public:
FormatStringHandler() {}
virtual ~FormatStringHandler();
virtual void HandleNullChar(const char *nullCharacter) {}
virtual void HandlePosition(const char *startPos, unsigned posLen) {}
virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
PositionContext p) {}
virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
virtual void HandleIncompleteSpecifier(const char *startSpecifier,
unsigned specifierLen) {}
// Printf-specific handlers.
virtual bool HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
// Scanf-specific handlers.
virtual bool HandleInvalidScanfConversionSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
virtual void HandleIncompleteScanList(const char *start, const char *end) {}
};
bool ParsePrintfString(FormatStringHandler &H,
const char *beg, const char *end, const LangOptions &LO,
const TargetInfo &Target);
bool ParseScanfString(FormatStringHandler &H,
const char *beg, const char *end, const LangOptions &LO,
const TargetInfo &Target);
} // end analyze_format_string namespace
} // end clang namespace
#endif

View File

@@ -0,0 +1,120 @@
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Live Variables analysis for source-level CFGs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIVEVARIABLES_H
#define LLVM_CLANG_LIVEVARIABLES_H
#include "clang/AST/Decl.h"
#include "clang/Analysis/AnalysisContext.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableSet.h"
namespace clang {
class CFG;
class CFGBlock;
class Stmt;
class DeclRefExpr;
class SourceManager;
class LiveVariables : public ManagedAnalysis {
public:
class LivenessValues {
public:
llvm::ImmutableSet<const Stmt *> liveStmts;
llvm::ImmutableSet<const VarDecl *> liveDecls;
bool equals(const LivenessValues &V) const;
LivenessValues()
: liveStmts(0), liveDecls(0) {}
LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts,
llvm::ImmutableSet<const VarDecl *> LiveDecls)
: liveStmts(LiveStmts), liveDecls(LiveDecls) {}
~LivenessValues() {}
bool isLive(const Stmt *S) const;
bool isLive(const VarDecl *D) const;
friend class LiveVariables;
};
class Observer {
virtual void anchor();
public:
virtual ~Observer() {}
/// A callback invoked right before invoking the
/// liveness transfer function on the given statement.
virtual void observeStmt(const Stmt *S,
const CFGBlock *currentBlock,
const LivenessValues& V) {}
/// Called when the live variables analysis registers
/// that a variable is killed.
virtual void observerKill(const DeclRefExpr *DR) {}
};
virtual ~LiveVariables();
/// Compute the liveness information for a given CFG.
static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext,
bool killAtAssign);
/// Return true if a variable is live at the end of a
/// specified block.
bool isLive(const CFGBlock *B, const VarDecl *D);
/// Returns true if a variable is live at the beginning of the
/// the statement. This query only works if liveness information
/// has been recorded at the statement level (see runOnAllBlocks), and
/// only returns liveness information for block-level expressions.
bool isLive(const Stmt *S, const VarDecl *D);
/// Returns true the block-level expression "value" is live
/// before the given block-level expression (see runOnAllBlocks).
bool isLive(const Stmt *Loc, const Stmt *StmtVal);
/// Print to stderr the liveness information associated with
/// each basic block.
void dumpBlockLiveness(const SourceManager& M);
void runOnAllBlocks(Observer &obs);
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, true);
}
static const void *getTag();
private:
LiveVariables(void *impl);
void *impl;
};
class RelaxedLiveVariables : public LiveVariables {
public:
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, false);
}
static const void *getTag();
};
} // end namespace clang
#endif

View File

@@ -0,0 +1,111 @@
//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements post order view of the blocks in a CFG.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_POSTORDER_CFGVIEW
#define LLVM_CLANG_POSTORDER_CFGVIEW
#include <vector>
//#include <algorithm>
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/BitVector.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
namespace clang {
class PostOrderCFGView : public ManagedAnalysis {
virtual void anchor();
public:
/// \brief Implements a set of CFGBlocks using a BitVector.
///
/// This class contains a minimal interface, primarily dictated by the SetType
/// template parameter of the llvm::po_iterator template, as used with
/// external storage. We also use this set to keep track of which CFGBlocks we
/// visit during the analysis.
class CFGBlockSet {
llvm::BitVector VisitedBlockIDs;
public:
// po_iterator requires this iterator, but the only interface needed is the
// value_type typedef.
struct iterator { typedef const CFGBlock *value_type; };
CFGBlockSet() {}
CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
/// \brief Set the bit associated with a particular CFGBlock.
/// This is the important method for the SetType template parameter.
bool insert(const CFGBlock *Block) {
// Note that insert() is called by po_iterator, which doesn't check to
// make sure that Block is non-null. Moreover, the CFGBlock iterator will
// occasionally hand out null pointers for pruned edges, so we catch those
// here.
if (Block == 0)
return false; // if an edge is trivially false.
if (VisitedBlockIDs.test(Block->getBlockID()))
return false;
VisitedBlockIDs.set(Block->getBlockID());
return true;
}
/// \brief Check if the bit for a CFGBlock has been already set.
/// This method is for tracking visited blocks in the main threadsafety
/// loop. Block must not be null.
bool alreadySet(const CFGBlock *Block) {
return VisitedBlockIDs.test(Block->getBlockID());
}
};
private:
typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator;
std::vector<const CFGBlock*> Blocks;
typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy;
BlockOrderTy BlockOrder;
public:
typedef std::vector<const CFGBlock*>::reverse_iterator iterator;
PostOrderCFGView(const CFG *cfg);
iterator begin() { return Blocks.rbegin(); }
iterator end() { return Blocks.rend(); }
bool empty() { return begin() == end(); }
struct BlockOrderCompare;
friend struct BlockOrderCompare;
struct BlockOrderCompare {
const PostOrderCFGView &POV;
public:
BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
};
BlockOrderCompare getComparator() const {
return BlockOrderCompare(*this);
}
// Used by AnalyisContext to construct this object.
static const void *getTag();
static PostOrderCFGView *create(AnalysisDeclContext &analysisContext);
};
} // end clang namespace
#endif

Some files were not shown because too many files have changed in this diff Show More