mirror of
https://github.com/opnsense/src.git
synced 2026-02-26 19:30:29 -05:00
Update clang to r96341.
This commit is contained in:
parent
5044f5c816
commit
ecb7e5c8af
725 changed files with 29387 additions and 10475 deletions
18
bindings/python/README.txt
Normal file
18
bindings/python/README.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
// Clang Python Bindings
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
This directory implements Python bindings for Clang. Currently, only bindings
|
||||
for the CIndex C API exist.
|
||||
|
||||
You may need to alter LD_LIBRARY_PATH so that the CIndex library can be
|
||||
found. The unit tests are designed to be run with 'nosetests'. For example:
|
||||
--
|
||||
$ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \
|
||||
LD_LIBRARY_PATH=$(llvm-config --libdir) \
|
||||
nosetests -v
|
||||
tests.cindex.test_index.test_create ... ok
|
||||
...
|
||||
|
||||
OK
|
||||
--
|
||||
24
bindings/python/clang/__init__.py
Normal file
24
bindings/python/clang/__init__.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#===- __init__.py - Clang Python Bindings --------------------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
r"""
|
||||
Clang Library Bindings
|
||||
======================
|
||||
|
||||
This package provides access to the Clang compiler and libraries.
|
||||
|
||||
The available modules are:
|
||||
|
||||
cindex
|
||||
|
||||
Bindings for the Clang indexing library.
|
||||
"""
|
||||
|
||||
__all__ = ['cindex']
|
||||
|
||||
933
bindings/python/clang/cindex.py
Normal file
933
bindings/python/clang/cindex.py
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
r"""
|
||||
Clang Indexing Library Bindings
|
||||
===============================
|
||||
|
||||
This module provides an interface to the Clang indexing library. It is a
|
||||
low-level interface to the indexing library which attempts to match the Clang
|
||||
API directly while also being "pythonic". Notable differences from the C API
|
||||
are:
|
||||
|
||||
* string results are returned as Python strings, not CXString objects.
|
||||
|
||||
* null cursors are translated to None.
|
||||
|
||||
* access to child cursors is done via iteration, not visitation.
|
||||
|
||||
The major indexing objects are:
|
||||
|
||||
Index
|
||||
|
||||
The top-level object which manages some global library state.
|
||||
|
||||
TranslationUnit
|
||||
|
||||
High-level object encapsulating the AST for a single translation unit. These
|
||||
can be loaded from .ast files or parsed on the fly.
|
||||
|
||||
Cursor
|
||||
|
||||
Generic object for representing a node in the AST.
|
||||
|
||||
SourceRange, SourceLocation, and File
|
||||
|
||||
Objects representing information about the input source.
|
||||
|
||||
Most object information is exposed using properties, when the underlying API
|
||||
call is efficient.
|
||||
"""
|
||||
|
||||
# TODO
|
||||
# ====
|
||||
#
|
||||
# o API support for invalid translation units. Currently we can't even get the
|
||||
# diagnostics on failure because they refer to locations in an object that
|
||||
# will have been invalidated.
|
||||
#
|
||||
# o fix memory management issues (currently client must hold on to index and
|
||||
# translation unit, or risk crashes).
|
||||
#
|
||||
# o expose code completion APIs.
|
||||
#
|
||||
# o cleanup ctypes wrapping, would be nice to separate the ctypes details more
|
||||
# clearly, and hide from the external interface (i.e., help(cindex)).
|
||||
#
|
||||
# o implement additional SourceLocation, SourceRange, and File methods.
|
||||
|
||||
from ctypes import *
|
||||
|
||||
def get_cindex_library():
|
||||
# FIXME: It's probably not the case that the library is actually found in
|
||||
# this location. We need a better system of identifying and loading the
|
||||
# CIndex library. It could be on path or elsewhere, or versioned, etc.
|
||||
import platform
|
||||
name = platform.system()
|
||||
if name == 'Darwin':
|
||||
return cdll.LoadLibrary('libCIndex.dylib')
|
||||
elif name == 'Windows':
|
||||
return cdll.LoadLibrary('libCIndex.dll')
|
||||
else:
|
||||
return cdll.LoadLibrary('libCIndex.so')
|
||||
|
||||
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
|
||||
# object. This is a problem, because it means that from_parameter will see an
|
||||
# integer and pass the wrong value on platforms where int != void*. Work around
|
||||
# this by marshalling object arguments as void**.
|
||||
c_object_p = POINTER(c_void_p)
|
||||
|
||||
lib = get_cindex_library()
|
||||
|
||||
### Structures and Utility Classes ###
|
||||
|
||||
class _CXString(Structure):
|
||||
"""Helper for transforming CXString results."""
|
||||
|
||||
_fields_ = [("spelling", c_char_p), ("free", c_int)]
|
||||
|
||||
def __del__(self):
|
||||
_CXString_dispose(self)
|
||||
|
||||
@staticmethod
|
||||
def from_result(res, fn, args):
|
||||
assert isinstance(res, _CXString)
|
||||
return _CXString_getCString(res)
|
||||
|
||||
class SourceLocation(Structure):
|
||||
"""
|
||||
A SourceLocation represents a particular location within a source file.
|
||||
"""
|
||||
_fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)]
|
||||
_data = None
|
||||
|
||||
def _get_instantiation(self):
|
||||
if self._data is None:
|
||||
f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint()
|
||||
SourceLocation_loc(self, byref(f), byref(l), byref(c), byref(o))
|
||||
f = File(f) if f else None
|
||||
self._data = (f, int(l.value), int(c.value), int(c.value))
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def file(self):
|
||||
"""Get the file represented by this source location."""
|
||||
return self._get_instantiation()[0]
|
||||
|
||||
@property
|
||||
def line(self):
|
||||
"""Get the line represented by this source location."""
|
||||
return self._get_instantiation()[1]
|
||||
|
||||
@property
|
||||
def column(self):
|
||||
"""Get the column represented by this source location."""
|
||||
return self._get_instantiation()[2]
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
"""Get the file offset represented by this source location."""
|
||||
return self._get_instantiation()[3]
|
||||
|
||||
def __repr__(self):
|
||||
return "<SourceLocation file %r, line %r, column %r>" % (
|
||||
self.file.name if self.file else None, self.line, self.column)
|
||||
|
||||
class SourceRange(Structure):
|
||||
"""
|
||||
A SourceRange describes a range of source locations within the source
|
||||
code.
|
||||
"""
|
||||
_fields_ = [
|
||||
("ptr_data", c_void_p * 2),
|
||||
("begin_int_data", c_uint),
|
||||
("end_int_data", c_uint)]
|
||||
|
||||
# FIXME: Eliminate this and make normal constructor? Requires hiding ctypes
|
||||
# object.
|
||||
@staticmethod
|
||||
def from_locations(start, end):
|
||||
return SourceRange_getRange(start, end)
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
"""
|
||||
Return a SourceLocation representing the first character within a
|
||||
source range.
|
||||
"""
|
||||
return SourceRange_start(self)
|
||||
|
||||
@property
|
||||
def end(self):
|
||||
"""
|
||||
Return a SourceLocation representing the last character within a
|
||||
source range.
|
||||
"""
|
||||
return SourceRange_end(self)
|
||||
|
||||
def __repr__(self):
|
||||
return "<SourceRange start %r, end %r>" % (self.start, self.end)
|
||||
|
||||
class Diagnostic(object):
|
||||
"""
|
||||
A Diagnostic is a single instance of a Clang diagnostic. It includes the
|
||||
diagnostic severity, the message, the location the diagnostic occurred, as
|
||||
well as additional source ranges and associated fix-it hints.
|
||||
"""
|
||||
|
||||
Ignored = 0
|
||||
Note = 1
|
||||
Warning = 2
|
||||
Error = 3
|
||||
Fatal = 4
|
||||
|
||||
def __init__(self, severity, location, spelling, ranges, fixits):
|
||||
self.severity = severity
|
||||
self.location = location
|
||||
self.spelling = spelling
|
||||
self.ranges = ranges
|
||||
self.fixits = fixits
|
||||
|
||||
def __repr__(self):
|
||||
return "<Diagnostic severity %r, location %r, spelling %r>" % (
|
||||
self.severity, self.location, self.spelling)
|
||||
|
||||
class FixIt(object):
|
||||
"""
|
||||
A FixIt represents a transformation to be applied to the source to
|
||||
"fix-it". The fix-it shouldbe applied by replacing the given source range
|
||||
with the given value.
|
||||
"""
|
||||
|
||||
def __init__(self, range, value):
|
||||
self.range = range
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return "<FixIt range %r, value %r>" % (self.range, self.value)
|
||||
|
||||
### Cursor Kinds ###
|
||||
|
||||
class CursorKind(object):
|
||||
"""
|
||||
A CursorKind describes the kind of entity that a cursor points to.
|
||||
"""
|
||||
|
||||
# The unique kind objects, indexed by id.
|
||||
_kinds = []
|
||||
_name_map = None
|
||||
|
||||
def __init__(self, value):
|
||||
if value >= len(CursorKind._kinds):
|
||||
CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1)
|
||||
if CursorKind._kinds[value] is not None:
|
||||
raise ValueError,'CursorKind already loaded'
|
||||
self.value = value
|
||||
CursorKind._kinds[value] = self
|
||||
CursorKind._name_map = None
|
||||
|
||||
def from_param(self):
|
||||
return self.value
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Get the enumeration name of this cursor kind."""
|
||||
if self._name_map is None:
|
||||
self._name_map = {}
|
||||
for key,value in CursorKind.__dict__.items():
|
||||
if isinstance(value,CursorKind):
|
||||
self._name_map[value] = key
|
||||
return self._name_map[self]
|
||||
|
||||
@staticmethod
|
||||
def from_id(id):
|
||||
if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None:
|
||||
raise ValueError,'Unknown cursor kind'
|
||||
return CursorKind._kinds[id]
|
||||
|
||||
@staticmethod
|
||||
def get_all_kinds():
|
||||
"""Return all CursorKind enumeration instances."""
|
||||
return filter(None, CursorKind._kinds)
|
||||
|
||||
def is_declaration(self):
|
||||
"""Test if this is a declaration kind."""
|
||||
return CursorKind_is_decl(self)
|
||||
|
||||
def is_reference(self):
|
||||
"""Test if this is a reference kind."""
|
||||
return CursorKind_is_ref(self)
|
||||
|
||||
def is_expression(self):
|
||||
"""Test if this is an expression kind."""
|
||||
return CursorKind_is_expr(self)
|
||||
|
||||
def is_statement(self):
|
||||
"""Test if this is a statement kind."""
|
||||
return CursorKind_is_stmt(self)
|
||||
|
||||
def is_invalid(self):
|
||||
"""Test if this is an invalid kind."""
|
||||
return CursorKind_is_inv(self)
|
||||
|
||||
def __repr__(self):
|
||||
return 'CursorKind.%s' % (self.name,)
|
||||
|
||||
# FIXME: Is there a nicer way to expose this enumeration? We could potentially
|
||||
# represent the nested structure, or even build a class hierarchy. The main
|
||||
# things we want for sure are (a) simple external access to kinds, (b) a place
|
||||
# to hang a description and name, (c) easy to keep in sync with Index.h.
|
||||
|
||||
###
|
||||
# Declaration Kinds
|
||||
|
||||
# A declaration whose specific kind is not exposed via this interface.
|
||||
#
|
||||
# Unexposed declarations have the same operations as any other kind of
|
||||
# declaration; one can extract their location information, spelling, find their
|
||||
# definitions, etc. However, the specific kind of the declaration is not
|
||||
# reported.
|
||||
CursorKind.UNEXPOSED_DECL = CursorKind(1)
|
||||
|
||||
# A C or C++ struct.
|
||||
CursorKind.STRUCT_DECL = CursorKind(2)
|
||||
|
||||
# A C or C++ union.
|
||||
CursorKind.UNION_DECL = CursorKind(3)
|
||||
|
||||
# A C++ class.
|
||||
CursorKind.CLASS_DECL = CursorKind(4)
|
||||
|
||||
# An enumeration.
|
||||
CursorKind.ENUM_DECL = CursorKind(5)
|
||||
|
||||
# A field (in C) or non-static data member (in C++) in a struct, union, or C++
|
||||
# class.
|
||||
CursorKind.FIELD_DECL = CursorKind(6)
|
||||
|
||||
# An enumerator constant.
|
||||
CursorKind.ENUM_CONSTANT_DECL = CursorKind(7)
|
||||
|
||||
# A function.
|
||||
CursorKind.FUNCTION_DECL = CursorKind(8)
|
||||
|
||||
# A variable.
|
||||
CursorKind.VAR_DECL = CursorKind(9)
|
||||
|
||||
# A function or method parameter.
|
||||
CursorKind.PARM_DECL = CursorKind(10)
|
||||
|
||||
# An Objective-C @interface.
|
||||
CursorKind.OBJC_INTERFACE_DECL = CursorKind(11)
|
||||
|
||||
# An Objective-C @interface for a category.
|
||||
CursorKind.OBJC_CATEGORY_DECL = CursorKind(12)
|
||||
|
||||
# An Objective-C @protocol declaration.
|
||||
CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13)
|
||||
|
||||
# An Objective-C @property declaration.
|
||||
CursorKind.OBJC_PROPERTY_DECL = CursorKind(14)
|
||||
|
||||
# An Objective-C instance variable.
|
||||
CursorKind.OBJC_IVAR_DECL = CursorKind(15)
|
||||
|
||||
# An Objective-C instance method.
|
||||
CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16)
|
||||
|
||||
# An Objective-C class method.
|
||||
CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17)
|
||||
|
||||
# An Objective-C @implementation.
|
||||
CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18)
|
||||
|
||||
# An Objective-C @implementation for a category.
|
||||
CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19)
|
||||
|
||||
# A typedef.
|
||||
CursorKind.TYPEDEF_DECL = CursorKind(20)
|
||||
|
||||
###
|
||||
# Reference Kinds
|
||||
|
||||
CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40)
|
||||
CursorKind.OBJC_PROTOCOL_REF = CursorKind(41)
|
||||
CursorKind.OBJC_CLASS_REF = CursorKind(42)
|
||||
|
||||
# A reference to a type declaration.
|
||||
#
|
||||
# A type reference occurs anywhere where a type is named but not
|
||||
# declared. For example, given:
|
||||
# typedef unsigned size_type;
|
||||
# size_type size;
|
||||
#
|
||||
# The typedef is a declaration of size_type (CXCursor_TypedefDecl),
|
||||
# while the type of the variable "size" is referenced. The cursor
|
||||
# referenced by the type of size is the typedef for size_type.
|
||||
CursorKind.TYPE_REF = CursorKind(43)
|
||||
|
||||
###
|
||||
# Invalid/Error Kinds
|
||||
|
||||
CursorKind.INVALID_FILE = CursorKind(70)
|
||||
CursorKind.NO_DECL_FOUND = CursorKind(71)
|
||||
CursorKind.NOT_IMPLEMENTED = CursorKind(72)
|
||||
|
||||
###
|
||||
# Expression Kinds
|
||||
|
||||
# An expression whose specific kind is not exposed via this interface.
|
||||
#
|
||||
# Unexposed expressions have the same operations as any other kind of
|
||||
# expression; one can extract their location information, spelling, children,
|
||||
# etc. However, the specific kind of the expression is not reported.
|
||||
CursorKind.UNEXPOSED_EXPR = CursorKind(100)
|
||||
|
||||
# An expression that refers to some value declaration, such as a function,
|
||||
# varible, or enumerator.
|
||||
CursorKind.DECL_REF_EXPR = CursorKind(101)
|
||||
|
||||
# An expression that refers to a member of a struct, union, class, Objective-C
|
||||
# class, etc.
|
||||
CursorKind.MEMBER_REF_EXPR = CursorKind(102)
|
||||
|
||||
# An expression that calls a function.
|
||||
CursorKind.CALL_EXPR = CursorKind(103)
|
||||
|
||||
# An expression that sends a message to an Objective-C object or class.
|
||||
CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104)
|
||||
|
||||
# A statement whose specific kind is not exposed via this interface.
|
||||
#
|
||||
# Unexposed statements have the same operations as any other kind of statement;
|
||||
# one can extract their location information, spelling, children, etc. However,
|
||||
# the specific kind of the statement is not reported.
|
||||
CursorKind.UNEXPOSED_STMT = CursorKind(200)
|
||||
|
||||
###
|
||||
# Other Kinds
|
||||
|
||||
# Cursor that represents the translation unit itself.
|
||||
#
|
||||
# The translation unit cursor exists primarily to act as the root cursor for
|
||||
# traversing the contents of a translation unit.
|
||||
CursorKind.TRANSLATION_UNIT = CursorKind(300)
|
||||
|
||||
### Cursors ###
|
||||
|
||||
class Cursor(Structure):
|
||||
"""
|
||||
The Cursor class represents a reference to an element within the AST. It
|
||||
acts as a kind of iterator.
|
||||
"""
|
||||
_fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
|
||||
|
||||
def __eq__(self, other):
|
||||
return Cursor_eq(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not Cursor_eq(self, other)
|
||||
|
||||
def is_definition(self):
|
||||
"""
|
||||
Returns true if the declaration pointed at by the cursor is also a
|
||||
definition of that entity.
|
||||
"""
|
||||
return Cursor_is_def(self)
|
||||
|
||||
def get_definition(self):
|
||||
"""
|
||||
If the cursor is a reference to a declaration or a declaration of
|
||||
some entity, return a cursor that points to the definition of that
|
||||
entity.
|
||||
"""
|
||||
# TODO: Should probably check that this is either a reference or
|
||||
# declaration prior to issuing the lookup.
|
||||
return Cursor_def(self)
|
||||
|
||||
def get_usr(self):
|
||||
"""Return the Unified Symbol Resultion (USR) for the entity referenced
|
||||
by the given cursor (or None).
|
||||
|
||||
A Unified Symbol Resolution (USR) is a string that identifies a
|
||||
particular entity (function, class, variable, etc.) within a
|
||||
program. USRs can be compared across translation units to determine,
|
||||
e.g., when references in one translation refer to an entity defined in
|
||||
another translation unit."""
|
||||
return Cursor_usr(self)
|
||||
|
||||
@property
|
||||
def kind(self):
|
||||
"""Return the kind of this cursor."""
|
||||
return CursorKind.from_id(self._kind_id)
|
||||
|
||||
@property
|
||||
def spelling(self):
|
||||
"""Return the spelling of the entity pointed at by the cursor."""
|
||||
if not self.kind.is_declaration():
|
||||
# FIXME: clang_getCursorSpelling should be fixed to not assert on
|
||||
# this, for consistency with clang_getCursorUSR.
|
||||
return None
|
||||
return Cursor_spelling(self)
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
"""
|
||||
Return the source location (the starting character) of the entity
|
||||
pointed at by the cursor.
|
||||
"""
|
||||
return Cursor_loc(self)
|
||||
|
||||
@property
|
||||
def extent(self):
|
||||
"""
|
||||
Return the source range (the range of text) occupied by the entity
|
||||
pointed at by the cursor.
|
||||
"""
|
||||
return Cursor_extent(self)
|
||||
|
||||
def get_children(self):
|
||||
"""Return an iterator for accessing the children of this cursor."""
|
||||
|
||||
# FIXME: Expose iteration from CIndex, PR6125.
|
||||
def visitor(child, parent, children):
|
||||
# FIXME: Document this assertion in API.
|
||||
# FIXME: There should just be an isNull method.
|
||||
assert child != Cursor_null()
|
||||
children.append(child)
|
||||
return 1 # continue
|
||||
children = []
|
||||
Cursor_visit(self, Cursor_visit_callback(visitor), children)
|
||||
return iter(children)
|
||||
|
||||
@staticmethod
|
||||
def from_result(res, fn, args):
|
||||
assert isinstance(res, Cursor)
|
||||
# FIXME: There should just be an isNull method.
|
||||
if res == Cursor_null():
|
||||
return None
|
||||
return res
|
||||
|
||||
## CIndex Objects ##
|
||||
|
||||
# CIndex objects (derived from ClangObject) are essentially lightweight
|
||||
# wrappers attached to some underlying object, which is exposed via CIndex as
|
||||
# a void*.
|
||||
|
||||
class ClangObject(object):
|
||||
"""
|
||||
A helper for Clang objects. This class helps act as an intermediary for
|
||||
the ctypes library and the Clang CIndex library.
|
||||
"""
|
||||
def __init__(self, obj):
|
||||
assert isinstance(obj, c_object_p) and obj
|
||||
self.obj = self._as_parameter_ = obj
|
||||
|
||||
def from_param(self):
|
||||
return self._as_parameter_
|
||||
|
||||
|
||||
class _CXUnsavedFile(Structure):
|
||||
"""Helper for passing unsaved file arguments."""
|
||||
_fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
|
||||
|
||||
## Diagnostic Conversion ##
|
||||
|
||||
# Diagnostic objects are temporary, we must extract all the information from the
|
||||
# diagnostic object when it is passed to the callback.
|
||||
|
||||
_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity
|
||||
_clang_getDiagnosticSeverity.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticSeverity.restype = c_int
|
||||
|
||||
_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation
|
||||
_clang_getDiagnosticLocation.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticLocation.restype = SourceLocation
|
||||
|
||||
_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling
|
||||
_clang_getDiagnosticSpelling.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticSpelling.restype = _CXString
|
||||
_clang_getDiagnosticSpelling.errcheck = _CXString.from_result
|
||||
|
||||
_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges
|
||||
_clang_getDiagnosticNumRanges.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticNumRanges.restype = c_uint
|
||||
|
||||
_clang_getDiagnosticRange = lib.clang_getDiagnosticRange
|
||||
_clang_getDiagnosticRange.argtypes = [c_object_p, c_uint]
|
||||
_clang_getDiagnosticRange.restype = SourceRange
|
||||
|
||||
_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
|
||||
_clang_getDiagnosticNumFixIts.argtypes = [c_object_p]
|
||||
_clang_getDiagnosticNumFixIts.restype = c_uint
|
||||
|
||||
_clang_getDiagnosticFixItKind = lib.clang_getDiagnosticFixItKind
|
||||
_clang_getDiagnosticFixItKind.argtypes = [c_object_p, c_uint]
|
||||
_clang_getDiagnosticFixItKind.restype = c_int
|
||||
|
||||
_clang_getDiagnosticFixItInsertion = lib.clang_getDiagnosticFixItInsertion
|
||||
_clang_getDiagnosticFixItInsertion.argtypes = [c_object_p, c_uint,
|
||||
POINTER(SourceLocation)]
|
||||
_clang_getDiagnosticFixItInsertion.restype = _CXString
|
||||
_clang_getDiagnosticFixItInsertion.errcheck = _CXString.from_result
|
||||
|
||||
_clang_getDiagnosticFixItRemoval = lib.clang_getDiagnosticFixItRemoval
|
||||
_clang_getDiagnosticFixItRemoval.argtypes = [c_object_p, c_uint,
|
||||
POINTER(SourceLocation)]
|
||||
_clang_getDiagnosticFixItRemoval.restype = _CXString
|
||||
_clang_getDiagnosticFixItRemoval.errcheck = _CXString.from_result
|
||||
|
||||
_clang_getDiagnosticFixItReplacement = lib.clang_getDiagnosticFixItReplacement
|
||||
_clang_getDiagnosticFixItReplacement.argtypes = [c_object_p, c_uint,
|
||||
POINTER(SourceRange)]
|
||||
_clang_getDiagnosticFixItReplacement.restype = _CXString
|
||||
_clang_getDiagnosticFixItReplacement.errcheck = _CXString.from_result
|
||||
|
||||
def _convert_fixit(diag_ptr, index):
|
||||
# We normalize all the fix-its to a single representation, this is more
|
||||
# convenient.
|
||||
#
|
||||
# FIXME: Push this back into API? It isn't exactly clear what the
|
||||
# SourceRange semantics are, we should make sure we can represent an empty
|
||||
# range.
|
||||
kind = _clang_getDiagnosticFixItKind(diag_ptr, index)
|
||||
range = None
|
||||
value = None
|
||||
if kind == 0: # insertion
|
||||
location = SourceLocation()
|
||||
value = _clang_getDiagnosticFixItInsertion(diag_ptr, index,
|
||||
byref(location))
|
||||
range = SourceRange.from_locations(location, location)
|
||||
elif kind == 1: # removal
|
||||
range = _clang_getDiagnosticFixItRemoval(diag_ptr, index)
|
||||
value = ''
|
||||
else: # replacement
|
||||
assert kind == 2
|
||||
range = SourceRange()
|
||||
value = _clang_getDiagnosticFixItReplacement(diag_ptr, index,
|
||||
byref(range))
|
||||
return FixIt(range, value)
|
||||
|
||||
def _convert_diag(diag_ptr, diag_list):
|
||||
severity = _clang_getDiagnosticSeverity(diag_ptr)
|
||||
loc = _clang_getDiagnosticLocation(diag_ptr)
|
||||
spelling = _clang_getDiagnosticSpelling(diag_ptr)
|
||||
|
||||
# Diagnostic ranges.
|
||||
num_ranges = _clang_getDiagnosticNumRanges(diag_ptr)
|
||||
ranges = [_clang_getDiagnosticRange(diag_ptr, i)
|
||||
for i in range(num_ranges)]
|
||||
|
||||
fixits = [_convert_fixit(diag_ptr, i)
|
||||
for i in range(_clang_getDiagnosticNumFixIts(diag_ptr))]
|
||||
|
||||
diag_list.append(Diagnostic(severity, loc, spelling, ranges, fixits))
|
||||
|
||||
###
|
||||
|
||||
class Index(ClangObject):
|
||||
"""
|
||||
The Index type provides the primary interface to the Clang CIndex library,
|
||||
primarily by providing an interface for reading and parsing translation
|
||||
units.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def create(excludeDecls=False):
|
||||
"""
|
||||
Create a new Index.
|
||||
Parameters:
|
||||
excludeDecls -- Exclude local declarations from translation units.
|
||||
"""
|
||||
return Index(Index_create(excludeDecls))
|
||||
|
||||
def __del__(self):
|
||||
Index_dispose(self)
|
||||
|
||||
def read(self, path):
|
||||
"""Load the translation unit from the given AST file."""
|
||||
# FIXME: In theory, we could support streaming diagnostics. It's hard to
|
||||
# integrate this into the API cleanly, however. Resolve.
|
||||
diags = []
|
||||
ptr = TranslationUnit_read(self, path,
|
||||
Diagnostic_callback(_convert_diag), diags)
|
||||
return TranslationUnit(ptr) if ptr else None
|
||||
|
||||
def parse(self, path, args = [], unsaved_files = []):
|
||||
"""
|
||||
Load the translation unit from the given source code file by running
|
||||
clang and generating the AST before loading. Additional command line
|
||||
parameters can be passed to clang via the args parameter.
|
||||
|
||||
In-memory contents for files can be provided by passing a list of pairs
|
||||
to as unsaved_files, the first item should be the filenames to be mapped
|
||||
and the second should be the contents to be substituted for the
|
||||
file. The contents may be passed as strings or file objects.
|
||||
"""
|
||||
arg_array = 0
|
||||
if len(args):
|
||||
arg_array = (c_char_p * len(args))(* args)
|
||||
unsaved_files_array = 0
|
||||
if len(unsaved_files):
|
||||
unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
|
||||
for i,(name,value) in enumerate(unsaved_files):
|
||||
if not isinstance(value, str):
|
||||
# FIXME: It would be great to support an efficient version
|
||||
# of this, one day.
|
||||
value = value.read()
|
||||
print value
|
||||
if not isinstance(value, str):
|
||||
raise TypeError,'Unexpected unsaved file contents.'
|
||||
unsaved_files_array[i].name = name
|
||||
unsaved_files_array[i].contents = value
|
||||
unsaved_files_array[i].length = len(value)
|
||||
# FIXME: In theory, we could support streaming diagnostics. It's hard to
|
||||
# integrate this into the API cleanly, however. Resolve.
|
||||
diags = []
|
||||
ptr = TranslationUnit_parse(self, path, len(args), arg_array,
|
||||
len(unsaved_files), unsaved_files_array,
|
||||
Diagnostic_callback(_convert_diag), diags)
|
||||
return TranslationUnit(ptr, diags) if ptr else None
|
||||
|
||||
|
||||
class TranslationUnit(ClangObject):
|
||||
"""
|
||||
The TranslationUnit class represents a source code translation unit and
|
||||
provides read-only access to its top-level declarations.
|
||||
"""
|
||||
|
||||
def __init__(self, ptr, diagnostics):
|
||||
ClangObject.__init__(self, ptr)
|
||||
self.diagnostics = diagnostics
|
||||
|
||||
def __del__(self):
|
||||
TranslationUnit_dispose(self)
|
||||
|
||||
@property
|
||||
def cursor(self):
|
||||
"""Retrieve the cursor that represents the given translation unit."""
|
||||
return TranslationUnit_cursor(self)
|
||||
|
||||
@property
|
||||
def spelling(self):
|
||||
"""Get the original translation unit source file name."""
|
||||
return TranslationUnit_spelling(self)
|
||||
|
||||
def get_includes(self):
|
||||
"""
|
||||
Return an iterable sequence of FileInclusion objects that describe the
|
||||
sequence of inclusions in a translation unit. The first object in
|
||||
this sequence is always the input file. Note that this method will not
|
||||
recursively iterate over header files included through precompiled
|
||||
headers.
|
||||
"""
|
||||
def visitor(fobj, lptr, depth, includes):
|
||||
loc = lptr.contents
|
||||
includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
|
||||
|
||||
# Automatically adapt CIndex/ctype pointers to python objects
|
||||
includes = []
|
||||
TranslationUnit_includes(self,
|
||||
TranslationUnit_includes_callback(visitor),
|
||||
includes)
|
||||
return iter(includes)
|
||||
|
||||
class File(ClangObject):
|
||||
"""
|
||||
The File class represents a particular source file that is part of a
|
||||
translation unit.
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the complete file and path name of the file."""
|
||||
return File_name(self)
|
||||
|
||||
@property
|
||||
def time(self):
|
||||
"""Return the last modification time of the file."""
|
||||
return File_time(self)
|
||||
|
||||
class FileInclusion(object):
|
||||
"""
|
||||
The FileInclusion class represents the inclusion of one source file by
|
||||
another via a '#include' directive or as the input file for the translation
|
||||
unit. This class provides information about the included file, the including
|
||||
file, the location of the '#include' directive and the depth of the included
|
||||
file in the stack. Note that the input file has depth 0.
|
||||
"""
|
||||
|
||||
def __init__(self, src, tgt, loc, depth):
|
||||
self.source = src
|
||||
self.include = tgt
|
||||
self.location = loc
|
||||
self.depth = depth
|
||||
|
||||
@property
|
||||
def is_input_file(self):
|
||||
"""True if the included file is the input file."""
|
||||
return self.depth == 0
|
||||
|
||||
# Additional Functions and Types
|
||||
|
||||
# String Functions
|
||||
_CXString_dispose = lib.clang_disposeString
|
||||
_CXString_dispose.argtypes = [_CXString]
|
||||
|
||||
_CXString_getCString = lib.clang_getCString
|
||||
_CXString_getCString.argtypes = [_CXString]
|
||||
_CXString_getCString.restype = c_char_p
|
||||
|
||||
# Source Location Functions
|
||||
SourceLocation_loc = lib.clang_getInstantiationLocation
|
||||
SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
|
||||
POINTER(c_uint), POINTER(c_uint),
|
||||
POINTER(c_uint)]
|
||||
|
||||
# Source Range Functions
|
||||
SourceRange_getRange = lib.clang_getRange
|
||||
SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
|
||||
SourceRange_getRange.restype = SourceRange
|
||||
|
||||
SourceRange_start = lib.clang_getRangeStart
|
||||
SourceRange_start.argtypes = [SourceRange]
|
||||
SourceRange_start.restype = SourceLocation
|
||||
|
||||
SourceRange_end = lib.clang_getRangeEnd
|
||||
SourceRange_end.argtypes = [SourceRange]
|
||||
SourceRange_end.restype = SourceLocation
|
||||
|
||||
# CursorKind Functions
|
||||
CursorKind_is_decl = lib.clang_isDeclaration
|
||||
CursorKind_is_decl.argtypes = [CursorKind]
|
||||
CursorKind_is_decl.restype = bool
|
||||
|
||||
CursorKind_is_ref = lib.clang_isReference
|
||||
CursorKind_is_ref.argtypes = [CursorKind]
|
||||
CursorKind_is_ref.restype = bool
|
||||
|
||||
CursorKind_is_expr = lib.clang_isExpression
|
||||
CursorKind_is_expr.argtypes = [CursorKind]
|
||||
CursorKind_is_expr.restype = bool
|
||||
|
||||
CursorKind_is_stmt = lib.clang_isStatement
|
||||
CursorKind_is_stmt.argtypes = [CursorKind]
|
||||
CursorKind_is_stmt.restype = bool
|
||||
|
||||
CursorKind_is_inv = lib.clang_isInvalid
|
||||
CursorKind_is_inv.argtypes = [CursorKind]
|
||||
CursorKind_is_inv.restype = bool
|
||||
|
||||
# Cursor Functions
|
||||
# TODO: Implement this function
|
||||
Cursor_get = lib.clang_getCursor
|
||||
Cursor_get.argtypes = [TranslationUnit, SourceLocation]
|
||||
Cursor_get.restype = Cursor
|
||||
|
||||
Cursor_null = lib.clang_getNullCursor
|
||||
Cursor_null.restype = Cursor
|
||||
|
||||
Cursor_usr = lib.clang_getCursorUSR
|
||||
Cursor_usr.argtypes = [Cursor]
|
||||
Cursor_usr.restype = _CXString
|
||||
Cursor_usr.errcheck = _CXString.from_result
|
||||
|
||||
Cursor_is_def = lib.clang_isCursorDefinition
|
||||
Cursor_is_def.argtypes = [Cursor]
|
||||
Cursor_is_def.restype = bool
|
||||
|
||||
Cursor_def = lib.clang_getCursorDefinition
|
||||
Cursor_def.argtypes = [Cursor]
|
||||
Cursor_def.restype = Cursor
|
||||
Cursor_def.errcheck = Cursor.from_result
|
||||
|
||||
Cursor_eq = lib.clang_equalCursors
|
||||
Cursor_eq.argtypes = [Cursor, Cursor]
|
||||
Cursor_eq.restype = c_uint
|
||||
|
||||
Cursor_spelling = lib.clang_getCursorSpelling
|
||||
Cursor_spelling.argtypes = [Cursor]
|
||||
Cursor_spelling.restype = _CXString
|
||||
Cursor_spelling.errcheck = _CXString.from_result
|
||||
|
||||
Cursor_loc = lib.clang_getCursorLocation
|
||||
Cursor_loc.argtypes = [Cursor]
|
||||
Cursor_loc.restype = SourceLocation
|
||||
|
||||
Cursor_extent = lib.clang_getCursorExtent
|
||||
Cursor_extent.argtypes = [Cursor]
|
||||
Cursor_extent.restype = SourceRange
|
||||
|
||||
Cursor_ref = lib.clang_getCursorReferenced
|
||||
Cursor_ref.argtypes = [Cursor]
|
||||
Cursor_ref.restype = Cursor
|
||||
Cursor_ref.errcheck = Cursor.from_result
|
||||
|
||||
Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
|
||||
Cursor_visit = lib.clang_visitChildren
|
||||
Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
|
||||
Cursor_visit.restype = c_uint
|
||||
|
||||
# Index Functions
|
||||
Index_create = lib.clang_createIndex
|
||||
Index_create.argtypes = [c_int]
|
||||
Index_create.restype = c_object_p
|
||||
|
||||
Index_dispose = lib.clang_disposeIndex
|
||||
Index_dispose.argtypes = [Index]
|
||||
|
||||
# Translation Unit Functions
|
||||
Diagnostic_callback = CFUNCTYPE(None, c_object_p, py_object)
|
||||
|
||||
TranslationUnit_read = lib.clang_createTranslationUnit
|
||||
TranslationUnit_read.argtypes = [Index, c_char_p,
|
||||
Diagnostic_callback, py_object]
|
||||
TranslationUnit_read.restype = c_object_p
|
||||
|
||||
TranslationUnit_parse = lib.clang_createTranslationUnitFromSourceFile
|
||||
TranslationUnit_parse.argtypes = [Index, c_char_p, c_int, c_void_p,
|
||||
c_int, c_void_p,
|
||||
Diagnostic_callback, py_object]
|
||||
TranslationUnit_parse.restype = c_object_p
|
||||
|
||||
TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
|
||||
TranslationUnit_cursor.argtypes = [TranslationUnit]
|
||||
TranslationUnit_cursor.restype = Cursor
|
||||
TranslationUnit_cursor.errcheck = Cursor.from_result
|
||||
|
||||
TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
|
||||
TranslationUnit_spelling.argtypes = [TranslationUnit]
|
||||
TranslationUnit_spelling.restype = _CXString
|
||||
TranslationUnit_spelling.errcheck = _CXString.from_result
|
||||
|
||||
TranslationUnit_dispose = lib.clang_disposeTranslationUnit
|
||||
TranslationUnit_dispose.argtypes = [TranslationUnit]
|
||||
|
||||
TranslationUnit_includes_callback = CFUNCTYPE(None,
|
||||
c_object_p,
|
||||
POINTER(SourceLocation),
|
||||
c_uint, py_object)
|
||||
TranslationUnit_includes = lib.clang_getInclusions
|
||||
TranslationUnit_includes.argtypes = [TranslationUnit,
|
||||
TranslationUnit_includes_callback,
|
||||
py_object]
|
||||
|
||||
# File Functions
|
||||
File_name = lib.clang_getFileName
|
||||
File_name.argtypes = [File]
|
||||
File_name.restype = c_char_p
|
||||
|
||||
File_time = lib.clang_getFileTime
|
||||
File_time.argtypes = [File]
|
||||
File_time.restype = c_uint
|
||||
|
||||
###
|
||||
|
||||
__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
|
||||
'Diagnostic', 'FixIt', 'SourceRange', 'SourceLocation', 'File']
|
||||
87
bindings/python/examples/cindex/cindex-dump.py
Normal file
87
bindings/python/examples/cindex/cindex-dump.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
"""
|
||||
A simple command line tool for dumping a source file using the Clang Index
|
||||
Library.
|
||||
"""
|
||||
|
||||
def get_diag_info(diag):
|
||||
return { 'severity' : diag.severity,
|
||||
'location' : diag.location,
|
||||
'spelling' : diag.spelling,
|
||||
'ranges' : diag.ranges,
|
||||
'fixits' : diag.fixits }
|
||||
|
||||
def get_cursor_id(cursor, cursor_list = []):
|
||||
if not opts.showIDs:
|
||||
return None
|
||||
|
||||
if cursor is None:
|
||||
return None
|
||||
|
||||
# FIXME: This is really slow. It would be nice if the index API exposed
|
||||
# something that let us hash cursors.
|
||||
for i,c in enumerate(cursor_list):
|
||||
if cursor == c:
|
||||
return i
|
||||
cursor_list.append(cursor)
|
||||
return len(cursor_list) - 1
|
||||
|
||||
def get_info(node, depth=0):
|
||||
if opts.maxDepth is not None and depth >= opts.maxDepth:
|
||||
children = None
|
||||
else:
|
||||
children = [get_info(c, depth+1)
|
||||
for c in node.get_children()]
|
||||
return { 'id' : get_cursor_id(node),
|
||||
'kind' : node.kind,
|
||||
'usr' : node.get_usr(),
|
||||
'spelling' : node.spelling,
|
||||
'location' : node.location,
|
||||
'extent.start' : node.extent.start,
|
||||
'extent.end' : node.extent.end,
|
||||
'is_definition' : node.is_definition(),
|
||||
'definition id' : get_cursor_id(node.get_definition()),
|
||||
'children' : children }
|
||||
|
||||
def main():
|
||||
from clang.cindex import Index
|
||||
from pprint import pprint
|
||||
|
||||
from optparse import OptionParser, OptionGroup
|
||||
|
||||
global opts
|
||||
|
||||
parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
|
||||
parser.add_option("", "--show-ids", dest="showIDs",
|
||||
help="Don't compute cursor IDs (very slow)",
|
||||
default=False)
|
||||
parser.add_option("", "--max-depth", dest="maxDepth",
|
||||
help="Limit cursor expansion to depth N",
|
||||
metavar="N", type=int, default=None)
|
||||
parser.disable_interspersed_args()
|
||||
(opts, args) = parser.parse_args()
|
||||
|
||||
if len(args) == 0:
|
||||
parser.error('invalid number arguments')
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(None, args)
|
||||
if not tu:
|
||||
parser.error("unable to load input")
|
||||
|
||||
pprint(('diags', map(get_diag_info, tu.diagnostics)))
|
||||
pprint(('nodes', get_info(tu.cursor)))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
58
bindings/python/examples/cindex/cindex-includes.py
Normal file
58
bindings/python/examples/cindex/cindex-includes.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#===- cindex-includes.py - cindex/Python Inclusion Graph -----*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
"""
|
||||
A simple command line tool for dumping a Graphviz description (dot) that
|
||||
describes include dependencies.
|
||||
"""
|
||||
|
||||
def main():
|
||||
import sys
|
||||
from clang.cindex import Index
|
||||
|
||||
from optparse import OptionParser, OptionGroup
|
||||
|
||||
parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
|
||||
parser.disable_interspersed_args()
|
||||
(opts, args) = parser.parse_args()
|
||||
if len(args) == 0:
|
||||
parser.error('invalid number arguments')
|
||||
|
||||
# FIXME: Add an output file option
|
||||
out = sys.stdout
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(None, args)
|
||||
if not tu:
|
||||
parser.error("unable to load input")
|
||||
|
||||
# A helper function for generating the node name.
|
||||
def name(f):
|
||||
if f:
|
||||
return "\"" + f.name + "\""
|
||||
|
||||
# Generate the include graph
|
||||
out.write("digraph G {\n")
|
||||
for i in tu.get_includes():
|
||||
line = " ";
|
||||
if i.is_input_file:
|
||||
# Always write the input file as a node just in case it doesn't
|
||||
# actually include anything. This would generate a 1 node graph.
|
||||
line += name(i.include)
|
||||
else:
|
||||
line += '%s->%s' % (name(i.source), name(i.include))
|
||||
line += "\n";
|
||||
out.write(line)
|
||||
out.write("}\n")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
0
bindings/python/tests/__init__.py
Normal file
0
bindings/python/tests/__init__.py
Normal file
6
bindings/python/tests/cindex/INPUTS/header1.h
Normal file
6
bindings/python/tests/cindex/INPUTS/header1.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef HEADER1
|
||||
#define HEADER1
|
||||
|
||||
#include "header3.h"
|
||||
|
||||
#endif
|
||||
6
bindings/python/tests/cindex/INPUTS/header2.h
Normal file
6
bindings/python/tests/cindex/INPUTS/header2.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef HEADER2
|
||||
#define HEADER2
|
||||
|
||||
#include "header3.h"
|
||||
|
||||
#endif
|
||||
3
bindings/python/tests/cindex/INPUTS/header3.h
Normal file
3
bindings/python/tests/cindex/INPUTS/header3.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// Not a guarded header!
|
||||
|
||||
void f();
|
||||
6
bindings/python/tests/cindex/INPUTS/hello.cpp
Normal file
6
bindings/python/tests/cindex/INPUTS/hello.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "stdio.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
printf("hello world\n");
|
||||
return 0;
|
||||
}
|
||||
5
bindings/python/tests/cindex/INPUTS/include.cpp
Normal file
5
bindings/python/tests/cindex/INPUTS/include.cpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#include "header1.h"
|
||||
#include "header2.h"
|
||||
#include "header1.h"
|
||||
|
||||
int main() { }
|
||||
2
bindings/python/tests/cindex/INPUTS/parse_arguments.c
Normal file
2
bindings/python/tests/cindex/INPUTS/parse_arguments.c
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
int DECL_ONE = 1;
|
||||
int DECL_TWO = 2;
|
||||
0
bindings/python/tests/cindex/__init__.py
Normal file
0
bindings/python/tests/cindex/__init__.py
Normal file
59
bindings/python/tests/cindex/test_cursor.py
Normal file
59
bindings/python/tests/cindex/test_cursor.py
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
from clang.cindex import Index, CursorKind
|
||||
|
||||
kInput = """\
|
||||
// FIXME: Find nicer way to drop builtins and other cruft.
|
||||
int start_decl;
|
||||
|
||||
struct s0 {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct s1;
|
||||
|
||||
void f0(int a0, int a1) {
|
||||
int l0, l1;
|
||||
|
||||
if (a0)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
def test_get_children():
|
||||
index = Index.create()
|
||||
tu = index.parse('t.c', unsaved_files = [('t.c',kInput)])
|
||||
|
||||
# Skip until past start_decl.
|
||||
it = tu.cursor.get_children()
|
||||
while it.next().spelling != 'start_decl':
|
||||
pass
|
||||
|
||||
tu_nodes = list(it)
|
||||
|
||||
assert len(tu_nodes) == 3
|
||||
|
||||
assert tu_nodes[0].kind == CursorKind.STRUCT_DECL
|
||||
assert tu_nodes[0].spelling == 's0'
|
||||
assert tu_nodes[0].is_definition() == True
|
||||
assert tu_nodes[0].location.file.name == 't.c'
|
||||
assert tu_nodes[0].location.line == 4
|
||||
assert tu_nodes[0].location.column == 8
|
||||
|
||||
s0_nodes = list(tu_nodes[0].get_children())
|
||||
assert len(s0_nodes) == 2
|
||||
assert s0_nodes[0].kind == CursorKind.FIELD_DECL
|
||||
assert s0_nodes[0].spelling == 'a'
|
||||
assert s0_nodes[1].kind == CursorKind.FIELD_DECL
|
||||
assert s0_nodes[1].spelling == 'b'
|
||||
|
||||
assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
|
||||
assert tu_nodes[1].spelling == 's1'
|
||||
assert tu_nodes[1].is_definition() == False
|
||||
|
||||
assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
|
||||
assert tu_nodes[2].spelling == 'f0'
|
||||
assert tu_nodes[2].is_definition() == True
|
||||
27
bindings/python/tests/cindex/test_cursor_kind.py
Normal file
27
bindings/python/tests/cindex/test_cursor_kind.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
from clang.cindex import CursorKind
|
||||
|
||||
def test_name():
|
||||
assert CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL'
|
||||
|
||||
def test_get_all_kinds():
|
||||
assert CursorKind.UNEXPOSED_DECL in CursorKind.get_all_kinds()
|
||||
assert CursorKind.TRANSLATION_UNIT in CursorKind.get_all_kinds()
|
||||
|
||||
def test_kind_groups():
|
||||
"""Check that every kind classifies to exactly one group."""
|
||||
|
||||
assert CursorKind.UNEXPOSED_DECL.is_declaration()
|
||||
assert CursorKind.TYPE_REF.is_reference()
|
||||
assert CursorKind.DECL_REF_EXPR.is_expression()
|
||||
assert CursorKind.UNEXPOSED_STMT.is_statement()
|
||||
assert CursorKind.INVALID_FILE.is_invalid()
|
||||
|
||||
for k in CursorKind.get_all_kinds():
|
||||
group = [n for n in ('is_declaration', 'is_reference', 'is_expression',
|
||||
'is_statement', 'is_invalid')
|
||||
if getattr(k, n)()]
|
||||
|
||||
if k == CursorKind.TRANSLATION_UNIT:
|
||||
assert len(group) == 0
|
||||
else:
|
||||
assert len(group) == 1
|
||||
48
bindings/python/tests/cindex/test_diagnostics.py
Normal file
48
bindings/python/tests/cindex/test_diagnostics.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
from clang.cindex import *
|
||||
|
||||
def tu_from_source(source):
|
||||
index = Index.create()
|
||||
tu = index.parse('INPUT.c', unsaved_files = [('INPUT.c', source)])
|
||||
# FIXME: Remove the need for this.
|
||||
tu.index = index
|
||||
return tu
|
||||
|
||||
# FIXME: We need support for invalid translation units to test better.
|
||||
|
||||
def test_diagnostic_warning():
|
||||
tu = tu_from_source("""int f0() {}\n""")
|
||||
assert len(tu.diagnostics) == 1
|
||||
assert tu.diagnostics[0].severity == Diagnostic.Warning
|
||||
assert tu.diagnostics[0].location.line == 1
|
||||
assert tu.diagnostics[0].location.column == 11
|
||||
assert (tu.diagnostics[0].spelling ==
|
||||
'control reaches end of non-void function')
|
||||
|
||||
def test_diagnostic_note():
|
||||
# FIXME: We aren't getting notes here for some reason.
|
||||
index = Index.create()
|
||||
tu = tu_from_source("""#define A x\nvoid *A = 1;\n""")
|
||||
assert len(tu.diagnostics) == 1
|
||||
assert tu.diagnostics[0].severity == Diagnostic.Warning
|
||||
assert tu.diagnostics[0].location.line == 2
|
||||
assert tu.diagnostics[0].location.column == 7
|
||||
assert 'incompatible' in tu.diagnostics[0].spelling
|
||||
# assert tu.diagnostics[1].severity == Diagnostic.Note
|
||||
# assert tu.diagnostics[1].location.line == 1
|
||||
# assert tu.diagnostics[1].location.column == 11
|
||||
# assert tu.diagnostics[1].spelling == 'instantiated from'
|
||||
|
||||
def test_diagnostic_fixit():
|
||||
index = Index.create()
|
||||
tu = tu_from_source("""struct { int f0; } x = { f0 : 1 };""")
|
||||
assert len(tu.diagnostics) == 1
|
||||
assert tu.diagnostics[0].severity == Diagnostic.Warning
|
||||
assert tu.diagnostics[0].location.line == 1
|
||||
assert tu.diagnostics[0].location.column == 31
|
||||
assert tu.diagnostics[0].spelling.startswith('use of GNU old-style')
|
||||
assert len(tu.diagnostics[0].fixits) == 1
|
||||
assert tu.diagnostics[0].fixits[0].range.start.line == 1
|
||||
assert tu.diagnostics[0].fixits[0].range.start.column == 26
|
||||
assert tu.diagnostics[0].fixits[0].range.end.line == 1
|
||||
assert tu.diagnostics[0].fixits[0].range.end.column == 30
|
||||
assert tu.diagnostics[0].fixits[0].value == '.f0 = '
|
||||
15
bindings/python/tests/cindex/test_index.py
Normal file
15
bindings/python/tests/cindex/test_index.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
from clang.cindex import *
|
||||
import os
|
||||
|
||||
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
|
||||
|
||||
def test_create():
|
||||
index = Index.create()
|
||||
|
||||
# FIXME: test Index.read
|
||||
|
||||
def test_parse():
|
||||
index = Index.create()
|
||||
assert isinstance(index, Index)
|
||||
tu = index.parse(os.path.join(kInputsDir, 'hello.cpp'))
|
||||
assert isinstance(tu, TranslationUnit)
|
||||
73
bindings/python/tests/cindex/test_translation_unit.py
Normal file
73
bindings/python/tests/cindex/test_translation_unit.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
from clang.cindex import *
|
||||
import os
|
||||
|
||||
kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
|
||||
|
||||
def test_spelling():
|
||||
path = os.path.join(kInputsDir, 'hello.cpp')
|
||||
index = Index.create()
|
||||
tu = index.parse(path)
|
||||
assert tu.spelling == path
|
||||
|
||||
def test_cursor():
|
||||
path = os.path.join(kInputsDir, 'hello.cpp')
|
||||
index = Index.create()
|
||||
tu = index.parse(path)
|
||||
c = tu.cursor
|
||||
assert isinstance(c, Cursor)
|
||||
assert c.kind is CursorKind.TRANSLATION_UNIT
|
||||
|
||||
def test_parse_arguments():
|
||||
path = os.path.join(kInputsDir, 'parse_arguments.c')
|
||||
index = Index.create()
|
||||
tu = index.parse(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi'])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-2] == 'hello'
|
||||
assert spellings[-1] == 'hi'
|
||||
|
||||
def test_unsaved_files():
|
||||
index = Index.create()
|
||||
# FIXME: Why can't we just use "fake.h" here (instead of /tmp/fake.h)?
|
||||
tu = index.parse('fake.c', unsaved_files = [
|
||||
('fake.c', """
|
||||
#include "/tmp/fake.h"
|
||||
int x;
|
||||
int SOME_DEFINE;
|
||||
"""),
|
||||
('/tmp/fake.h', """
|
||||
#define SOME_DEFINE y
|
||||
""")
|
||||
])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-2] == 'x'
|
||||
assert spellings[-1] == 'y'
|
||||
|
||||
def test_unsaved_files_2():
|
||||
import StringIO
|
||||
index = Index.create()
|
||||
tu = index.parse('fake.c', unsaved_files = [
|
||||
('fake.c', StringIO.StringIO('int x;'))])
|
||||
spellings = [c.spelling for c in tu.cursor.get_children()]
|
||||
assert spellings[-1] == 'x'
|
||||
|
||||
|
||||
def test_includes():
|
||||
def eq(expected, actual):
|
||||
if not actual.is_input_file:
|
||||
return expected[0] == actual.source.name and \
|
||||
expected[1] == actual.include.name
|
||||
else:
|
||||
return expected[1] == actual.include.name
|
||||
|
||||
src = os.path.join(kInputsDir, 'include.cpp')
|
||||
h1 = os.path.join(kInputsDir, "header1.h")
|
||||
h2 = os.path.join(kInputsDir, "header2.h")
|
||||
h3 = os.path.join(kInputsDir, "header3.h")
|
||||
inc = [(None, src), (src, h1), (h1, h3), (src, h2), (h2, h3)]
|
||||
|
||||
index = Index.create()
|
||||
tu = index.parse(src)
|
||||
for i in zip(inc, tu.get_includes()):
|
||||
assert eq(i[0], i[1])
|
||||
|
||||
|
||||
|
|
@ -33,6 +33,12 @@
|
|||
1A4C41BF105B4C0B0047B5E7 /* CGClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4C41BE105B4C0B0047B5E7 /* CGClass.cpp */; };
|
||||
1A535ED9107BC45E000C3AE7 /* CXXInheritance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A535ED8107BC45E000C3AE7 /* CXXInheritance.cpp */; };
|
||||
1A5D5E580E5E81010023C059 /* CGCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A5D5E570E5E81010023C059 /* CGCXX.cpp */; };
|
||||
1A621BB7110FE6AA009E6834 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621BB5110FE6AA009E6834 /* TargetInfo.cpp */; };
|
||||
1A621C4211111D61009E6834 /* CIndexCodeCompletion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3A11111D61009E6834 /* CIndexCodeCompletion.cpp */; };
|
||||
1A621C4311111D61009E6834 /* CIndexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3B11111D61009E6834 /* CIndexer.cpp */; };
|
||||
1A621C4411111D61009E6834 /* CIndexInclusionStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3D11111D61009E6834 /* CIndexInclusionStack.cpp */; };
|
||||
1A621C4511111D61009E6834 /* CIndexUSRs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3E11111D61009E6834 /* CIndexUSRs.cpp */; };
|
||||
1A621C4611111D61009E6834 /* CXCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A621C3F11111D61009E6834 /* CXCursor.cpp */; };
|
||||
1A6B6CD410693FC900BB4A8F /* CodeCompleteConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */; };
|
||||
1A6B6CD510693FC900BB4A8F /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */; };
|
||||
1A6B6E9A1069833600BB4A8F /* CGExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */; };
|
||||
|
|
@ -62,7 +68,6 @@
|
|||
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795310A90C6100741BBA /* TemplateBase.cpp */; };
|
||||
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
|
||||
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */; };
|
||||
1AE4EE40103B8A0A00888A23 /* TargetABIInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */; };
|
||||
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; };
|
||||
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
|
||||
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
|
||||
|
|
@ -382,6 +387,16 @@
|
|||
1A535ED8107BC45E000C3AE7 /* CXXInheritance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXXInheritance.cpp; path = lib/AST/CXXInheritance.cpp; sourceTree = "<group>"; };
|
||||
1A535EDB107BC47B000C3AE7 /* CanonicalType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CanonicalType.h; path = clang/AST/CanonicalType.h; sourceTree = "<group>"; };
|
||||
1A5D5E570E5E81010023C059 /* CGCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXX.cpp; path = lib/CodeGen/CGCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A621BB5110FE6AA009E6834 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetInfo.cpp; path = lib/CodeGen/TargetInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A621BB6110FE6AA009E6834 /* TargetInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TargetInfo.h; path = lib/CodeGen/TargetInfo.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A621C3A11111D61009E6834 /* CIndexCodeCompletion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexCodeCompletion.cpp; path = tools/CIndex/CIndexCodeCompletion.cpp; sourceTree = "<group>"; };
|
||||
1A621C3B11111D61009E6834 /* CIndexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexer.cpp; path = tools/CIndex/CIndexer.cpp; sourceTree = "<group>"; };
|
||||
1A621C3C11111D61009E6834 /* CIndexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CIndexer.h; path = tools/CIndex/CIndexer.h; sourceTree = "<group>"; };
|
||||
1A621C3D11111D61009E6834 /* CIndexInclusionStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexInclusionStack.cpp; path = tools/CIndex/CIndexInclusionStack.cpp; sourceTree = "<group>"; };
|
||||
1A621C3E11111D61009E6834 /* CIndexUSRs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexUSRs.cpp; path = tools/CIndex/CIndexUSRs.cpp; sourceTree = "<group>"; };
|
||||
1A621C3F11111D61009E6834 /* CXCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXCursor.cpp; path = tools/CIndex/CXCursor.cpp; sourceTree = "<group>"; };
|
||||
1A621C4011111D61009E6834 /* CXCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXCursor.h; path = tools/CIndex/CXCursor.h; sourceTree = "<group>"; };
|
||||
1A621C4111111D61009E6834 /* CXSourceLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXSourceLocation.h; path = tools/CIndex/CXSourceLocation.h; sourceTree = "<group>"; };
|
||||
1A649E1D0F9599D9005B965E /* CGBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGBlocks.h; path = lib/CodeGen/CGBlocks.h; sourceTree = "<group>"; };
|
||||
1A649E1E0F9599DA005B965E /* CGCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGCXX.h; path = lib/CodeGen/CGCXX.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CodeCompleteConsumer.cpp; path = lib/Sema/CodeCompleteConsumer.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
|
|
@ -428,7 +443,6 @@
|
|||
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiateDecl.cpp; path = lib/Sema/SemaTemplateInstantiateDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
|
|
@ -543,7 +557,6 @@
|
|||
9012911510470FCE0083456D /* Index.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Index.h; path = "clang-c/Index.h"; sourceTree = "<group>"; };
|
||||
9012911C1048068D0083456D /* ASTUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTUnit.cpp; path = lib/Frontend/ASTUnit.cpp; sourceTree = "<group>"; };
|
||||
9012911F104812F90083456D /* CIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndex.cpp; path = tools/CIndex/CIndex.cpp; sourceTree = "<group>"; };
|
||||
90129120104812F90083456D /* CIndex.exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CIndex.exports; path = tools/CIndex/CIndex.exports; sourceTree = "<group>"; };
|
||||
904753791096376F00CBDDDD /* CXXInheritance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXXInheritance.h; path = clang/AST/CXXInheritance.h; sourceTree = "<group>"; };
|
||||
9047537A1096376F00CBDDDD /* Redeclarable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Redeclarable.h; path = clang/AST/Redeclarable.h; sourceTree = "<group>"; };
|
||||
9047537B1096376F00CBDDDD /* TypeLoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLoc.h; path = clang/AST/TypeLoc.h; sourceTree = "<group>"; };
|
||||
|
|
@ -727,7 +740,7 @@
|
|||
DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitPreprocessor.cpp; path = lib/Frontend/InitPreprocessor.cpp; sourceTree = "<group>"; };
|
||||
DECB734E0FA3ED8400F5FBC7 /* StmtObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StmtObjC.h; path = clang/AST/StmtObjC.h; sourceTree = "<group>"; };
|
||||
DECB73550FA3EE5A00F5FBC7 /* StmtCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StmtCXX.h; path = clang/AST/StmtCXX.h; sourceTree = "<group>"; };
|
||||
DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderStmt.cpp; path = lib/Frontend/PCHReaderStmt.cpp; sourceTree = "<group>"; };
|
||||
DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderStmt.cpp; path = lib/Frontend/PCHReaderStmt.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderDecl.cpp; path = lib/Frontend/PCHReaderDecl.cpp; sourceTree = "<group>"; };
|
||||
DECB77F60FA5850200F5FBC7 /* PCHWriterDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriterDecl.cpp; path = lib/Frontend/PCHWriterDecl.cpp; sourceTree = "<group>"; };
|
||||
DECB78160FA5882F00F5FBC7 /* PCHWriterStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriterStmt.cpp; path = lib/Frontend/PCHWriterStmt.cpp; sourceTree = "<group>"; };
|
||||
|
|
@ -1037,6 +1050,7 @@
|
|||
356EF9B30C8F7DCA006650F5 /* Analysis */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DE67E70A0C020EC500F66BC5 /* SemaType.cpp */,
|
||||
35544B840F5C7F9D00D92AA9 /* Path-Sensitive */,
|
||||
3507E4CC0E27FEB900FB7B57 /* Flow-Sensitive Analyses */,
|
||||
3507E4C30E27FE3800FB7B57 /* Checks */,
|
||||
|
|
@ -1093,7 +1107,14 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
9012911F104812F90083456D /* CIndex.cpp */,
|
||||
90129120104812F90083456D /* CIndex.exports */,
|
||||
1A621C3B11111D61009E6834 /* CIndexer.cpp */,
|
||||
1A621C3A11111D61009E6834 /* CIndexCodeCompletion.cpp */,
|
||||
1A621C3C11111D61009E6834 /* CIndexer.h */,
|
||||
1A621C3D11111D61009E6834 /* CIndexInclusionStack.cpp */,
|
||||
1A621C3E11111D61009E6834 /* CIndexUSRs.cpp */,
|
||||
1A621C3F11111D61009E6834 /* CXCursor.cpp */,
|
||||
1A621C4011111D61009E6834 /* CXCursor.h */,
|
||||
1A621C4111111D61009E6834 /* CXSourceLocation.h */,
|
||||
);
|
||||
name = CIndex;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1265,7 +1286,6 @@
|
|||
BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */,
|
||||
35544B8B0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp */,
|
||||
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */,
|
||||
DE67E70A0C020EC500F66BC5 /* SemaType.cpp */,
|
||||
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */,
|
||||
);
|
||||
name = Sema;
|
||||
|
|
@ -1330,7 +1350,8 @@
|
|||
1A2193CC0F45EEB700C0713D /* Mangle.cpp */,
|
||||
1A2193CD0F45EEB700C0713D /* Mangle.h */,
|
||||
DE928B120C05659200231DA4 /* ModuleBuilder.cpp */,
|
||||
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */,
|
||||
1A621BB5110FE6AA009E6834 /* TargetInfo.cpp */,
|
||||
1A621BB6110FE6AA009E6834 /* TargetInfo.h */,
|
||||
);
|
||||
name = CodeGen;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1927,7 +1948,6 @@
|
|||
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */,
|
||||
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */,
|
||||
1AE4EE3E103B89ED00888A23 /* StmtProfile.cpp in Sources */,
|
||||
1AE4EE40103B8A0A00888A23 /* TargetABIInfo.cpp in Sources */,
|
||||
90FD6D7B103C3D49005F5B73 /* Analyzer.cpp in Sources */,
|
||||
90FD6D7C103C3D49005F5B73 /* ASTLocation.cpp in Sources */,
|
||||
90FD6D7D103C3D49005F5B73 /* DeclReferenceMap.cpp in Sources */,
|
||||
|
|
@ -1967,6 +1987,12 @@
|
|||
1ACB57EB1105820D0047B991 /* TypeXML.cpp in Sources */,
|
||||
1ACB57EC1105820D0047B991 /* VerifyDiagnosticsClient.cpp in Sources */,
|
||||
1A97825B1108BA18002B98FC /* CGVTT.cpp in Sources */,
|
||||
1A621BB7110FE6AA009E6834 /* TargetInfo.cpp in Sources */,
|
||||
1A621C4211111D61009E6834 /* CIndexCodeCompletion.cpp in Sources */,
|
||||
1A621C4311111D61009E6834 /* CIndexer.cpp in Sources */,
|
||||
1A621C4411111D61009E6834 /* CIndexInclusionStack.cpp in Sources */,
|
||||
1A621C4511111D61009E6834 /* CIndexUSRs.cpp in Sources */,
|
||||
1A621C4611111D61009E6834 /* CXCursor.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -205,12 +205,28 @@ is used in the file argument.</p>
|
|||
<h2 id="vectors">Vectors and Extended Vectors</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Supports the GCC vector extensions, plus some stuff like V[1]. ext_vector
|
||||
with V.xyzw syntax and other tidbits. See also <a
|
||||
href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
|
||||
<p>Supports the GCC vector extensions, plus some stuff like V[1].</p>
|
||||
|
||||
<p>Also supports <tt>ext_vector</tt>, which additionally support for V.xyzw
|
||||
syntax and other tidbits as seen in OpenCL. An example is:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
typedef float float4 <b>__attribute__((ext_vector_type(4)))</b>;
|
||||
typedef float float2 <b>__attribute__((ext_vector_type(2)))</b>;
|
||||
|
||||
float4 foo(float2 a, float2 b) {
|
||||
float4 c;
|
||||
c.xz = a;
|
||||
c.yw = b;
|
||||
return c;
|
||||
}
|
||||
</blockquote>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p>
|
||||
|
||||
<p>See also <a href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="checking_language_features">Checks for Standard Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
|
|
|||
|
|
@ -789,14 +789,12 @@ definition.</li>
|
|||
<h2 id="cxx">C++ Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>At this point, Clang C++ is not generally useful. However, Clang C++ support
|
||||
<p>At this point, Clang C++ is not production-quality and is not recommended for use beyond experimentation. However, Clang C++ support
|
||||
is under active development and is progressing rapidly. Please see the <a
|
||||
href="http://clang.llvm.org/cxx_status.html">C++ Status</a> page for details or
|
||||
ask on the mailing list about how you can help.</p>
|
||||
|
||||
<p>Note that the clang driver will refuse to even try to use clang to compile
|
||||
C++ code unless you pass the <tt>-ccc-clang-cxx</tt> option to the driver. If
|
||||
you really want to play with Clang's C++ support, please pass that flag. </p>
|
||||
<p>Note that released Clang compilers will refuse to even try to use clang to compile C++ code unless you pass the <tt>-ccc-clang-cxx</tt> option to the driver. To turn on Clang's C++ support, please pass that flag. Clang compilers built from the Subversion trunk enable C++ support by default, and do not require the <tt>-ccc-clang-cxx</tt> flag.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="objcxx">Objective C++ Language Features</h2>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ LEVEL = ../../../..
|
|||
LIBRARYNAME = PrintFunctionNames
|
||||
|
||||
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
|
||||
CXXFLAGS = -fno-rtti
|
||||
|
||||
# Include this here so we can get the configuration of the targets that have
|
||||
# been configured for construction. We have to do this early so we can set up
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ LEVEL = ../../../..
|
|||
|
||||
TOOLNAME = clang-wpa
|
||||
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
|
||||
CXXFLAGS = -fno-rtti
|
||||
NO_INSTALL = 1
|
||||
|
||||
# No plugins, optimize startup time.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,6 +27,7 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ namespace clang {
|
|||
class SourceManager;
|
||||
class TargetInfo;
|
||||
// Decls
|
||||
class DeclContext;
|
||||
class CXXMethodDecl;
|
||||
class CXXRecordDecl;
|
||||
class Decl;
|
||||
|
|
@ -502,7 +504,8 @@ public:
|
|||
|
||||
/// getVectorType - Return the unique reference to a vector type of
|
||||
/// the specified element type and size. VectorType must be a built-in type.
|
||||
QualType getVectorType(QualType VectorType, unsigned NumElts);
|
||||
QualType getVectorType(QualType VectorType, unsigned NumElts,
|
||||
bool AltiVec, bool IsPixel);
|
||||
|
||||
/// getExtVectorType - Return the unique reference to an extended vector type
|
||||
/// of the specified element type and size. VectorType must be a built-in
|
||||
|
|
@ -534,11 +537,11 @@ public:
|
|||
|
||||
/// getTypeDeclType - Return the unique reference to the type for
|
||||
/// the specified type declaration.
|
||||
QualType getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl=0);
|
||||
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl* PrevDecl=0);
|
||||
|
||||
/// getTypedefType - Return the unique reference to the type for the
|
||||
/// specified typename decl.
|
||||
QualType getTypedefType(TypedefDecl *Decl);
|
||||
QualType getTypedefType(const TypedefDecl *Decl);
|
||||
|
||||
QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced,
|
||||
QualType Replacement);
|
||||
|
|
@ -835,13 +838,23 @@ public:
|
|||
return getTypeInfo(T).second;
|
||||
}
|
||||
|
||||
/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
|
||||
/// characters. This method does not work on incomplete types.
|
||||
CharUnits getTypeAlignInChars(QualType T);
|
||||
CharUnits getTypeAlignInChars(const Type *T);
|
||||
|
||||
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
|
||||
/// type for the current target in bits. This can be different than the ABI
|
||||
/// alignment in cases where it is beneficial for performance to overalign
|
||||
/// a data type.
|
||||
unsigned getPreferredTypeAlign(const Type *T);
|
||||
|
||||
unsigned getDeclAlignInBytes(const Decl *D, bool RefAsPointee = false);
|
||||
/// getDeclAlign - Return a conservative estimate of the alignment of
|
||||
/// the specified decl. Note that bitfields do not have a valid alignment, so
|
||||
/// this method will assert on them.
|
||||
/// If @p RefAsPointee, references are treated like their underlying type
|
||||
/// (for alignof), else they're treated like pointers (for CodeGen).
|
||||
CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false);
|
||||
|
||||
/// getASTRecordLayout - Get or compute information about the layout of the
|
||||
/// specified record (struct/union/class), which indicates its size and field
|
||||
|
|
@ -878,7 +891,7 @@ public:
|
|||
unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
|
||||
unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
|
||||
void CollectInheritedProtocols(const Decl *CDecl,
|
||||
llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols);
|
||||
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Operators
|
||||
|
|
@ -960,6 +973,20 @@ public:
|
|||
NestedNameSpecifier *
|
||||
getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS);
|
||||
|
||||
/// \brief Retrieves the canonical representation of the given
|
||||
/// calling convention.
|
||||
CallingConv getCanonicalCallConv(CallingConv CC) {
|
||||
if (CC == CC_C)
|
||||
return CC_Default;
|
||||
return CC;
|
||||
}
|
||||
|
||||
/// \brief Determines whether two calling conventions name the same
|
||||
/// calling convention.
|
||||
bool isSameCallConv(CallingConv lcc, CallingConv rcc) {
|
||||
return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc));
|
||||
}
|
||||
|
||||
/// \brief Retrieves the "canonical" template name that refers to a
|
||||
/// given template.
|
||||
///
|
||||
|
|
@ -1187,6 +1214,15 @@ private:
|
|||
|
||||
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
|
||||
const ObjCImplementationDecl *Impl);
|
||||
|
||||
private:
|
||||
// FIXME: This currently contains the set of StoredDeclMaps used
|
||||
// by DeclContext objects. This probably should not be in ASTContext,
|
||||
// but we include it here so that ASTContext can quickly deallocate them.
|
||||
std::vector<void*> SDMs;
|
||||
friend class DeclContext;
|
||||
void *CreateStoredDeclsMap();
|
||||
void ReleaseDeclContextMaps();
|
||||
};
|
||||
|
||||
/// @brief Utility function for constructing a nullary selector.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//===--- DiagnosticAST.h - Diagnostics for the AST library ------*- C++ -*-===//
|
||||
//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
|
@ -22,6 +22,26 @@ namespace clang {
|
|||
NUM_BUILTIN_AST_DIAGNOSTICS
|
||||
};
|
||||
} // end namespace diag
|
||||
|
||||
/// \brief Diagnostic 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 Diagnostic::SetArgToStringFn(), where the cookie is an \c ASTContext
|
||||
/// pointer.
|
||||
void FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind,
|
||||
intptr_t Val,
|
||||
const char *Modifier,
|
||||
unsigned ModLen,
|
||||
const char *Argument,
|
||||
unsigned ArgLen,
|
||||
const Diagnostic::ArgumentValue *PrevArgs,
|
||||
unsigned NumPrevArgs,
|
||||
llvm::SmallVectorImpl<char> &Output,
|
||||
void *Cookie);
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
|||
234
include/clang/AST/ASTImporter.h
Normal file
234
include/clang/AST/ASTImporter.h
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
//===--- 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/Type.h"
|
||||
#include "clang/AST/DeclarationName.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 Diagnostic;
|
||||
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 The diagnostics object that we should use to emit diagnostics.
|
||||
Diagnostic &Diags;
|
||||
|
||||
/// \brief Mapping from the already-imported types in the "from" context
|
||||
/// to the corresponding types in the "to" context.
|
||||
llvm::DenseMap<Type *, 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<unsigned, FileID> ImportedFileIDs;
|
||||
|
||||
/// \brief Imported, anonymous tag declarations that are missing their
|
||||
/// corresponding typedefs.
|
||||
llvm::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:
|
||||
ASTImporter(Diagnostic &Diags,
|
||||
ASTContext &ToContext, FileManager &ToFileManager,
|
||||
ASTContext &FromContext, FileManager &FromFileManager);
|
||||
|
||||
virtual ~ASTImporter();
|
||||
|
||||
/// \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 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(IdentifierInfo *FromId);
|
||||
|
||||
/// \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 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 Retrieve the diagnostic formatter.
|
||||
Diagnostic &getDiags() const { return Diags; }
|
||||
|
||||
/// \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 Note that we have imported the "from" declaration by mapping it
|
||||
/// to the (potentially-newly-created) "to" declaration.
|
||||
///
|
||||
/// \returns \p To
|
||||
Decl *Imported(Decl *From, Decl *To);
|
||||
|
||||
/// \brief Determine whether the given types are structurally
|
||||
/// equivalent.
|
||||
bool IsStructurallyEquivalent(QualType From, QualType To);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LLVM_CLANG_AST_ASTIMPORTER_H
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
using llvm::dyn_cast;
|
||||
|
||||
|
|
@ -96,7 +95,8 @@ public:
|
|||
FIRST_TARGET_ATTRIBUTE,
|
||||
DLLExport,
|
||||
DLLImport,
|
||||
MSP430Interrupt
|
||||
MSP430Interrupt,
|
||||
X86ForceAlignArgPointer
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -119,8 +119,7 @@ protected:
|
|||
assert(Next == 0 && "Destroy didn't work");
|
||||
}
|
||||
public:
|
||||
|
||||
void Destroy(ASTContext &C);
|
||||
virtual void Destroy(ASTContext &C);
|
||||
|
||||
/// \brief Whether this attribute should be merged to new
|
||||
/// declarations.
|
||||
|
|
@ -156,6 +155,18 @@ public:
|
|||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Attr *) { return true; }
|
||||
};
|
||||
|
||||
class AttrWithString : public Attr {
|
||||
private:
|
||||
const char *Str;
|
||||
unsigned StrLen;
|
||||
protected:
|
||||
AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s);
|
||||
llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
|
||||
void ReplaceString(ASTContext &C, llvm::StringRef newS);
|
||||
public:
|
||||
virtual void Destroy(ASTContext &C);
|
||||
};
|
||||
|
||||
#define DEF_SIMPLE_ATTR(ATTR) \
|
||||
class ATTR##Attr : public Attr { \
|
||||
|
|
@ -213,12 +224,12 @@ public:
|
|||
static bool classof(const AlignedAttr *A) { return true; }
|
||||
};
|
||||
|
||||
class AnnotateAttr : public Attr {
|
||||
std::string Annotation;
|
||||
class AnnotateAttr : public AttrWithString {
|
||||
public:
|
||||
AnnotateAttr(llvm::StringRef ann) : Attr(Annotate), Annotation(ann) {}
|
||||
AnnotateAttr(ASTContext &C, llvm::StringRef ann)
|
||||
: AttrWithString(Annotate, C, ann) {}
|
||||
|
||||
const std::string& getAnnotation() const { return Annotation; }
|
||||
llvm::StringRef getAnnotation() const { return getString(); }
|
||||
|
||||
virtual Attr* clone(ASTContext &C) const;
|
||||
|
||||
|
|
@ -229,12 +240,12 @@ public:
|
|||
static bool classof(const AnnotateAttr *A) { return true; }
|
||||
};
|
||||
|
||||
class AsmLabelAttr : public Attr {
|
||||
std::string Label;
|
||||
class AsmLabelAttr : public AttrWithString {
|
||||
public:
|
||||
AsmLabelAttr(llvm::StringRef L) : Attr(AsmLabel), Label(L) {}
|
||||
AsmLabelAttr(ASTContext &C, llvm::StringRef L)
|
||||
: AttrWithString(AsmLabel, C, L) {}
|
||||
|
||||
const std::string& getLabel() const { return Label; }
|
||||
llvm::StringRef getLabel() const { return getString(); }
|
||||
|
||||
virtual Attr* clone(ASTContext &C) const;
|
||||
|
||||
|
|
@ -247,12 +258,12 @@ public:
|
|||
|
||||
DEF_SIMPLE_ATTR(AlwaysInline);
|
||||
|
||||
class AliasAttr : public Attr {
|
||||
std::string Aliasee;
|
||||
class AliasAttr : public AttrWithString {
|
||||
public:
|
||||
AliasAttr(llvm::StringRef aliasee) : Attr(Alias), Aliasee(aliasee) {}
|
||||
AliasAttr(ASTContext &C, llvm::StringRef aliasee)
|
||||
: AttrWithString(Alias, C, aliasee) {}
|
||||
|
||||
const std::string& getAliasee() const { return Aliasee; }
|
||||
llvm::StringRef getAliasee() const { return getString(); }
|
||||
|
||||
virtual Attr *clone(ASTContext &C) const;
|
||||
|
||||
|
|
@ -321,12 +332,12 @@ DEF_SIMPLE_ATTR(AnalyzerNoReturn);
|
|||
DEF_SIMPLE_ATTR(Deprecated);
|
||||
DEF_SIMPLE_ATTR(Final);
|
||||
|
||||
class SectionAttr : public Attr {
|
||||
std::string Name;
|
||||
class SectionAttr : public AttrWithString {
|
||||
public:
|
||||
SectionAttr(llvm::StringRef N) : Attr(Section), Name(N) {}
|
||||
SectionAttr(ASTContext &C, llvm::StringRef N)
|
||||
: AttrWithString(Section, C, N) {}
|
||||
|
||||
const std::string& getName() const { return Name; }
|
||||
llvm::StringRef getName() const { return getString(); }
|
||||
|
||||
virtual Attr *clone(ASTContext &C) const;
|
||||
|
||||
|
|
@ -350,19 +361,9 @@ class NonNullAttr : public Attr {
|
|||
unsigned* ArgNums;
|
||||
unsigned Size;
|
||||
public:
|
||||
NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull),
|
||||
ArgNums(0), Size(0) {
|
||||
NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
|
||||
|
||||
if (size == 0) return;
|
||||
assert(arg_nums);
|
||||
ArgNums = new unsigned[size];
|
||||
Size = size;
|
||||
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
|
||||
}
|
||||
|
||||
virtual ~NonNullAttr() {
|
||||
delete [] ArgNums;
|
||||
}
|
||||
virtual void Destroy(ASTContext &C);
|
||||
|
||||
typedef const unsigned *iterator;
|
||||
iterator begin() const { return ArgNums; }
|
||||
|
|
@ -379,15 +380,14 @@ public:
|
|||
static bool classof(const NonNullAttr *A) { return true; }
|
||||
};
|
||||
|
||||
class FormatAttr : public Attr {
|
||||
std::string Type;
|
||||
class FormatAttr : public AttrWithString {
|
||||
int formatIdx, firstArg;
|
||||
public:
|
||||
FormatAttr(llvm::StringRef type, int idx, int first) : Attr(Format),
|
||||
Type(type), formatIdx(idx), firstArg(first) {}
|
||||
FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
|
||||
: AttrWithString(Format, C, type), formatIdx(idx), firstArg(first) {}
|
||||
|
||||
const std::string& getType() const { return Type; }
|
||||
void setType(llvm::StringRef type) { Type = type; }
|
||||
llvm::StringRef getType() const { return getString(); }
|
||||
void setType(ASTContext &C, llvm::StringRef type);
|
||||
int getFormatIdx() const { return formatIdx; }
|
||||
int getFirstArg() const { return firstArg; }
|
||||
|
||||
|
|
@ -570,6 +570,8 @@ public:
|
|||
static bool classof(const MSP430InterruptAttr *A) { return true; }
|
||||
};
|
||||
|
||||
DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
|
||||
|
||||
#undef DEF_SIMPLE_ATTR
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
|||
|
|
@ -161,7 +161,8 @@ class CXXBasePaths {
|
|||
void ComputeDeclsFound();
|
||||
|
||||
public:
|
||||
typedef std::list<CXXBasePath>::const_iterator paths_iterator;
|
||||
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
|
||||
|
|
@ -175,8 +176,10 @@ public:
|
|||
|
||||
~CXXBasePaths() { delete [] DeclsFound; }
|
||||
|
||||
paths_iterator begin() const { return Paths.begin(); }
|
||||
paths_iterator end() const { return Paths.end(); }
|
||||
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(); }
|
||||
|
|
@ -206,7 +209,7 @@ public:
|
|||
const RecordType* getDetectedVirtual() const {
|
||||
return DetectedVirtual;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve the type from which this base-paths search
|
||||
/// began
|
||||
CXXRecordDecl *getOrigin() const { return Origin; }
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "clang/AST/Redeclarable.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
#include "clang/Basic/Linkage.h"
|
||||
|
||||
namespace clang {
|
||||
class CXXTemporary;
|
||||
|
|
@ -75,8 +76,9 @@ public:
|
|||
|
||||
static TranslationUnitDecl *Create(ASTContext &C);
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TranslationUnitDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == TranslationUnit; }
|
||||
static DeclContext *castToDeclContext(const TranslationUnitDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D));
|
||||
}
|
||||
|
|
@ -194,23 +196,6 @@ public:
|
|||
return DC->isRecord();
|
||||
}
|
||||
|
||||
/// \brief Describes the different kinds of linkage
|
||||
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
|
||||
enum Linkage {
|
||||
/// \brief No linkage, which means that the entity is unique and
|
||||
/// can only be referred to from within its scope.
|
||||
NoLinkage = 0,
|
||||
|
||||
/// \brief Internal linkage, which indicates that the entity can
|
||||
/// be referred to from within the translation unit (but not other
|
||||
/// translation units).
|
||||
InternalLinkage,
|
||||
|
||||
/// \brief External linkage, which indicates that the entity can
|
||||
/// be referred to from other translation units.
|
||||
ExternalLinkage
|
||||
};
|
||||
|
||||
/// \brief Determine what kind of linkage this entity has.
|
||||
Linkage getLinkage() const;
|
||||
|
||||
|
|
@ -221,10 +206,9 @@ public:
|
|||
return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const NamedDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K >= NamedFirst && K <= NamedLast; }
|
||||
};
|
||||
|
||||
/// NamespaceDecl - Represent a C++ namespace.
|
||||
|
|
@ -301,8 +285,9 @@ public:
|
|||
void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == Namespace; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const NamespaceDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Namespace; }
|
||||
static DeclContext *castToDeclContext(const NamespaceDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D));
|
||||
}
|
||||
|
|
@ -326,10 +311,9 @@ public:
|
|||
void setType(QualType newType) { DeclType = newType; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= ValueFirst && D->getKind() <= ValueLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ValueDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K >= ValueFirst && K <= ValueLast; }
|
||||
};
|
||||
|
||||
/// \brief Represents a ValueDecl that came out of a declarator.
|
||||
|
|
@ -349,10 +333,11 @@ public:
|
|||
SourceLocation getTypeSpecStartLoc() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= DeclaratorFirst && D->getKind() <= DeclaratorLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const DeclaratorDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= DeclaratorFirst && K <= DeclaratorLast;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Structure used to store a statement, the constant value to
|
||||
|
|
@ -474,14 +459,142 @@ public:
|
|||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, TypeSourceInfo *TInfo, StorageClass S);
|
||||
|
||||
virtual ~VarDecl();
|
||||
virtual void Destroy(ASTContext& C);
|
||||
virtual ~VarDecl();
|
||||
|
||||
virtual SourceRange getSourceRange() const;
|
||||
|
||||
StorageClass getStorageClass() const { return (StorageClass)SClass; }
|
||||
void setStorageClass(StorageClass SC) { SClass = SC; }
|
||||
|
||||
virtual SourceRange getSourceRange() const;
|
||||
void setThreadSpecified(bool T) { ThreadSpecified = T; }
|
||||
bool isThreadSpecified() const {
|
||||
return ThreadSpecified;
|
||||
}
|
||||
|
||||
/// hasLocalStorage - Returns true if a variable with function scope
|
||||
/// is a non-static local variable.
|
||||
bool hasLocalStorage() const {
|
||||
if (getStorageClass() == None)
|
||||
return !isFileVarDecl();
|
||||
|
||||
// Return true for: Auto, Register.
|
||||
// Return false for: Extern, Static, PrivateExtern.
|
||||
|
||||
return getStorageClass() <= Register;
|
||||
}
|
||||
|
||||
/// hasExternStorage - Returns true if a variable has extern or
|
||||
/// __private_extern__ storage.
|
||||
bool hasExternalStorage() const {
|
||||
return getStorageClass() == Extern || getStorageClass() == PrivateExtern;
|
||||
}
|
||||
|
||||
/// hasGlobalStorage - Returns true for all variables that do not
|
||||
/// have local storage. This includs all global variables as well
|
||||
/// as static variables declared within a function.
|
||||
bool hasGlobalStorage() const { return !hasLocalStorage(); }
|
||||
|
||||
/// \brief Determines whether this variable is a variable with
|
||||
/// external, C linkage.
|
||||
bool isExternC() const;
|
||||
|
||||
/// isBlockVarDecl - Returns true for local variable declarations. Note that
|
||||
/// this includes static variables inside of functions.
|
||||
///
|
||||
/// void foo() { int x; static int y; extern int z; }
|
||||
///
|
||||
bool isBlockVarDecl() const {
|
||||
if (getKind() != Decl::Var)
|
||||
return false;
|
||||
if (const DeclContext *DC = getDeclContext())
|
||||
return DC->getLookupContext()->isFunctionOrMethod();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this is a static data member.
|
||||
///
|
||||
/// This will only be true in C++, and applies to, e.g., the
|
||||
/// variable 'x' in:
|
||||
/// \code
|
||||
/// struct S {
|
||||
/// static int x;
|
||||
/// };
|
||||
/// \endcode
|
||||
bool isStaticDataMember() const {
|
||||
// If it wasn't static, it would be a FieldDecl.
|
||||
return getDeclContext()->isRecord();
|
||||
}
|
||||
|
||||
virtual VarDecl *getCanonicalDecl();
|
||||
const VarDecl *getCanonicalDecl() const {
|
||||
return const_cast<VarDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
enum DefinitionKind {
|
||||
DeclarationOnly, ///< This declaration is only a declaration.
|
||||
TentativeDefinition, ///< This declaration is a tentative definition.
|
||||
Definition ///< This declaration is definitely a definition.
|
||||
};
|
||||
|
||||
/// \brief Check whether this declaration is a definition. If this could be
|
||||
/// a tentative definition (in C), don't check whether there's an overriding
|
||||
/// definition.
|
||||
DefinitionKind isThisDeclarationADefinition() const;
|
||||
|
||||
/// \brief Get the tentative definition that acts as the real definition in
|
||||
/// a TU. Returns null if there is a proper definition available.
|
||||
VarDecl *getActingDefinition();
|
||||
const VarDecl *getActingDefinition() const {
|
||||
return const_cast<VarDecl*>(this)->getActingDefinition();
|
||||
}
|
||||
|
||||
/// \brief Determine whether this is a tentative definition of a
|
||||
/// variable in C.
|
||||
bool isTentativeDefinitionNow() const;
|
||||
|
||||
/// \brief Get the real (not just tentative) definition for this declaration.
|
||||
VarDecl *getDefinition();
|
||||
const VarDecl *getDefinition() const {
|
||||
return const_cast<VarDecl*>(this)->getDefinition();
|
||||
}
|
||||
|
||||
/// \brief Determine whether this is or was instantiated from an out-of-line
|
||||
/// definition of a static data member.
|
||||
bool isOutOfLine() const;
|
||||
|
||||
/// \brief If this is a static data member, find its out-of-line definition.
|
||||
VarDecl *getOutOfLineDefinition();
|
||||
|
||||
/// isFileVarDecl - Returns true for file scoped variable declaration.
|
||||
bool isFileVarDecl() const {
|
||||
if (getKind() != Decl::Var)
|
||||
return false;
|
||||
if (const DeclContext *Ctx = getDeclContext()) {
|
||||
Ctx = Ctx->getLookupContext();
|
||||
if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
|
||||
return true;
|
||||
}
|
||||
if (isStaticDataMember())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getAnyInitializer - Get the initializer for this variable, no matter which
|
||||
/// declaration it is attached to.
|
||||
const Expr *getAnyInitializer() const {
|
||||
const VarDecl *D;
|
||||
return getAnyInitializer(D);
|
||||
}
|
||||
|
||||
/// getAnyInitializer - Get the initializer for this variable, no matter which
|
||||
/// declaration it is attached to. Also get that declaration.
|
||||
const Expr *getAnyInitializer(const VarDecl *&D) const;
|
||||
|
||||
bool hasInit() const {
|
||||
return !Init.isNull();
|
||||
}
|
||||
const Expr *getInit() const {
|
||||
if (Init.isNull())
|
||||
return 0;
|
||||
|
|
@ -521,7 +634,7 @@ public:
|
|||
return StmtPtr;
|
||||
}
|
||||
|
||||
void setInit(ASTContext &C, Expr *I);
|
||||
void setInit(Expr *I);
|
||||
|
||||
EvaluatedStmt *EnsureEvaluatedStmt() const {
|
||||
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
|
||||
|
|
@ -614,17 +727,6 @@ public:
|
|||
Eval->IsICE = IsICE;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the definition of this variable, which may come
|
||||
/// from a previous declaration. Def will be set to the VarDecl that
|
||||
/// contains the initializer, and the result will be that
|
||||
/// initializer.
|
||||
const Expr *getDefinition(const VarDecl *&Def) const;
|
||||
|
||||
void setThreadSpecified(bool T) { ThreadSpecified = T; }
|
||||
bool isThreadSpecified() const {
|
||||
return ThreadSpecified;
|
||||
}
|
||||
|
||||
void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; }
|
||||
|
||||
/// hasCXXDirectInitializer - If true, the initializer was a direct
|
||||
|
|
@ -648,67 +750,6 @@ public:
|
|||
void setDeclaredInCondition(bool InCondition) {
|
||||
DeclaredInCondition = InCondition;
|
||||
}
|
||||
|
||||
virtual VarDecl *getCanonicalDecl();
|
||||
const VarDecl *getCanonicalDecl() const {
|
||||
return const_cast<VarDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
/// hasLocalStorage - Returns true if a variable with function scope
|
||||
/// is a non-static local variable.
|
||||
bool hasLocalStorage() const {
|
||||
if (getStorageClass() == None)
|
||||
return !isFileVarDecl();
|
||||
|
||||
// Return true for: Auto, Register.
|
||||
// Return false for: Extern, Static, PrivateExtern.
|
||||
|
||||
return getStorageClass() <= Register;
|
||||
}
|
||||
|
||||
/// hasExternStorage - Returns true if a variable has extern or
|
||||
/// __private_extern__ storage.
|
||||
bool hasExternalStorage() const {
|
||||
return getStorageClass() == Extern || getStorageClass() == PrivateExtern;
|
||||
}
|
||||
|
||||
/// hasGlobalStorage - Returns true for all variables that do not
|
||||
/// have local storage. This includs all global variables as well
|
||||
/// as static variables declared within a function.
|
||||
bool hasGlobalStorage() const { return !hasLocalStorage(); }
|
||||
|
||||
/// isBlockVarDecl - Returns true for local variable declarations. Note that
|
||||
/// this includes static variables inside of functions.
|
||||
///
|
||||
/// void foo() { int x; static int y; extern int z; }
|
||||
///
|
||||
bool isBlockVarDecl() const {
|
||||
if (getKind() != Decl::Var)
|
||||
return false;
|
||||
if (const DeclContext *DC = getDeclContext())
|
||||
return DC->getLookupContext()->isFunctionOrMethod();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this is a static data member.
|
||||
///
|
||||
/// This will only be true in C++, and applies to, e.g., the
|
||||
/// variable 'x' in:
|
||||
/// \code
|
||||
/// struct S {
|
||||
/// static int x;
|
||||
/// };
|
||||
/// \endcode
|
||||
bool isStaticDataMember() const {
|
||||
return getDeclContext()->isRecord();
|
||||
}
|
||||
|
||||
/// \brief Determine whether this is or was instantiated from an out-of-line
|
||||
/// definition of a static data member.
|
||||
bool isOutOfLine() const;
|
||||
|
||||
/// \brief If this is a static data member, find its out-of-line definition.
|
||||
VarDecl *getOutOfLineDefinition();
|
||||
|
||||
/// \brief If this variable is an instantiated static data member of a
|
||||
/// class template specialization, returns the templated static data member
|
||||
|
|
@ -728,35 +769,11 @@ public:
|
|||
/// data member of a class template, set the template specialiation kind.
|
||||
void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
|
||||
SourceLocation PointOfInstantiation = SourceLocation());
|
||||
|
||||
/// isFileVarDecl - Returns true for file scoped variable declaration.
|
||||
bool isFileVarDecl() const {
|
||||
if (getKind() != Decl::Var)
|
||||
return false;
|
||||
if (const DeclContext *Ctx = getDeclContext()) {
|
||||
Ctx = Ctx->getLookupContext();
|
||||
if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
|
||||
return true;
|
||||
}
|
||||
if (isStaticDataMember())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this is a tentative definition of a
|
||||
/// variable in C.
|
||||
bool isTentativeDefinition(ASTContext &Context) const;
|
||||
|
||||
/// \brief Determines whether this variable is a variable with
|
||||
/// external, C linkage.
|
||||
bool isExternC() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= VarFirst && D->getKind() <= VarLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const VarDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K >= VarFirst && K <= VarLast; }
|
||||
};
|
||||
|
||||
class ImplicitParamDecl : public VarDecl {
|
||||
|
|
@ -770,7 +787,8 @@ public:
|
|||
QualType T);
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const ImplicitParamDecl *D) { return true; }
|
||||
static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == ImplicitParam; }
|
||||
};
|
||||
|
||||
/// ParmVarDecl - Represent a parameter to a function.
|
||||
|
|
@ -876,10 +894,9 @@ public:
|
|||
void setOwningFunction(DeclContext *FD) { setDeclContext(FD); }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return (D->getKind() == ParmVar);
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ParmVarDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ParmVar; }
|
||||
};
|
||||
|
||||
/// FunctionDecl - An instance of this class is created to represent a
|
||||
|
|
@ -1096,8 +1113,6 @@ public:
|
|||
|
||||
unsigned getBuiltinID() const;
|
||||
|
||||
unsigned getNumParmVarDeclsFromType() const;
|
||||
|
||||
// Iterator access to formal parameters.
|
||||
unsigned param_size() const { return getNumParams(); }
|
||||
typedef ParmVarDecl **param_iterator;
|
||||
|
|
@ -1110,7 +1125,7 @@ public:
|
|||
param_const_iterator param_end() const { return ParamInfo+param_size(); }
|
||||
|
||||
/// getNumParams - Return the number of parameters this function must have
|
||||
/// based on its functiontype. This is the length of the PararmInfo array
|
||||
/// based on its FunctionType. This is the length of the ParamInfo array
|
||||
/// after it has been created.
|
||||
unsigned getNumParams() const;
|
||||
|
||||
|
|
@ -1122,7 +1137,7 @@ public:
|
|||
assert(i < getNumParams() && "Illegal param #");
|
||||
return ParamInfo[i];
|
||||
}
|
||||
void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams);
|
||||
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
|
||||
|
||||
/// getMinRequiredArguments - Returns the minimum number of arguments
|
||||
/// needed to call this function. This may be fewer than the number of
|
||||
|
|
@ -1267,8 +1282,7 @@ public:
|
|||
/// be inserted.
|
||||
///
|
||||
/// \param TSK the kind of template specialization this is.
|
||||
void setFunctionTemplateSpecialization(ASTContext &Context,
|
||||
FunctionTemplateDecl *Template,
|
||||
void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
|
||||
const TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos,
|
||||
TemplateSpecializationKind TSK = TSK_ImplicitInstantiation);
|
||||
|
|
@ -1295,10 +1309,11 @@ public:
|
|||
bool isOutOfLine() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FunctionDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= FunctionFirst && K <= FunctionLast;
|
||||
}
|
||||
static DeclContext *castToDeclContext(const FunctionDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D));
|
||||
}
|
||||
|
|
@ -1347,11 +1362,20 @@ public:
|
|||
Expr *getBitWidth() const { return BitWidth; }
|
||||
void setBitWidth(Expr *BW) { BitWidth = BW; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
|
||||
/// getParent - Returns the parent of this field declaration, which
|
||||
/// is the struct in which this method is defined.
|
||||
const RecordDecl *getParent() const {
|
||||
return cast<RecordDecl>(getDeclContext());
|
||||
}
|
||||
|
||||
RecordDecl *getParent() {
|
||||
return cast<RecordDecl>(getDeclContext());
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FieldDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K >= FieldFirst && K <= FieldLast; }
|
||||
};
|
||||
|
||||
/// EnumConstantDecl - An instance of this object exists for each enum constant
|
||||
|
|
@ -1385,8 +1409,9 @@ public:
|
|||
void setInitVal(const llvm::APSInt &V) { Val = V; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == EnumConstant; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const EnumConstantDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == EnumConstant; }
|
||||
|
||||
friend class StmtIteratorBase;
|
||||
};
|
||||
|
|
@ -1418,10 +1443,9 @@ public:
|
|||
void setTypeForDecl(Type *TD) { TypeForDecl = TD; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= TypeFirst && D->getKind() <= TypeLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TypeDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K >= TypeFirst && K <= TypeLast; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1460,8 +1484,9 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == Typedef; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TypedefDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Typedef; }
|
||||
};
|
||||
|
||||
class TypedefDecl;
|
||||
|
|
@ -1486,6 +1511,11 @@ private:
|
|||
/// it is a declaration ("struct foo;").
|
||||
bool IsDefinition : 1;
|
||||
|
||||
/// IsEmbeddedInDeclarator - True if this tag declaration is
|
||||
/// "embedded" (i.e., defined or declared for the very first time)
|
||||
/// in the syntax of a declarator,
|
||||
bool IsEmbeddedInDeclarator : 1;
|
||||
|
||||
/// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef,
|
||||
/// this points to the TypedefDecl. Used for mangling.
|
||||
TypedefDecl *TypedefForAnonDecl;
|
||||
|
|
@ -1502,6 +1532,7 @@ protected:
|
|||
assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum");
|
||||
TagDeclKind = TK;
|
||||
IsDefinition = false;
|
||||
IsEmbeddedInDeclarator = false;
|
||||
setPreviousDeclaration(PrevDecl);
|
||||
}
|
||||
|
||||
|
|
@ -1535,6 +1566,13 @@ public:
|
|||
return IsDefinition;
|
||||
}
|
||||
|
||||
bool isEmbeddedInDeclarator() const {
|
||||
return IsEmbeddedInDeclarator;
|
||||
}
|
||||
void setEmbeddedInDeclarator(bool isInDeclarator) {
|
||||
IsEmbeddedInDeclarator = isInDeclarator;
|
||||
}
|
||||
|
||||
/// \brief Whether this declaration declares a type that is
|
||||
/// dependent, i.e., a type that somehow depends on template
|
||||
/// parameters.
|
||||
|
|
@ -1557,7 +1595,9 @@ public:
|
|||
/// specific TagDecl is defining declaration, not whether or not the
|
||||
/// struct/union/class/enum type is defined. This method returns NULL if
|
||||
/// there is no TagDecl that defines the struct/union/class/enum.
|
||||
TagDecl* getDefinition(ASTContext& C) const;
|
||||
TagDecl* getDefinition() const;
|
||||
|
||||
void setDefinition(bool V) { IsDefinition = V; }
|
||||
|
||||
const char *getKindName() const {
|
||||
return ElaboratedType::getNameForTagKind(getTagKind());
|
||||
|
|
@ -1583,10 +1623,9 @@ public:
|
|||
void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= TagFirst && D->getKind() <= TagLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TagDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K >= TagFirst && K <= TagLast; }
|
||||
|
||||
static DeclContext *castToDeclContext(const TagDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<TagDecl*>(D));
|
||||
|
|
@ -1594,8 +1633,6 @@ public:
|
|||
static TagDecl *castFromDeclContext(const DeclContext *DC) {
|
||||
return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
|
||||
}
|
||||
|
||||
void setDefinition(bool V) { IsDefinition = V; }
|
||||
};
|
||||
|
||||
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
|
||||
|
|
@ -1641,7 +1678,7 @@ public:
|
|||
/// declaration as being defined; it's enumerators have already been
|
||||
/// added (via DeclContext::addDecl). NewType is the new underlying
|
||||
/// type of the enumeration type.
|
||||
void completeDefinition(ASTContext &C, QualType NewType,
|
||||
void completeDefinition(QualType NewType,
|
||||
QualType PromotionType);
|
||||
|
||||
// enumerator_iterator - Iterates through the enumerators of this
|
||||
|
|
@ -1679,8 +1716,9 @@ public:
|
|||
|
||||
void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; }
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == Enum; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const EnumDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Enum; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1763,8 +1801,8 @@ public:
|
|||
/// RecordDecl is defining declaration, not whether or not the record
|
||||
/// type is defined. This method returns NULL if there is no RecordDecl
|
||||
/// that defines the struct/union/tag.
|
||||
RecordDecl* getDefinition(ASTContext& C) const {
|
||||
return cast_or_null<RecordDecl>(TagDecl::getDefinition(C));
|
||||
RecordDecl* getDefinition() const {
|
||||
return cast_or_null<RecordDecl>(TagDecl::getDefinition());
|
||||
}
|
||||
|
||||
// Iterator access to field members. The field iterator only visits
|
||||
|
|
@ -1787,12 +1825,13 @@ public:
|
|||
|
||||
/// completeDefinition - Notes that the definition of this type is
|
||||
/// now complete.
|
||||
void completeDefinition(ASTContext& C);
|
||||
void completeDefinition();
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= RecordFirst && D->getKind() <= RecordLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const RecordDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= RecordFirst && K <= RecordLast;
|
||||
}
|
||||
};
|
||||
|
||||
class FileScopeAsmDecl : public Decl {
|
||||
|
|
@ -1807,10 +1846,9 @@ public:
|
|||
StringLiteral *getAsmString() { return AsmString; }
|
||||
void setAsmString(StringLiteral *Asm) { AsmString = Asm; }
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == FileScopeAsm;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FileScopeAsmDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == FileScopeAsm; }
|
||||
};
|
||||
|
||||
/// BlockDecl - This represents a block literal declaration, which is like an
|
||||
|
|
@ -1869,11 +1907,12 @@ public:
|
|||
assert(i < getNumParams() && "Illegal param #");
|
||||
return ParamInfo[i];
|
||||
}
|
||||
void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams);
|
||||
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == Block; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const BlockDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Block; }
|
||||
static DeclContext *castToDeclContext(const BlockDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<BlockDecl*>(D));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ public:
|
|||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *) { return true; }
|
||||
static bool classofKind(Kind K) { return true; }
|
||||
static DeclContext *castToDeclContext(const Decl *);
|
||||
static Decl *castFromDeclContext(const DeclContext *);
|
||||
|
||||
|
|
@ -1020,17 +1021,43 @@ inline bool Decl::isTemplateParameter() const {
|
|||
getKind() == TemplateTemplateParm;
|
||||
}
|
||||
|
||||
|
||||
// Specialization selected when ToTy is not a known subclass of DeclContext.
|
||||
template <class ToTy,
|
||||
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
|
||||
struct cast_convert_decl_context {
|
||||
static const ToTy *doit(const DeclContext *Val) {
|
||||
return static_cast<const ToTy*>(Decl::castFromDeclContext(Val));
|
||||
}
|
||||
|
||||
static ToTy *doit(DeclContext *Val) {
|
||||
return static_cast<ToTy*>(Decl::castFromDeclContext(Val));
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization selected when ToTy is a known subclass of DeclContext.
|
||||
template <class ToTy>
|
||||
struct cast_convert_decl_context<ToTy, true> {
|
||||
static const ToTy *doit(const DeclContext *Val) {
|
||||
return static_cast<const ToTy*>(Val);
|
||||
}
|
||||
|
||||
static ToTy *doit(DeclContext *Val) {
|
||||
return static_cast<ToTy*>(Val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end clang.
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Implement a isa_impl_wrap specialization to check whether a DeclContext is
|
||||
/// a specific Decl.
|
||||
/// isa<T>(DeclContext*)
|
||||
template<class ToTy>
|
||||
struct isa_impl_wrap<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {
|
||||
static bool doit(const ::clang::DeclContext &Val) {
|
||||
return ToTy::classof(::clang::Decl::castFromDeclContext(&Val));
|
||||
return ToTy::classofKind(Val.getDeclKind());
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
|
|
@ -1038,6 +1065,34 @@ struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
|
|||
: public isa_impl_wrap<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {};
|
||||
|
||||
/// cast<T>(DeclContext*)
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {
|
||||
static const ToTy &doit(const ::clang::DeclContext &Val) {
|
||||
return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext> {
|
||||
static ToTy &doit(::clang::DeclContext &Val) {
|
||||
return *::clang::cast_convert_decl_context<ToTy>::doit(&Val);
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy,
|
||||
const ::clang::DeclContext*, const ::clang::DeclContext*> {
|
||||
static const ToTy *doit(const ::clang::DeclContext *Val) {
|
||||
return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*> {
|
||||
static ToTy *doit(::clang::DeclContext *Val) {
|
||||
return ::clang::cast_convert_decl_context<ToTy>::doit(Val);
|
||||
}
|
||||
};
|
||||
|
||||
/// Implement cast_convert_val for Decl -> DeclContext conversions.
|
||||
template<class FromTy>
|
||||
struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> {
|
||||
|
|
@ -1067,31 +1122,6 @@ struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Implement cast_convert_val for DeclContext -> Decl conversions.
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {
|
||||
static ToTy &doit(const ::clang::DeclContext &Val) {
|
||||
return *reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(&Val));
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext>
|
||||
: public cast_convert_val<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {};
|
||||
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy,
|
||||
const ::clang::DeclContext*, const ::clang::DeclContext*> {
|
||||
static ToTy *doit(const ::clang::DeclContext *Val) {
|
||||
return reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(Val));
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*>
|
||||
: public cast_convert_val<ToTy,
|
||||
const ::clang::DeclContext*,const ::clang::DeclContext*> {};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@ public:
|
|||
/// class (or not).
|
||||
bool isVirtual() const { return Virtual; }
|
||||
|
||||
/// \brief Determine whether this base class if a base of a class declared
|
||||
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
|
||||
bool isBaseOfClass() const { return BaseOfClass; }
|
||||
|
||||
/// getAccessSpecifier - Returns the access specifier for this base
|
||||
/// specifier. This is the actual base specifier as used for
|
||||
/// semantic analysis, so the result can never be AS_none. To
|
||||
|
|
@ -174,115 +178,137 @@ public:
|
|||
/// FIXME: This class will disappear once we've properly taught RecordDecl
|
||||
/// to deal with C++-specific things.
|
||||
class CXXRecordDecl : public RecordDecl {
|
||||
/// UserDeclaredConstructor - True when this class has a
|
||||
/// user-declared constructor.
|
||||
bool UserDeclaredConstructor : 1;
|
||||
|
||||
/// UserDeclaredCopyConstructor - True when this class has a
|
||||
/// user-declared copy constructor.
|
||||
bool UserDeclaredCopyConstructor : 1;
|
||||
friend void TagDecl::startDefinition();
|
||||
|
||||
/// UserDeclaredCopyAssignment - True when this class has a
|
||||
/// user-declared copy assignment operator.
|
||||
bool UserDeclaredCopyAssignment : 1;
|
||||
struct DefinitionData {
|
||||
DefinitionData(CXXRecordDecl *D);
|
||||
|
||||
/// UserDeclaredDestructor - True when this class has a
|
||||
/// user-declared destructor.
|
||||
bool UserDeclaredDestructor : 1;
|
||||
/// UserDeclaredConstructor - True when this class has a
|
||||
/// user-declared constructor.
|
||||
bool UserDeclaredConstructor : 1;
|
||||
|
||||
/// Aggregate - True when this class is an aggregate.
|
||||
bool Aggregate : 1;
|
||||
/// UserDeclaredCopyConstructor - True when this class has a
|
||||
/// user-declared copy constructor.
|
||||
bool UserDeclaredCopyConstructor : 1;
|
||||
|
||||
/// PlainOldData - True when this class is a POD-type.
|
||||
bool PlainOldData : 1;
|
||||
/// UserDeclaredCopyAssignment - True when this class has a
|
||||
/// user-declared copy assignment operator.
|
||||
bool UserDeclaredCopyAssignment : 1;
|
||||
|
||||
/// Empty - true when this class is empty for traits purposes, i.e. has no
|
||||
/// data members other than 0-width bit-fields, has no virtual function/base,
|
||||
/// and doesn't inherit from a non-empty class. Doesn't take union-ness into
|
||||
/// account.
|
||||
bool Empty : 1;
|
||||
/// UserDeclaredDestructor - True when this class has a
|
||||
/// user-declared destructor.
|
||||
bool UserDeclaredDestructor : 1;
|
||||
|
||||
/// Polymorphic - True when this class is polymorphic, i.e. has at least one
|
||||
/// virtual member or derives from a polymorphic class.
|
||||
bool Polymorphic : 1;
|
||||
/// Aggregate - True when this class is an aggregate.
|
||||
bool Aggregate : 1;
|
||||
|
||||
/// Abstract - True when this class is abstract, i.e. has at least one
|
||||
/// pure virtual function, (that can come from a base class).
|
||||
bool Abstract : 1;
|
||||
/// PlainOldData - True when this class is a POD-type.
|
||||
bool PlainOldData : 1;
|
||||
|
||||
/// HasTrivialConstructor - True when this class has a trivial constructor.
|
||||
///
|
||||
/// C++ [class.ctor]p5. A constructor is trivial if it is an
|
||||
/// implicitly-declared default constructor and if:
|
||||
/// * its class has no virtual functions and no virtual base classes, and
|
||||
/// * all the direct base classes of its class have trivial constructors, and
|
||||
/// * for all the nonstatic data members of its class that are of class type
|
||||
/// (or array thereof), each such class has a trivial constructor.
|
||||
bool HasTrivialConstructor : 1;
|
||||
/// Empty - true when this class is empty for traits purposes,
|
||||
/// i.e. has no data members other than 0-width bit-fields, has no
|
||||
/// virtual function/base, and doesn't inherit from a non-empty
|
||||
/// class. Doesn't take union-ness into account.
|
||||
bool Empty : 1;
|
||||
|
||||
/// HasTrivialCopyConstructor - True when this class has a trivial copy
|
||||
/// constructor.
|
||||
///
|
||||
/// C++ [class.copy]p6. A copy constructor for class X is trivial
|
||||
/// if it is implicitly declared and if
|
||||
/// * class X has no virtual functions and no virtual base classes, and
|
||||
/// * each direct base class of X has a trivial copy constructor, and
|
||||
/// * for all the nonstatic data members of X that are of class type (or
|
||||
/// array thereof), each such class type has a trivial copy constructor;
|
||||
/// otherwise the copy constructor is non-trivial.
|
||||
bool HasTrivialCopyConstructor : 1;
|
||||
/// Polymorphic - True when this class is polymorphic, i.e. has at
|
||||
/// least one virtual member or derives from a polymorphic class.
|
||||
bool Polymorphic : 1;
|
||||
|
||||
/// HasTrivialCopyAssignment - True when this class has a trivial copy
|
||||
/// assignment operator.
|
||||
///
|
||||
/// C++ [class.copy]p11. A copy assignment operator for class X is
|
||||
/// trivial if it is implicitly declared and if
|
||||
/// * class X has no virtual functions and no virtual base classes, and
|
||||
/// * each direct base class of X has a trivial copy assignment operator, and
|
||||
/// * for all the nonstatic data members of X that are of class type (or
|
||||
/// array thereof), each such class type has a trivial copy assignment
|
||||
/// operator;
|
||||
/// otherwise the copy assignment operator is non-trivial.
|
||||
bool HasTrivialCopyAssignment : 1;
|
||||
/// Abstract - True when this class is abstract, i.e. has at least
|
||||
/// one pure virtual function, (that can come from a base class).
|
||||
bool Abstract : 1;
|
||||
|
||||
/// HasTrivialDestructor - True when this class has a trivial destructor.
|
||||
///
|
||||
/// C++ [class.dtor]p3. A destructor is trivial if it is an
|
||||
/// implicitly-declared destructor and if:
|
||||
/// * all of the direct base classes of its class have trivial destructors
|
||||
/// and
|
||||
/// * for all of the non-static data members of its class that are of class
|
||||
/// type (or array thereof), each such class has a trivial destructor.
|
||||
bool HasTrivialDestructor : 1;
|
||||
/// HasTrivialConstructor - True when this class has a trivial constructor.
|
||||
///
|
||||
/// C++ [class.ctor]p5. A constructor is trivial if it is an
|
||||
/// implicitly-declared default constructor and if:
|
||||
/// * its class has no virtual functions and no virtual base classes, and
|
||||
/// * all the direct base classes of its class have trivial constructors, and
|
||||
/// * for all the nonstatic data members of its class that are of class type
|
||||
/// (or array thereof), each such class has a trivial constructor.
|
||||
bool HasTrivialConstructor : 1;
|
||||
|
||||
/// ComputedVisibleConversions - True when visible conversion functions are
|
||||
/// already computed and are available.
|
||||
bool ComputedVisibleConversions : 1;
|
||||
/// HasTrivialCopyConstructor - True when this class has a trivial copy
|
||||
/// constructor.
|
||||
///
|
||||
/// C++ [class.copy]p6. A copy constructor for class X is trivial
|
||||
/// if it is implicitly declared and if
|
||||
/// * class X has no virtual functions and no virtual base classes, and
|
||||
/// * each direct base class of X has a trivial copy constructor, and
|
||||
/// * for all the nonstatic data members of X that are of class type (or
|
||||
/// array thereof), each such class type has a trivial copy constructor;
|
||||
/// otherwise the copy constructor is non-trivial.
|
||||
bool HasTrivialCopyConstructor : 1;
|
||||
|
||||
/// HasTrivialCopyAssignment - True when this class has a trivial copy
|
||||
/// assignment operator.
|
||||
///
|
||||
/// C++ [class.copy]p11. A copy assignment operator for class X is
|
||||
/// trivial if it is implicitly declared and if
|
||||
/// * class X has no virtual functions and no virtual base classes, and
|
||||
/// * each direct base class of X has a trivial copy assignment operator, and
|
||||
/// * for all the nonstatic data members of X that are of class type (or
|
||||
/// array thereof), each such class type has a trivial copy assignment
|
||||
/// operator;
|
||||
/// otherwise the copy assignment operator is non-trivial.
|
||||
bool HasTrivialCopyAssignment : 1;
|
||||
|
||||
/// HasTrivialDestructor - True when this class has a trivial destructor.
|
||||
///
|
||||
/// C++ [class.dtor]p3. A destructor is trivial if it is an
|
||||
/// implicitly-declared destructor and if:
|
||||
/// * all of the direct base classes of its class have trivial destructors
|
||||
/// and
|
||||
/// * for all of the non-static data members of its class that are of class
|
||||
/// type (or array thereof), each such class has a trivial destructor.
|
||||
bool HasTrivialDestructor : 1;
|
||||
|
||||
/// ComputedVisibleConversions - True when visible conversion functions are
|
||||
/// already computed and are available.
|
||||
bool ComputedVisibleConversions : 1;
|
||||
|
||||
/// Bases - Base classes of this class.
|
||||
/// FIXME: This is wasted space for a union.
|
||||
CXXBaseSpecifier *Bases;
|
||||
/// Bases - Base classes of this class.
|
||||
/// FIXME: This is wasted space for a union.
|
||||
CXXBaseSpecifier *Bases;
|
||||
|
||||
/// NumBases - The number of base class specifiers in Bases.
|
||||
unsigned NumBases;
|
||||
/// NumBases - The number of base class specifiers in Bases.
|
||||
unsigned NumBases;
|
||||
|
||||
/// VBases - direct and indirect virtual base classes of this class.
|
||||
CXXBaseSpecifier *VBases;
|
||||
/// VBases - direct and indirect virtual base classes of this class.
|
||||
CXXBaseSpecifier *VBases;
|
||||
|
||||
/// NumVBases - The number of virtual base class specifiers in VBases.
|
||||
unsigned NumVBases;
|
||||
/// NumVBases - The number of virtual base class specifiers in VBases.
|
||||
unsigned NumVBases;
|
||||
|
||||
/// Conversions - Overload set containing the conversion functions
|
||||
/// of this C++ class (but not its inherited conversion
|
||||
/// functions). Each of the entries in this overload set is a
|
||||
/// CXXConversionDecl.
|
||||
UnresolvedSet<4> Conversions;
|
||||
/// Conversions - Overload set containing the conversion functions
|
||||
/// of this C++ class (but not its inherited conversion
|
||||
/// functions). Each of the entries in this overload set is a
|
||||
/// CXXConversionDecl.
|
||||
UnresolvedSet<4> Conversions;
|
||||
|
||||
/// VisibleConversions - Overload set containing the conversion functions
|
||||
/// of this C++ class and all those inherited conversion functions that
|
||||
/// are visible in this class. Each of the entries in this overload set is
|
||||
/// a CXXConversionDecl or a FunctionTemplateDecl.
|
||||
UnresolvedSet<4> VisibleConversions;
|
||||
/// VisibleConversions - Overload set containing the conversion
|
||||
/// functions of this C++ class and all those inherited conversion
|
||||
/// functions that are visible in this class. Each of the entries
|
||||
/// in this overload set is a CXXConversionDecl or a
|
||||
/// FunctionTemplateDecl.
|
||||
UnresolvedSet<4> VisibleConversions;
|
||||
|
||||
/// Definition - The declaration which defines this record.
|
||||
CXXRecordDecl *Definition;
|
||||
|
||||
} *DefinitionData;
|
||||
|
||||
struct DefinitionData &data() {
|
||||
assert(DefinitionData && "queried property of class with no definition");
|
||||
return *DefinitionData;
|
||||
}
|
||||
|
||||
const struct DefinitionData &data() const {
|
||||
assert(DefinitionData && "queried property of class with no definition");
|
||||
return *DefinitionData;
|
||||
}
|
||||
|
||||
/// \brief The template or declaration that this declaration
|
||||
/// describes or was instantiated from, respectively.
|
||||
|
|
@ -336,6 +362,13 @@ public:
|
|||
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
|
||||
}
|
||||
|
||||
CXXRecordDecl *getDefinition() const {
|
||||
if (!DefinitionData) return 0;
|
||||
return data().Definition;
|
||||
}
|
||||
|
||||
bool hasDefinition() const { return DefinitionData != 0; }
|
||||
|
||||
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
SourceLocation TKL = SourceLocation(),
|
||||
|
|
@ -345,21 +378,22 @@ public:
|
|||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
bool isDynamicClass() const {
|
||||
return Polymorphic || NumVBases != 0;
|
||||
return data().Polymorphic || data().NumVBases != 0;
|
||||
}
|
||||
|
||||
/// setBases - Sets the base classes of this struct or class.
|
||||
void setBases(ASTContext &C,
|
||||
CXXBaseSpecifier const * const *Bases, unsigned NumBases);
|
||||
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
|
||||
|
||||
/// getNumBases - Retrieves the number of base classes of this
|
||||
/// class.
|
||||
unsigned getNumBases() const { return NumBases; }
|
||||
unsigned getNumBases() const { return data().NumBases; }
|
||||
|
||||
base_class_iterator bases_begin() { return Bases; }
|
||||
base_class_const_iterator bases_begin() const { return Bases; }
|
||||
base_class_iterator bases_end() { return Bases + NumBases; }
|
||||
base_class_const_iterator bases_end() const { return Bases + NumBases; }
|
||||
base_class_iterator bases_begin() { return data().Bases; }
|
||||
base_class_const_iterator bases_begin() const { return data().Bases; }
|
||||
base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
|
||||
base_class_const_iterator bases_end() const {
|
||||
return bases_begin() + data().NumBases;
|
||||
}
|
||||
reverse_base_class_iterator bases_rbegin() {
|
||||
return reverse_base_class_iterator(bases_end());
|
||||
}
|
||||
|
|
@ -375,12 +409,14 @@ public:
|
|||
|
||||
/// getNumVBases - Retrieves the number of virtual base classes of this
|
||||
/// class.
|
||||
unsigned getNumVBases() const { return NumVBases; }
|
||||
unsigned getNumVBases() const { return data().NumVBases; }
|
||||
|
||||
base_class_iterator vbases_begin() { return VBases; }
|
||||
base_class_const_iterator vbases_begin() const { return VBases; }
|
||||
base_class_iterator vbases_end() { return VBases + NumVBases; }
|
||||
base_class_const_iterator vbases_end() const { return VBases + NumVBases; }
|
||||
base_class_iterator vbases_begin() { return data().VBases; }
|
||||
base_class_const_iterator vbases_begin() const { return data().VBases; }
|
||||
base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
|
||||
base_class_const_iterator vbases_end() const {
|
||||
return vbases_begin() + data().NumVBases;
|
||||
}
|
||||
reverse_base_class_iterator vbases_rbegin() {
|
||||
return reverse_base_class_iterator(vbases_end());
|
||||
}
|
||||
|
|
@ -445,17 +481,14 @@ public:
|
|||
/// user-declared constructors. When true, a default constructor
|
||||
/// will not be implicitly declared.
|
||||
bool hasUserDeclaredConstructor() const {
|
||||
assert((isDefinition() ||
|
||||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
|
||||
"Incomplete record decl!");
|
||||
return UserDeclaredConstructor;
|
||||
return data().UserDeclaredConstructor;
|
||||
}
|
||||
|
||||
/// hasUserDeclaredCopyConstructor - Whether this class has a
|
||||
/// user-declared copy constructor. When false, a copy constructor
|
||||
/// will be implicitly declared.
|
||||
bool hasUserDeclaredCopyConstructor() const {
|
||||
return UserDeclaredCopyConstructor;
|
||||
return data().UserDeclaredCopyConstructor;
|
||||
}
|
||||
|
||||
/// addedAssignmentOperator - Notify the class that another assignment
|
||||
|
|
@ -467,45 +500,45 @@ public:
|
|||
/// user-declared copy assignment operator. When false, a copy
|
||||
/// assigment operator will be implicitly declared.
|
||||
bool hasUserDeclaredCopyAssignment() const {
|
||||
return UserDeclaredCopyAssignment;
|
||||
return data().UserDeclaredCopyAssignment;
|
||||
}
|
||||
|
||||
/// hasUserDeclaredDestructor - Whether this class has a
|
||||
/// user-declared destructor. When false, a destructor will be
|
||||
/// implicitly declared.
|
||||
bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; }
|
||||
bool hasUserDeclaredDestructor() const {
|
||||
return data().UserDeclaredDestructor;
|
||||
}
|
||||
|
||||
/// setUserDeclaredDestructor - Set whether this class has a
|
||||
/// user-declared destructor. If not set by the time the class is
|
||||
/// fully defined, a destructor will be implicitly declared.
|
||||
void setUserDeclaredDestructor(bool UCD) {
|
||||
UserDeclaredDestructor = UCD;
|
||||
data().UserDeclaredDestructor = UCD;
|
||||
}
|
||||
|
||||
/// getConversions - Retrieve the overload set containing all of the
|
||||
/// conversion functions in this class.
|
||||
UnresolvedSetImpl *getConversionFunctions() {
|
||||
assert((this->isDefinition() ||
|
||||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
|
||||
"getConversionFunctions() called on incomplete type");
|
||||
return &Conversions;
|
||||
return &data().Conversions;
|
||||
}
|
||||
const UnresolvedSetImpl *getConversionFunctions() const {
|
||||
assert((this->isDefinition() ||
|
||||
cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
|
||||
"getConversionFunctions() called on incomplete type");
|
||||
return &Conversions;
|
||||
return &data().Conversions;
|
||||
}
|
||||
|
||||
typedef UnresolvedSetImpl::iterator conversion_iterator;
|
||||
conversion_iterator conversion_begin() const { return Conversions.begin(); }
|
||||
conversion_iterator conversion_end() const { return Conversions.end(); }
|
||||
conversion_iterator conversion_begin() const {
|
||||
return getConversionFunctions()->begin();
|
||||
}
|
||||
conversion_iterator conversion_end() const {
|
||||
return getConversionFunctions()->end();
|
||||
}
|
||||
|
||||
/// Replaces a conversion function with a new declaration.
|
||||
///
|
||||
/// Returns true if the old conversion was found.
|
||||
bool replaceConversion(const NamedDecl* Old, NamedDecl *New) {
|
||||
return Conversions.replace(Old, New);
|
||||
return getConversionFunctions()->replace(Old, New);
|
||||
}
|
||||
|
||||
/// getVisibleConversionFunctions - get all conversion functions visible
|
||||
|
|
@ -532,11 +565,11 @@ public:
|
|||
/// [dcl.init.aggr]), which is a class with no user-declared
|
||||
/// constructors, no private or protected non-static data members,
|
||||
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
|
||||
bool isAggregate() const { return Aggregate; }
|
||||
bool isAggregate() const { return data().Aggregate; }
|
||||
|
||||
/// setAggregate - Set whether this class is an aggregate (C++
|
||||
/// [dcl.init.aggr]).
|
||||
void setAggregate(bool Agg) { Aggregate = Agg; }
|
||||
void setAggregate(bool Agg) { data().Aggregate = Agg; }
|
||||
|
||||
/// setMethodAsVirtual - Make input method virtual and set the necesssary
|
||||
/// special function bits and other bits accordingly.
|
||||
|
|
@ -546,66 +579,74 @@ public:
|
|||
/// that is an aggregate that has no non-static non-POD data members, no
|
||||
/// reference data members, no user-defined copy assignment operator and no
|
||||
/// user-defined destructor.
|
||||
bool isPOD() const { return PlainOldData; }
|
||||
bool isPOD() const { return data().PlainOldData; }
|
||||
|
||||
/// setPOD - Set whether this class is a POD-type (C++ [class]p4).
|
||||
void setPOD(bool POD) { PlainOldData = POD; }
|
||||
void setPOD(bool POD) { data().PlainOldData = POD; }
|
||||
|
||||
/// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
|
||||
/// means it has a virtual function, virtual base, data member (other than
|
||||
/// 0-width bit-field) or inherits from a non-empty class. Does NOT include
|
||||
/// a check for union-ness.
|
||||
bool isEmpty() const { return Empty; }
|
||||
bool isEmpty() const { return data().Empty; }
|
||||
|
||||
/// Set whether this class is empty (C++0x [meta.unary.prop])
|
||||
void setEmpty(bool Emp) { Empty = Emp; }
|
||||
void setEmpty(bool Emp) { data().Empty = Emp; }
|
||||
|
||||
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
|
||||
/// which means that the class contains or inherits a virtual function.
|
||||
bool isPolymorphic() const { return Polymorphic; }
|
||||
bool isPolymorphic() const { return data().Polymorphic; }
|
||||
|
||||
/// setPolymorphic - Set whether this class is polymorphic (C++
|
||||
/// [class.virtual]).
|
||||
void setPolymorphic(bool Poly) { Polymorphic = Poly; }
|
||||
void setPolymorphic(bool Poly) { data().Polymorphic = Poly; }
|
||||
|
||||
/// isAbstract - Whether this class is abstract (C++ [class.abstract]),
|
||||
/// which means that the class contains or inherits a pure virtual function.
|
||||
bool isAbstract() const { return Abstract; }
|
||||
bool isAbstract() const { return data().Abstract; }
|
||||
|
||||
/// setAbstract - Set whether this class is abstract (C++ [class.abstract])
|
||||
void setAbstract(bool Abs) { Abstract = Abs; }
|
||||
void setAbstract(bool Abs) { data().Abstract = Abs; }
|
||||
|
||||
// hasTrivialConstructor - Whether this class has a trivial constructor
|
||||
// (C++ [class.ctor]p5)
|
||||
bool hasTrivialConstructor() const { return HasTrivialConstructor; }
|
||||
bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
|
||||
|
||||
// setHasTrivialConstructor - Set whether this class has a trivial constructor
|
||||
// (C++ [class.ctor]p5)
|
||||
void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; }
|
||||
void setHasTrivialConstructor(bool TC) { data().HasTrivialConstructor = TC; }
|
||||
|
||||
// hasTrivialCopyConstructor - Whether this class has a trivial copy
|
||||
// constructor (C++ [class.copy]p6)
|
||||
bool hasTrivialCopyConstructor() const { return HasTrivialCopyConstructor; }
|
||||
bool hasTrivialCopyConstructor() const {
|
||||
return data().HasTrivialCopyConstructor;
|
||||
}
|
||||
|
||||
// setHasTrivialCopyConstructor - Set whether this class has a trivial
|
||||
// copy constructor (C++ [class.copy]p6)
|
||||
void setHasTrivialCopyConstructor(bool TC) { HasTrivialCopyConstructor = TC; }
|
||||
void setHasTrivialCopyConstructor(bool TC) {
|
||||
data().HasTrivialCopyConstructor = TC;
|
||||
}
|
||||
|
||||
// hasTrivialCopyAssignment - Whether this class has a trivial copy
|
||||
// assignment operator (C++ [class.copy]p11)
|
||||
bool hasTrivialCopyAssignment() const { return HasTrivialCopyAssignment; }
|
||||
bool hasTrivialCopyAssignment() const {
|
||||
return data().HasTrivialCopyAssignment;
|
||||
}
|
||||
|
||||
// setHasTrivialCopyAssignment - Set whether this class has a
|
||||
// trivial copy assignment operator (C++ [class.copy]p11)
|
||||
void setHasTrivialCopyAssignment(bool TC) { HasTrivialCopyAssignment = TC; }
|
||||
void setHasTrivialCopyAssignment(bool TC) {
|
||||
data().HasTrivialCopyAssignment = TC;
|
||||
}
|
||||
|
||||
// hasTrivialDestructor - Whether this class has a trivial destructor
|
||||
// (C++ [class.dtor]p3)
|
||||
bool hasTrivialDestructor() const { return HasTrivialDestructor; }
|
||||
bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
|
||||
|
||||
// setHasTrivialDestructor - Set whether this class has a trivial destructor
|
||||
// (C++ [class.dtor]p3)
|
||||
void setHasTrivialDestructor(bool TC) { HasTrivialDestructor = TC; }
|
||||
void setHasTrivialDestructor(bool TC) { data().HasTrivialDestructor = TC; }
|
||||
|
||||
/// \brief If this record is an instantiation of a member class,
|
||||
/// retrieves the member class from which it was instantiated.
|
||||
|
|
@ -826,10 +867,11 @@ public:
|
|||
return (PathAccess > DeclAccess ? PathAccess : DeclAccess);
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == CXXRecord ||
|
||||
D->getKind() == ClassTemplateSpecialization ||
|
||||
D->getKind() == ClassTemplatePartialSpecialization;
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) {
|
||||
return K == CXXRecord ||
|
||||
K == ClassTemplateSpecialization ||
|
||||
K == ClassTemplatePartialSpecialization;
|
||||
}
|
||||
static bool classof(const CXXRecordDecl *D) { return true; }
|
||||
static bool classof(const ClassTemplateSpecializationDecl *D) {
|
||||
|
|
@ -911,10 +953,11 @@ public:
|
|||
bool hasInlineBody() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const CXXMethodDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= CXXMethod && K <= CXXConversion;
|
||||
}
|
||||
};
|
||||
|
||||
/// CXXBaseOrMemberInitializer - Represents a C++ base or member
|
||||
|
|
@ -939,9 +982,9 @@ class CXXBaseOrMemberInitializer {
|
|||
/// \brief The source location for the field name.
|
||||
SourceLocation MemberLocation;
|
||||
|
||||
/// Args - The arguments used to initialize the base or member.
|
||||
Stmt **Args;
|
||||
unsigned NumArgs;
|
||||
/// \brief The argument used to initialize the base or member, which may
|
||||
/// end up constructing an object (when multiple arguments are involved).
|
||||
Stmt *Init;
|
||||
|
||||
/// \brief Stores either the constructor to call to initialize this base or
|
||||
/// member (a CXXConstructorDecl pointer), or stores the anonymous union of
|
||||
|
|
@ -961,7 +1004,7 @@ class CXXBaseOrMemberInitializer {
|
|||
/// @endcode
|
||||
/// In above example, BaseOrMember holds the field decl. for anonymous union
|
||||
/// and AnonUnionMember holds field decl for au_i1.
|
||||
llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion;
|
||||
FieldDecl *AnonUnionMember;
|
||||
|
||||
/// LParenLoc - Location of the left paren of the ctor-initializer.
|
||||
SourceLocation LParenLoc;
|
||||
|
|
@ -973,30 +1016,22 @@ public:
|
|||
/// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(ASTContext &Context,
|
||||
TypeSourceInfo *TInfo, CXXConstructorDecl *C,
|
||||
TypeSourceInfo *TInfo,
|
||||
SourceLocation L,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
Expr *Init,
|
||||
SourceLocation R);
|
||||
|
||||
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
|
||||
explicit
|
||||
CXXBaseOrMemberInitializer(ASTContext &Context,
|
||||
FieldDecl *Member, SourceLocation MemberLoc,
|
||||
CXXConstructorDecl *C, SourceLocation L,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation L,
|
||||
Expr *Init,
|
||||
SourceLocation R);
|
||||
|
||||
/// \brief Destroy the base or member initializer.
|
||||
void Destroy(ASTContext &Context);
|
||||
|
||||
/// arg_iterator - Iterates through the member initialization
|
||||
/// arguments.
|
||||
typedef ExprIterator arg_iterator;
|
||||
|
||||
/// arg_const_iterator - Iterates through the member initialization
|
||||
/// arguments.
|
||||
typedef ConstExprIterator const_arg_iterator;
|
||||
|
||||
/// isBaseInitializer - Returns true when this initializer is
|
||||
/// initializing a base class.
|
||||
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
|
||||
|
|
@ -1046,32 +1081,16 @@ public:
|
|||
SourceRange getSourceRange() const;
|
||||
|
||||
FieldDecl *getAnonUnionMember() const {
|
||||
return CtorOrAnonUnion.dyn_cast<FieldDecl *>();
|
||||
return AnonUnionMember;
|
||||
}
|
||||
void setAnonUnionMember(FieldDecl *anonMember) {
|
||||
CtorOrAnonUnion = anonMember;
|
||||
}
|
||||
|
||||
const CXXConstructorDecl *getConstructor() const {
|
||||
return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>();
|
||||
AnonUnionMember = anonMember;
|
||||
}
|
||||
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
SourceLocation getRParenLoc() const { return RParenLoc; }
|
||||
|
||||
/// arg_begin() - Retrieve an iterator to the first initializer argument.
|
||||
arg_iterator arg_begin() { return Args; }
|
||||
/// arg_begin() - Retrieve an iterator to the first initializer argument.
|
||||
const_arg_iterator const_arg_begin() const { return Args; }
|
||||
|
||||
/// arg_end() - Retrieve an iterator past the last initializer argument.
|
||||
arg_iterator arg_end() { return Args + NumArgs; }
|
||||
/// arg_end() - Retrieve an iterator past the last initializer argument.
|
||||
const_arg_iterator const_arg_end() const { return Args + NumArgs; }
|
||||
|
||||
/// getNumArgs - Determine the number of arguments used to
|
||||
/// initialize the member or base.
|
||||
unsigned getNumArgs() const { return NumArgs; }
|
||||
Expr *getInit() { return static_cast<Expr *>(Init); }
|
||||
};
|
||||
|
||||
/// CXXConstructorDecl - Represents a C++ constructor within a
|
||||
|
|
@ -1084,8 +1103,9 @@ public:
|
|||
/// };
|
||||
/// @endcode
|
||||
class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// Explicit - Whether this constructor is explicit.
|
||||
bool Explicit : 1;
|
||||
/// IsExplicitSpecified - Whether this constructor declaration has the
|
||||
/// 'explicit' keyword specified.
|
||||
bool IsExplicitSpecified : 1;
|
||||
|
||||
/// ImplicitlyDefined - Whether this constructor was implicitly
|
||||
/// defined by the compiler. When false, the constructor was defined
|
||||
|
|
@ -1103,9 +1123,10 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
|||
|
||||
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
|
||||
bool isExplicitSpecified, bool isInline,
|
||||
bool isImplicitlyDeclared)
|
||||
: CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline),
|
||||
Explicit(isExplicit), ImplicitlyDefined(false),
|
||||
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
|
||||
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
|
||||
setImplicit(isImplicitlyDeclared);
|
||||
}
|
||||
|
|
@ -1118,8 +1139,15 @@ public:
|
|||
bool isExplicit,
|
||||
bool isInline, bool isImplicitlyDeclared);
|
||||
|
||||
/// isExplicitSpecified - Whether this constructor declaration has the
|
||||
/// 'explicit' keyword specified.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// isExplicit - Whether this constructor was marked "explicit" or not.
|
||||
bool isExplicit() const { return Explicit; }
|
||||
bool isExplicit() const {
|
||||
return cast<CXXConstructorDecl>(getFirstDeclaration())
|
||||
->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// isImplicitlyDefined - Whether this constructor was implicitly
|
||||
/// defined. If false, then this constructor was defined by the
|
||||
|
|
@ -1212,10 +1240,9 @@ public:
|
|||
bool isCopyConstructorLikeSpecialization() const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == CXXConstructor;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const CXXConstructorDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == CXXConstructor; }
|
||||
};
|
||||
|
||||
/// CXXDestructorDecl - Represents a C++ destructor within a
|
||||
|
|
@ -1274,10 +1301,9 @@ public:
|
|||
const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == CXXDestructor;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const CXXDestructorDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == CXXDestructor; }
|
||||
};
|
||||
|
||||
/// CXXConversionDecl - Represents a C++ conversion function within a
|
||||
|
|
@ -1290,16 +1316,16 @@ public:
|
|||
/// };
|
||||
/// @endcode
|
||||
class CXXConversionDecl : public CXXMethodDecl {
|
||||
/// Explicit - Whether this conversion function is marked
|
||||
/// "explicit", meaning that it can only be applied when the user
|
||||
/// IsExplicitSpecified - Whether this conversion function declaration is
|
||||
/// marked "explicit", meaning that it can only be applied when the user
|
||||
/// explicitly wrote a cast. This is a C++0x feature.
|
||||
bool Explicit : 1;
|
||||
bool IsExplicitSpecified : 1;
|
||||
|
||||
CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
|
||||
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isExplicit)
|
||||
bool isInline, bool isExplicitSpecified)
|
||||
: CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline),
|
||||
Explicit(isExplicit) { }
|
||||
IsExplicitSpecified(isExplicitSpecified) { }
|
||||
|
||||
public:
|
||||
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
|
|
@ -1307,10 +1333,18 @@ public:
|
|||
QualType T, TypeSourceInfo *TInfo,
|
||||
bool isInline, bool isExplicit);
|
||||
|
||||
/// IsExplicitSpecified - Whether this conversion function declaration is
|
||||
/// marked "explicit", meaning that it can only be applied when the user
|
||||
/// explicitly wrote a cast. This is a C++0x feature.
|
||||
bool isExplicitSpecified() const { return IsExplicitSpecified; }
|
||||
|
||||
/// isExplicit - Whether this is an explicit conversion operator
|
||||
/// (C++0x only). Explicit conversion operators are only considered
|
||||
/// when the user has explicitly written a cast.
|
||||
bool isExplicit() const { return Explicit; }
|
||||
bool isExplicit() const {
|
||||
return cast<CXXConversionDecl>(getFirstDeclaration())
|
||||
->isExplicitSpecified();
|
||||
}
|
||||
|
||||
/// getConversionType - Returns the type that this conversion
|
||||
/// function is converting to.
|
||||
|
|
@ -1319,10 +1353,9 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == CXXConversion;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const CXXConversionDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == CXXConversion; }
|
||||
};
|
||||
|
||||
/// FriendDecl - Represents the declaration of a friend entity,
|
||||
|
|
@ -1391,10 +1424,9 @@ public:
|
|||
void setSpecialization(bool WS) { WasSpecialization = WS; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::Friend;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FriendDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::Friend; }
|
||||
};
|
||||
|
||||
/// LinkageSpecDecl - This represents a linkage specification. For example:
|
||||
|
|
@ -1432,10 +1464,9 @@ public:
|
|||
/// braces in its syntactic form.
|
||||
bool hasBraces() const { return HadBraces; }
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == LinkageSpec;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const LinkageSpecDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == LinkageSpec; }
|
||||
static DeclContext *castToDeclContext(const LinkageSpecDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<LinkageSpecDecl*>(D));
|
||||
}
|
||||
|
|
@ -1537,10 +1568,9 @@ public:
|
|||
NamedDecl *Nominated,
|
||||
DeclContext *CommonAncestor);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UsingDirective;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const UsingDirectiveDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::UsingDirective; }
|
||||
|
||||
// Friend for getUsingDirectiveName.
|
||||
friend class DeclContext;
|
||||
|
|
@ -1598,6 +1628,16 @@ public:
|
|||
return const_cast<NamespaceAliasDecl*>(this)->getNamespace();
|
||||
}
|
||||
|
||||
/// Returns the location of the alias name, i.e. 'foo' in
|
||||
/// "namespace foo = ns::bar;".
|
||||
SourceLocation getAliasLoc() const { return AliasLoc; }
|
||||
|
||||
/// Returns the location of the 'namespace' keyword.
|
||||
SourceLocation getNamespaceLoc() const { return getLocation(); }
|
||||
|
||||
/// Returns the location of the identifier in the named namespace.
|
||||
SourceLocation getTargetNameLoc() const { return IdentLoc; }
|
||||
|
||||
/// \brief Retrieve the namespace that this alias refers to, which
|
||||
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
|
||||
NamedDecl *getAliasedNamespace() const { return Namespace; }
|
||||
|
|
@ -1610,10 +1650,9 @@ public:
|
|||
SourceLocation IdentLoc,
|
||||
NamedDecl *Namespace);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::NamespaceAlias;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const NamespaceAliasDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::NamespaceAlias; }
|
||||
};
|
||||
|
||||
/// UsingShadowDecl - Represents a shadow declaration introduced into
|
||||
|
|
@ -1660,10 +1699,9 @@ public:
|
|||
return Using;
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UsingShadow;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const UsingShadowDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
|
||||
};
|
||||
|
||||
/// UsingDecl - Represents a C++ using-declaration. For example:
|
||||
|
|
@ -1732,10 +1770,9 @@ public:
|
|||
SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
|
||||
NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::Using;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const UsingDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::Using; }
|
||||
};
|
||||
|
||||
/// UnresolvedUsingValueDecl - Represents a dependent using
|
||||
|
|
@ -1784,10 +1821,9 @@ public:
|
|||
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
|
||||
SourceLocation TargetNameLoc, DeclarationName TargetName);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UnresolvedUsingValue;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingValue; }
|
||||
};
|
||||
|
||||
/// UnresolvedUsingTypenameDecl - Represents a dependent using
|
||||
|
|
@ -1843,10 +1879,9 @@ public:
|
|||
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
|
||||
SourceLocation TargetNameLoc, DeclarationName TargetName);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::UnresolvedUsingTypename;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingTypename; }
|
||||
};
|
||||
|
||||
/// StaticAssertDecl - Represents a C++0x static_assert declaration.
|
||||
|
|
@ -1872,10 +1907,9 @@ public:
|
|||
virtual ~StaticAssertDecl();
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::StaticAssert;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(StaticAssertDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == Decl::StaticAssert; }
|
||||
};
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
|
||||
|
|
|
|||
|
|
@ -193,6 +193,9 @@ public:
|
|||
ImplementationControl impControl = None);
|
||||
|
||||
virtual ObjCMethodDecl *getCanonicalDecl();
|
||||
const ObjCMethodDecl *getCanonicalDecl() const {
|
||||
return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
ObjCDeclQualifier getObjCDeclQualifier() const {
|
||||
return ObjCDeclQualifier(objcDeclQualifier);
|
||||
|
|
@ -277,8 +280,9 @@ public:
|
|||
bool isThisDeclarationADefinition() const { return Body; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCMethodDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCMethod; }
|
||||
static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
|
||||
}
|
||||
|
|
@ -383,11 +387,12 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= ObjCContainerFirst &&
|
||||
D->getKind() <= ObjCContainerLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCContainerDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= ObjCContainerFirst &&
|
||||
K <= ObjCContainerLast;
|
||||
}
|
||||
|
||||
static DeclContext *castToDeclContext(const ObjCContainerDecl *D) {
|
||||
return static_cast<DeclContext *>(const_cast<ObjCContainerDecl*>(D));
|
||||
|
|
@ -584,8 +589,9 @@ public:
|
|||
Type *getTypeForDecl() const { return TypeForDecl; }
|
||||
void setTypeForDecl(Type *TD) const { TypeForDecl = TD; }
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCInterfaceDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCInterface; }
|
||||
};
|
||||
|
||||
/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
|
||||
|
|
@ -630,8 +636,9 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCIvar; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCIvarDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCIvar; }
|
||||
private:
|
||||
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
|
||||
unsigned DeclAccess : 3;
|
||||
|
|
@ -657,8 +664,9 @@ public:
|
|||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCAtDefsField; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
|
||||
};
|
||||
|
||||
/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols
|
||||
|
|
@ -749,8 +757,9 @@ public:
|
|||
SourceLocation getLocEnd() const { return EndLoc; }
|
||||
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCProtocolDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCProtocol; }
|
||||
};
|
||||
|
||||
/// ObjCClassDecl - Specifies a list of forward class declarations. For example:
|
||||
|
|
@ -796,8 +805,9 @@ public:
|
|||
void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List,
|
||||
const SourceLocation *Locs, unsigned Num);
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCClass; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCClassDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCClass; }
|
||||
};
|
||||
|
||||
/// ObjCForwardProtocolDecl - Specifies a list of forward protocol declarations.
|
||||
|
|
@ -846,10 +856,9 @@ public:
|
|||
const SourceLocation *Locs, ASTContext &C) {
|
||||
ReferencedProtocols.set(List, Num, Locs, C);
|
||||
}
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ObjCForwardProtocol;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCForwardProtocolDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCForwardProtocol; }
|
||||
};
|
||||
|
||||
/// ObjCCategoryDecl - Represents a category declaration. A category allows
|
||||
|
|
@ -940,6 +949,8 @@ public:
|
|||
ClassInterface->setCategoryList(this);
|
||||
}
|
||||
|
||||
bool IsClassExtension() const { return getIdentifier() == 0; }
|
||||
|
||||
SourceLocation getAtLoc() const { return AtLoc; }
|
||||
void setAtLoc(SourceLocation At) { AtLoc = At; }
|
||||
|
||||
|
|
@ -950,8 +961,9 @@ public:
|
|||
return SourceRange(AtLoc, getAtEndRange().getEnd());
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCCategoryDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCCategory; }
|
||||
};
|
||||
|
||||
class ObjCImplDecl : public ObjCContainerDecl {
|
||||
|
|
@ -997,10 +1009,11 @@ public:
|
|||
return propimpl_iterator(decls_end());
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= ObjCImplFirst && D->getKind() <= ObjCImplLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCImplDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= ObjCImplFirst && K <= ObjCImplLast;
|
||||
}
|
||||
};
|
||||
|
||||
/// ObjCCategoryImplDecl - An object of this class encapsulates a category
|
||||
|
|
@ -1068,8 +1081,9 @@ public:
|
|||
return getName();
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCCategoryImplDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCCategoryImpl;}
|
||||
};
|
||||
|
||||
/// ObjCImplementationDecl - Represents a class definition - this is where
|
||||
|
|
@ -1152,10 +1166,9 @@ public:
|
|||
return ivar_begin() == ivar_end();
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ObjCImplementation;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCImplementationDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCImplementation; }
|
||||
};
|
||||
|
||||
/// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is
|
||||
|
|
@ -1176,10 +1189,9 @@ public:
|
|||
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
|
||||
void setClassInterface(ObjCInterfaceDecl *D) { AliasedClass = D; }
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ObjCCompatibleAlias;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCCompatibleAlias; }
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -1294,10 +1306,9 @@ public:
|
|||
return PropertyIvarDecl;
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ObjCProperty;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCPropertyDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ObjCProperty; }
|
||||
};
|
||||
|
||||
/// ObjCPropertyImplDecl - Represents implementation declaration of a property
|
||||
|
|
@ -1354,10 +1365,9 @@ public:
|
|||
}
|
||||
void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; }
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ObjCPropertyImpl;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCPropertyImplDecl *D) { return true; }
|
||||
static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
|||
|
|
@ -247,13 +247,14 @@ public:
|
|||
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TemplateDecl *D) { return true; }
|
||||
static bool classof(const FunctionTemplateDecl *D) { return true; }
|
||||
static bool classof(const ClassTemplateDecl *D) { return true; }
|
||||
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= TemplateFirst && K <= TemplateLast;
|
||||
}
|
||||
|
||||
protected:
|
||||
NamedDecl *TemplatedDecl;
|
||||
|
|
@ -510,10 +511,9 @@ public:
|
|||
NamedDecl *Decl);
|
||||
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D)
|
||||
{ return D->getKind() == FunctionTemplate; }
|
||||
static bool classof(const FunctionTemplateDecl *D)
|
||||
{ return true; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const FunctionTemplateDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == FunctionTemplate; }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -634,10 +634,9 @@ public:
|
|||
bool isParameterPack() const { return ParameterPack; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == TemplateTypeParm;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TemplateTypeParmDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == TemplateTypeParm; }
|
||||
};
|
||||
|
||||
/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
|
||||
|
|
@ -682,10 +681,9 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == NonTypeTemplateParm;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == NonTypeTemplateParm; }
|
||||
};
|
||||
|
||||
/// TemplateTemplateParmDecl - Declares a template template parameter,
|
||||
|
|
@ -735,10 +733,9 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == TemplateTemplateParm;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
|
||||
};
|
||||
|
||||
/// \brief Represents a class template specialization, which refers to
|
||||
|
|
@ -903,9 +900,10 @@ public:
|
|||
TemplateArgs[Arg].Profile(ID, Context);
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ClassTemplateSpecialization ||
|
||||
D->getKind() == ClassTemplatePartialSpecialization;
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) {
|
||||
return K == ClassTemplateSpecialization ||
|
||||
K == ClassTemplatePartialSpecialization;
|
||||
}
|
||||
|
||||
static bool classof(const ClassTemplateSpecializationDecl *) {
|
||||
|
|
@ -1039,8 +1037,9 @@ public:
|
|||
|
||||
// FIXME: Add Profile support!
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == ClassTemplatePartialSpecialization;
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) {
|
||||
return K == ClassTemplatePartialSpecialization;
|
||||
}
|
||||
|
||||
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
|
||||
|
|
@ -1212,10 +1211,9 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D)
|
||||
{ return D->getKind() == ClassTemplate; }
|
||||
static bool classof(const ClassTemplateDecl *D)
|
||||
{ return true; }
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ClassTemplateDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == ClassTemplate; }
|
||||
|
||||
virtual void Destroy(ASTContext& C);
|
||||
};
|
||||
|
|
@ -1293,9 +1291,8 @@ public:
|
|||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Decl::FriendTemplate;
|
||||
}
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
|
||||
static bool classof(const FriendTemplateDecl *D) { return true; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -274,30 +274,34 @@ public:
|
|||
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.
|
||||
bool operator<(DeclarationName LHS, DeclarationName RHS);
|
||||
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 RHS < LHS;
|
||||
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 !(RHS < LHS);
|
||||
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 !(LHS < RHS);
|
||||
return DeclarationName::compare(LHS, RHS) >= 0;
|
||||
}
|
||||
|
||||
/// DeclarationNameTable - Used to store and retrieve DeclarationName
|
||||
|
|
|
|||
|
|
@ -149,7 +149,8 @@ public:
|
|||
LV_DuplicateVectorComponents,
|
||||
LV_InvalidExpression,
|
||||
LV_MemberFunction,
|
||||
LV_SubObjCPropertySetting
|
||||
LV_SubObjCPropertySetting,
|
||||
LV_SubObjCPropertyGetterSetting
|
||||
};
|
||||
isLvalueResult isLvalue(ASTContext &Ctx) const;
|
||||
|
||||
|
|
@ -179,7 +180,8 @@ public:
|
|||
MLV_ReadonlyProperty,
|
||||
MLV_NoSetterProperty,
|
||||
MLV_MemberFunction,
|
||||
MLV_SubObjCPropertySetting
|
||||
MLV_SubObjCPropertySetting,
|
||||
MLV_SubObjCPropertyGetterSetting
|
||||
};
|
||||
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
|
||||
SourceLocation *Loc = 0) const;
|
||||
|
|
@ -192,6 +194,9 @@ public:
|
|||
return const_cast<Expr*>(this)->getBitField();
|
||||
}
|
||||
|
||||
/// \brief Returns whether this expression refers to a vector element.
|
||||
bool refersToVectorElement() const;
|
||||
|
||||
/// isIntegerConstantExpr - Return true if this expression is a valid integer
|
||||
/// constant expression, and, if so, return its value in Result. If not a
|
||||
/// valid i-c-e, return false and fill in Loc (if specified) with the location
|
||||
|
|
@ -563,7 +568,10 @@ public:
|
|||
enum IdentType {
|
||||
Func,
|
||||
Function,
|
||||
PrettyFunction
|
||||
PrettyFunction,
|
||||
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
|
||||
/// 'virtual' keyword is omitted for virtual member functions.
|
||||
PrettyFunctionNoVirtual
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -584,8 +592,7 @@ public:
|
|||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
static std::string ComputeName(ASTContext &Context, IdentType IT,
|
||||
const Decl *CurrentDecl);
|
||||
static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
|
|
@ -1745,7 +1752,7 @@ public:
|
|||
|
||||
static bool classof(const Stmt *T) {
|
||||
StmtClass SC = T->getStmtClass();
|
||||
if (SC >= ExplicitCastExprClass && SC <= CStyleCastExprClass)
|
||||
if (SC >= CStyleCastExprClass && SC <= CStyleCastExprClass)
|
||||
return true;
|
||||
if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -241,10 +241,17 @@ public:
|
|||
CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
|
||||
Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {}
|
||||
|
||||
explicit CXXBoolLiteralExpr(EmptyShell Empty)
|
||||
: Expr(CXXBoolLiteralExprClass, Empty) { }
|
||||
|
||||
bool getValue() const { return Value; }
|
||||
void setValue(bool V) { Value = V; }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXBoolLiteralExprClass;
|
||||
}
|
||||
|
|
@ -262,8 +269,14 @@ public:
|
|||
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
|
||||
Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {}
|
||||
|
||||
explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
|
||||
: Expr(CXXNullPtrLiteralExprClass, Empty) { }
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXNullPtrLiteralExprClass;
|
||||
}
|
||||
|
|
@ -544,6 +557,68 @@ public:
|
|||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// CXXBindReferenceExpr - Represents binding an expression to a reference.
|
||||
/// In the example:
|
||||
///
|
||||
/// const int &i = 10;
|
||||
///
|
||||
/// a bind reference expression is inserted to indicate that 10 is bound to
|
||||
/// a reference. (Ans also that a temporary needs to be created to hold the
|
||||
/// value).
|
||||
class CXXBindReferenceExpr : public Expr {
|
||||
// SubExpr - The expression being bound.
|
||||
Stmt *SubExpr;
|
||||
|
||||
// ExtendsLifetime - Whether binding this reference extends the lifetime of
|
||||
// the expression being bound. FIXME: Add C++ reference.
|
||||
bool ExtendsLifetime;
|
||||
|
||||
/// RequiresTemporaryCopy - Whether binding the subexpression requires a
|
||||
/// temporary copy.
|
||||
bool RequiresTemporaryCopy;
|
||||
|
||||
CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime,
|
||||
bool RequiresTemporaryCopy)
|
||||
: Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false),
|
||||
SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime),
|
||||
RequiresTemporaryCopy(RequiresTemporaryCopy) { }
|
||||
~CXXBindReferenceExpr() { }
|
||||
|
||||
protected:
|
||||
virtual void DoDestroy(ASTContext &C);
|
||||
|
||||
public:
|
||||
static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr,
|
||||
bool ExtendsLifetime,
|
||||
bool RequiresTemporaryCopy);
|
||||
|
||||
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
|
||||
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
|
||||
void setSubExpr(Expr *E) { SubExpr = E; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SubExpr->getSourceRange();
|
||||
}
|
||||
|
||||
/// requiresTemporaryCopy - Whether binding the subexpression requires a
|
||||
/// temporary copy.
|
||||
bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; }
|
||||
|
||||
// extendsLifetime - Whether binding this reference extends the lifetime of
|
||||
// the expression being bound. FIXME: Add C++ reference.
|
||||
bool extendsLifetime() { return ExtendsLifetime; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXBindReferenceExprClass;
|
||||
}
|
||||
static bool classof(const CXXBindReferenceExpr *) { return true; }
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// CXXConstructExpr - Represents a call to a C++ constructor.
|
||||
class CXXConstructExpr : public Expr {
|
||||
CXXConstructorDecl *Constructor;
|
||||
|
|
@ -551,6 +626,7 @@ class CXXConstructExpr : public Expr {
|
|||
SourceLocation Loc;
|
||||
bool Elidable : 1;
|
||||
bool ZeroInitialization : 1;
|
||||
bool BaseInitialization : 1;
|
||||
Stmt **Args;
|
||||
unsigned NumArgs;
|
||||
|
||||
|
|
@ -559,7 +635,8 @@ protected:
|
|||
SourceLocation Loc,
|
||||
CXXConstructorDecl *d, bool elidable,
|
||||
Expr **args, unsigned numargs,
|
||||
bool ZeroInitialization = false);
|
||||
bool ZeroInitialization = false,
|
||||
bool BaseInitialization = false);
|
||||
~CXXConstructExpr() { }
|
||||
|
||||
virtual void DoDestroy(ASTContext &C);
|
||||
|
|
@ -573,7 +650,8 @@ public:
|
|||
SourceLocation Loc,
|
||||
CXXConstructorDecl *D, bool Elidable,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
bool ZeroInitialization = false);
|
||||
bool ZeroInitialization = false,
|
||||
bool BaseInitialization = false);
|
||||
|
||||
|
||||
CXXConstructorDecl* getConstructor() const { return Constructor; }
|
||||
|
|
@ -593,6 +671,11 @@ public:
|
|||
ZeroInitialization = ZeroInit;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this constructor is actually constructing
|
||||
/// a base class (rather than a complete object).
|
||||
bool isBaseInitialization() const { return BaseInitialization; }
|
||||
void setBaseInitialization(bool BI) { BaseInitialization = BI; }
|
||||
|
||||
typedef ExprIterator arg_iterator;
|
||||
typedef ConstExprIterator const_arg_iterator;
|
||||
|
||||
|
|
@ -779,15 +862,14 @@ class CXXNewExpr : public Expr {
|
|||
SourceLocation EndLoc;
|
||||
|
||||
public:
|
||||
CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs,
|
||||
unsigned numPlaceArgs, bool ParenTypeId, Expr *arraySize,
|
||||
CXXConstructorDecl *constructor, bool initializer,
|
||||
CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
|
||||
Expr **placementArgs, unsigned numPlaceArgs, bool ParenTypeId,
|
||||
Expr *arraySize, CXXConstructorDecl *constructor, bool initializer,
|
||||
Expr **constructorArgs, unsigned numConsArgs,
|
||||
FunctionDecl *operatorDelete, QualType ty,
|
||||
SourceLocation startLoc, SourceLocation endLoc);
|
||||
~CXXNewExpr() {
|
||||
delete[] SubExprs;
|
||||
}
|
||||
|
||||
virtual void DoDestroy(ASTContext &C);
|
||||
|
||||
QualType getAllocatedType() const {
|
||||
assert(getType()->isPointerType());
|
||||
|
|
@ -1059,6 +1141,112 @@ public:
|
|||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// \brief A reference to an overloaded function set, either an
|
||||
/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr.
|
||||
class OverloadExpr : public Expr {
|
||||
/// The results. These are undesugared, which is to say, they may
|
||||
/// include UsingShadowDecls. Access is relative to the naming
|
||||
/// class.
|
||||
UnresolvedSet<4> Results;
|
||||
|
||||
/// The common name of these declarations.
|
||||
DeclarationName Name;
|
||||
|
||||
/// The scope specifier, if any.
|
||||
NestedNameSpecifier *Qualifier;
|
||||
|
||||
/// The source range of the scope specifier.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// The location of the name.
|
||||
SourceLocation NameLoc;
|
||||
|
||||
/// True if the name was a template-id.
|
||||
bool HasExplicitTemplateArgs;
|
||||
|
||||
protected:
|
||||
OverloadExpr(StmtClass K, QualType T, bool Dependent,
|
||||
NestedNameSpecifier *Qualifier, SourceRange QRange,
|
||||
DeclarationName Name, SourceLocation NameLoc,
|
||||
bool HasTemplateArgs)
|
||||
: Expr(K, T, Dependent, Dependent),
|
||||
Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
|
||||
NameLoc(NameLoc), HasExplicitTemplateArgs(HasTemplateArgs)
|
||||
{}
|
||||
|
||||
public:
|
||||
/// Computes whether an unresolved lookup on the given declarations
|
||||
/// and optional template arguments is type- and value-dependent.
|
||||
static bool ComputeDependence(UnresolvedSetIterator Begin,
|
||||
UnresolvedSetIterator End,
|
||||
const TemplateArgumentListInfo *Args);
|
||||
|
||||
/// Finds the overloaded expression in the given expression of
|
||||
/// OverloadTy.
|
||||
///
|
||||
/// \return the expression (which must be there) and true if it is
|
||||
/// within an address-of operator.
|
||||
static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) {
|
||||
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
|
||||
|
||||
bool op = false;
|
||||
E = E->IgnoreParens();
|
||||
if (isa<UnaryOperator>(E))
|
||||
op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
|
||||
return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op);
|
||||
}
|
||||
|
||||
void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) {
|
||||
Results.append(Begin, End);
|
||||
}
|
||||
|
||||
typedef UnresolvedSetImpl::iterator decls_iterator;
|
||||
decls_iterator decls_begin() const { return Results.begin(); }
|
||||
decls_iterator decls_end() const { return Results.end(); }
|
||||
|
||||
/// Gets the decls as an unresolved set.
|
||||
const UnresolvedSetImpl &getDecls() { return Results; }
|
||||
|
||||
/// Gets the number of declarations in the unresolved set.
|
||||
unsigned getNumDecls() const { return Results.size(); }
|
||||
|
||||
/// Gets the name looked up.
|
||||
DeclarationName getName() const { return Name; }
|
||||
void setName(DeclarationName N) { Name = N; }
|
||||
|
||||
/// Gets the location of the name.
|
||||
SourceLocation getNameLoc() const { return NameLoc; }
|
||||
void setNameLoc(SourceLocation Loc) { NameLoc = Loc; }
|
||||
|
||||
/// Fetches the nested-name qualifier, if one was given.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier; }
|
||||
|
||||
/// Fetches the range of the nested-name qualifier.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
|
||||
/// \brief Determines whether this expression had an explicit
|
||||
/// template argument list, e.g. f<int>.
|
||||
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
|
||||
|
||||
ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below
|
||||
|
||||
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
|
||||
return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
|
||||
}
|
||||
|
||||
ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
|
||||
if (hasExplicitTemplateArgs())
|
||||
return &getExplicitTemplateArgs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == UnresolvedLookupExprClass ||
|
||||
T->getStmtClass() == UnresolvedMemberExprClass;
|
||||
}
|
||||
static bool classof(const OverloadExpr *) { return true; }
|
||||
};
|
||||
|
||||
/// \brief A reference to a name which we were able to look up during
|
||||
/// parsing but could not resolve to a specific declaration. This
|
||||
/// arises in several ways:
|
||||
|
|
@ -1069,23 +1257,7 @@ public:
|
|||
/// These never include UnresolvedUsingValueDecls, which are always
|
||||
/// class members and therefore appear only in
|
||||
/// UnresolvedMemberLookupExprs.
|
||||
class UnresolvedLookupExpr : public Expr {
|
||||
/// The results. These are undesugared, which is to say, they may
|
||||
/// include UsingShadowDecls.
|
||||
UnresolvedSet<4> Results;
|
||||
|
||||
/// The name declared.
|
||||
DeclarationName Name;
|
||||
|
||||
/// The qualifier given, if any.
|
||||
NestedNameSpecifier *Qualifier;
|
||||
|
||||
/// The source range of the nested name specifier.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// The location of the name.
|
||||
SourceLocation NameLoc;
|
||||
|
||||
class UnresolvedLookupExpr : public OverloadExpr {
|
||||
/// True if these lookup results should be extended by
|
||||
/// argument-dependent lookup if this is the operand of a function
|
||||
/// call.
|
||||
|
|
@ -1095,35 +1267,40 @@ class UnresolvedLookupExpr : public Expr {
|
|||
/// trivially rederivable if we urgently need to kill this field.
|
||||
bool Overloaded;
|
||||
|
||||
/// True if the name looked up had explicit template arguments.
|
||||
/// This requires all the results to be function templates.
|
||||
bool HasExplicitTemplateArgs;
|
||||
/// The naming class (C++ [class.access.base]p5) of the lookup, if
|
||||
/// any. This can generally be recalculated from the context chain,
|
||||
/// but that can be fairly expensive for unqualified lookups. If we
|
||||
/// want to improve memory use here, this could go in a union
|
||||
/// against the qualified-lookup bits.
|
||||
CXXRecordDecl *NamingClass;
|
||||
|
||||
UnresolvedLookupExpr(QualType T, bool Dependent,
|
||||
UnresolvedLookupExpr(QualType T, bool Dependent, CXXRecordDecl *NamingClass,
|
||||
NestedNameSpecifier *Qualifier, SourceRange QRange,
|
||||
DeclarationName Name, SourceLocation NameLoc,
|
||||
bool RequiresADL, bool Overloaded, bool HasTemplateArgs)
|
||||
: Expr(UnresolvedLookupExprClass, T, Dependent, Dependent),
|
||||
Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
|
||||
NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded),
|
||||
HasExplicitTemplateArgs(HasTemplateArgs)
|
||||
: OverloadExpr(UnresolvedLookupExprClass, T, Dependent, Qualifier, QRange,
|
||||
Name, NameLoc, HasTemplateArgs),
|
||||
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
|
||||
{}
|
||||
|
||||
public:
|
||||
static UnresolvedLookupExpr *Create(ASTContext &C,
|
||||
bool Dependent,
|
||||
CXXRecordDecl *NamingClass,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
DeclarationName Name,
|
||||
SourceLocation NameLoc,
|
||||
bool ADL, bool Overloaded) {
|
||||
return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy,
|
||||
Dependent, Qualifier, QualifierRange,
|
||||
Dependent, NamingClass,
|
||||
Qualifier, QualifierRange,
|
||||
Name, NameLoc, ADL, Overloaded, false);
|
||||
}
|
||||
|
||||
static UnresolvedLookupExpr *Create(ASTContext &C,
|
||||
bool Dependent,
|
||||
CXXRecordDecl *NamingClass,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
DeclarationName Name,
|
||||
|
|
@ -1131,20 +1308,6 @@ public:
|
|||
bool ADL,
|
||||
const TemplateArgumentListInfo &Args);
|
||||
|
||||
/// Computes whether an unresolved lookup on the given declarations
|
||||
/// and optional template arguments is type- and value-dependent.
|
||||
static bool ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
|
||||
UnresolvedSetImpl::const_iterator End,
|
||||
const TemplateArgumentListInfo *Args);
|
||||
|
||||
void addDecl(NamedDecl *Decl) {
|
||||
Results.addDecl(Decl);
|
||||
}
|
||||
|
||||
typedef UnresolvedSetImpl::iterator decls_iterator;
|
||||
decls_iterator decls_begin() const { return Results.begin(); }
|
||||
decls_iterator decls_end() const { return Results.end(); }
|
||||
|
||||
/// True if this declaration should be extended by
|
||||
/// argument-dependent lookup.
|
||||
bool requiresADL() const { return RequiresADL; }
|
||||
|
|
@ -1152,25 +1315,20 @@ public:
|
|||
/// True if this lookup is overloaded.
|
||||
bool isOverloaded() const { return Overloaded; }
|
||||
|
||||
/// Fetches the name looked up.
|
||||
DeclarationName getName() const { return Name; }
|
||||
|
||||
/// Gets the location of the name.
|
||||
SourceLocation getNameLoc() const { return NameLoc; }
|
||||
|
||||
/// Fetches the nested-name qualifier, if one was given.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier; }
|
||||
|
||||
/// Fetches the range of the nested-name qualifier.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
|
||||
/// Determines whether this lookup had explicit template arguments.
|
||||
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
|
||||
/// Gets the 'naming class' (in the sense of C++0x
|
||||
/// [class.access.base]p5) of the lookup. This is the scope
|
||||
/// that was looked in to find these results.
|
||||
CXXRecordDecl *getNamingClass() const { return NamingClass; }
|
||||
|
||||
// Note that, inconsistently with the explicit-template-argument AST
|
||||
// nodes, users are *forbidden* from calling these methods on objects
|
||||
// without explicit template arguments.
|
||||
|
||||
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
|
||||
assert(hasExplicitTemplateArgs());
|
||||
return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1);
|
||||
}
|
||||
|
||||
/// Gets a reference to the explicit template argument list.
|
||||
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
|
||||
assert(hasExplicitTemplateArgs());
|
||||
|
|
@ -1200,8 +1358,8 @@ public:
|
|||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
SourceRange Range(NameLoc);
|
||||
if (Qualifier) Range.setBegin(QualifierRange.getBegin());
|
||||
SourceRange Range(getNameLoc());
|
||||
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
|
||||
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
|
||||
return Range;
|
||||
}
|
||||
|
|
@ -1456,11 +1614,24 @@ public:
|
|||
arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
|
||||
arg_iterator arg_end() { return arg_begin() + NumArgs; }
|
||||
|
||||
typedef const Expr* const * const_arg_iterator;
|
||||
const_arg_iterator arg_begin() const {
|
||||
return reinterpret_cast<const Expr* const *>(this + 1);
|
||||
}
|
||||
const_arg_iterator arg_end() const {
|
||||
return arg_begin() + NumArgs;
|
||||
}
|
||||
|
||||
Expr *getArg(unsigned I) {
|
||||
assert(I < NumArgs && "Argument index out-of-range");
|
||||
return *(arg_begin() + I);
|
||||
}
|
||||
|
||||
const Expr *getArg(unsigned I) const {
|
||||
assert(I < NumArgs && "Argument index out-of-range");
|
||||
return *(arg_begin() + I);
|
||||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(TyBeginLoc, RParenLoc);
|
||||
}
|
||||
|
|
@ -1713,10 +1884,14 @@ public:
|
|||
/// In the final AST, an explicit access always becomes a MemberExpr.
|
||||
/// An implicit access may become either a MemberExpr or a
|
||||
/// DeclRefExpr, depending on whether the member is static.
|
||||
class UnresolvedMemberExpr : public Expr {
|
||||
/// The results. These are undesugared, which is to say, they may
|
||||
/// include UsingShadowDecls.
|
||||
UnresolvedSet<4> Results;
|
||||
class UnresolvedMemberExpr : public OverloadExpr {
|
||||
/// \brief Whether this member expression used the '->' operator or
|
||||
/// the '.' operator.
|
||||
bool IsArrow : 1;
|
||||
|
||||
/// \brief Whether the lookup results contain an unresolved using
|
||||
/// declaration.
|
||||
bool HasUnresolvedUsing : 1;
|
||||
|
||||
/// \brief The expression for the base pointer or class reference,
|
||||
/// e.g., the \c x in x.f. This can be null if this is an 'unbased'
|
||||
|
|
@ -1726,47 +1901,9 @@ class UnresolvedMemberExpr : public Expr {
|
|||
/// \brief The type of the base expression; never null.
|
||||
QualType BaseType;
|
||||
|
||||
/// \brief Whether this member expression used the '->' operator or
|
||||
/// the '.' operator.
|
||||
bool IsArrow : 1;
|
||||
|
||||
/// \brief Whether the lookup results contain an unresolved using
|
||||
/// declaration.
|
||||
bool HasUnresolvedUsing : 1;
|
||||
|
||||
/// \brief Whether this member expression has explicitly-specified template
|
||||
/// arguments.
|
||||
bool HasExplicitTemplateArgs : 1;
|
||||
|
||||
/// \brief The location of the '->' or '.' operator.
|
||||
SourceLocation OperatorLoc;
|
||||
|
||||
/// \brief The nested-name-specifier that precedes the member name, if any.
|
||||
NestedNameSpecifier *Qualifier;
|
||||
|
||||
/// \brief The source range covering the nested name specifier.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// \brief The member to which this member expression refers, which
|
||||
/// can be a name or an overloaded operator.
|
||||
DeclarationName MemberName;
|
||||
|
||||
/// \brief The location of the member name.
|
||||
SourceLocation MemberLoc;
|
||||
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name.
|
||||
ExplicitTemplateArgumentList *getExplicitTemplateArgs() {
|
||||
assert(HasExplicitTemplateArgs);
|
||||
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name, if any.
|
||||
const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const {
|
||||
return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs();
|
||||
}
|
||||
|
||||
UnresolvedMemberExpr(QualType T, bool Dependent,
|
||||
bool HasUnresolvedUsing,
|
||||
Expr *Base, QualType BaseType, bool IsArrow,
|
||||
|
|
@ -1788,19 +1925,6 @@ public:
|
|||
SourceLocation MemberLoc,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
/// Adds a declaration to the unresolved set. By assumption, all of
|
||||
/// these happen at initialization time and properties like
|
||||
/// 'Dependent' and 'HasUnresolvedUsing' take them into account.
|
||||
void addDecl(NamedDecl *Decl) {
|
||||
Results.addDecl(Decl);
|
||||
}
|
||||
|
||||
typedef UnresolvedSetImpl::iterator decls_iterator;
|
||||
decls_iterator decls_begin() const { return Results.begin(); }
|
||||
decls_iterator decls_end() const { return Results.end(); }
|
||||
|
||||
unsigned getNumDecls() const { return Results.size(); }
|
||||
|
||||
/// \brief True if this is an implicit access, i.e. one in which the
|
||||
/// member being accessed was not written in the source. The source
|
||||
/// location of the operator is invalid in this case.
|
||||
|
|
@ -1812,6 +1936,10 @@ public:
|
|||
assert(!isImplicitAccess());
|
||||
return cast<Expr>(Base);
|
||||
}
|
||||
const Expr *getBase() const {
|
||||
assert(!isImplicitAccess());
|
||||
return cast<Expr>(Base);
|
||||
}
|
||||
void setBase(Expr *E) { Base = E; }
|
||||
|
||||
QualType getBaseType() const { return BaseType; }
|
||||
|
|
@ -1825,57 +1953,60 @@ public:
|
|||
SourceLocation getOperatorLoc() const { return OperatorLoc; }
|
||||
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
|
||||
|
||||
/// \brief Retrieve the nested-name-specifier that qualifies the member
|
||||
/// name.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier; }
|
||||
|
||||
/// \brief Retrieve the source range covering the nested-name-specifier
|
||||
/// that qualifies the member name.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
/// \brief Retrieves the naming class of this lookup.
|
||||
CXXRecordDecl *getNamingClass() const;
|
||||
|
||||
/// \brief Retrieve the name of the member that this expression
|
||||
/// refers to.
|
||||
DeclarationName getMemberName() const { return MemberName; }
|
||||
void setMemberName(DeclarationName N) { MemberName = N; }
|
||||
DeclarationName getMemberName() const { return getName(); }
|
||||
void setMemberName(DeclarationName N) { setName(N); }
|
||||
|
||||
// \brief Retrieve the location of the name of the member that this
|
||||
// expression refers to.
|
||||
SourceLocation getMemberLoc() const { return MemberLoc; }
|
||||
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
|
||||
SourceLocation getMemberLoc() const { return getNameLoc(); }
|
||||
void setMemberLoc(SourceLocation L) { setNameLoc(L); }
|
||||
|
||||
/// \brief Determines whether this member expression actually had a C++
|
||||
/// template argument list explicitly specified, e.g., x.f<int>.
|
||||
bool hasExplicitTemplateArgs() const {
|
||||
return HasExplicitTemplateArgs;
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name.
|
||||
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
|
||||
assert(hasExplicitTemplateArgs());
|
||||
return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name, if any.
|
||||
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
|
||||
assert(hasExplicitTemplateArgs());
|
||||
return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
|
||||
}
|
||||
|
||||
/// \brief Copies the template arguments into the given structure.
|
||||
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
|
||||
getExplicitTemplateArgs()->copyInto(List);
|
||||
getExplicitTemplateArgs().copyInto(List);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the left angle bracket following
|
||||
/// the member name ('<').
|
||||
SourceLocation getLAngleLoc() const {
|
||||
return getExplicitTemplateArgs()->LAngleLoc;
|
||||
return getExplicitTemplateArgs().LAngleLoc;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
return getExplicitTemplateArgs()->getTemplateArgs();
|
||||
return getExplicitTemplateArgs().getTemplateArgs();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the number of template arguments provided as
|
||||
/// part of this template-id.
|
||||
unsigned getNumTemplateArgs() const {
|
||||
return getExplicitTemplateArgs()->NumTemplateArgs;
|
||||
return getExplicitTemplateArgs().NumTemplateArgs;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the right angle bracket
|
||||
/// following the template arguments ('>').
|
||||
SourceLocation getRAngleLoc() const {
|
||||
return getExplicitTemplateArgs()->RAngleLoc;
|
||||
return getExplicitTemplateArgs().RAngleLoc;
|
||||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
|
|
@ -1885,12 +2016,12 @@ public:
|
|||
else if (getQualifier())
|
||||
Range.setBegin(getQualifierRange().getBegin());
|
||||
else
|
||||
Range.setBegin(MemberLoc);
|
||||
Range.setBegin(getMemberLoc());
|
||||
|
||||
if (hasExplicitTemplateArgs())
|
||||
Range.setEnd(getRAngleLoc());
|
||||
else
|
||||
Range.setEnd(MemberLoc);
|
||||
Range.setEnd(getMemberLoc());
|
||||
return Range;
|
||||
}
|
||||
|
||||
|
|
@ -1904,6 +2035,13 @@ public:
|
|||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
|
||||
if (isa<UnresolvedLookupExpr>(this))
|
||||
return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
|
||||
else
|
||||
return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs();
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ class ObjCMessageExpr : public Expr {
|
|||
public:
|
||||
/// This constructor is used to represent class messages where the
|
||||
/// ObjCInterfaceDecl* of the receiver is not known.
|
||||
ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
|
||||
ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, Selector selInfo,
|
||||
QualType retType, ObjCMethodDecl *methDecl,
|
||||
SourceLocation LBrac, SourceLocation RBrac,
|
||||
Expr **ArgExprs, unsigned NumArgs);
|
||||
|
|
@ -375,13 +375,13 @@ public:
|
|||
/// This constructor is used to represent class messages where the
|
||||
/// ObjCInterfaceDecl* of the receiver is known.
|
||||
// FIXME: clsName should be typed to ObjCInterfaceType
|
||||
ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
|
||||
ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, Selector selInfo,
|
||||
QualType retType, ObjCMethodDecl *methDecl,
|
||||
SourceLocation LBrac, SourceLocation RBrac,
|
||||
Expr **ArgExprs, unsigned NumArgs);
|
||||
|
||||
// constructor for instance messages.
|
||||
ObjCMessageExpr(Expr *receiver, Selector selInfo,
|
||||
ObjCMessageExpr(ASTContext &C, Expr *receiver, Selector selInfo,
|
||||
QualType retType, ObjCMethodDecl *methDecl,
|
||||
SourceLocation LBrac, SourceLocation RBrac,
|
||||
Expr **ArgExprs, unsigned NumArgs);
|
||||
|
|
@ -389,9 +389,7 @@ public:
|
|||
explicit ObjCMessageExpr(EmptyShell Empty)
|
||||
: Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {}
|
||||
|
||||
~ObjCMessageExpr() {
|
||||
delete [] SubExprs;
|
||||
}
|
||||
virtual void DoDestroy(ASTContext &C);
|
||||
|
||||
/// getReceiver - Returns the receiver of the message expression.
|
||||
/// This can be NULL if the message is for class methods. For
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ public:
|
|||
#define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class,
|
||||
#define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class,
|
||||
#define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class
|
||||
#define ABSTRACT_EXPR(CLASS, PARENT)
|
||||
#include "clang/AST/StmtNodes.def"
|
||||
};
|
||||
private:
|
||||
|
|
@ -1120,21 +1121,27 @@ class AsmStmt : public Stmt {
|
|||
|
||||
unsigned NumOutputs;
|
||||
unsigned NumInputs;
|
||||
unsigned NumClobbers;
|
||||
|
||||
llvm::SmallVector<std::string, 4> Names;
|
||||
llvm::SmallVector<StringLiteral*, 4> Constraints;
|
||||
llvm::SmallVector<Stmt*, 4> Exprs;
|
||||
// FIXME: If we wanted to, we could allocate all of these in one big array.
|
||||
IdentifierInfo **Names;
|
||||
StringLiteral **Constraints;
|
||||
Stmt **Exprs;
|
||||
StringLiteral **Clobbers;
|
||||
|
||||
llvm::SmallVector<StringLiteral*, 4> Clobbers;
|
||||
protected:
|
||||
virtual void DoDestroy(ASTContext &Ctx);
|
||||
|
||||
public:
|
||||
AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, bool msasm,
|
||||
unsigned numoutputs, unsigned numinputs,
|
||||
std::string *names, StringLiteral **constraints,
|
||||
AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile,
|
||||
bool msasm, unsigned numoutputs, unsigned numinputs,
|
||||
IdentifierInfo **names, StringLiteral **constraints,
|
||||
Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
|
||||
StringLiteral **clobbers, SourceLocation rparenloc);
|
||||
|
||||
/// \brief Build an empty inline-assembly statement.
|
||||
explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { }
|
||||
explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty),
|
||||
Names(0), Constraints(0), Exprs(0), Clobbers(0) { }
|
||||
|
||||
SourceLocation getAsmLoc() const { return AsmLoc; }
|
||||
void setAsmLoc(SourceLocation L) { AsmLoc = L; }
|
||||
|
|
@ -1208,14 +1215,21 @@ public:
|
|||
|
||||
unsigned getNumOutputs() const { return NumOutputs; }
|
||||
|
||||
const std::string &getOutputName(unsigned i) const {
|
||||
IdentifierInfo *getOutputIdentifier(unsigned i) const {
|
||||
return Names[i];
|
||||
}
|
||||
|
||||
llvm::StringRef getOutputName(unsigned i) const {
|
||||
if (IdentifierInfo *II = getOutputIdentifier(i))
|
||||
return II->getName();
|
||||
|
||||
return llvm::StringRef();
|
||||
}
|
||||
|
||||
/// getOutputConstraint - Return the constraint string for the specified
|
||||
/// output operand. All output constraints are known to be non-empty (either
|
||||
/// '=' or '+').
|
||||
std::string getOutputConstraint(unsigned i) const;
|
||||
llvm::StringRef getOutputConstraint(unsigned i) const;
|
||||
|
||||
const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
|
||||
return Constraints[i];
|
||||
|
|
@ -1224,7 +1238,6 @@ public:
|
|||
return Constraints[i];
|
||||
}
|
||||
|
||||
|
||||
Expr *getOutputExpr(unsigned i);
|
||||
|
||||
const Expr *getOutputExpr(unsigned i) const {
|
||||
|
|
@ -1246,13 +1259,20 @@ public:
|
|||
|
||||
unsigned getNumInputs() const { return NumInputs; }
|
||||
|
||||
const std::string &getInputName(unsigned i) const {
|
||||
IdentifierInfo *getInputIdentifier(unsigned i) const {
|
||||
return Names[i + NumOutputs];
|
||||
}
|
||||
|
||||
llvm::StringRef getInputName(unsigned i) const {
|
||||
if (IdentifierInfo *II = getInputIdentifier(i))
|
||||
return II->getName();
|
||||
|
||||
return llvm::StringRef();
|
||||
}
|
||||
|
||||
/// getInputConstraint - Return the specified input constraint. Unlike output
|
||||
/// constraints, these can be empty.
|
||||
std::string getInputConstraint(unsigned i) const;
|
||||
llvm::StringRef getInputConstraint(unsigned i) const;
|
||||
|
||||
const StringLiteral *getInputConstraintLiteral(unsigned i) const {
|
||||
return Constraints[i + NumOutputs];
|
||||
|
|
@ -1261,32 +1281,31 @@ public:
|
|||
return Constraints[i + NumOutputs];
|
||||
}
|
||||
|
||||
|
||||
Expr *getInputExpr(unsigned i);
|
||||
|
||||
const Expr *getInputExpr(unsigned i) const {
|
||||
return const_cast<AsmStmt*>(this)->getInputExpr(i);
|
||||
}
|
||||
|
||||
void setOutputsAndInputs(unsigned NumOutputs,
|
||||
unsigned NumInputs,
|
||||
const std::string *Names,
|
||||
StringLiteral **Constraints,
|
||||
Stmt **Exprs);
|
||||
void setOutputsAndInputsAndClobbers(ASTContext &C,
|
||||
IdentifierInfo **Names,
|
||||
StringLiteral **Constraints,
|
||||
Stmt **Exprs,
|
||||
unsigned NumOutputs,
|
||||
unsigned NumInputs,
|
||||
StringLiteral **Clobbers,
|
||||
unsigned NumClobbers);
|
||||
|
||||
//===--- Other ---===//
|
||||
|
||||
/// getNamedOperand - Given a symbolic operand reference like %[foo],
|
||||
/// translate this into a numeric value needed to reference the same operand.
|
||||
/// This returns -1 if the operand name is invalid.
|
||||
int getNamedOperand(const std::string &SymbolicName) const;
|
||||
int getNamedOperand(llvm::StringRef SymbolicName) const;
|
||||
|
||||
|
||||
|
||||
unsigned getNumClobbers() const { return Clobbers.size(); }
|
||||
unsigned getNumClobbers() const { return NumClobbers; }
|
||||
StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
|
||||
const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
|
||||
void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers);
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(AsmLoc, RParenLoc);
|
||||
|
|
@ -1301,19 +1320,19 @@ public:
|
|||
typedef ConstExprIterator const_inputs_iterator;
|
||||
|
||||
inputs_iterator begin_inputs() {
|
||||
return Exprs.data() + NumOutputs;
|
||||
return &Exprs[0] + NumOutputs;
|
||||
}
|
||||
|
||||
inputs_iterator end_inputs() {
|
||||
return Exprs.data() + NumOutputs + NumInputs;
|
||||
return &Exprs[0] + NumOutputs + NumInputs;
|
||||
}
|
||||
|
||||
const_inputs_iterator begin_inputs() const {
|
||||
return Exprs.data() + NumOutputs;
|
||||
return &Exprs[0] + NumOutputs;
|
||||
}
|
||||
|
||||
const_inputs_iterator end_inputs() const {
|
||||
return Exprs.data() + NumOutputs + NumInputs;
|
||||
return &Exprs[0] + NumOutputs + NumInputs;
|
||||
}
|
||||
|
||||
// Output expr iterators.
|
||||
|
|
@ -1322,27 +1341,17 @@ public:
|
|||
typedef ConstExprIterator const_outputs_iterator;
|
||||
|
||||
outputs_iterator begin_outputs() {
|
||||
return Exprs.data();
|
||||
return &Exprs[0];
|
||||
}
|
||||
outputs_iterator end_outputs() {
|
||||
return Exprs.data() + NumOutputs;
|
||||
return &Exprs[0] + NumOutputs;
|
||||
}
|
||||
|
||||
const_outputs_iterator begin_outputs() const {
|
||||
return Exprs.data();
|
||||
return &Exprs[0];
|
||||
}
|
||||
const_outputs_iterator end_outputs() const {
|
||||
return Exprs.data() + NumOutputs;
|
||||
}
|
||||
|
||||
// Input name iterator.
|
||||
|
||||
const std::string *begin_output_names() const {
|
||||
return &Names[0];
|
||||
}
|
||||
|
||||
const std::string *end_output_names() const {
|
||||
return &Names[0] + NumOutputs;
|
||||
return &Exprs[0] + NumOutputs;
|
||||
}
|
||||
|
||||
// Child iterators
|
||||
|
|
|
|||
|
|
@ -59,31 +59,42 @@ public:
|
|||
///
|
||||
class CXXTryStmt : public Stmt {
|
||||
SourceLocation TryLoc;
|
||||
// First place is the guarded CompoundStatement. Subsequent are the handlers.
|
||||
// More than three handlers should be rare.
|
||||
llvm::SmallVector<Stmt*, 4> Stmts;
|
||||
unsigned NumHandlers;
|
||||
|
||||
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers,
|
||||
unsigned numHandlers);
|
||||
|
||||
public:
|
||||
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
|
||||
Stmt **handlers, unsigned numHandlers);
|
||||
static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
|
||||
Stmt *tryBlock, Stmt **handlers,
|
||||
unsigned numHandlers);
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(getTryLoc(), getEndLoc());
|
||||
}
|
||||
|
||||
SourceLocation getTryLoc() const { return TryLoc; }
|
||||
SourceLocation getEndLoc() const { return Stmts.back()->getLocEnd(); }
|
||||
SourceLocation getEndLoc() const {
|
||||
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
|
||||
return Stmts[NumHandlers]->getLocEnd();
|
||||
}
|
||||
|
||||
CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); }
|
||||
CompoundStmt *getTryBlock() {
|
||||
Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
|
||||
return llvm::cast<CompoundStmt>(Stmts[0]);
|
||||
}
|
||||
const CompoundStmt *getTryBlock() const {
|
||||
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
|
||||
return llvm::cast<CompoundStmt>(Stmts[0]);
|
||||
}
|
||||
|
||||
unsigned getNumHandlers() const { return Stmts.size() - 1; }
|
||||
unsigned getNumHandlers() const { return NumHandlers; }
|
||||
CXXCatchStmt *getHandler(unsigned i) {
|
||||
Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
|
||||
return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
|
||||
}
|
||||
const CXXCatchStmt *getHandler(unsigned i) const {
|
||||
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
|
||||
return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,8 +68,7 @@ STMT(CXXTryStmt , Stmt)
|
|||
LAST_STMT(CXXTryStmt)
|
||||
|
||||
// Expressions.
|
||||
ABSTRACT_EXPR(Expr , Stmt)
|
||||
FIRST_EXPR(Expr)
|
||||
ABSTRACT_EXPR(Expr , Stmt)
|
||||
EXPR(PredefinedExpr , Expr)
|
||||
EXPR(DeclRefExpr , Expr)
|
||||
EXPR(IntegerLiteral , Expr)
|
||||
|
|
@ -83,12 +82,12 @@ EXPR(SizeOfAlignOfExpr , Expr)
|
|||
EXPR(ArraySubscriptExpr , Expr)
|
||||
EXPR(CallExpr , Expr)
|
||||
EXPR(MemberExpr , Expr)
|
||||
EXPR(CastExpr , Expr)
|
||||
ABSTRACT_EXPR(CastExpr , Expr)
|
||||
EXPR(BinaryOperator , Expr)
|
||||
EXPR(CompoundAssignOperator, BinaryOperator)
|
||||
EXPR(ConditionalOperator , Expr)
|
||||
EXPR(ImplicitCastExpr , CastExpr)
|
||||
EXPR(ExplicitCastExpr , CastExpr)
|
||||
ABSTRACT_EXPR(ExplicitCastExpr, CastExpr)
|
||||
EXPR(CStyleCastExpr , ExplicitCastExpr)
|
||||
EXPR(CompoundLiteralExpr , Expr)
|
||||
EXPR(ExtVectorElementExpr , Expr)
|
||||
|
|
@ -129,6 +128,7 @@ EXPR(UnaryTypeTraitExpr , Expr)
|
|||
EXPR(DependentScopeDeclRefExpr , Expr)
|
||||
EXPR(CXXConstructExpr , Expr)
|
||||
EXPR(CXXBindTemporaryExpr , Expr)
|
||||
EXPR(CXXBindReferenceExpr , Expr)
|
||||
EXPR(CXXExprWithTemporaries , Expr)
|
||||
EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
|
||||
EXPR(CXXUnresolvedConstructExpr, Expr)
|
||||
|
|
@ -152,6 +152,7 @@ EXPR(ShuffleVectorExpr , Expr)
|
|||
EXPR(BlockExpr , Expr)
|
||||
EXPR(BlockDeclRefExpr , Expr)
|
||||
|
||||
FIRST_EXPR(PredefinedExpr)
|
||||
LAST_EXPR(BlockDeclRefExpr)
|
||||
|
||||
#undef ABSTRACT_EXPR
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ public:
|
|||
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
|
||||
switch (S->getStmtClass()) {
|
||||
default: assert(0 && "Unknown stmt kind!");
|
||||
#define ABSTRACT_EXPR(CLASS, PARENT)
|
||||
#define STMT(CLASS, PARENT) \
|
||||
case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);
|
||||
#include "clang/AST/StmtNodes.def"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/Linkage.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
|
@ -750,24 +751,22 @@ class Type {
|
|||
public:
|
||||
enum TypeClass {
|
||||
#define TYPE(Class, Base) Class,
|
||||
#define LAST_TYPE(Class) TypeLast = Class,
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#include "clang/AST/TypeNodes.def"
|
||||
TagFirst = Record, TagLast = Enum
|
||||
};
|
||||
|
||||
protected:
|
||||
enum { TypeClassBitSize = 6 };
|
||||
|
||||
private:
|
||||
QualType CanonicalType;
|
||||
|
||||
/// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
|
||||
bool Dependent : 1;
|
||||
|
||||
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
|
||||
unsigned TC : 8;
|
||||
|
||||
/// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
|
||||
/// Note that this should stay at the end of the ivars for Type so that
|
||||
/// subclasses can pack their bitfields into the same word.
|
||||
unsigned TC : TypeClassBitSize;
|
||||
bool Dependent : 1;
|
||||
|
||||
Type(const Type&); // DO NOT IMPLEMENT.
|
||||
void operator=(const Type&); // DO NOT IMPLEMENT.
|
||||
|
|
@ -776,7 +775,7 @@ protected:
|
|||
Type *this_() { return this; }
|
||||
Type(TypeClass tc, QualType Canonical, bool dependent)
|
||||
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
|
||||
Dependent(dependent), TC(tc) {}
|
||||
TC(tc), Dependent(dependent) {}
|
||||
virtual ~Type() {}
|
||||
virtual void Destroy(ASTContext& C);
|
||||
friend class ASTContext;
|
||||
|
|
@ -974,6 +973,9 @@ public:
|
|||
|
||||
const char *getTypeClassName() const;
|
||||
|
||||
/// \brief Determine the linkage of this type.
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
QualType getCanonicalTypeInternal() const { return CanonicalType; }
|
||||
void dump() const;
|
||||
static bool classof(const Type *) { return true; }
|
||||
|
|
@ -1062,6 +1064,8 @@ public:
|
|||
return TypeKind >= Float && TypeKind <= LongDouble;
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
|
||||
static bool classof(const BuiltinType *) { return true; }
|
||||
};
|
||||
|
|
@ -1089,6 +1093,8 @@ public:
|
|||
ID.AddPointer(Element.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
|
||||
static bool classof(const ComplexType *) { return true; }
|
||||
};
|
||||
|
|
@ -1116,6 +1122,8 @@ public:
|
|||
ID.AddPointer(Pointee.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
|
||||
static bool classof(const PointerType *) { return true; }
|
||||
};
|
||||
|
|
@ -1146,6 +1154,8 @@ public:
|
|||
ID.AddPointer(Pointee.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == BlockPointer;
|
||||
}
|
||||
|
|
@ -1183,7 +1193,8 @@ protected:
|
|||
}
|
||||
public:
|
||||
bool isSpelledAsLValue() const { return SpelledAsLValue; }
|
||||
|
||||
bool isInnerRef() const { return InnerRef; }
|
||||
|
||||
QualType getPointeeTypeAsWritten() const { return PointeeType; }
|
||||
QualType getPointeeType() const {
|
||||
// FIXME: this might strip inner qualifiers; okay?
|
||||
|
|
@ -1203,6 +1214,8 @@ public:
|
|||
ID.AddBoolean(SpelledAsLValue);
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == LValueReference ||
|
||||
T->getTypeClass() == RValueReference;
|
||||
|
|
@ -1277,6 +1290,8 @@ public:
|
|||
ID.AddPointer(Class);
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == MemberPointer;
|
||||
}
|
||||
|
|
@ -1328,6 +1343,8 @@ public:
|
|||
}
|
||||
unsigned getIndexTypeCVRQualifiers() const { return IndexTypeQuals; }
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ConstantArray ||
|
||||
T->getTypeClass() == VariableArray ||
|
||||
|
|
@ -1576,7 +1593,8 @@ public:
|
|||
|
||||
/// VectorType - GCC generic vector type. This type is created using
|
||||
/// __attribute__((vector_size(n)), where "n" specifies the vector size in
|
||||
/// bytes. Since the constructor takes the number of vector elements, the
|
||||
/// bytes; or from an Altivec __vector or vector declaration.
|
||||
/// Since the constructor takes the number of vector elements, the
|
||||
/// client is responsible for converting the size into the number of elements.
|
||||
class VectorType : public Type, public llvm::FoldingSetNode {
|
||||
protected:
|
||||
|
|
@ -1586,13 +1604,21 @@ protected:
|
|||
/// NumElements - The number of elements in the vector.
|
||||
unsigned NumElements;
|
||||
|
||||
VectorType(QualType vecType, unsigned nElements, QualType canonType) :
|
||||
/// AltiVec - True if this is for an Altivec vector.
|
||||
bool AltiVec;
|
||||
|
||||
/// Pixel - True if this is for an Altivec vector pixel.
|
||||
bool Pixel;
|
||||
|
||||
VectorType(QualType vecType, unsigned nElements, QualType canonType,
|
||||
bool isAltiVec, bool isPixel) :
|
||||
Type(Vector, canonType, vecType->isDependentType()),
|
||||
ElementType(vecType), NumElements(nElements) {}
|
||||
ElementType(vecType), NumElements(nElements),
|
||||
AltiVec(isAltiVec), Pixel(isPixel) {}
|
||||
VectorType(TypeClass tc, QualType vecType, unsigned nElements,
|
||||
QualType canonType)
|
||||
QualType canonType, bool isAltiVec, bool isPixel)
|
||||
: Type(tc, canonType, vecType->isDependentType()), ElementType(vecType),
|
||||
NumElements(nElements) {}
|
||||
NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
|
|
@ -1602,15 +1628,26 @@ public:
|
|||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
bool isAltiVec() const { return AltiVec; }
|
||||
|
||||
bool isPixel() const { return Pixel; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getElementType(), getNumElements(), getTypeClass());
|
||||
Profile(ID, getElementType(), getNumElements(), getTypeClass(),
|
||||
AltiVec, Pixel);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType,
|
||||
unsigned NumElements, TypeClass TypeClass) {
|
||||
unsigned NumElements, TypeClass TypeClass,
|
||||
bool isAltiVec, bool isPixel) {
|
||||
ID.AddPointer(ElementType.getAsOpaquePtr());
|
||||
ID.AddInteger(NumElements);
|
||||
ID.AddInteger(TypeClass);
|
||||
ID.AddBoolean(isAltiVec);
|
||||
ID.AddBoolean(isPixel);
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Vector || T->getTypeClass() == ExtVector;
|
||||
}
|
||||
|
|
@ -1624,7 +1661,7 @@ public:
|
|||
/// points, colors, and textures (modeled after OpenGL Shading Language).
|
||||
class ExtVectorType : public VectorType {
|
||||
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
|
||||
VectorType(ExtVector, vecType, nElements, canonType) {}
|
||||
VectorType(ExtVector, vecType, nElements, canonType, false, false) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
static int getPointAccessorIdx(char c) {
|
||||
|
|
@ -1723,6 +1760,8 @@ public:
|
|||
bool getNoReturnAttr() const { return NoReturn; }
|
||||
CallingConv getCallConv() const { return (CallingConv)CallConv; }
|
||||
|
||||
static llvm::StringRef getNameForCallConv(CallingConv CC);
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == FunctionNoProto ||
|
||||
T->getTypeClass() == FunctionProto;
|
||||
|
|
@ -1745,14 +1784,17 @@ public:
|
|||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getResultType(), getNoReturnAttr());
|
||||
Profile(ID, getResultType(), getNoReturnAttr(), getCallConv());
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
|
||||
bool NoReturn) {
|
||||
bool NoReturn, CallingConv CallConv) {
|
||||
ID.AddInteger(CallConv);
|
||||
ID.AddInteger(NoReturn);
|
||||
ID.AddPointer(ResultType.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == FunctionNoProto;
|
||||
}
|
||||
|
|
@ -1856,6 +1898,8 @@ public:
|
|||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == FunctionProto;
|
||||
}
|
||||
|
|
@ -1867,7 +1911,7 @@ public:
|
|||
bool isVariadic, unsigned TypeQuals,
|
||||
bool hasExceptionSpec, bool anyExceptionSpec,
|
||||
unsigned NumExceptions, exception_iterator Exs,
|
||||
bool NoReturn);
|
||||
bool NoReturn, CallingConv CallConv);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1878,8 +1922,9 @@ public:
|
|||
class UnresolvedUsingType : public Type {
|
||||
UnresolvedUsingTypenameDecl *Decl;
|
||||
|
||||
UnresolvedUsingType(UnresolvedUsingTypenameDecl *D)
|
||||
: Type(UnresolvedUsing, QualType(), true), Decl(D) {}
|
||||
UnresolvedUsingType(const UnresolvedUsingTypenameDecl *D)
|
||||
: Type(UnresolvedUsing, QualType(), true),
|
||||
Decl(const_cast<UnresolvedUsingTypenameDecl*>(D)) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
|
|
@ -1906,8 +1951,9 @@ public:
|
|||
class TypedefType : public Type {
|
||||
TypedefDecl *Decl;
|
||||
protected:
|
||||
TypedefType(TypeClass tc, TypedefDecl *D, QualType can)
|
||||
: Type(tc, can, can->isDependentType()), Decl(D) {
|
||||
TypedefType(TypeClass tc, const TypedefDecl *D, QualType can)
|
||||
: Type(tc, can, can->isDependentType()),
|
||||
Decl(const_cast<TypedefDecl*>(D)) {
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonical type");
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
|
@ -1950,8 +1996,12 @@ public:
|
|||
static bool classof(const TypeOfExprType *) { return true; }
|
||||
};
|
||||
|
||||
/// Subclass of TypeOfExprType that is used for canonical, dependent
|
||||
/// \brief Internal representation of canonical, dependent
|
||||
/// typeof(expr) types.
|
||||
///
|
||||
/// This class is used internally by the ASTContext to manage
|
||||
/// canonical, dependent types, only. Clients will only see instances
|
||||
/// of this class via TypeOfExprType nodes.
|
||||
class DependentTypeOfExprType
|
||||
: public TypeOfExprType, public llvm::FoldingSetNode {
|
||||
ASTContext &Context;
|
||||
|
|
@ -2018,8 +2068,12 @@ public:
|
|||
static bool classof(const DecltypeType *) { return true; }
|
||||
};
|
||||
|
||||
/// Subclass of DecltypeType that is used for canonical, dependent
|
||||
/// C++0x decltype types.
|
||||
/// \brief Internal representation of canonical, dependent
|
||||
/// decltype(expr) types.
|
||||
///
|
||||
/// This class is used internally by the ASTContext to manage
|
||||
/// canonical, dependent types, only. Clients will only see instances
|
||||
/// of this class via DecltypeType nodes.
|
||||
class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
|
||||
ASTContext &Context;
|
||||
|
||||
|
|
@ -2048,7 +2102,7 @@ class TagType : public Type {
|
|||
friend class TagDecl;
|
||||
|
||||
protected:
|
||||
TagType(TypeClass TC, TagDecl *D, QualType can);
|
||||
TagType(TypeClass TC, const TagDecl *D, QualType can);
|
||||
|
||||
public:
|
||||
TagDecl *getDecl() const { return decl.getPointer(); }
|
||||
|
|
@ -2058,6 +2112,8 @@ public:
|
|||
bool isBeingDefined() const { return decl.getInt(); }
|
||||
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
|
||||
}
|
||||
|
|
@ -2070,10 +2126,10 @@ public:
|
|||
/// to detect TagType objects of structs/unions/classes.
|
||||
class RecordType : public TagType {
|
||||
protected:
|
||||
explicit RecordType(RecordDecl *D)
|
||||
: TagType(Record, reinterpret_cast<TagDecl*>(D), QualType()) { }
|
||||
explicit RecordType(const RecordDecl *D)
|
||||
: TagType(Record, reinterpret_cast<const TagDecl*>(D), QualType()) { }
|
||||
explicit RecordType(TypeClass TC, RecordDecl *D)
|
||||
: TagType(TC, reinterpret_cast<TagDecl*>(D), QualType()) { }
|
||||
: TagType(TC, reinterpret_cast<const TagDecl*>(D), QualType()) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
|
|
@ -2103,8 +2159,8 @@ public:
|
|||
/// EnumType - This is a helper class that allows the use of isa/cast/dyncast
|
||||
/// to detect TagType objects of enums.
|
||||
class EnumType : public TagType {
|
||||
explicit EnumType(EnumDecl *D)
|
||||
: TagType(Enum, reinterpret_cast<TagDecl*>(D), QualType()) { }
|
||||
explicit EnumType(const EnumDecl *D)
|
||||
: TagType(Enum, reinterpret_cast<const TagDecl*>(D), QualType()) { }
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
||||
|
|
@ -2512,12 +2568,12 @@ public:
|
|||
class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
|
||||
ObjCInterfaceDecl *Decl;
|
||||
|
||||
// List of protocols for this protocol conforming object type
|
||||
// List is sorted on protocol name. No protocol is enterred more than once.
|
||||
ObjCProtocolDecl **Protocols;
|
||||
/// \brief The number of protocols stored after the ObjCInterfaceType node.
|
||||
/// The list of protocols is sorted on protocol name. No protocol is enterred
|
||||
/// more than once.
|
||||
unsigned NumProtocols;
|
||||
|
||||
ObjCInterfaceType(ASTContext &Ctx, QualType Canonical, ObjCInterfaceDecl *D,
|
||||
ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D,
|
||||
ObjCProtocolDecl **Protos, unsigned NumP);
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
|
|
@ -2529,14 +2585,20 @@ public:
|
|||
/// interface type, or 0 if there are none.
|
||||
unsigned getNumProtocols() const { return NumProtocols; }
|
||||
|
||||
/// \brief Retrieve the Ith protocol.
|
||||
ObjCProtocolDecl *getProtocol(unsigned I) const {
|
||||
assert(I < getNumProtocols() && "Out-of-range protocol access");
|
||||
return qual_begin()[I];
|
||||
}
|
||||
|
||||
/// qual_iterator and friends: this provides access to the (potentially empty)
|
||||
/// list of protocols qualifying this interface.
|
||||
typedef ObjCProtocolDecl* const * qual_iterator;
|
||||
qual_iterator qual_begin() const {
|
||||
return Protocols;
|
||||
return reinterpret_cast<qual_iterator>(this + 1);
|
||||
}
|
||||
qual_iterator qual_end() const {
|
||||
return Protocols ? Protocols + NumProtocols : 0;
|
||||
return qual_begin() + NumProtocols;
|
||||
}
|
||||
bool qual_empty() const { return NumProtocols == 0; }
|
||||
|
||||
|
|
@ -2546,7 +2608,10 @@ public:
|
|||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const ObjCInterfaceDecl *Decl,
|
||||
ObjCProtocolDecl **protocols, unsigned NumProtocols);
|
||||
ObjCProtocolDecl * const *protocols,
|
||||
unsigned NumProtocols);
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCInterface;
|
||||
|
|
@ -2562,12 +2627,14 @@ public:
|
|||
class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
|
||||
QualType PointeeType; // A builtin or interface type.
|
||||
|
||||
// List of protocols for this protocol conforming object type
|
||||
// List is sorted on protocol name. No protocol is entered more than once.
|
||||
ObjCProtocolDecl **Protocols;
|
||||
/// \brief The number of protocols stored after the ObjCObjectPointerType
|
||||
/// node.
|
||||
///
|
||||
/// The list of protocols is sorted on protocol name. No protocol is enterred
|
||||
/// more than once.
|
||||
unsigned NumProtocols;
|
||||
|
||||
ObjCObjectPointerType(ASTContext &Ctx, QualType Canonical, QualType T,
|
||||
ObjCObjectPointerType(QualType Canonical, QualType T,
|
||||
ObjCProtocolDecl **Protos, unsigned NumP);
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
|
|
@ -2614,10 +2681,10 @@ public:
|
|||
typedef ObjCProtocolDecl* const * qual_iterator;
|
||||
|
||||
qual_iterator qual_begin() const {
|
||||
return Protocols;
|
||||
return reinterpret_cast<qual_iterator> (this + 1);
|
||||
}
|
||||
qual_iterator qual_end() const {
|
||||
return Protocols ? Protocols + NumProtocols : NULL;
|
||||
return qual_begin() + NumProtocols;
|
||||
}
|
||||
bool qual_empty() const { return NumProtocols == 0; }
|
||||
|
||||
|
|
@ -2625,12 +2692,21 @@ public:
|
|||
/// interface type, or 0 if there are none.
|
||||
unsigned getNumProtocols() const { return NumProtocols; }
|
||||
|
||||
/// \brief Retrieve the Ith protocol.
|
||||
ObjCProtocolDecl *getProtocol(unsigned I) const {
|
||||
assert(I < getNumProtocols() && "Out-of-range protocol access");
|
||||
return qual_begin()[I];
|
||||
}
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
virtual Linkage getLinkage() const;
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T,
|
||||
ObjCProtocolDecl **protocols, unsigned NumProtocols);
|
||||
ObjCProtocolDecl *const *protocols,
|
||||
unsigned NumProtocols);
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == ObjCObjectPointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ DEPENDENT_TYPE(Typename, Type)
|
|||
TYPE(ObjCInterface, Type)
|
||||
TYPE(ObjCObjectPointer, Type)
|
||||
|
||||
#ifdef LAST_TYPE
|
||||
LAST_TYPE(ObjCObjectPointer)
|
||||
#undef LAST_TYPE
|
||||
#endif
|
||||
|
||||
// These types are always leaves in the type hierarchy.
|
||||
#ifdef LEAF_TYPE
|
||||
LEAF_TYPE(Enum)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#define LLVM_CLANG_AST_UNRESOLVEDSET_H
|
||||
|
||||
#include <iterator>
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
|
||||
|
|
@ -24,12 +23,58 @@ 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 this is POD.
|
||||
namespace llvm {
|
||||
template<typename> struct isPodLike;
|
||||
template<> struct isPodLike<clang::DeclAccessPair> {
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// The iterator over UnresolvedSets. Serves as both the const and
|
||||
/// non-const iterator.
|
||||
class UnresolvedSetIterator {
|
||||
|
||||
typedef llvm::PointerIntPair<NamedDecl*, 2> DeclEntry;
|
||||
typedef llvm::SmallVectorImpl<DeclEntry> DeclsTy;
|
||||
private:
|
||||
typedef llvm::SmallVectorImpl<DeclAccessPair> DeclsTy;
|
||||
typedef DeclsTy::iterator IteratorTy;
|
||||
|
||||
IteratorTy ir;
|
||||
|
|
@ -47,8 +92,8 @@ public:
|
|||
typedef NamedDecl *reference;
|
||||
typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
|
||||
|
||||
NamedDecl *getDecl() const { return ir->getPointer(); }
|
||||
AccessSpecifier getAccess() const { return AccessSpecifier(ir->getInt()); }
|
||||
NamedDecl *getDecl() const { return ir->getDecl(); }
|
||||
AccessSpecifier getAccess() const { return ir->getAccess(); }
|
||||
|
||||
NamedDecl *operator*() const { return getDecl(); }
|
||||
|
||||
|
|
@ -87,7 +132,6 @@ public:
|
|||
/// in a lot of places, but isn't really worth breaking into its own
|
||||
/// header right now.
|
||||
class UnresolvedSetImpl {
|
||||
typedef UnresolvedSetIterator::DeclEntry DeclEntry;
|
||||
typedef UnresolvedSetIterator::DeclsTy DeclsTy;
|
||||
|
||||
// Don't allow direct construction, and only permit subclassing by
|
||||
|
|
@ -114,7 +158,7 @@ public:
|
|||
}
|
||||
|
||||
void addDecl(NamedDecl *D, AccessSpecifier AS) {
|
||||
decls().push_back(DeclEntry(D, AS));
|
||||
decls().push_back(DeclAccessPair::make(D, AS));
|
||||
}
|
||||
|
||||
/// Replaces the given declaration with the new one, once.
|
||||
|
|
@ -122,19 +166,24 @@ public:
|
|||
/// \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->getPointer() == Old)
|
||||
return (I->setPointer(New), true);
|
||||
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->setPointer(New);
|
||||
I.ir->setDecl(New);
|
||||
}
|
||||
|
||||
void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
|
||||
*I.ir = DeclEntry(New, AS);
|
||||
I.ir->set(New, AS);
|
||||
}
|
||||
|
||||
void erase(unsigned I) {
|
||||
decls()[I] = decls().back();
|
||||
decls().pop_back();
|
||||
}
|
||||
|
||||
void erase(iterator I) {
|
||||
|
|
@ -142,6 +191,10 @@ public:
|
|||
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); }
|
||||
|
||||
|
|
@ -152,41 +205,8 @@ public:
|
|||
decls().append(I.ir, E.ir);
|
||||
}
|
||||
|
||||
/// A proxy reference for implementing operator[].
|
||||
class Proxy {
|
||||
DeclEntry &Ref;
|
||||
|
||||
friend class UnresolvedSetImpl;
|
||||
Proxy(DeclEntry &Ref) : Ref(Ref) {}
|
||||
|
||||
public:
|
||||
NamedDecl *getDecl() const { return Ref.getPointer(); }
|
||||
void setDecl(NamedDecl *D) { Ref.setPointer(D); }
|
||||
|
||||
AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); }
|
||||
void setAccess(AccessSpecifier AS) const { Ref.setInt(AS); }
|
||||
|
||||
NamedDecl* operator->() const { return getDecl(); }
|
||||
operator NamedDecl*() const { return getDecl(); }
|
||||
Proxy &operator=(const Proxy &D) { Ref = D.Ref; return *this; }
|
||||
};
|
||||
Proxy operator[](unsigned I) { return Proxy(decls()[I]); }
|
||||
|
||||
/// A proxy reference for implementing operator[] const.
|
||||
class ConstProxy {
|
||||
const DeclEntry &Ref;
|
||||
|
||||
friend class UnresolvedSetImpl;
|
||||
ConstProxy(const DeclEntry &Ref) : Ref(Ref) {}
|
||||
|
||||
public:
|
||||
NamedDecl *getDecl() const { return Ref.getPointer(); }
|
||||
AccessSpecifier getAccess() const { return AccessSpecifier(Ref.getInt()); }
|
||||
|
||||
NamedDecl *operator->() const { return getDecl(); }
|
||||
operator NamedDecl*() const { return getDecl(); }
|
||||
};
|
||||
ConstProxy operator[](unsigned I) const { return ConstProxy(decls()[I]); }
|
||||
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
|
||||
|
|
@ -202,7 +222,7 @@ private:
|
|||
/// A set of unresolved declarations
|
||||
template <unsigned InlineCapacity> class UnresolvedSet :
|
||||
public UnresolvedSetImpl {
|
||||
llvm::SmallVector<UnresolvedSetImpl::DeclEntry, InlineCapacity> Decls;
|
||||
llvm::SmallVector<DeclAccessPair, InlineCapacity> Decls;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
279
include/clang/Analysis/Analyses/PrintfFormatString.h
Normal file
279
include/clang/Analysis/Analyses/PrintfFormatString.h
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Handling of format string in printf and friends. The structure of format
|
||||
// strings for fprintf() are described in C99 7.19.6.1.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_FPRINTF_FORMAT_H
|
||||
#define LLVM_CLANG_FPRINTF_FORMAT_H
|
||||
|
||||
#include "clang/AST/CanonicalType.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ASTContext;
|
||||
|
||||
namespace analyze_printf {
|
||||
|
||||
class ArgTypeResult {
|
||||
public:
|
||||
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CStrTy,
|
||||
WCStrTy };
|
||||
private:
|
||||
const Kind K;
|
||||
QualType T;
|
||||
ArgTypeResult(bool) : K(InvalidTy) {}
|
||||
public:
|
||||
ArgTypeResult(Kind k = UnknownTy) : K(k) {}
|
||||
ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
|
||||
ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
|
||||
|
||||
static ArgTypeResult Invalid() { return ArgTypeResult(true); }
|
||||
|
||||
bool isValid() const { return K != InvalidTy; }
|
||||
|
||||
const QualType *getSpecificType() const {
|
||||
return K == SpecificTy ? &T : 0;
|
||||
}
|
||||
|
||||
bool matchesType(ASTContext &C, QualType argTy) const;
|
||||
|
||||
bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
|
||||
|
||||
QualType getRepresentativeType(ASTContext &C) const;
|
||||
};
|
||||
|
||||
class ConversionSpecifier {
|
||||
public:
|
||||
enum Kind {
|
||||
InvalidSpecifier = 0,
|
||||
// C99 conversion specifiers.
|
||||
dArg, // 'd'
|
||||
iArg, // 'i',
|
||||
oArg, // 'o',
|
||||
uArg, // 'u',
|
||||
xArg, // 'x',
|
||||
XArg, // 'X',
|
||||
fArg, // 'f',
|
||||
FArg, // 'F',
|
||||
eArg, // 'e',
|
||||
EArg, // 'E',
|
||||
gArg, // 'g',
|
||||
GArg, // 'G',
|
||||
aArg, // 'a',
|
||||
AArg, // 'A',
|
||||
IntAsCharArg, // 'c'
|
||||
CStrArg, // 's'
|
||||
VoidPtrArg, // 'p'
|
||||
OutIntPtrArg, // 'n'
|
||||
PercentArg, // '%'
|
||||
// Objective-C specific specifiers.
|
||||
ObjCObjArg, // '@'
|
||||
// GlibC specific specifiers.
|
||||
PrintErrno, // 'm'
|
||||
// Specifier ranges.
|
||||
IntArgBeg = dArg,
|
||||
IntArgEnd = iArg,
|
||||
UIntArgBeg = oArg,
|
||||
UIntArgEnd = XArg,
|
||||
DoubleArgBeg = fArg,
|
||||
DoubleArgEnd = AArg,
|
||||
C99Beg = IntArgBeg,
|
||||
C99End = DoubleArgEnd,
|
||||
ObjCBeg = ObjCObjArg,
|
||||
ObjCEnd = ObjCObjArg
|
||||
};
|
||||
|
||||
ConversionSpecifier()
|
||||
: Position(0), kind(InvalidSpecifier) {}
|
||||
|
||||
ConversionSpecifier(const char *pos, Kind k)
|
||||
: Position(pos), kind(k) {}
|
||||
|
||||
const char *getStart() const {
|
||||
return Position;
|
||||
}
|
||||
|
||||
llvm::StringRef getCharacters() const {
|
||||
return llvm::StringRef(getStart(), getLength());
|
||||
}
|
||||
|
||||
bool consumesDataArgument() const {
|
||||
switch (kind) {
|
||||
case PercentArg:
|
||||
case PrintErrno:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
|
||||
bool isIntArg() const { return kind >= dArg && kind <= iArg; }
|
||||
bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
|
||||
bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
|
||||
Kind getKind() const { return kind; }
|
||||
unsigned getLength() const {
|
||||
// Conversion specifiers currently only are represented by
|
||||
// single characters, but we be flexible.
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
const char *Position;
|
||||
Kind kind;
|
||||
};
|
||||
|
||||
enum LengthModifier {
|
||||
None,
|
||||
AsChar, // 'hh'
|
||||
AsShort, // 'h'
|
||||
AsLong, // 'l'
|
||||
AsLongLong, // 'll', 'q' (BSD, deprecated)
|
||||
AsIntMax, // 'j'
|
||||
AsSizeT, // 'z'
|
||||
AsPtrDiff, // 't'
|
||||
AsLongDouble, // 'L'
|
||||
AsWideChar = AsLong // for '%ls'
|
||||
};
|
||||
|
||||
class OptionalAmount {
|
||||
public:
|
||||
enum HowSpecified { NotSpecified, Constant, Arg };
|
||||
|
||||
OptionalAmount(HowSpecified h, const char *st)
|
||||
: start(st), hs(h), amt(0) {}
|
||||
|
||||
OptionalAmount()
|
||||
: start(0), hs(NotSpecified), amt(0) {}
|
||||
|
||||
OptionalAmount(unsigned i, const char *st)
|
||||
: start(st), hs(Constant), amt(i) {}
|
||||
|
||||
HowSpecified getHowSpecified() const { return hs; }
|
||||
bool hasDataArgument() const { return hs == Arg; }
|
||||
|
||||
unsigned getConstantAmount() const {
|
||||
assert(hs == Constant);
|
||||
return amt;
|
||||
}
|
||||
|
||||
const char *getStart() const {
|
||||
return start;
|
||||
}
|
||||
|
||||
ArgTypeResult getArgType(ASTContext &Ctx) const;
|
||||
|
||||
private:
|
||||
const char *start;
|
||||
HowSpecified hs;
|
||||
unsigned amt;
|
||||
};
|
||||
|
||||
class FormatSpecifier {
|
||||
LengthModifier LM;
|
||||
unsigned IsLeftJustified : 1;
|
||||
unsigned HasPlusPrefix : 1;
|
||||
unsigned HasSpacePrefix : 1;
|
||||
unsigned HasAlternativeForm : 1;
|
||||
unsigned HasLeadingZeroes : 1;
|
||||
unsigned flags : 5;
|
||||
ConversionSpecifier CS;
|
||||
OptionalAmount FieldWidth;
|
||||
OptionalAmount Precision;
|
||||
public:
|
||||
FormatSpecifier() : LM(None),
|
||||
IsLeftJustified(0), HasPlusPrefix(0), HasSpacePrefix(0),
|
||||
HasAlternativeForm(0), HasLeadingZeroes(0) {}
|
||||
|
||||
static FormatSpecifier Parse(const char *beg, const char *end);
|
||||
|
||||
// Methods for incrementally constructing the FormatSpecifier.
|
||||
void setConversionSpecifier(const ConversionSpecifier &cs) {
|
||||
CS = cs;
|
||||
}
|
||||
void setLengthModifier(LengthModifier lm) {
|
||||
LM = lm;
|
||||
}
|
||||
void setIsLeftJustified() { IsLeftJustified = 1; }
|
||||
void setHasPlusPrefix() { HasPlusPrefix = 1; }
|
||||
void setHasSpacePrefix() { HasSpacePrefix = 1; }
|
||||
void setHasAlternativeForm() { HasAlternativeForm = 1; }
|
||||
void setHasLeadingZeros() { HasLeadingZeroes = 1; }
|
||||
|
||||
// Methods for querying the format specifier.
|
||||
|
||||
const ConversionSpecifier &getConversionSpecifier() const {
|
||||
return CS;
|
||||
}
|
||||
|
||||
LengthModifier getLengthModifier() const {
|
||||
return LM;
|
||||
}
|
||||
|
||||
const OptionalAmount &getFieldWidth() const {
|
||||
return FieldWidth;
|
||||
}
|
||||
|
||||
void setFieldWidth(const OptionalAmount &Amt) {
|
||||
FieldWidth = Amt;
|
||||
}
|
||||
|
||||
void setPrecision(const OptionalAmount &Amt) {
|
||||
Precision = Amt;
|
||||
}
|
||||
|
||||
const OptionalAmount &getPrecision() const {
|
||||
return Precision;
|
||||
}
|
||||
|
||||
/// \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.
|
||||
ArgTypeResult getArgType(ASTContext &Ctx) const;
|
||||
|
||||
bool isLeftJustified() const { return (bool) IsLeftJustified; }
|
||||
bool hasPlusPrefix() const { return (bool) HasPlusPrefix; }
|
||||
bool hasAlternativeForm() const { return (bool) HasAlternativeForm; }
|
||||
bool hasLeadingZeros() const { return (bool) HasLeadingZeroes; }
|
||||
bool hasSpacePrefix() const { return (bool) HasSpacePrefix; }
|
||||
};
|
||||
|
||||
class FormatStringHandler {
|
||||
public:
|
||||
FormatStringHandler() {}
|
||||
virtual ~FormatStringHandler();
|
||||
|
||||
virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier,
|
||||
unsigned specifierLen) {}
|
||||
|
||||
virtual void HandleNullChar(const char *nullCharacter) {}
|
||||
|
||||
virtual void
|
||||
HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
unsigned specifierLen) {}
|
||||
|
||||
virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
|
||||
const char *startSpecifier,
|
||||
unsigned specifierLen) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool ParseFormatString(FormatStringHandler &H,
|
||||
const char *beg, const char *end);
|
||||
|
||||
} // end printf namespace
|
||||
} // end clang namespace
|
||||
#endif
|
||||
|
|
@ -70,5 +70,8 @@ public:
|
|||
void InitializeValues(const CFG& cfg);
|
||||
};
|
||||
|
||||
|
||||
void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
|
||||
bool FullUninitTaint=false);
|
||||
} // end namespace clang
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ class LiveVariables;
|
|||
class ParentMap;
|
||||
class ImplicitParamDecl;
|
||||
class LocationContextManager;
|
||||
class BlockDataRegion;
|
||||
class StackFrameContext;
|
||||
|
||||
/// AnalysisContext contains the context data for the function or method under
|
||||
|
|
@ -207,35 +206,23 @@ public:
|
|||
};
|
||||
|
||||
class BlockInvocationContext : public LocationContext {
|
||||
llvm::PointerUnion<const BlockDataRegion *, const BlockDecl *> Data;
|
||||
// FIXME: Add back context-sensivity (we don't want libAnalysis to know
|
||||
// about MemRegion).
|
||||
const BlockDecl *BD;
|
||||
|
||||
friend class LocationContextManager;
|
||||
|
||||
BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDataRegion *br)
|
||||
: LocationContext(Block, ctx, parent), Data(br) {}
|
||||
|
||||
BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDecl *bd)
|
||||
: LocationContext(Block, ctx, parent), Data(bd) {}
|
||||
: LocationContext(Block, ctx, parent), BD(bd) {}
|
||||
|
||||
public:
|
||||
~BlockInvocationContext() {}
|
||||
|
||||
const BlockDataRegion *getBlockRegion() const {
|
||||
return Data.is<const BlockDataRegion*>() ?
|
||||
Data.get<const BlockDataRegion*>() : 0;
|
||||
}
|
||||
|
||||
const BlockDecl *getBlockDecl() const;
|
||||
|
||||
|
||||
const BlockDecl *getBlockDecl() const { return BD; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID);
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const BlockDataRegion *br){
|
||||
ProfileCommon(ID, Block, ctx, parent, br);
|
||||
}
|
||||
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
|
||||
const LocationContext *parent, const BlockDecl *bd) {
|
||||
ProfileCommon(ID, Block, ctx, parent, bd);
|
||||
|
|
@ -260,10 +247,6 @@ public:
|
|||
const LocationContext *parent,
|
||||
const Stmt *s);
|
||||
|
||||
const BlockInvocationContext *
|
||||
getBlockInvocation(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const BlockDataRegion *BR);
|
||||
|
||||
/// Discard all previously created LocationContext objects.
|
||||
void clear();
|
||||
private:
|
||||
|
|
@ -20,19 +20,27 @@ namespace clang {
|
|||
|
||||
template<typename T>
|
||||
class Optional {
|
||||
const T x;
|
||||
T x;
|
||||
unsigned hasVal : 1;
|
||||
public:
|
||||
explicit Optional() : hasVal(false) {}
|
||||
explicit Optional() : x(), hasVal(false) {}
|
||||
Optional(const T &y) : x(y), hasVal(true) {}
|
||||
|
||||
static inline Optional create(const T* y) {
|
||||
return y ? Optional(*y) : Optional();
|
||||
}
|
||||
|
||||
Optional &operator=(const T &y) {
|
||||
x = y;
|
||||
hasVal = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T* getPointer() const { assert(hasVal); return &x; }
|
||||
const T& getValue() const { assert(hasVal); return x; }
|
||||
|
||||
operator bool() const { return hasVal; }
|
||||
bool hasValue() const { return hasVal; }
|
||||
const T* operator->() const { return getPointer(); }
|
||||
const T& operator*() const { assert(hasVal); return x; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
|
||||
// adding stuff on demand.
|
||||
//
|
||||
// FIXME: This should really be a .td file, but that requires modifying tblgen.
|
||||
// Perhaps tblgen should have plugins.
|
||||
|
||||
|
|
@ -52,6 +49,7 @@
|
|||
// * -> pointer
|
||||
// & -> reference
|
||||
// C -> const
|
||||
// D -> volatile
|
||||
|
||||
// The third value provided to the macro specifies information about attributes
|
||||
// of the function. These must be kept in sync with the predicates in the
|
||||
|
|
@ -235,7 +233,7 @@ BUILTIN(__builtin_islessgreater , "i.", "nc")
|
|||
BUILTIN(__builtin_isunordered , "i.", "nc")
|
||||
|
||||
// Unary FP classification
|
||||
// BUILTIN(__builtin_fpclassify, "iiiii.", "nc")
|
||||
BUILTIN(__builtin_fpclassify, "iiiii.", "nc")
|
||||
BUILTIN(__builtin_isfinite, "i.", "nc")
|
||||
BUILTIN(__builtin_isinf, "i.", "nc")
|
||||
BUILTIN(__builtin_isinf_sign, "i.", "nc")
|
||||
|
|
@ -277,7 +275,7 @@ BUILTIN(__builtin_va_copy, "vAA", "n")
|
|||
BUILTIN(__builtin_stdarg_start, "vA.", "n")
|
||||
BUILTIN(__builtin_bcmp, "iv*v*z", "n")
|
||||
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
|
||||
BUILTIN(__builtin_bzero, "vv*z", "n")
|
||||
BUILTIN(__builtin_bzero, "vv*z", "nF")
|
||||
BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
|
||||
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
|
||||
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
|
||||
|
|
@ -308,11 +306,19 @@ BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
|
|||
BUILTIN(__builtin_frame_address, "v*Ui", "n")
|
||||
BUILTIN(__builtin_flt_rounds, "i", "nc")
|
||||
BUILTIN(__builtin_setjmp, "iv**", "")
|
||||
BUILTIN(__builtin_longjmp, "vv**i", "")
|
||||
BUILTIN(__builtin_longjmp, "vv**i", "r")
|
||||
BUILTIN(__builtin_unwind_init, "v", "")
|
||||
BUILTIN(__builtin_eh_return_data_regno, "ii", "nc")
|
||||
BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
|
||||
|
||||
// GCC exception builtins
|
||||
BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t!
|
||||
BUILTIN(__builtin_frob_return_addr, "v*v*", "n")
|
||||
BUILTIN(__builtin_dwarf_cfa, "v*", "n")
|
||||
BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
|
||||
BUILTIN(__builtin_dwarf_sp_column, "Ui", "n")
|
||||
BUILTIN(__builtin_extend_pointer, "iv*", "n")
|
||||
|
||||
// GCC Object size checking builtins
|
||||
BUILTIN(__builtin_object_size, "zv*i", "n")
|
||||
BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF")
|
||||
|
|
@ -438,18 +444,18 @@ BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n")
|
|||
|
||||
|
||||
BUILTIN(__sync_bool_compare_and_swap, "v.", "")
|
||||
BUILTIN(__sync_bool_compare_and_swap_1, "bc*cc.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_2, "bs*ss.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_4, "bi*ii.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_8, "bLLi*LLi.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_16, "bLLLi*LLLiLLLi.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_4, "biD*ii.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_8, "bLLiD*LLiLLi.", "n")
|
||||
BUILTIN(__sync_bool_compare_and_swap_16, "bLLLiD*LLLiLLLi.", "n")
|
||||
|
||||
BUILTIN(__sync_val_compare_and_swap, "v.", "")
|
||||
BUILTIN(__sync_val_compare_and_swap_1, "cc*cc.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_2, "ss*ss.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_4, "ii*ii.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_8, "LLiLLi*LLi.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLi*LLLiLLLi.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_1, "ccD*cc.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_2, "ssD*ss.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_4, "iiD*ii.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n")
|
||||
BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n")
|
||||
|
||||
BUILTIN(__sync_lock_test_and_set, "v.", "")
|
||||
BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n")
|
||||
|
|
@ -527,6 +533,7 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h")
|
|||
// POSIX strings.h
|
||||
LIBBUILTIN(index, "c*cC*i", "f", "strings.h")
|
||||
LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h")
|
||||
LIBBUILTIN(bzero, "vv*z", "f", "strings.h")
|
||||
// POSIX unistd.h
|
||||
LIBBUILTIN(_exit, "vi", "fr", "unistd.h")
|
||||
// POSIX setjmp.h
|
||||
|
|
|
|||
|
|
@ -23,16 +23,19 @@
|
|||
|
||||
namespace llvm {
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class raw_ostream;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class DeclContext;
|
||||
class DiagnosticBuilder;
|
||||
class DiagnosticClient;
|
||||
class FileManager;
|
||||
class IdentifierInfo;
|
||||
class LangOptions;
|
||||
class PartialDiagnostic;
|
||||
class Preprocessor;
|
||||
class SourceManager;
|
||||
class SourceRange;
|
||||
|
||||
// Import the diagnostic enums themselves.
|
||||
|
|
@ -400,6 +403,13 @@ public:
|
|||
/// \brief Clear out the current diagnostic.
|
||||
void Clear() { CurDiagID = ~0U; }
|
||||
|
||||
/// Deserialize - Deserialize the first diagnostic within the memory
|
||||
/// [Memory, MemoryEnd), producing a new diagnostic builder describing the
|
||||
/// deserialized diagnostic. If the memory does not contain a
|
||||
/// diagnostic, returns a diagnostic builder with no diagnostic ID.
|
||||
DiagnosticBuilder Deserialize(FileManager &FM, SourceManager &SM,
|
||||
const char *&Memory, const char *MemoryEnd);
|
||||
|
||||
private:
|
||||
/// getDiagnosticMappingInfo - Return the mapping info currently set for the
|
||||
/// specified builtin diagnostic. This returns the high bit encoding, or zero
|
||||
|
|
@ -472,7 +482,7 @@ private:
|
|||
|
||||
/// DiagRanges - The list of ranges added to this diagnostic. It currently
|
||||
/// only support 10 ranges, could easily be extended if needed.
|
||||
const SourceRange *DiagRanges[10];
|
||||
SourceRange DiagRanges[10];
|
||||
|
||||
enum { MaxCodeModificationHints = 3 };
|
||||
|
||||
|
|
@ -568,6 +578,9 @@ public:
|
|||
/// been emitted.
|
||||
~DiagnosticBuilder() { Emit(); }
|
||||
|
||||
/// isActive - Determine whether this diagnostic is still active.
|
||||
bool isActive() const { return DiagObj != 0; }
|
||||
|
||||
/// Operator bool: conversion of DiagnosticBuilder to bool always returns
|
||||
/// true. This allows is to be used in boolean error contexts like:
|
||||
/// return Diag(...);
|
||||
|
|
@ -596,7 +609,7 @@ public:
|
|||
sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
|
||||
"Too many arguments to diagnostic!");
|
||||
if (DiagObj)
|
||||
DiagObj->DiagRanges[NumRanges++] = &R;
|
||||
DiagObj->DiagRanges[NumRanges++] = R;
|
||||
}
|
||||
|
||||
void AddCodeModificationHint(const CodeModificationHint &Hint) const {
|
||||
|
|
@ -759,9 +772,9 @@ public:
|
|||
return DiagObj->NumDiagRanges;
|
||||
}
|
||||
|
||||
const SourceRange &getRange(unsigned Idx) const {
|
||||
SourceRange getRange(unsigned Idx) const {
|
||||
assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
|
||||
return *DiagObj->DiagRanges[Idx];
|
||||
return DiagObj->DiagRanges[Idx];
|
||||
}
|
||||
|
||||
unsigned getNumCodeModificationHints() const {
|
||||
|
|
@ -786,6 +799,12 @@ public:
|
|||
/// output buffer using the arguments stored in this diagnostic.
|
||||
void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
|
||||
llvm::SmallVectorImpl<char> &OutStr) const;
|
||||
|
||||
/// Serialize - Serialize the given diagnostic (with its diagnostic
|
||||
/// level) to the given stream. Serialization is a lossy operation,
|
||||
/// since the specific diagnostic ID and any macro-instantiation
|
||||
/// information is lost.
|
||||
void Serialize(Diagnostic::Level DiagLevel, llvm::raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
/// DiagnosticClient - This is an abstract interface implemented by clients of
|
||||
|
|
|
|||
|
|
@ -26,4 +26,33 @@ def err_asm_empty_symbolic_operand_name : Error<
|
|||
def err_asm_invalid_operand_number : Error<
|
||||
"invalid operand number in inline asm string">;
|
||||
|
||||
// Importing ASTs
|
||||
def err_odr_variable_type_inconsistent : Error<
|
||||
"external variable %0 declared with incompatible types in different "
|
||||
"translation units (%1 vs. %2)">;
|
||||
def err_odr_variable_multiple_def : Error<
|
||||
"external variable %0 defined in multiple translation units">;
|
||||
def note_odr_value_here : Note<"declared here with type %0">;
|
||||
def note_odr_defined_here : Note<"also defined here">;
|
||||
def err_odr_function_type_inconsistent : Error<
|
||||
"external function %0 declared with incompatible types in different "
|
||||
"translation units (%1 vs. %2)">;
|
||||
def warn_odr_tag_type_inconsistent : Warning<
|
||||
"type %0 has incompatible definitions in different translation units">;
|
||||
def note_odr_tag_kind_here: Note<
|
||||
"%0 is a %select{struct|union|class|enum}1 here">;
|
||||
def note_odr_field : Note<"field %0 has type %1 here">;
|
||||
def note_odr_missing_field : Note<"no corresponding field here">;
|
||||
def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
|
||||
def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
|
||||
def note_odr_base : Note<"class has base type %0">;
|
||||
def note_odr_virtual_base : Note<
|
||||
"%select{non-virtual|virtual}0 derivation here">;
|
||||
def note_odr_missing_base : Note<"no corresponding base class here">;
|
||||
def note_odr_number_of_bases : Note<
|
||||
"class has %0 base %plural{1:class|:classes}0">;
|
||||
def note_odr_enumerator : Note<"enumerator %0 with value %1 here">;
|
||||
def note_odr_missing_enumerator : Note<"no corresponding enumerator here">;
|
||||
|
||||
def err_unsupported_ast_node: Error<"cannot import unsupported AST node %0">;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ def note_also_found : Note<"also found">;
|
|||
|
||||
// Parse && Lex
|
||||
def err_expected_colon : Error<"expected ':'">;
|
||||
def err_expected_colon_after_setter_name : Error<
|
||||
"method name referenced in property setter attribute "
|
||||
"must end with ':'">;
|
||||
|
||||
// Parse && Sema
|
||||
def err_no_declarators : Error<"declaration does not declare anything">;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">;
|
|||
def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">;
|
||||
def err_drv_invalid_remap_file : Error<
|
||||
"invalid option '%0' not of the form <from-file>;<to-file>">;
|
||||
def err_drv_invalid_gcc_output_type : Error<
|
||||
"invalid output type '%0' for use with gcc tool">;
|
||||
|
||||
def warn_drv_input_file_unused : Warning<
|
||||
"%0: '%1' input unused when '%2' is present">;
|
||||
|
|
@ -85,5 +87,7 @@ def warn_ignoring_ftabstop_value : Warning<
|
|||
"ignoring invalid -ftabstop value '%0', using default value %1">;
|
||||
def warn_drv_missing_resource_library : Warning<
|
||||
"missing resource library '%0', link may fail">;
|
||||
def warn_drv_conflicting_deployment_targets : Warning<
|
||||
"conflicting deployment targets, both MACOSX_DEPLOYMENT_TARGET '%0' and IPHONEOS_DEPLOYMENT_TARGET '%1' are present in environment">;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ def err_fe_invalid_code_complete_file : Error<
|
|||
"cannot locate code-completion file %0">, DefaultFatal;
|
||||
def err_fe_stdout_binary : Error<"unable to change standard output to binary">,
|
||||
DefaultFatal;
|
||||
def err_fe_stderr_binary : Error<"unable to change standard error to binary">,
|
||||
DefaultFatal;
|
||||
def err_fe_dependency_file_requires_MT : Error<
|
||||
"-dependency-file requires at least one -MT option">;
|
||||
def err_fe_incompatible_options : Error<
|
||||
|
|
@ -80,6 +82,8 @@ def note_fixit_main_file_unchanged : Note<
|
|||
def warn_fixit_no_changes : Note<
|
||||
"FIX-IT detected errors it could not fix; no output will be generated">;
|
||||
|
||||
def err_fe_clang : Error<"error invoking%s: %s">, DefaultFatal;
|
||||
|
||||
// PCH reader
|
||||
def err_relocatable_without_without_isysroot : Error<
|
||||
"must specify system root with -isysroot when building a relocatable "
|
||||
|
|
@ -105,6 +109,10 @@ def warn_pch_objective_c2 : Error<
|
|||
def warn_pch_nonfragile_abi : Error<
|
||||
"PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C "
|
||||
"ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">;
|
||||
def warn_pch_nonfragile_abi2 : Error<
|
||||
"PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 "
|
||||
"Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 "
|
||||
"Objective-C ABI is selected">;
|
||||
def warn_pch_extensions : Error<
|
||||
"extensions were %select{enabled|disabled}0 in PCH file but are "
|
||||
"currently %select{enabled|disabled}1">;
|
||||
|
|
@ -132,6 +140,9 @@ def warn_pch_elide_constructors : Error<
|
|||
def warn_pch_exceptions : Error<
|
||||
"exceptions were %select{disabled|enabled}0 in PCH file but "
|
||||
"are currently %select{disabled|enabled}1">;
|
||||
def warn_pch_sjlj_exceptions : Error<
|
||||
"sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
|
||||
"are currently %select{disabled|enabled}1">;
|
||||
def warn_pch_objc_runtime : Error<
|
||||
"PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
|
||||
"%select{NeXT|GNU}1 runtime is selected">;
|
||||
|
|
|
|||
|
|
@ -96,7 +96,8 @@ def : DiagGroup<"strict-overflow">;
|
|||
def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
|
||||
def : DiagGroup<"strict-prototypes">;
|
||||
def : DiagGroup<"strict-selector-match">;
|
||||
def Switch : DiagGroup<"switch">;
|
||||
def SwitchEnum : DiagGroup<"switch-enum">;
|
||||
def Switch : DiagGroup<"switch", [SwitchEnum]>;
|
||||
def Trigraphs : DiagGroup<"trigraphs">;
|
||||
|
||||
def : DiagGroup<"type-limits">;
|
||||
|
|
@ -118,6 +119,7 @@ def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
|
|||
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
|
||||
def : DiagGroup<"write-strings">;
|
||||
def CharSubscript : DiagGroup<"char-subscripts">;
|
||||
def ForceAlignArgPointer : DiagGroup<"force-align-arg-pointer">;
|
||||
|
||||
// Aggregation warning settings.
|
||||
|
||||
|
|
@ -178,4 +180,4 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
|
|||
// A warning group for warnings that we want to have on by default in clang,
|
||||
// but which aren't on by default in GCC.
|
||||
def NonGCC : DiagGroup<"non-gcc",
|
||||
[SignCompare, Conversion]>;
|
||||
[SignCompare, Conversion, ForceAlignArgPointer]>;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
let Component = "Parse" in {
|
||||
|
||||
def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">;
|
||||
def warn_file_asm_volatile : Warning<
|
||||
"meaningless 'volatile' on asm outside function">;
|
||||
|
||||
def ext_empty_source_file : Extension<"ISO C forbids an empty source file">;
|
||||
def ext_top_level_semi : Extension<
|
||||
|
|
@ -158,12 +160,20 @@ def err_typename_invalid_functionspec : Error<
|
|||
"type name does not allow function specifier to be specified">;
|
||||
def err_invalid_decl_spec_combination : Error<
|
||||
"cannot combine with previous '%0' declaration specifier">;
|
||||
def err_invalid_vector_decl_spec_combination : Error<
|
||||
"cannot combine with previous '%0' declaration specifier. \"__vector\" must be first">;
|
||||
def err_invalid_pixel_decl_spec_combination : Error<
|
||||
"\"__pixel\" must be preceded by \"__vector\". '%0' declaration specifier not allowed here">;
|
||||
def err_invalid_vector_double_decl_spec_combination : Error<
|
||||
"cannot use \"double\" with \"__vector\"">;
|
||||
def warn_vector_long_decl_spec_combination : Warning<
|
||||
"Use of \"long\" with \"__vector\" is deprecated">;
|
||||
def err_friend_invalid_in_context : Error<
|
||||
"'friend' used outside of class">;
|
||||
def err_unknown_typename : Error<
|
||||
"unknown type name %0">;
|
||||
def err_use_of_tag_name_without_tag : Error<
|
||||
"use of tagged type %0 without '%1' tag">;
|
||||
"must use '%1' tag to refer to type %0%select{| in this scope}2">;
|
||||
def err_expected_ident_in_using : Error<
|
||||
"expected an identifier in using directive">;
|
||||
def err_unexected_colon_in_nested_name_spec : Error<
|
||||
|
|
@ -303,6 +313,9 @@ def err_out_of_line_type_names_constructor : Error<
|
|||
|
||||
def err_expected_qualified_after_typename : Error<
|
||||
"expected a qualified name after 'typename'">;
|
||||
def err_expected_semi_after_tagdecl : Error<
|
||||
"expected ';' after %0">;
|
||||
|
||||
def err_typename_refers_to_non_type_template : Error<
|
||||
"typename specifier refers to a non-template">;
|
||||
def err_expected_type_name_after_typename : Error<
|
||||
|
|
|
|||
|
|
@ -85,7 +85,11 @@ def warn_unused_variable : Warning<"unused variable %0">,
|
|||
InGroup<UnusedVariable>, DefaultIgnore;
|
||||
def warn_decl_in_param_list : Warning<
|
||||
"declaration of %0 will not be visible outside of this function">;
|
||||
|
||||
def err_array_star_in_function_definition : Error<
|
||||
"variable length array must be bound in function definition">;
|
||||
def warn_unused_function : Warning<"unused function %0">,
|
||||
InGroup<UnusedFunction>, DefaultIgnore;
|
||||
|
||||
def warn_implicit_function_decl : Warning<
|
||||
"implicit declaration of function %0">,
|
||||
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
|
||||
|
|
@ -388,6 +392,11 @@ def err_deleted_non_function : Error<
|
|||
def err_deleted_decl_not_first : Error<
|
||||
"deleted definition must be first declaration">;
|
||||
|
||||
def warn_weak_vtable : Warning<
|
||||
"%0 has no out-of-line virtual method definitions; its vtable will be "
|
||||
"emitted in every translation unit">,
|
||||
InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore;
|
||||
|
||||
// C++ exception specifications
|
||||
def err_exception_spec_in_typedef : Error<
|
||||
"exception specifications are not allowed in typedefs">;
|
||||
|
|
@ -410,17 +419,20 @@ def err_deep_exception_specs_differ : Error<
|
|||
// C++ access checking
|
||||
def err_class_redeclared_with_different_access : Error<
|
||||
"%0 redeclared with '%1' access">;
|
||||
def err_access_private : Error<"%0 is a private member of %1">;
|
||||
def err_access_ctor_private : Error<"calling a private constructor of %0">;
|
||||
// Say something about the context for these?
|
||||
def err_access_protected : Error<"%0 is a protected member of %1">;
|
||||
def err_access_ctor_protected : Error<"calling a protected constructor of %0">;
|
||||
def note_previous_access_declaration : Note<
|
||||
"previously declared '%1' here">;
|
||||
def err_access_outside_class : Error<
|
||||
"access to %select{private|protected}0 member outside any class context">;
|
||||
def note_access_natural : Note<"declared %select{private|protected}0 here">;
|
||||
def note_access_natural : Note<
|
||||
"%select{|implicitly }1declared %select{private|protected}0 here">;
|
||||
def note_access_constrained_by_path : Note<
|
||||
"access to decl constrained by %select{private|protected}0 inheritance">;
|
||||
def err_access_protected : Error<
|
||||
"access to protected member of %0 from %1, which is not a subclass">;
|
||||
def err_access_private : Error<
|
||||
"access to private member of %0 from %1">;
|
||||
"constrained by %select{|implicitly }1%select{private|protected}0"
|
||||
" inheritance here">;
|
||||
|
||||
// C++ name lookup
|
||||
def err_incomplete_nested_name_spec : Error<
|
||||
|
|
@ -446,10 +458,14 @@ def err_mutable_nonmember : Error<
|
|||
"'mutable' can only be applied to member variables">;
|
||||
def err_virtual_non_function : Error<
|
||||
"'virtual' can only appear on non-static member functions">;
|
||||
def err_explicit_non_function : Error<
|
||||
"'explicit' can only appear on non-static member functions">;
|
||||
def err_virtual_out_of_class : Error<
|
||||
"'virtual' can only be specified inside the class definition">;
|
||||
def err_explicit_non_function : Error<
|
||||
"'explicit' can only appear on non-static member functions">;
|
||||
def err_explicit_out_of_class : Error<
|
||||
"'explicit' can only be specified inside the class definition">;
|
||||
def err_explicit_non_ctor_or_conv_function : Error<
|
||||
"'explicit' can only be applied to a constructor or conversion function">;
|
||||
def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
|
||||
def err_static_out_of_line : Error<
|
||||
"'static' can only be specified inside the class definition">;
|
||||
|
|
@ -498,9 +514,8 @@ def note_overridden_virtual_function : Note<
|
|||
"overridden virtual function is here">;
|
||||
|
||||
def err_covariant_return_inaccessible_base : Error<
|
||||
"return type of virtual function %2 is not covariant with the return type "
|
||||
"of the function it overrides "
|
||||
"(conversion from %0 to inaccessible base class %1)">, NoSFINAE;
|
||||
"invalid covariant return for virtual function: %1 is a "
|
||||
"%select{private|protected}2 base class of %0">, NoSFINAE;
|
||||
def err_covariant_return_ambiguous_derived_to_base_conv : Error<
|
||||
"return type of virtual function %3 is not covariant with the return type of "
|
||||
"the function it overrides (ambiguous conversion from derived class "
|
||||
|
|
@ -547,7 +562,7 @@ def err_destructor_name : Error<
|
|||
def err_init_conversion_failed : Error<
|
||||
"cannot initialize %select{a variable|a parameter|return object|an "
|
||||
"exception object|a member subobject|an array element|a new value|a value|a "
|
||||
"base class|an array element}0 of type %1 with an %select{rvalue|lvalue}2 of "
|
||||
"base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of "
|
||||
"type %3">;
|
||||
|
||||
def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
|
||||
|
|
@ -556,14 +571,14 @@ def err_invalid_initialization : Error<
|
|||
def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue "
|
||||
"due to multiple conversion functions">;
|
||||
def err_not_reference_to_const_init : Error<
|
||||
"non-const lvalue reference to type %0 cannot be initialized "
|
||||
"with a %select{value|temporary}1 of type %2">;
|
||||
"%select{non-const|volatile}0 lvalue reference to type %1 cannot be "
|
||||
"initialized with a %select{value|temporary}2 of type %3">;
|
||||
def err_lvalue_reference_bind_to_temporary : Error<
|
||||
"non-const lvalue reference to type %0 cannot bind to a temporary of type "
|
||||
"%1">;
|
||||
"%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
|
||||
"temporary of type %2">;
|
||||
def err_lvalue_reference_bind_to_unrelated : Error<
|
||||
"non-const lvalue reference to type %0 cannot bind to a value of unrelated "
|
||||
"type %1">;
|
||||
"%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
|
||||
"value of unrelated type %2">;
|
||||
def err_reference_bind_drops_quals : Error<
|
||||
"binding of reference to type %0 to a value of type %1 drops qualifiers">;
|
||||
def err_reference_bind_failed : Error<
|
||||
|
|
@ -580,10 +595,14 @@ def err_reference_init_drops_quals : Error<
|
|||
"qualifiers">;
|
||||
def err_reference_bind_to_bitfield : Error<
|
||||
"%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
|
||||
def err_reference_bind_to_vector_element : Error<
|
||||
"%select{non-const|volatile}0 reference cannot bind to vector element">;
|
||||
def err_reference_var_requires_init : Error<
|
||||
"declaration of reference variable %0 requires an initializer">;
|
||||
def err_const_var_requires_init : Error<
|
||||
"declaration of const variable '%0' requires an initializer">;
|
||||
def err_reference_without_init : Error<
|
||||
"reference to type %0 requires an initializer">;
|
||||
def err_reference_has_multiple_inits : Error<
|
||||
"reference cannot be initialized with multiple values">;
|
||||
def err_init_non_aggr_init_list : Error<
|
||||
|
|
@ -597,13 +616,16 @@ def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
|
|||
|
||||
def err_temp_copy_no_viable : Error<
|
||||
"no viable copy constructor %select{copying variable|copying parameter|"
|
||||
"returning object|throwing object}0 of type %1">;
|
||||
"returning object|throwing object|copying member subobject|copying array "
|
||||
"element}0 of type %1">;
|
||||
def err_temp_copy_ambiguous : Error<
|
||||
"ambiguous copy constructor call when %select{copying variable|copying "
|
||||
"parameter|returning object|throwing object}0 of type %1">;
|
||||
"parameter|returning object|throwing object|copying member subobject|copying "
|
||||
"array element}0 of type %1">;
|
||||
def err_temp_copy_deleted : Error<
|
||||
"%select{copying variable|copying parameter|returning object|throwing "
|
||||
"object}0 of type %1 invokes deleted copy constructor">;
|
||||
"object|copying member subobject|copying array element}0 of type %1 invokes "
|
||||
"deleted copy constructor">;
|
||||
|
||||
// C++0x decltype
|
||||
def err_cannot_determine_declared_type_of_overloaded_function : Error<
|
||||
|
|
@ -702,6 +724,9 @@ def err_attribute_aligned_not_power_of_two : Error<
|
|||
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
|
||||
"'%0' redeclared without %1 attribute: previous %1 ignored">;
|
||||
def warn_attribute_ignored : Warning<"%0 attribute ignored">;
|
||||
def warn_faap_attribute_ignored : Warning<
|
||||
"force_align_arg_pointer used on function pointer; attribute ignored">,
|
||||
InGroup<ForceAlignArgPointer>;
|
||||
def warn_attribute_precede_definition : Warning<
|
||||
"attribute declaration must precede definition">;
|
||||
def warn_attribute_void_function : Warning<
|
||||
|
|
@ -728,13 +753,18 @@ def err_attribute_wrong_decl_type : Error<
|
|||
"parameter or Objective-C method |function, method or block|"
|
||||
"virtual method or class|function, method, or parameter|class|virtual method"
|
||||
"|member}1 types">;
|
||||
def warn_function_attribute_wrong_type : Warning<
|
||||
"%0 only applies to function types; type here is %1">;
|
||||
def warn_gnu_inline_attribute_requires_inline : Warning<
|
||||
"'gnu_inline' attribute requires function to be marked 'inline',"
|
||||
" attribute ignored">;
|
||||
def err_cconv_change : Error<
|
||||
"function declared '%0' here was previously declared "
|
||||
"%select{'%2'|without calling convention}1">;
|
||||
def err_cconv_knr : Error<
|
||||
"function with no prototype cannot use '%0' calling convention">;
|
||||
"function with no prototype cannot use %0 calling convention">;
|
||||
def err_cconv_varargs : Error<
|
||||
"variadic function cannot use '%0' calling convention">;
|
||||
"variadic function cannot use %0 calling convention">;
|
||||
|
||||
def warn_impcast_vector_scalar : Warning<
|
||||
"implicit cast turns vector to scalar: %0 to %1">,
|
||||
|
|
@ -873,10 +903,7 @@ def err_uninitialized_member_for_assign : Error<
|
|||
"assignment operator">;
|
||||
def note_first_required_here : Note<
|
||||
"synthesized method is first required here">;
|
||||
def err_null_intialized_reference_member : Error<
|
||||
"cannot initialize the member to null in default constructor because "
|
||||
"reference member %0 cannot be null-initialized">;
|
||||
def err_unintialized_member_in_ctor : Error<
|
||||
def err_uninitialized_member_in_ctor : Error<
|
||||
"%select{|implicit default }0constructor for %1 must explicitly initialize "
|
||||
"the %select{reference|const}2 member %3">;
|
||||
|
||||
|
|
@ -915,6 +942,12 @@ def note_ovl_candidate : Note<"candidate "
|
|||
"is the implicit default constructor|"
|
||||
"is the implicit copy constructor|"
|
||||
"is the implicit copy assignment operator}0%1">;
|
||||
|
||||
def note_ovl_candidate_bad_deduction : Note<
|
||||
"candidate template ignored: failed template argument deduction">;
|
||||
def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
|
||||
"couldn't infer template argument %0">;
|
||||
|
||||
// Note that we don't treat templates differently for this diagnostic.
|
||||
def note_ovl_candidate_arity : Note<"candidate "
|
||||
"%select{function|function|constructor|function|function|constructor|"
|
||||
|
|
@ -941,6 +974,13 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
|
|||
"constructor (the implicit copy constructor)|"
|
||||
"function (the implicit copy assignment operator)}0%1 "
|
||||
"not viable: cannot convert argument of incomplete type %2 to %3">;
|
||||
def note_ovl_candidate_bad_overload : Note<"candidate "
|
||||
"%select{function|function|constructor|"
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"function (the implicit copy assignment operator)}0%1"
|
||||
" not viable: no overload of %3 matching %2 for %ordinal4 argument">;
|
||||
def note_ovl_candidate_bad_conv : Note<"candidate "
|
||||
"%select{function|function|constructor|"
|
||||
"function |function |constructor |"
|
||||
|
|
@ -1068,9 +1108,6 @@ def err_template_tag_noparams : Error<
|
|||
def err_template_decl_ref : Error<
|
||||
"cannot refer to class template %0 without a template argument list">;
|
||||
|
||||
def err_typedef_in_def_scope : Error<
|
||||
"cannot use typedef %0 in scope specifier for out-of-line declaration">;
|
||||
|
||||
// C++ Template Argument Lists
|
||||
def err_template_arg_list_different_arity : Error<
|
||||
"%select{too few|too many}0 template arguments for "
|
||||
|
|
@ -1122,6 +1159,8 @@ def err_template_arg_no_ref_bind : Error<
|
|||
def err_template_arg_ref_bind_ignores_quals : Error<
|
||||
"reference binding of non-type template parameter of type %0 to template "
|
||||
"argument of type %1 ignores qualifiers">;
|
||||
def err_template_arg_not_decl_ref : Error<
|
||||
"non-type template argument does not refer to any declaration">;
|
||||
def err_template_arg_not_object_or_func_form : Error<
|
||||
"non-type template argument does not directly refer to an object or "
|
||||
"function">;
|
||||
|
|
@ -1236,6 +1275,8 @@ def err_partial_spec_redeclared : Error<
|
|||
"class template partial specialization %0 cannot be redeclared">;
|
||||
def note_prev_partial_spec_here : Note<
|
||||
"previous declaration of class template partial specialization %0 is here">;
|
||||
def err_partial_spec_fully_specialized : Error<
|
||||
"partial specialization of %0 does not use any of its template parameters">;
|
||||
|
||||
// C++ Function template specializations
|
||||
def err_function_template_spec_no_match : Error<
|
||||
|
|
@ -1442,9 +1483,13 @@ def err_forward_ref_enum : Error<
|
|||
def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
|
||||
def err_duplicate_member : Error<"duplicate member %0">;
|
||||
def ext_enum_value_not_int : Extension<
|
||||
"ISO C restricts enumerator values to range of 'int' (%0 is too large)">;
|
||||
"ISO C restricts enumerator values to range of 'int' (%0 is too "
|
||||
"%select{small|large}1)">;
|
||||
def warn_enum_too_large : Warning<
|
||||
"enumeration values exceed range of largest integer">;
|
||||
def warn_enumerator_too_large : Warning<
|
||||
"enumerator value %0 is not representable in the largest integer type">;
|
||||
|
||||
def warn_illegal_constant_array_size : Extension<
|
||||
"size of static array must be an integer constant expression">;
|
||||
def err_vla_decl_in_file_scope : Error<
|
||||
|
|
@ -1677,6 +1722,8 @@ def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
|
|||
def err_no_member : Error<"no member named %0 in %1">;
|
||||
|
||||
def err_member_redeclared : Error<"class member cannot be redeclared">;
|
||||
def err_member_def_undefined_record : Error<
|
||||
"out-of-line definition of %0 from class %1 without definition">;
|
||||
def err_member_def_does_not_match : Error<
|
||||
"out-of-line definition of %0 does not match any declaration in %1">;
|
||||
def err_nonstatic_member_out_of_line : Error<
|
||||
|
|
@ -1824,7 +1871,11 @@ def ext_integer_complement_complex : Extension<
|
|||
def error_nosetter_property_assignment : Error<
|
||||
"setter method is needed to assign to object using property" " assignment syntax">;
|
||||
def error_no_subobject_property_setting : Error<
|
||||
"cannot assign to a sub-structure of an ivar using property" " assignment syntax">;
|
||||
"cannot assign to a sub-structure of an ivar using property"
|
||||
" assignment syntax">;
|
||||
def error_no_subobject_property_getter_setting : Error<
|
||||
"cannot assign to a sub-structure returned via a getter using property"
|
||||
" assignment syntax">;
|
||||
|
||||
def ext_freestanding_complex : Extension<
|
||||
"complex numbers are an extension in a freestanding C99 implementation">;
|
||||
|
|
@ -1915,7 +1966,9 @@ def err_ambiguous_base_to_derived_cast : Error<
|
|||
def err_static_downcast_via_virtual : Error<
|
||||
"cannot cast %0 to %1 via virtual base %2">;
|
||||
def err_downcast_from_inaccessible_base : Error<
|
||||
"cannot cast %1 to %0 due to inaccessible conversion path">;
|
||||
"cannot cast %select{private|protected}2 base class %1 to %0">;
|
||||
def err_upcast_to_inaccessible_base : Error<
|
||||
"cannot cast %0 to its %select{private|protected}2 base class %1">;
|
||||
def err_bad_dynamic_cast_not_ref_or_ptr : Error<
|
||||
"%0 is not a reference or pointer">;
|
||||
def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">;
|
||||
|
|
@ -1942,7 +1995,8 @@ def err_new_paren_array_nonconst : Error<
|
|||
def err_array_size_not_integral : Error<
|
||||
"array size expression must have integral or enumerated type, not %0">;
|
||||
def err_default_init_const : Error<
|
||||
"default initialization of an object of const type %0">;
|
||||
"default initialization of an object of const type %0"
|
||||
"%select{| requires a user-provided default constructor}1">;
|
||||
def err_delete_operand : Error<"cannot delete expression of type %0">;
|
||||
def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
|
||||
"expression of type %0 to a pointer">;
|
||||
|
|
@ -2245,8 +2299,6 @@ def error_multiple_base_initialization : Error <
|
|||
def err_mem_init_not_member_or_class : Error<
|
||||
"member initializer %0 does not name a non-static data member or base "
|
||||
"class">;
|
||||
def err_mem_initializer_mismatch : Error<
|
||||
"Too many arguments for member initializer %0">;
|
||||
|
||||
def warn_field_initialized : Warning<
|
||||
"member '%0' will be initialized after">,
|
||||
|
|
@ -2435,11 +2487,16 @@ def warn_printf_write_back : Warning<
|
|||
def warn_printf_insufficient_data_args : Warning<
|
||||
"more '%%' conversions than data arguments">, InGroup<Format>;
|
||||
def warn_printf_too_many_data_args : Warning<
|
||||
"more data arguments than '%%' conversions">, InGroup<FormatExtraArgs>;
|
||||
"more data arguments than format specifiers">, InGroup<FormatExtraArgs>;
|
||||
def warn_printf_invalid_conversion : Warning<
|
||||
"invalid conversion '%0'">, InGroup<Format>;
|
||||
"invalid conversion specifier '%0'">, InGroup<Format>;
|
||||
def warn_printf_incomplete_specifier : Warning<
|
||||
"incomplete format specifier">, InGroup<Format>;
|
||||
def warn_printf_missing_format_string : Warning<
|
||||
"format string missing">, InGroup<Format>;
|
||||
def warn_printf_conversion_argument_type_mismatch : Warning<
|
||||
"conversion specifies type %0 but the argument has type %1">,
|
||||
InGroup<Format>;
|
||||
def warn_null_arg : Warning<
|
||||
"null passed to a callee which requires a non-null argument">,
|
||||
InGroup<NonNull>;
|
||||
|
|
@ -2454,12 +2511,18 @@ def warn_printf_asterisk_width_missing_arg : Warning<
|
|||
def warn_printf_asterisk_precision_missing_arg : Warning<
|
||||
"'.*' specified field precision is missing a matching 'int' argument">;
|
||||
def warn_printf_asterisk_width_wrong_type : Warning<
|
||||
"field width should have type 'int', but argument has type %0">,
|
||||
"field width should have type %0, but argument has type %1">,
|
||||
InGroup<Format>;
|
||||
def warn_printf_asterisk_precision_wrong_type : Warning<
|
||||
"field precision should have type 'int', but argument has type %0">,
|
||||
"field precision should have type %0, but argument has type %1">,
|
||||
InGroup<Format>;
|
||||
|
||||
def warn_printf_nonsensical_precision: Warning<
|
||||
"precision used in '%0' conversion specifier (where it has no meaning)">,
|
||||
InGroup<Format>;
|
||||
def warn_printf_nonsensical_flag: Warning<
|
||||
"flag '%0' results in undefined behavior in '%1' conversion specifier">,
|
||||
InGroup<Format>;
|
||||
|
||||
// CHECK: returning address/reference of stack memory
|
||||
def warn_ret_stack_addr : Warning<
|
||||
"address of stack memory associated with local variable %0 returned">;
|
||||
|
|
@ -2511,6 +2574,10 @@ def warn_case_value_overflow : Warning<
|
|||
"overflow converting case value to switch condition type (%0 to %1)">;
|
||||
def err_duplicate_case : Error<"duplicate case value '%0'">;
|
||||
def warn_case_empty_range : Warning<"empty case range specified">;
|
||||
def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">,
|
||||
InGroup<DiagGroup<"switch-enum"> >;
|
||||
def not_in_enum : Warning<"case value not in enumerated type %0">,
|
||||
InGroup<DiagGroup<"switch-enum"> >;
|
||||
def err_typecheck_statement_requires_scalar : Error<
|
||||
"statement requires expression of scalar type (%0 invalid)">;
|
||||
def err_typecheck_statement_requires_integer : Error<
|
||||
|
|
@ -2679,6 +2746,7 @@ def err_undeclared_protocol_suggest : Error<
|
|||
"cannot find protocol declaration for %0; did you mean %1?">;
|
||||
def note_base_class_specified_here : Note<
|
||||
"base class %0 specified here">;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,14 @@ public:
|
|||
unsigned ObjC1 : 1; // Objective-C 1 support enabled.
|
||||
unsigned ObjC2 : 1; // Objective-C 2 support enabled.
|
||||
unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled
|
||||
unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled
|
||||
|
||||
unsigned PascalStrings : 1; // Allow Pascal strings
|
||||
unsigned WritableStrings : 1; // Allow writable strings
|
||||
unsigned LaxVectorConversions : 1;
|
||||
unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
|
||||
unsigned Exceptions : 1; // Support exception handling.
|
||||
unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
|
||||
unsigned RTTI : 1; // Support RTTI information.
|
||||
|
||||
unsigned NeXTRuntime : 1; // Use NeXT runtime.
|
||||
|
|
@ -95,7 +97,9 @@ public:
|
|||
// operators
|
||||
unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
|
||||
// elided if possible.
|
||||
unsigned CatchUndefined :1; // Generate code to check for undefined ops.
|
||||
unsigned CatchUndefined : 1; // Generate code to check for undefined ops.
|
||||
unsigned DumpVtableLayouts : 1; // Dump the layouts of all the emitted
|
||||
// vtables.
|
||||
private:
|
||||
unsigned GC : 2; // Objective-C Garbage Collection modes. We
|
||||
// declare this enum as unsigned because MSVC
|
||||
|
|
@ -124,10 +128,10 @@ public:
|
|||
Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
|
||||
GNUMode = ImplicitInt = Digraphs = 0;
|
||||
HexFloats = 0;
|
||||
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0;
|
||||
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
|
||||
C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
|
||||
CXXOperatorNames = PascalStrings = WritableStrings = 0;
|
||||
Exceptions = Freestanding = NoBuiltin = 0;
|
||||
Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
|
||||
NeXTRuntime = 1;
|
||||
RTTI = 1;
|
||||
LaxVectorConversions = 1;
|
||||
|
|
@ -136,8 +140,7 @@ public:
|
|||
|
||||
SymbolVisibility = (unsigned) Default;
|
||||
|
||||
// FIXME: The default should be 1.
|
||||
ThreadsafeStatics = 0;
|
||||
ThreadsafeStatics = 1;
|
||||
POSIXThreads = 0;
|
||||
Blocks = 0;
|
||||
BlockIntrospection = 0;
|
||||
|
|
@ -167,6 +170,7 @@ public:
|
|||
CharIsSigned = 1;
|
||||
ShortWChar = 0;
|
||||
CatchUndefined = 0;
|
||||
DumpVtableLayouts = 0;
|
||||
}
|
||||
|
||||
GCMode getGCMode() const { return (GCMode) GC; }
|
||||
|
|
|
|||
57
include/clang/Basic/Linkage.h
Normal file
57
include/clang/Basic/Linkage.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//===--- Linkage.h - Linkage enumeration and utilities ----------*- 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 Linkage enumeration and various utility
|
||||
// functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
|
||||
#define LLVM_CLANG_BASIC_LINKAGE_H
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// \brief Describes the different kinds of linkage
|
||||
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
|
||||
enum Linkage {
|
||||
/// \brief No linkage, which means that the entity is unique and
|
||||
/// can only be referred to from within its scope.
|
||||
NoLinkage = 0,
|
||||
|
||||
/// \brief Internal linkage, which indicates that the entity can
|
||||
/// be referred to from within the translation unit (but not other
|
||||
/// translation units).
|
||||
InternalLinkage,
|
||||
|
||||
/// \brief External linkage within a unique namespace. From the
|
||||
/// langauge perspective, these entities have external
|
||||
/// linkage. However, since they reside in an anonymous namespace,
|
||||
/// their names are unique to this translation unit, which is
|
||||
/// equivalent to having internal linkage from the code-generation
|
||||
/// point of view.
|
||||
UniqueExternalLinkage,
|
||||
|
||||
/// \brief External linkage, which indicates that the entity can
|
||||
/// be referred to from other translation units.
|
||||
ExternalLinkage
|
||||
};
|
||||
|
||||
/// \brief Determine whether the given linkage is semantically
|
||||
/// external.
|
||||
inline bool isExternalLinkage(Linkage L) {
|
||||
return L == UniqueExternalLinkage || L == ExternalLinkage;
|
||||
}
|
||||
|
||||
/// \brief Compute the minimum linkage given two linages.
|
||||
static inline Linkage minLinkage(Linkage L1, Linkage L2) {
|
||||
return L1 < L2? L1 : L2;
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_LINKAGE_H
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//===--- PartialDiagnostic.h - Diagnostic "closures" ----------------------===//
|
||||
//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
|
|
|||
|
|
@ -669,12 +669,20 @@ public:
|
|||
::const_iterator fileinfo_iterator;
|
||||
fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
|
||||
fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
|
||||
bool hasFileInfo(const FileEntry *File) const {
|
||||
return FileInfos.find(File) != FileInfos.end();
|
||||
}
|
||||
|
||||
/// PrintStats - Print statistics to stderr.
|
||||
///
|
||||
void PrintStats() const;
|
||||
|
||||
unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
|
||||
|
||||
// FIXME: Exposing this is a little gross; what we want is a good way
|
||||
// to iterate the entries that were not defined in a PCH file (or
|
||||
// any other external source).
|
||||
unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }
|
||||
|
||||
const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const {
|
||||
assert(ID < SLocEntryTable.size() && "Invalid id");
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ namespace clang {
|
|||
AS_private,
|
||||
AS_none
|
||||
};
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
|
||||
|
|
|
|||
|
|
@ -226,11 +226,11 @@ public:
|
|||
/// isValidGCCRegisterName - Returns whether the passed in string
|
||||
/// is a valid register name according to GCC. This is used by Sema for
|
||||
/// inline asm statements.
|
||||
bool isValidGCCRegisterName(const char *Name) const;
|
||||
bool isValidGCCRegisterName(llvm::StringRef Name) const;
|
||||
|
||||
// getNormalizedGCCRegisterName - Returns the "normalized" GCC register name.
|
||||
// For example, on x86 it will return "ax" when "eax" is passed in.
|
||||
const char *getNormalizedGCCRegisterName(const char *Name) const;
|
||||
llvm::StringRef getNormalizedGCCRegisterName(llvm::StringRef Name) const;
|
||||
|
||||
struct ConstraintInfo {
|
||||
enum {
|
||||
|
|
@ -246,10 +246,9 @@ public:
|
|||
std::string ConstraintStr; // constraint: "=rm"
|
||||
std::string Name; // Operand name: [foo] with no []'s.
|
||||
public:
|
||||
ConstraintInfo(const char *str, unsigned strlen, const std::string &name)
|
||||
: Flags(0), TiedOperand(-1), ConstraintStr(str, str+strlen), Name(name) {}
|
||||
explicit ConstraintInfo(const std::string &Str, const std::string &name)
|
||||
: Flags(0), TiedOperand(-1), ConstraintStr(Str), Name(name) {}
|
||||
ConstraintInfo(llvm::StringRef ConstraintStr, llvm::StringRef Name)
|
||||
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
|
||||
Name(Name.str()) {}
|
||||
|
||||
const std::string &getConstraintStr() const { return ConstraintStr; }
|
||||
const std::string &getName() const { return Name; }
|
||||
|
|
@ -321,12 +320,6 @@ public:
|
|||
|
||||
virtual bool useGlobalsForAutomaticVariables() const { return false; }
|
||||
|
||||
/// getUnicodeStringSection - Return the section to use for unicode
|
||||
/// string literals, or 0 if no special section is used.
|
||||
virtual const char *getUnicodeStringSection() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getCFStringSection - Return the section to use for CFString
|
||||
/// literals, or 0 if no special section is used.
|
||||
virtual const char *getCFStringSection() const {
|
||||
|
|
@ -343,7 +336,7 @@ public:
|
|||
/// and give good diagnostics in cases when the assembler or code generator
|
||||
/// would otherwise reject the section specifier.
|
||||
///
|
||||
virtual std::string isValidSectionSpecifier(const llvm::StringRef &SR) const {
|
||||
virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ KEYWORD(__func__ , KEYALL)
|
|||
|
||||
// C++ 2.11p1: Keywords.
|
||||
KEYWORD(asm , KEYCXX|KEYGNU)
|
||||
KEYWORD(bool , BOOLSUPPORT)
|
||||
KEYWORD(bool , BOOLSUPPORT|KEYALTIVEC)
|
||||
KEYWORD(catch , KEYCXX)
|
||||
KEYWORD(class , KEYCXX)
|
||||
KEYWORD(const_cast , KEYCXX)
|
||||
|
|
@ -235,7 +235,7 @@ KEYWORD(delete , KEYCXX)
|
|||
KEYWORD(dynamic_cast , KEYCXX)
|
||||
KEYWORD(explicit , KEYCXX)
|
||||
KEYWORD(export , KEYCXX)
|
||||
KEYWORD(false , BOOLSUPPORT)
|
||||
KEYWORD(false , BOOLSUPPORT|KEYALTIVEC)
|
||||
KEYWORD(friend , KEYCXX)
|
||||
KEYWORD(mutable , KEYCXX)
|
||||
KEYWORD(namespace , KEYCXX)
|
||||
|
|
@ -249,7 +249,7 @@ KEYWORD(static_cast , KEYCXX)
|
|||
KEYWORD(template , KEYCXX)
|
||||
KEYWORD(this , KEYCXX)
|
||||
KEYWORD(throw , KEYCXX)
|
||||
KEYWORD(true , BOOLSUPPORT)
|
||||
KEYWORD(true , BOOLSUPPORT|KEYALTIVEC)
|
||||
KEYWORD(try , KEYCXX)
|
||||
KEYWORD(typename , KEYCXX)
|
||||
KEYWORD(typeid , KEYCXX)
|
||||
|
|
@ -340,6 +340,10 @@ KEYWORD(__ptr64 , KEYALL)
|
|||
KEYWORD(__w64 , KEYALL)
|
||||
KEYWORD(__forceinline , KEYALL)
|
||||
|
||||
// Altivec Extension.
|
||||
KEYWORD(__vector , KEYALTIVEC)
|
||||
KEYWORD(__pixel , KEYALTIVEC)
|
||||
|
||||
// Alternate spelling for various tokens. There are GCC extensions in all
|
||||
// languages, but should not be disabled in strict conformance mode.
|
||||
ALIAS("__attribute__", __attribute, KEYALL)
|
||||
|
|
|
|||
|
|
@ -56,16 +56,16 @@ namespace clang {
|
|||
|
||||
/// \brief Retrieves the repository revision number (or identifer) from which
|
||||
/// this Clang was built.
|
||||
llvm::StringRef getClangRevision();
|
||||
std::string getClangRevision();
|
||||
|
||||
/// \brief Retrieves the full repository version that is an amalgamation of
|
||||
/// the information in getClangRepositoryPath() and getClangRevision().
|
||||
llvm::StringRef getClangFullRepositoryVersion();
|
||||
std::string getClangFullRepositoryVersion();
|
||||
|
||||
/// \brief Retrieves a string representing the complete clang version,
|
||||
/// which includes the clang version number, the repository version,
|
||||
/// and the vendor tag.
|
||||
const char *getClangFullVersion();
|
||||
std::string getClangFullVersion();
|
||||
}
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_VERSION_H
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/Analysis/PathSensitive/BugType.h"
|
||||
#include "clang/Checker/PathSensitive/GRState.h"
|
||||
#include "clang/Checker/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/Checker/BugReporter/BugType.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
|
|
@ -202,7 +202,7 @@ public:
|
|||
~RangedBugReport();
|
||||
|
||||
// FIXME: Move this out of line.
|
||||
void addRange(SourceRange R) {
|
||||
void addRange(SourceRange R) {
|
||||
assert(R.isValid());
|
||||
Ranges.push_back(R);
|
||||
}
|
||||
|
|
@ -464,6 +464,10 @@ const Stmt *GetRetValExpr(const ExplodedNode *N);
|
|||
void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt,
|
||||
const ExplodedNode* N);
|
||||
|
||||
void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
|
||||
const ExplodedNode *N);
|
||||
|
||||
|
||||
} // end namespace clang::bugreporter
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -14,7 +14,6 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
|
||||
#define LLVM_CLANG_ANALYSIS_BUGTYPE
|
||||
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
#include <llvm/ADT/FoldingSet.h>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -31,13 +31,11 @@ class BugReporter;
|
|||
class ObjCImplementationDecl;
|
||||
class LangOptions;
|
||||
class GRExprEngine;
|
||||
class TranslationUnitDecl;
|
||||
|
||||
void CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &map,
|
||||
BugReporter& BR);
|
||||
|
||||
void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
|
||||
bool FullUninitTaint=false);
|
||||
|
||||
GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
|
||||
const LangOptions& lopts);
|
||||
|
||||
|
|
@ -53,8 +51,8 @@ void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D);
|
|||
void RegisterExperimentalChecks(GRExprEngine &Eng);
|
||||
void RegisterExperimentalInternalChecks(GRExprEngine &Eng);
|
||||
|
||||
void CheckLLVMConventions(TranslationUnitDecl &TU, BugReporter &BR);
|
||||
void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR);
|
||||
|
||||
void CheckSizeofPointer(const Decl *D, BugReporter &BR);
|
||||
|
||||
void RegisterCallInliner(GRExprEngine &Eng);
|
||||
40
include/clang/Checker/DomainSpecific/CocoaConventions.h
Normal file
40
include/clang/Checker/DomainSpecific/CocoaConventions.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//===- CocoaConventions.h - Special handling of Cocoa conventions -*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_CHECKER_DS_COCOA
|
||||
#define LLVM_CLANG_CHECKER_DS_COCOA
|
||||
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
||||
namespace clang {
|
||||
namespace cocoa {
|
||||
|
||||
enum NamingConvention { NoConvention, CreateRule, InitRule };
|
||||
|
||||
NamingConvention deriveNamingConvention(Selector S);
|
||||
|
||||
static inline bool followsFundamentalRule(Selector S) {
|
||||
return deriveNamingConvention(S) == CreateRule;
|
||||
}
|
||||
|
||||
bool isRefType(QualType RetTy, llvm::StringRef Prefix,
|
||||
llvm::StringRef Name = llvm::StringRef());
|
||||
|
||||
bool isCFObjectRef(QualType T);
|
||||
|
||||
bool isCocoaObjectRef(QualType T);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H
|
||||
#define LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Checker/PathSensitive/GRState.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H
|
||||
#define LLVM_CLANG_ANALYSIS_ANALYSISMANAGER_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
#include "clang/Analysis/PathSensitive/AnalysisContext.h"
|
||||
#include "clang/Analysis/PathDiagnostic.h"
|
||||
#include "clang/Analysis/AnalysisContext.h"
|
||||
#include "clang/Checker/BugReporter/BugReporter.h"
|
||||
#include "clang/Checker/BugReporter/PathDiagnostic.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
|
||||
#define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
|
|
@ -46,19 +46,19 @@ public:
|
|||
};
|
||||
|
||||
class LazyCompoundValData : public llvm::FoldingSetNode {
|
||||
const GRState *state;
|
||||
const void *store;
|
||||
const TypedRegion *region;
|
||||
public:
|
||||
LazyCompoundValData(const GRState *st, const TypedRegion *r)
|
||||
: state(st), region(r) {}
|
||||
LazyCompoundValData(const void *st, const TypedRegion *r)
|
||||
: store(st), region(r) {}
|
||||
|
||||
const GRState *getState() const { return state; }
|
||||
const void *getStore() const { return store; }
|
||||
const TypedRegion *getRegion() const { return region; }
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const GRState *state,
|
||||
static void Profile(llvm::FoldingSetNodeID& ID, const void *store,
|
||||
const TypedRegion *region);
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, state, region); }
|
||||
void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
|
||||
};
|
||||
|
||||
class BasicValueFactory {
|
||||
|
|
@ -169,7 +169,7 @@ public:
|
|||
const CompoundValData *getCompoundValData(QualType T,
|
||||
llvm::ImmutableList<SVal> Vals);
|
||||
|
||||
const LazyCompoundValData *getLazyCompoundValData(const GRState *state,
|
||||
const LazyCompoundValData *getLazyCompoundValData(const void *store,
|
||||
const TypedRegion *region);
|
||||
|
||||
llvm::ImmutableList<SVal> getEmptySValList() {
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_CHECKER
|
||||
#define LLVM_CLANG_ANALYSIS_CHECKER
|
||||
#include "clang/Analysis/Support/SaveAndRestore.h"
|
||||
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRState.h"
|
||||
#include "clang/Checker/PathSensitive/GRExprEngine.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
PREVISIT(ArraySubscriptExpr, Stmt)
|
||||
PREVISIT(BinaryOperator, Stmt)
|
||||
PREVISIT(CallExpr, Stmt)
|
||||
PREVISIT(CastExpr, Stmt)
|
||||
PREVISIT(CXXOperatorCallExpr, CallExpr)
|
||||
PREVISIT(DeclStmt, Stmt)
|
||||
PREVISIT(ObjCMessageExpr, Stmt)
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_CHECKERVISITOR
|
||||
#define LLVM_CLANG_ANALYSIS_CHECKERVISITOR
|
||||
#include "clang/Analysis/PathSensitive/Checker.h"
|
||||
#include "clang/Checker/PathSensitive/Checker.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -42,7 +42,6 @@ public:
|
|||
return;
|
||||
|
||||
case Stmt::ImplicitCastExprClass:
|
||||
case Stmt::ExplicitCastExprClass:
|
||||
case Stmt::CStyleCastExprClass:
|
||||
static_cast<ImplClass*>(this)->PreVisitCastExpr(C,
|
||||
static_cast<const CastExpr*>(S));
|
||||
|
|
@ -57,7 +56,7 @@ public:
|
|||
case Stmt::NAME ## Class:\
|
||||
static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
|
||||
break;
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
#include "clang/Checker/PathSensitive/CheckerVisitor.def"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,24 +75,26 @@ case Stmt::NAME ## Class:\
|
|||
static_cast<ImplClass*>(this)->\
|
||||
PostVisit ## NAME(C,static_cast<const NAME*>(S));\
|
||||
break;
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
#include "clang/Checker/PathSensitive/CheckerVisitor.def"
|
||||
}
|
||||
}
|
||||
|
||||
void PreVisitStmt(CheckerContext &C, const Stmt *S) {}
|
||||
void PostVisitStmt(CheckerContext &C, const Stmt *S) {}
|
||||
|
||||
void PreVisitCastExpr(CheckerContext &C, const CastExpr *E) {
|
||||
static_cast<ImplClass*>(this)->PreVisitStmt(C, E);
|
||||
}
|
||||
|
||||
#define PREVISIT(NAME, FALLBACK) \
|
||||
void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\
|
||||
PreVisit ## FALLBACK(C, S);\
|
||||
static_cast<ImplClass*>(this)->PreVisit ## FALLBACK(C, S);\
|
||||
}
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
|
||||
#define POSTVISIT(NAME, FALLBACK) \
|
||||
void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\
|
||||
PostVisit ## FALLBACK(C, S);\
|
||||
static_cast<ImplClass*>(this)->PostVisit ## FALLBACK(C, S);\
|
||||
}
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
|
||||
#include "clang/Checker/PathSensitive/CheckerVisitor.def"
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#define LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
|
||||
|
||||
// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place.
|
||||
#include "clang/Analysis/PathSensitive/Store.h"
|
||||
#include "clang/Checker/PathSensitive/Store.h"
|
||||
|
||||
namespace llvm {
|
||||
class APSInt;
|
||||
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
// For using typedefs in StoreManager. Should find a better place for these
|
||||
// typedefs.
|
||||
#include "clang/Analysis/PathSensitive/Store.h"
|
||||
#include "clang/Checker/PathSensitive/Store.h"
|
||||
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
|
||||
|
||||
#include "clang/Analysis/ProgramPoint.h"
|
||||
#include "clang/Analysis/PathSensitive/AnalysisContext.h"
|
||||
#include "clang/Analysis/AnalysisContext.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
|
@ -16,11 +16,11 @@
|
|||
#define LLVM_CLANG_ANALYSIS_GRENGINE
|
||||
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/Analysis/PathSensitive/GRWorkList.h"
|
||||
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
|
||||
#include "clang/Analysis/PathSensitive/GRAuditor.h"
|
||||
#include "clang/Analysis/PathSensitive/GRSubEngine.h"
|
||||
#include "clang/Checker/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/Checker/PathSensitive/GRWorkList.h"
|
||||
#include "clang/Checker/PathSensitive/GRBlockCounter.h"
|
||||
#include "clang/Checker/PathSensitive/GRAuditor.h"
|
||||
#include "clang/Checker/PathSensitive/GRSubEngine.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -16,13 +16,13 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
|
||||
#define LLVM_CLANG_ANALYSIS_GREXPRENGINE
|
||||
|
||||
#include "clang/Analysis/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/Analysis/PathSensitive/GRSubEngine.h"
|
||||
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
|
||||
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
#include "clang/Checker/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/Checker/PathSensitive/GRSubEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRState.h"
|
||||
#include "clang/Checker/PathSensitive/GRSimpleAPICheck.h"
|
||||
#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
|
||||
#include "clang/Checker/BugReporter/BugReporter.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
|
|
@ -328,17 +328,6 @@ protected:
|
|||
void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
|
||||
ExplodedNodeSet& Dst, bool asLValue);
|
||||
|
||||
void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
|
||||
ObjCMessageExpr::arg_iterator I,
|
||||
ObjCMessageExpr::arg_iterator E,
|
||||
ExplodedNode* Pred, ExplodedNodeSet& Dst,
|
||||
bool asLValue);
|
||||
|
||||
void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
|
||||
ExplodedNode* Pred,
|
||||
ExplodedNodeSet& Dst,
|
||||
bool asLValue);
|
||||
|
||||
/// VisitReturnStmt - Transfer function logic for return statements.
|
||||
void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS
|
||||
#define LLVM_CLANG_ANALYSIS_GREXPRENGINE_BUILDERS
|
||||
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRExprEngine.h"
|
||||
#include "clang/Analysis/Support/SaveAndRestore.h"
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_GRAPICHECKS
|
||||
#define LLVM_CLANG_ANALYSIS_GRAPICHECKS
|
||||
|
||||
#include "clang/Analysis/PathSensitive/GRAuditor.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Checker/PathSensitive/GRAuditor.h"
|
||||
#include "clang/Checker/PathSensitive/GRState.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
// FIXME: Reduce the number of includes.
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Environment.h"
|
||||
#include "clang/Analysis/PathSensitive/Store.h"
|
||||
#include "clang/Analysis/PathSensitive/ConstraintManager.h"
|
||||
#include "clang/Analysis/PathSensitive/ValueManager.h"
|
||||
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Checker/PathSensitive/Environment.h"
|
||||
#include "clang/Checker/PathSensitive/Store.h"
|
||||
#include "clang/Checker/PathSensitive/ConstraintManager.h"
|
||||
#include "clang/Checker/PathSensitive/ValueManager.h"
|
||||
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
|
@ -216,7 +216,7 @@ public:
|
|||
/// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
const GRState *bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
const LocationContext *LC,
|
||||
SVal V) const;
|
||||
|
||||
|
|
@ -607,19 +607,24 @@ inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
|
|||
inline const GRState *
|
||||
GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
const LocationContext *LC, SVal V) const {
|
||||
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, LC, V);
|
||||
Store new_store =
|
||||
getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V);
|
||||
return makeWithStore(new_store);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
|
||||
return getStateManager().StoreMgr->BindDecl(this, VR, IVal);
|
||||
Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal);
|
||||
return makeWithStore(new_store);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
|
||||
return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR);
|
||||
Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR);
|
||||
return makeWithStore(new_store);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
|
||||
return getStateManager().StoreMgr->Bind(this, LV, V);
|
||||
Store new_store = getStateManager().StoreMgr->Bind(St, LV, V);
|
||||
return makeWithStore(new_store);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
|
||||
|
|
@ -671,11 +676,11 @@ inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
|
|||
}
|
||||
|
||||
inline SVal GRState::getSVal(Loc LV, QualType T) const {
|
||||
return getStateManager().StoreMgr->Retrieve(this, LV, T).getSVal();
|
||||
return getStateManager().StoreMgr->Retrieve(St, LV, T);
|
||||
}
|
||||
|
||||
inline SVal GRState::getSVal(const MemRegion* R) const {
|
||||
return getStateManager().StoreMgr->Retrieve(this, loc::MemRegionVal(R)).getSVal();
|
||||
return getStateManager().StoreMgr->Retrieve(St, loc::MemRegionVal(R));
|
||||
}
|
||||
|
||||
inline BasicValueFactory &GRState::getBasicVals() const {
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
|
||||
#define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_GRTF
|
||||
#define LLVM_CLANG_ANALYSIS_GRTF
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/Checker/PathSensitive/GRState.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST
|
||||
#define LLVM_CLANG_ANALYSIS_GRWORKLIST
|
||||
|
||||
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
|
||||
#include "clang/Checker/PathSensitive/GRBlockCounter.h"
|
||||
#include <cstddef>
|
||||
|
||||
namespace clang {
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
|
|
@ -249,17 +249,20 @@ public:
|
|||
|
||||
class ElementRegion;
|
||||
|
||||
class RegionRawOffset : public std::pair<const MemRegion*, int64_t> {
|
||||
class RegionRawOffset {
|
||||
private:
|
||||
friend class ElementRegion;
|
||||
|
||||
const MemRegion *Region;
|
||||
int64_t Offset;
|
||||
|
||||
RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
|
||||
: std::pair<const MemRegion*, int64_t>(reg, offset) {}
|
||||
: Region(reg), Offset(offset) {}
|
||||
|
||||
public:
|
||||
// FIXME: Eventually support symbolic offsets.
|
||||
int64_t getByteOffset() const { return second; }
|
||||
const MemRegion *getRegion() const { return first; }
|
||||
int64_t getByteOffset() const { return Offset; }
|
||||
const MemRegion *getRegion() const { return Region; }
|
||||
|
||||
void dumpToStream(llvm::raw_ostream& os) const;
|
||||
void dump() const;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
|
||||
#define LLVM_CLANG_ANALYSIS_RVALUE_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Checker/PathSensitive/SymbolManager.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/ADT/ImmutableList.h"
|
||||
|
||||
|
|
@ -388,7 +388,7 @@ public:
|
|||
const LazyCompoundValData *getCVData() const {
|
||||
return static_cast<const LazyCompoundValData*>(Data);
|
||||
}
|
||||
const GRState *getState() const;
|
||||
const void *getStore() const;
|
||||
const TypedRegion *getRegion() const;
|
||||
|
||||
static bool classof(const SVal *V) {
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
#define LLVM_CLANG_ANALYSIS_SVALUATOR
|
||||
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
|
@ -38,33 +38,8 @@ public:
|
|||
SValuator(ValueManager &valMgr) : ValMgr(valMgr) {}
|
||||
virtual ~SValuator() {}
|
||||
|
||||
template <typename T>
|
||||
class GenericCastResult : public std::pair<const GRState *, T> {
|
||||
public:
|
||||
const GRState *getState() const { return this->first; }
|
||||
T getSVal() const { return this->second; }
|
||||
GenericCastResult(const GRState *s, T v)
|
||||
: std::pair<const GRState*,T>(s, v) {}
|
||||
};
|
||||
SVal EvalCast(SVal V, QualType castTy, QualType originalType);
|
||||
|
||||
class CastResult : public GenericCastResult<SVal> {
|
||||
public:
|
||||
CastResult(const GRState *s, SVal v) : GenericCastResult<SVal>(s, v) {}
|
||||
};
|
||||
|
||||
class DefinedOrUnknownCastResult :
|
||||
public GenericCastResult<DefinedOrUnknownSVal> {
|
||||
public:
|
||||
DefinedOrUnknownCastResult(const GRState *s, DefinedOrUnknownSVal v)
|
||||
: GenericCastResult<DefinedOrUnknownSVal>(s, v) {}
|
||||
};
|
||||
|
||||
CastResult EvalCast(SVal V, const GRState *ST,
|
||||
QualType castTy, QualType originalType);
|
||||
|
||||
DefinedOrUnknownCastResult EvalCast(DefinedOrUnknownSVal V, const GRState *ST,
|
||||
QualType castTy, QualType originalType);
|
||||
|
||||
virtual SVal EvalMinus(NonLoc val) = 0;
|
||||
|
||||
virtual SVal EvalComplement(NonLoc val) = 0;
|
||||
|
|
@ -14,9 +14,9 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_STORE_H
|
||||
#define LLVM_CLANG_ANALYSIS_STORE_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/MemRegion.h"
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Analysis/PathSensitive/ValueManager.h"
|
||||
#include "clang/Checker/PathSensitive/MemRegion.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/ValueManager.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
|
|
@ -41,6 +41,7 @@ protected:
|
|||
|
||||
/// MRMgr - Manages region objects associated with this StoreManager.
|
||||
MemRegionManager &MRMgr;
|
||||
ASTContext &Ctx;
|
||||
|
||||
StoreManager(GRStateManager &stateMgr);
|
||||
|
||||
|
|
@ -54,8 +55,7 @@ public:
|
|||
/// expected type of the returned value. This is used if the value is
|
||||
/// lazily computed.
|
||||
/// \return The value bound to the location \c loc.
|
||||
virtual SValuator::CastResult Retrieve(const GRState *state, Loc loc,
|
||||
QualType T = QualType()) = 0;
|
||||
virtual SVal Retrieve(Store store, Loc loc, QualType T = QualType()) = 0;
|
||||
|
||||
/// Return a state with the specified value bound to the given location.
|
||||
/// \param[in] state The analysis state.
|
||||
|
|
@ -64,7 +64,7 @@ public:
|
|||
/// \return A pointer to a GRState object that contains the same bindings as
|
||||
/// \c state with the addition of having the value specified by \c val bound
|
||||
/// to the location given for \c loc.
|
||||
virtual const GRState *Bind(const GRState *state, Loc loc, SVal val) = 0;
|
||||
virtual Store Bind(Store store, Loc loc, SVal val) = 0;
|
||||
|
||||
virtual Store Remove(Store St, Loc L) = 0;
|
||||
|
||||
|
|
@ -72,10 +72,9 @@ public:
|
|||
/// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
|
||||
/// for the compound literal and 'BegInit' and 'EndInit' represent an
|
||||
/// array of initializer values.
|
||||
virtual const GRState *BindCompoundLiteral(const GRState *state,
|
||||
const CompoundLiteralExpr* cl,
|
||||
const LocationContext *LC,
|
||||
SVal v) = 0;
|
||||
virtual Store BindCompoundLiteral(Store store,
|
||||
const CompoundLiteralExpr* cl,
|
||||
const LocationContext *LC, SVal v) = 0;
|
||||
|
||||
/// getInitialStore - Returns the initial "empty" store representing the
|
||||
/// value bindings upon entry to an analyzed function.
|
||||
|
|
@ -88,20 +87,30 @@ public:
|
|||
/// getSubRegionMap - Returns an opaque map object that clients can query
|
||||
/// to get the subregions of a given MemRegion object. It is the
|
||||
// caller's responsibility to 'delete' the returned map.
|
||||
virtual SubRegionMap *getSubRegionMap(const GRState *state) = 0;
|
||||
virtual SubRegionMap *getSubRegionMap(Store store) = 0;
|
||||
|
||||
virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) = 0;
|
||||
virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) {
|
||||
return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC));
|
||||
}
|
||||
|
||||
virtual SVal getLValueString(const StringLiteral* sl) = 0;
|
||||
virtual SVal getLValueString(const StringLiteral* S) {
|
||||
return ValMgr.makeLoc(MRMgr.getStringRegion(S));
|
||||
}
|
||||
|
||||
SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl,
|
||||
const LocationContext *LC);
|
||||
SVal getLValueCompoundLiteral(const CompoundLiteralExpr* CL,
|
||||
const LocationContext *LC) {
|
||||
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
|
||||
}
|
||||
|
||||
virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0;
|
||||
virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) {
|
||||
return getLValueFieldOrIvar(decl, base);
|
||||
}
|
||||
|
||||
virtual SVal getLValueField(const FieldDecl* D, SVal Base) = 0;
|
||||
virtual SVal getLValueField(const FieldDecl* D, SVal Base) {
|
||||
return getLValueFieldOrIvar(D, Base);
|
||||
}
|
||||
|
||||
virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0;
|
||||
virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base);
|
||||
|
||||
// FIXME: Make out-of-line.
|
||||
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
|
||||
|
|
@ -129,33 +138,31 @@ public:
|
|||
const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy);
|
||||
|
||||
/// EvalBinOp - Perform pointer arithmetic.
|
||||
virtual SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,
|
||||
virtual SVal EvalBinOp(BinaryOperator::Opcode Op,
|
||||
Loc lhs, NonLoc rhs, QualType resultTy) {
|
||||
return UnknownVal();
|
||||
}
|
||||
|
||||
virtual void RemoveDeadBindings(GRState &state, Stmt* Loc,
|
||||
SymbolReaper& SymReaper,
|
||||
virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
|
||||
SymbolReaper& SymReaper,
|
||||
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
|
||||
|
||||
virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
|
||||
SVal initVal) = 0;
|
||||
virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
|
||||
|
||||
virtual const GRState *BindDeclWithNoInit(const GRState *ST,
|
||||
const VarRegion *VR) = 0;
|
||||
virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
|
||||
|
||||
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
|
||||
|
||||
virtual const GRState *InvalidateRegion(const GRState *state,
|
||||
const MemRegion *R,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS) = 0;
|
||||
virtual Store InvalidateRegion(Store store,
|
||||
const MemRegion *R,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS) = 0;
|
||||
|
||||
virtual const GRState *InvalidateRegions(const GRState *state,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS);
|
||||
virtual Store InvalidateRegions(Store store,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS);
|
||||
|
||||
// FIXME: Make out-of-line.
|
||||
virtual const GRState *setExtent(const GRState *state,
|
||||
|
|
@ -192,6 +199,9 @@ protected:
|
|||
/// as another region.
|
||||
SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy,
|
||||
bool performTestOnly = true);
|
||||
|
||||
private:
|
||||
SVal getLValueFieldOrIvar(const Decl* D, SVal Base);
|
||||
};
|
||||
|
||||
// FIXME: Do we still need this?
|
||||
|
|
@ -214,7 +224,7 @@ public:
|
|||
StoreManager *CreateBasicStoreManager(GRStateManager& StMgr);
|
||||
StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
|
||||
StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
|
||||
|
||||
StoreManager *CreateFlatStoreManager(GRStateManager &StMgr);
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
57
include/clang/Checker/PathSensitive/SummaryManager.h
Normal file
57
include/clang/Checker/PathSensitive/SummaryManager.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//== SummaryManager.h - Generic handling of function summaries --*- 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 SummaryManager and related classes, which provides
|
||||
// a generic mechanism for managing function summaries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_CHECKER_SUMMARY
|
||||
#define LLVM_CLANG_CHECKER_SUMMARY
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace summMgr {
|
||||
|
||||
|
||||
/* Key kinds:
|
||||
|
||||
- C functions
|
||||
- C++ functions (name + parameter types)
|
||||
- ObjC methods:
|
||||
- Class, selector (class method)
|
||||
- Class, selector (instance method)
|
||||
- Category, selector (instance method)
|
||||
- Protocol, selector (instance method)
|
||||
- C++ methods
|
||||
- Class, function name + parameter types + const
|
||||
*/
|
||||
|
||||
class SummaryKey {
|
||||
|
||||
};
|
||||
|
||||
} // end namespace clang::summMgr
|
||||
|
||||
class SummaryManagerImpl {
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class SummaryManager : SummaryManagerImpl {
|
||||
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -17,11 +17,11 @@
|
|||
#define LLVM_CLANG_ANALYSIS_AGGREGATE_VALUE_MANAGER_H
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "clang/Analysis/PathSensitive/MemRegion.h"
|
||||
#include "clang/Analysis/PathSensitive/SVals.h"
|
||||
#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Analysis/PathSensitive/SValuator.h"
|
||||
#include "clang/Checker/PathSensitive/MemRegion.h"
|
||||
#include "clang/Checker/PathSensitive/SVals.h"
|
||||
#include "clang/Checker/PathSensitive/BasicValueFactory.h"
|
||||
#include "clang/Checker/PathSensitive/SymbolManager.h"
|
||||
#include "clang/Checker/PathSensitive/SValuator.h"
|
||||
|
||||
namespace llvm { class BumpPtrAllocator; }
|
||||
|
||||
|
|
@ -115,8 +115,8 @@ public:
|
|||
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
|
||||
}
|
||||
|
||||
NonLoc makeLazyCompoundVal(const GRState *state, const TypedRegion *R) {
|
||||
return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(state, R));
|
||||
NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *R) {
|
||||
return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(store, R));
|
||||
}
|
||||
|
||||
NonLoc makeZeroArrayIndex() {
|
||||
|
|
@ -41,6 +41,8 @@ public:
|
|||
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
|
||||
unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
|
||||
unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss
|
||||
unsigned ObjCLegacyDispatch: 1; /// Use legacy Objective-C dispatch, even with
|
||||
/// 2.0 runtime.
|
||||
unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
|
||||
unsigned OptimizeSize : 1; /// If -Os is specified.
|
||||
unsigned SoftFloat : 1; /// -soft-float.
|
||||
|
|
@ -90,12 +92,13 @@ public:
|
|||
NoCommon = 0;
|
||||
NoImplicitFloat = 0;
|
||||
NoZeroInitializedInBSS = 0;
|
||||
ObjCLegacyDispatch = 0;
|
||||
OptimizationLevel = 0;
|
||||
OptimizeSize = 0;
|
||||
UnrollLoops = 0;
|
||||
SoftFloat = 0;
|
||||
TimePasses = 0;
|
||||
UnitAtATime = 1;
|
||||
UnrollLoops = 0;
|
||||
UnwindTables = 0;
|
||||
VerifyModule = 1;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue