diff --git a/bindings/python/README.txt b/bindings/python/README.txt
new file mode 100644
index 00000000000..ccc2619ccf5
--- /dev/null
+++ b/bindings/python/README.txt
@@ -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
+--
diff --git a/bindings/python/clang/__init__.py b/bindings/python/clang/__init__.py
new file mode 100644
index 00000000000..88f30812383
--- /dev/null
+++ b/bindings/python/clang/__init__.py
@@ -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']
+
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
new file mode 100644
index 00000000000..c37c69b79b3
--- /dev/null
+++ b/bindings/python/clang/cindex.py
@@ -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 "" % (
+ 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 "" % (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 "" % (
+ 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 "" % (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']
diff --git a/bindings/python/examples/cindex/cindex-dump.py b/bindings/python/examples/cindex/cindex-dump.py
new file mode 100644
index 00000000000..af7ddab6ea5
--- /dev/null
+++ b/bindings/python/examples/cindex/cindex-dump.py
@@ -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()
+
diff --git a/bindings/python/examples/cindex/cindex-includes.py b/bindings/python/examples/cindex/cindex-includes.py
new file mode 100644
index 00000000000..17500227a34
--- /dev/null
+++ b/bindings/python/examples/cindex/cindex-includes.py
@@ -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()
+
diff --git a/bindings/python/tests/__init__.py b/bindings/python/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/bindings/python/tests/cindex/INPUTS/header1.h b/bindings/python/tests/cindex/INPUTS/header1.h
new file mode 100644
index 00000000000..b4eacbee375
--- /dev/null
+++ b/bindings/python/tests/cindex/INPUTS/header1.h
@@ -0,0 +1,6 @@
+#ifndef HEADER1
+#define HEADER1
+
+#include "header3.h"
+
+#endif
diff --git a/bindings/python/tests/cindex/INPUTS/header2.h b/bindings/python/tests/cindex/INPUTS/header2.h
new file mode 100644
index 00000000000..c4eddc0c562
--- /dev/null
+++ b/bindings/python/tests/cindex/INPUTS/header2.h
@@ -0,0 +1,6 @@
+#ifndef HEADER2
+#define HEADER2
+
+#include "header3.h"
+
+#endif
diff --git a/bindings/python/tests/cindex/INPUTS/header3.h b/bindings/python/tests/cindex/INPUTS/header3.h
new file mode 100644
index 00000000000..6dca764860e
--- /dev/null
+++ b/bindings/python/tests/cindex/INPUTS/header3.h
@@ -0,0 +1,3 @@
+// Not a guarded header!
+
+void f();
diff --git a/bindings/python/tests/cindex/INPUTS/hello.cpp b/bindings/python/tests/cindex/INPUTS/hello.cpp
new file mode 100644
index 00000000000..7ef086e56b2
--- /dev/null
+++ b/bindings/python/tests/cindex/INPUTS/hello.cpp
@@ -0,0 +1,6 @@
+#include "stdio.h"
+
+int main(int argc, char* argv[]) {
+ printf("hello world\n");
+ return 0;
+}
diff --git a/bindings/python/tests/cindex/INPUTS/include.cpp b/bindings/python/tests/cindex/INPUTS/include.cpp
new file mode 100644
index 00000000000..60cfdaae4d0
--- /dev/null
+++ b/bindings/python/tests/cindex/INPUTS/include.cpp
@@ -0,0 +1,5 @@
+#include "header1.h"
+#include "header2.h"
+#include "header1.h"
+
+int main() { }
diff --git a/bindings/python/tests/cindex/INPUTS/parse_arguments.c b/bindings/python/tests/cindex/INPUTS/parse_arguments.c
new file mode 100644
index 00000000000..7196486c78a
--- /dev/null
+++ b/bindings/python/tests/cindex/INPUTS/parse_arguments.c
@@ -0,0 +1,2 @@
+int DECL_ONE = 1;
+int DECL_TWO = 2;
diff --git a/bindings/python/tests/cindex/__init__.py b/bindings/python/tests/cindex/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
new file mode 100644
index 00000000000..a653ba7bf28
--- /dev/null
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -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
diff --git a/bindings/python/tests/cindex/test_cursor_kind.py b/bindings/python/tests/cindex/test_cursor_kind.py
new file mode 100644
index 00000000000..bdfa3185583
--- /dev/null
+++ b/bindings/python/tests/cindex/test_cursor_kind.py
@@ -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
diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py
new file mode 100644
index 00000000000..85187652917
--- /dev/null
+++ b/bindings/python/tests/cindex/test_diagnostics.py
@@ -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 = '
diff --git a/bindings/python/tests/cindex/test_index.py b/bindings/python/tests/cindex/test_index.py
new file mode 100644
index 00000000000..dc173f04d21
--- /dev/null
+++ b/bindings/python/tests/cindex/test_index.py
@@ -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)
diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py
new file mode 100644
index 00000000000..3c05c3f06af
--- /dev/null
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -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])
+
+
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index d1cd032ec03..e24b54d3e89 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -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 = ""; };
1A535EDB107BC47B000C3AE7 /* CanonicalType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CanonicalType.h; path = clang/AST/CanonicalType.h; sourceTree = ""; };
1A5D5E570E5E81010023C059 /* CGCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXX.cpp; path = lib/CodeGen/CGCXX.cpp; sourceTree = ""; tabWidth = 2; };
+ 1A621BB5110FE6AA009E6834 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetInfo.cpp; path = lib/CodeGen/TargetInfo.cpp; sourceTree = ""; tabWidth = 2; };
+ 1A621BB6110FE6AA009E6834 /* TargetInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TargetInfo.h; path = lib/CodeGen/TargetInfo.h; sourceTree = ""; tabWidth = 2; };
+ 1A621C3A11111D61009E6834 /* CIndexCodeCompletion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexCodeCompletion.cpp; path = tools/CIndex/CIndexCodeCompletion.cpp; sourceTree = ""; };
+ 1A621C3B11111D61009E6834 /* CIndexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexer.cpp; path = tools/CIndex/CIndexer.cpp; sourceTree = ""; };
+ 1A621C3C11111D61009E6834 /* CIndexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CIndexer.h; path = tools/CIndex/CIndexer.h; sourceTree = ""; };
+ 1A621C3D11111D61009E6834 /* CIndexInclusionStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexInclusionStack.cpp; path = tools/CIndex/CIndexInclusionStack.cpp; sourceTree = ""; };
+ 1A621C3E11111D61009E6834 /* CIndexUSRs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndexUSRs.cpp; path = tools/CIndex/CIndexUSRs.cpp; sourceTree = ""; };
+ 1A621C3F11111D61009E6834 /* CXCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXCursor.cpp; path = tools/CIndex/CXCursor.cpp; sourceTree = ""; };
+ 1A621C4011111D61009E6834 /* CXCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXCursor.h; path = tools/CIndex/CXCursor.h; sourceTree = ""; };
+ 1A621C4111111D61009E6834 /* CXSourceLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXSourceLocation.h; path = tools/CIndex/CXSourceLocation.h; sourceTree = ""; };
1A649E1D0F9599D9005B965E /* CGBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGBlocks.h; path = lib/CodeGen/CGBlocks.h; sourceTree = ""; };
1A649E1E0F9599DA005B965E /* CGCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGCXX.h; path = lib/CodeGen/CGCXX.h; sourceTree = ""; tabWidth = 2; };
1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CodeCompleteConsumer.cpp; path = lib/Sema/CodeCompleteConsumer.cpp; sourceTree = ""; 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 = ""; tabWidth = 2; };
1AE4EE3B103B89CA00888A23 /* TreeTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TreeTransform.h; path = lib/Sema/TreeTransform.h; sourceTree = ""; tabWidth = 2; };
1AE4EE3D103B89ED00888A23 /* StmtProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtProfile.cpp; path = lib/AST/StmtProfile.cpp; sourceTree = ""; tabWidth = 2; };
- 1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = ""; tabWidth = 2; };
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = ""; tabWidth = 2; };
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = ""; tabWidth = 2; };
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = ""; 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 = ""; };
9012911C1048068D0083456D /* ASTUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTUnit.cpp; path = lib/Frontend/ASTUnit.cpp; sourceTree = ""; };
9012911F104812F90083456D /* CIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndex.cpp; path = tools/CIndex/CIndex.cpp; sourceTree = ""; };
- 90129120104812F90083456D /* CIndex.exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CIndex.exports; path = tools/CIndex/CIndex.exports; sourceTree = ""; };
904753791096376F00CBDDDD /* CXXInheritance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXXInheritance.h; path = clang/AST/CXXInheritance.h; sourceTree = ""; };
9047537A1096376F00CBDDDD /* Redeclarable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Redeclarable.h; path = clang/AST/Redeclarable.h; sourceTree = ""; };
9047537B1096376F00CBDDDD /* TypeLoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLoc.h; path = clang/AST/TypeLoc.h; sourceTree = ""; };
@@ -727,7 +740,7 @@
DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitPreprocessor.cpp; path = lib/Frontend/InitPreprocessor.cpp; sourceTree = ""; };
DECB734E0FA3ED8400F5FBC7 /* StmtObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StmtObjC.h; path = clang/AST/StmtObjC.h; sourceTree = ""; };
DECB73550FA3EE5A00F5FBC7 /* StmtCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StmtCXX.h; path = clang/AST/StmtCXX.h; sourceTree = ""; };
- DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderStmt.cpp; path = lib/Frontend/PCHReaderStmt.cpp; sourceTree = ""; };
+ DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderStmt.cpp; path = lib/Frontend/PCHReaderStmt.cpp; sourceTree = ""; tabWidth = 2; };
DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderDecl.cpp; path = lib/Frontend/PCHReaderDecl.cpp; sourceTree = ""; };
DECB77F60FA5850200F5FBC7 /* PCHWriterDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriterDecl.cpp; path = lib/Frontend/PCHWriterDecl.cpp; sourceTree = ""; };
DECB78160FA5882F00F5FBC7 /* PCHWriterStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriterStmt.cpp; path = lib/Frontend/PCHWriterStmt.cpp; sourceTree = ""; };
@@ -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 = "";
@@ -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 = "";
@@ -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;
};
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index e2a44eaed0b..d32842b5d23 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -205,12 +205,28 @@ is used in the file argument.
Vectors and Extended Vectors
-Supports the GCC vector extensions, plus some stuff like V[1]. ext_vector
-with V.xyzw syntax and other tidbits. See also __builtin_shufflevector.
+Supports the GCC vector extensions, plus some stuff like V[1].
+
+Also supports ext_vector, which additionally support for V.xyzw
+syntax and other tidbits as seen in OpenCL. An example is:
+
+
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+
+float4 foo(float2 a, float2 b) {
+ float4 c;
+ c.xz = a;
+ c.yw = b;
+ return c;
+}
+
Query for this feature with __has_feature(attribute_ext_vector_type).
+See also __builtin_shufflevector.
+
Checks for Standard Language Features
diff --git a/docs/UsersManual.html b/docs/UsersManual.html
index 13e02094147..41715bb2ac6 100644
--- a/docs/UsersManual.html
+++ b/docs/UsersManual.html
@@ -789,14 +789,12 @@ definition.
C++ Language Features
-At this point, Clang C++ is not generally useful. However, Clang C++ support
+
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 C++ Status page for details or
ask on the mailing list about how you can help.
-Note that the clang driver will refuse to even try to use clang to compile
-C++ code unless you pass the -ccc-clang-cxx option to the driver. If
-you really want to play with Clang's C++ support, please pass that flag.
+Note that released Clang compilers will refuse to even try to use clang to compile C++ code unless you pass the -ccc-clang-cxx 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 -ccc-clang-cxx flag.
Objective C++ Language Features
diff --git a/examples/PrintFunctionNames/Makefile b/examples/PrintFunctionNames/Makefile
index 3c0c1f82ad8..57d3ba9b0cd 100644
--- a/examples/PrintFunctionNames/Makefile
+++ b/examples/PrintFunctionNames/Makefile
@@ -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
diff --git a/examples/wpa/Makefile b/examples/wpa/Makefile
index 54b61d08571..2be7ff10d89 100644
--- a/examples/wpa/Makefile
+++ b/examples/wpa/Makefile
@@ -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.
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index ef17ed1ca8b..84ec4724e0d 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -36,23 +36,23 @@ extern "C" {
/** \defgroup CINDEX C Interface to Clang
*
- * The C Interface to Clang provides a relatively small API that exposes
+ * The C Interface to Clang provides a relatively small API that exposes
* facilities for parsing source code into an abstract syntax tree (AST),
* loading already-parsed ASTs, traversing the AST, associating
* physical source locations with elements within the AST, and other
* facilities that support Clang-based development tools.
*
- * This C interface to Clang will never provide all of the information
+ * This C interface to Clang will never provide all of the information
* representation stored in Clang's C++ AST, nor should it: the intent is to
* maintain an API that is relatively stable from one release to the next,
* providing only the basic functionality needed to support development tools.
- *
- * To avoid namespace pollution, data types are prefixed with "CX" and
+ *
+ * To avoid namespace pollution, data types are prefixed with "CX" and
* functions are prefixed with "clang_".
*
* @{
*/
-
+
/**
* \brief An "index" that consists of a set of translation units that would
* typically be linked together into an executable or library.
@@ -69,7 +69,7 @@ typedef void *CXTranslationUnit; /* A translation unit instance. */
* to various callbacks and visitors.
*/
typedef void *CXClientData;
-
+
/**
* \brief Provides the contents of a file that has not yet been saved to disk.
*
@@ -78,14 +78,14 @@ typedef void *CXClientData;
* yet been saved to disk.
*/
struct CXUnsavedFile {
- /**
- * \brief The file whose contents have not yet been saved.
+ /**
+ * \brief The file whose contents have not yet been saved.
*
* This file must already exist in the file system.
*/
const char *Filename;
- /**
+ /**
* \brief A null-terminated buffer containing the unsaved contents
* of this file.
*/
@@ -103,7 +103,7 @@ struct CXUnsavedFile {
*
* @{
*/
-
+
/**
* \brief A character string.
*
@@ -132,38 +132,36 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
/**
* @}
*/
-
-/**
+
+/**
* \brief clang_createIndex() provides a shared context for creating
* translation units. It provides two options:
*
* - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
* declarations (when loading any new translation units). A "local" declaration
- * is one that belongs in the translation unit itself and not in a precompiled
+ * is one that belongs in the translation unit itself and not in a precompiled
* header that was used by the translation unit. If zero, all declarations
* will be enumerated.
*
- * - displayDiagnostics: when non-zero, diagnostics will be output. If zero,
- * diagnostics will be ignored.
- *
* Here is an example:
*
- * // excludeDeclsFromPCH = 1, displayDiagnostics = 1
- * Idx = clang_createIndex(1, 1);
+ * // excludeDeclsFromPCH = 1
+ * Idx = clang_createIndex(1);
*
* // IndexTest.pch was produced with the following command:
* // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
* TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
*
* // This will load all the symbols from 'IndexTest.pch'
- * clang_visitChildren(clang_getTranslationUnitCursor(TU),
+ * clang_visitChildren(clang_getTranslationUnitCursor(TU),
* TranslationUnitVisitor, 0);
* clang_disposeTranslationUnit(TU);
*
* // This will load all the symbols from 'IndexTest.c', excluding symbols
* // from 'IndexTest.pch'.
- * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch", 0 };
- * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args);
+ * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" };
+ * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args,
+ * 0, 0);
* clang_visitChildren(clang_getTranslationUnitCursor(TU),
* TranslationUnitVisitor, 0);
* clang_disposeTranslationUnit(TU);
@@ -172,14 +170,18 @@ CINDEX_LINKAGE void clang_disposeString(CXString string);
* -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
* (which gives the indexer the same performance benefit as the compiler).
*/
-CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
- int displayDiagnostics);
+CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH);
+
+/**
+ * \brief Destroy the given index.
+ *
+ * The index must not be destroyed until all of the translation units created
+ * within that index have been destroyed.
+ */
CINDEX_LINKAGE void clang_disposeIndex(CXIndex index);
-CINDEX_LINKAGE CXString
-clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
/**
- * \brief Request that AST's be generated external for API calls which parse
+ * \brief Request that AST's be generated externally for API calls which parse
* source code on the fly, e.g. \see createTranslationUnitFromSourceFile.
*
* Note: This is for debugging purposes only, and may be removed at a later
@@ -190,18 +192,373 @@ clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
*/
CINDEX_LINKAGE void clang_setUseExternalASTGeneration(CXIndex index,
int value);
-
/**
- * \brief Create a translation unit from an AST file (-emit-ast).
+ * \defgroup CINDEX_FILES File manipulation routines
+ *
+ * @{
*/
-CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
- CXIndex, const char *ast_filename
-);
/**
- * \brief Destroy the specified CXTranslationUnit object.
- */
-CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
+ * \brief A particular source file that is part of a translation unit.
+ */
+typedef void *CXFile;
+
+
+/**
+ * \brief Retrieve the complete file and path name of the given file.
+ */
+CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
+
+/**
+ * \brief Retrieve the last modification time of the given file.
+ */
+CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
+
+/**
+ * \brief Retrieve a file handle within the given translation unit.
+ *
+ * \param tu the translation unit
+ *
+ * \param file_name the name of the file.
+ *
+ * \returns the file handle for the named file in the translation unit \p tu,
+ * or a NULL file handle if the file was not a part of this translation unit.
+ */
+CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
+ const char *file_name);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_LOCATIONS Physical source locations
+ *
+ * Clang represents physical source locations in its abstract syntax tree in
+ * great detail, with file, line, and column information for the majority of
+ * the tokens parsed in the source code. These data types and functions are
+ * used to represent source location information, either for a particular
+ * point in the program or for a range of points in the program, and extract
+ * specific location information from those data types.
+ *
+ * @{
+ */
+
+/**
+ * \brief Identifies a specific source location within a translation
+ * unit.
+ *
+ * Use clang_getInstantiationLocation() to map a source location to a
+ * particular file, line, and column.
+ */
+typedef struct {
+ void *ptr_data[2];
+ unsigned int_data;
+} CXSourceLocation;
+
+/**
+ * \brief Identifies a half-open character range in the source code.
+ *
+ * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
+ * starting and end locations from a source range, respectively.
+ */
+typedef struct {
+ void *ptr_data[2];
+ unsigned begin_int_data;
+ unsigned end_int_data;
+} CXSourceRange;
+
+/**
+ * \brief Retrieve a NULL (invalid) source location.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getNullLocation();
+
+/**
+ * \determine Determine whether two source locations, which must refer into
+ * the same translation unit, refer to exactly the same point in the source
+ * code.
+ *
+ * \returns non-zero if the source locations refer to the same location, zero
+ * if they refer to different locations.
+ */
+CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
+ CXSourceLocation loc2);
+
+/**
+ * \brief Retrieves the source location associated with a given file/line/column
+ * in a particular translation unit.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+ CXFile file,
+ unsigned line,
+ unsigned column);
+
+/**
+ * \brief Retrieve a NULL (invalid) source range.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getNullRange();
+
+/**
+ * \brief Retrieve a source range given the beginning and ending source
+ * locations.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
+ CXSourceLocation end);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param file [out] if non-NULL, will be set to the file to which the given
+ * source location points.
+ *
+ * \param line [out] if non-NULL, will be set to the line to which the given
+ * source location points.
+ *
+ * \param column [out] if non-NULL, will be set to the column to which the given
+ * source location points.
+ *
+ * \param offset [out] if non-NULL, will be set to the offset into the
+ * buffer to which the given source location points.
+ */
+CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+/**
+ * \brief Retrieve a source location representing the first character within a
+ * source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
+
+/**
+ * \brief Retrieve a source location representing the last character within a
+ * source range.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_DIAG Diagnostic reporting
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes the severity of a particular diagnostic.
+ */
+enum CXDiagnosticSeverity {
+ /**
+ * \brief A diagnostic that has been suppressed, e.g., by a command-line
+ * option.
+ */
+ CXDiagnostic_Ignored = 0,
+
+ /**
+ * \brief This diagnostic is a note that should be attached to the
+ * previous (non-note) diagnostic.
+ */
+ CXDiagnostic_Note = 1,
+
+ /**
+ * \brief This diagnostic indicates suspicious code that may not be
+ * wrong.
+ */
+ CXDiagnostic_Warning = 2,
+
+ /**
+ * \brief This diagnostic indicates that the code is ill-formed.
+ */
+ CXDiagnostic_Error = 3,
+
+ /**
+ * \brief This diagnostic indicates that the code is ill-formed such
+ * that future parser recovery is unlikely to produce useful
+ * results.
+ */
+ CXDiagnostic_Fatal = 4
+};
+
+/**
+ * \brief Describes the kind of fix-it hint expressed within a
+ * diagnostic.
+ */
+enum CXFixItKind {
+ /**
+ * \brief A fix-it hint that inserts code at a particular position.
+ */
+ CXFixIt_Insertion = 0,
+
+ /**
+ * \brief A fix-it hint that removes code within a range.
+ */
+ CXFixIt_Removal = 1,
+
+ /**
+ * \brief A fix-it hint that replaces the code within a range with another
+ * string.
+ */
+ CXFixIt_Replacement = 2
+};
+
+/**
+ * \brief A single diagnostic, containing the diagnostic's severity,
+ * location, text, source ranges, and fix-it hints.
+ */
+typedef void *CXDiagnostic;
+
+/**
+ * \brief Callback function invoked for each diagnostic emitted during
+ * translation.
+ *
+ * \param Diagnostic the diagnostic emitted during translation. This
+ * diagnostic pointer is only valid during the execution of the
+ * callback.
+ *
+ * \param ClientData the callback client data.
+ */
+typedef void (*CXDiagnosticCallback)(CXDiagnostic Diagnostic,
+ CXClientData ClientData);
+
+/**
+ * \brief Determine the severity of the given diagnostic.
+ */
+CINDEX_LINKAGE enum CXDiagnosticSeverity
+clang_getDiagnosticSeverity(CXDiagnostic);
+
+/**
+ * \brief Retrieve the source location of the given diagnostic.
+ *
+ * This location is where Clang would print the caret ('^') when
+ * displaying the diagnostic on the command line.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
+
+/**
+ * \brief Retrieve the text of the given diagnostic.
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
+
+/**
+ * \brief Determine the number of source ranges associated with the given
+ * diagnostic.
+ */
+CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
+
+/**
+ * \brief Retrieve a source range associated with the diagnostic.
+ *
+ * A diagnostic's source ranges highlight important elements in the source
+ * code. On the command line, Clang displays source ranges by
+ * underlining them with '~' characters.
+ *
+ * \param Diagnostic the diagnostic whose range is being extracted.
+ *
+ * \param Range the zero-based index specifying which range to
+ *
+ * \returns the requested source range.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
+ unsigned Range);
+
+/**
+ * \brief Determine the number of fix-it hints associated with the
+ * given diagnostic.
+ */
+CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
+
+/**
+ * \brief Retrieve the kind of the given fix-it.
+ *
+ * \param Diagnostic the diagnostic whose fix-its are being queried.
+ *
+ * \param FixIt the zero-based index of the fix-it to query.
+ */
+CINDEX_LINKAGE enum CXFixItKind
+clang_getDiagnosticFixItKind(CXDiagnostic Diagnostic, unsigned FixIt);
+
+/**
+ * \brief Retrieve the insertion information for an insertion fix-it.
+ *
+ * For a fix-it that describes an insertion into a text buffer,
+ * retrieve the source location where the text should be inserted and
+ * the text to be inserted.
+ *
+ * \param Diagnostic the diagnostic whose fix-its are being queried.
+ *
+ * \param FixIt the zero-based index of the insertion fix-it.
+ *
+ * \param Location will be set to the location where text should be
+ * inserted.
+ *
+ * \returns the text string to insert at the given location.
+ */
+CINDEX_LINKAGE CXString
+clang_getDiagnosticFixItInsertion(CXDiagnostic Diagnostic, unsigned FixIt,
+ CXSourceLocation *Location);
+
+/**
+ * \brief Retrieve the removal information for a removal fix-it.
+ *
+ * For a fix-it that describes a removal from a text buffer, retrieve
+ * the source range that should be removed.
+ *
+ * \param Diagnostic the diagnostic whose fix-its are being queried.
+ *
+ * \param FixIt the zero-based index of the removal fix-it.
+ *
+ * \returns a source range describing the text that should be removed
+ * from the buffer.
+ */
+CINDEX_LINKAGE CXSourceRange
+clang_getDiagnosticFixItRemoval(CXDiagnostic Diagnostic, unsigned FixIt);
+
+/**
+ * \brief Retrieve the replacement information for an replacement fix-it.
+ *
+ * For a fix-it that describes replacement of text in the text buffer
+ * with alternative text.
+ *
+ * \param Diagnostic the diagnostic whose fix-its are being queried.
+ *
+ * \param FixIt the zero-based index of the replacement fix-it.
+ *
+ * \param Range will be set to the source range whose text should be
+ * replaced with the returned text.
+ *
+ * \returns the text string to use as replacement text.
+ */
+CINDEX_LINKAGE CXString
+clang_getDiagnosticFixItReplacement(CXDiagnostic Diagnostic, unsigned FixIt,
+ CXSourceRange *Range);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation
+ *
+ * The routines in this group provide the ability to create and destroy
+ * translation units from files, either by parsing the contents of the files or
+ * by reading in a serialized representation of a translation unit.
+ *
+ * @{
+ */
+
+/**
+ * \brief Get the original translation unit source file name.
+ */
+CINDEX_LINKAGE CXString
+clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
/**
* \brief Return the CXTranslationUnit for a given source file and the provided
@@ -229,169 +586,50 @@ CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
* \param unsaved_files the files that have not yet been saved to disk
* but may be required for code completion, including the contents of
* those files.
+ *
+ * \param diag_callback callback function that will receive any diagnostics
+ * emitted while processing this source file. If NULL, diagnostics will be
+ * suppressed.
+ *
+ * \param diag_client_data client data that will be passed to the diagnostic
+ * callback function.
*/
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
- CXIndex CIdx,
- const char *source_filename,
- int num_clang_command_line_args,
- const char **clang_command_line_args,
- unsigned num_unsaved_files,
- struct CXUnsavedFile *unsaved_files);
+ CXIndex CIdx,
+ const char *source_filename,
+ int num_clang_command_line_args,
+ const char **clang_command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ CXDiagnosticCallback diag_callback,
+ CXClientData diag_client_data);
+
+/**
+ * \brief Create a translation unit from an AST file (-emit-ast).
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
+ const char *ast_filename,
+ CXDiagnosticCallback diag_callback,
+ CXClientData diag_client_data);
/**
- * \defgroup CINDEX_FILES File manipulation routines
- *
- * @{
+ * \brief Destroy the specified CXTranslationUnit object.
*/
-
-/**
- * \brief A particular source file that is part of a translation unit.
- */
-typedef void *CXFile;
-
-
-/**
- * \brief Retrieve the complete file and path name of the given file.
- */
-CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
-
-/**
- * \brief Retrieve the last modification time of the given file.
- */
-CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
-
-/**
- * \brief Retrieve a file handle within the given translation unit.
- *
- * \param tu the translation unit
- *
- * \param file_name the name of the file.
- *
- * \returns the file handle for the named file in the translation unit \p tu,
- * or a NULL file handle if the file was not a part of this translation unit.
- */
-CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
- const char *file_name);
-
+CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
+
/**
* @}
*/
-
-/**
- * \defgroup CINDEX_LOCATIONS Physical source locations
- *
- * Clang represents physical source locations in its abstract syntax tree in
- * great detail, with file, line, and column information for the majority of
- * the tokens parsed in the source code. These data types and functions are
- * used to represent source location information, either for a particular
- * point in the program or for a range of points in the program, and extract
- * specific location information from those data types.
- *
- * @{
- */
-/**
- * \brief Identifies a specific source location within a translation
- * unit.
- *
- * Use clang_getInstantiationLocation() to map a source location to a
- * particular file, line, and column.
- */
-typedef struct {
- void *ptr_data;
- unsigned int_data;
-} CXSourceLocation;
-
-/**
- * \brief Identifies a range of source locations in the source code.
- *
- * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
- * starting and end locations from a source range, respectively.
- */
-typedef struct {
- void *ptr_data;
- unsigned begin_int_data;
- unsigned end_int_data;
-} CXSourceRange;
-
-/**
- * \brief Retrieve a NULL (invalid) source location.
- */
-CINDEX_LINKAGE CXSourceLocation clang_getNullLocation();
-
-/**
- * \determine Determine whether two source locations, which must refer into
- * the same translation unit, refer to exactly the same point in the source
- * code.
- *
- * \returns non-zero if the source locations refer to the same location, zero
- * if they refer to different locations.
- */
-CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
- CXSourceLocation loc2);
-
-/**
- * \brief Retrieves the source location associated with a given
- * file/line/column in a particular translation unit.
- */
-CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu,
- CXFile file,
- unsigned line,
- unsigned column);
-
-/**
- * \brief Retrieve a source range given the beginning and ending source
- * locations.
- */
-CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
- CXSourceLocation end);
-
-/**
- * \brief Retrieve the file, line, and column represented by the
- * given source location.
- *
- * \param location the location within a source file that will be
- * decomposed into its parts.
- *
- * \param file if non-NULL, will be set to the file to which the given
- * source location points.
- *
- * \param line if non-NULL, will be set to the line to which the given
- * source location points.
- *
- * \param column if non-NULL, will be set to the column to which the
- * given source location points.
- */
-CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
- CXFile *file,
- unsigned *line,
- unsigned *column);
-
-/**
- * \brief Retrieve a source location representing the first
- * character within a source range.
- */
-CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
-
-/**
- * \brief Retrieve a source location representing the last
- * character within a source range.
- */
-CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
-
-/**
- * @}
- */
-
/**
* \brief Describes the kind of entity that a cursor refers to.
*/
enum CXCursorKind {
/* Declarations */
CXCursor_FirstDecl = 1,
- /**
+ /**
* \brief A declaration whose specific kind is not exposed via this
- * interface.
+ * interface.
*
* Unexposed declarations have the same operations as any other kind
* of declaration; one can extract their location information,
@@ -400,14 +638,14 @@ enum CXCursorKind {
*/
CXCursor_UnexposedDecl = 1,
/** \brief A C or C++ struct. */
- CXCursor_StructDecl = 2,
+ CXCursor_StructDecl = 2,
/** \brief A C or C++ union. */
CXCursor_UnionDecl = 3,
/** \brief A C++ class. */
CXCursor_ClassDecl = 4,
/** \brief An enumeration. */
CXCursor_EnumDecl = 5,
- /**
+ /**
* \brief A field (in C) or non-static data member (in C++) in a
* struct, union, or C++ class.
*/
@@ -441,10 +679,10 @@ enum CXCursorKind {
/** \brief A typedef */
CXCursor_TypedefDecl = 20,
CXCursor_LastDecl = 20,
-
+
/* References */
CXCursor_FirstRef = 40, /* Decl references */
- CXCursor_ObjCSuperClassRef = 40,
+ CXCursor_ObjCSuperClassRef = 40,
CXCursor_ObjCProtocolRef = 41,
CXCursor_ObjCClassRef = 42,
/**
@@ -464,20 +702,20 @@ enum CXCursorKind {
*/
CXCursor_TypeRef = 43,
CXCursor_LastRef = 43,
-
+
/* Error conditions */
CXCursor_FirstInvalid = 70,
CXCursor_InvalidFile = 70,
CXCursor_NoDeclFound = 71,
CXCursor_NotImplemented = 72,
CXCursor_LastInvalid = 72,
-
+
/* Expressions */
CXCursor_FirstExpr = 100,
-
+
/**
* \brief An expression whose specific kind is not exposed via this
- * interface.
+ * interface.
*
* Unexposed expressions have the same operations as any other kind
* of expression; one can extract their location information,
@@ -485,27 +723,27 @@ enum CXCursorKind {
* expression is not reported.
*/
CXCursor_UnexposedExpr = 100,
-
+
/**
* \brief An expression that refers to some value declaration, such
* as a function, varible, or enumerator.
*/
CXCursor_DeclRefExpr = 101,
-
+
/**
* \brief An expression that refers to a member of a struct, union,
* class, Objective-C class, etc.
*/
CXCursor_MemberRefExpr = 102,
-
+
/** \brief An expression that calls a function. */
CXCursor_CallExpr = 103,
-
+
/** \brief An expression that sends a message to an Objective-C
object or class. */
CXCursor_ObjCMessageExpr = 104,
CXCursor_LastExpr = 104,
-
+
/* Statements */
CXCursor_FirstStmt = 200,
/**
@@ -519,7 +757,7 @@ enum CXCursorKind {
*/
CXCursor_UnexposedStmt = 200,
CXCursor_LastStmt = 200,
-
+
/**
* \brief Cursor that represents the translation unit itself.
*
@@ -533,7 +771,7 @@ enum CXCursorKind {
* \brief A cursor representing some element in the abstract syntax tree for
* a translation unit.
*
- * The cursor abstraction unifies the different kinds of entities in a
+ * The cursor abstraction unifies the different kinds of entities in a
* program--declaration, statements, expressions, references to declarations,
* etc.--under a single "cursor" abstraction with a common set of operations.
* Common operation for a cursor include: getting the physical location in
@@ -550,19 +788,19 @@ enum CXCursorKind {
typedef struct {
enum CXCursorKind kind;
void *data[3];
-} CXCursor;
+} CXCursor;
/**
* \defgroup CINDEX_CURSOR_MANIP Cursor manipulations
*
* @{
*/
-
+
/**
* \brief Retrieve the NULL cursor, which represents no entity.
*/
CINDEX_LINKAGE CXCursor clang_getNullCursor(void);
-
+
/**
* \brief Retrieve the cursor that represents the given translation unit.
*
@@ -575,7 +813,7 @@ CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
* \brief Determine whether two cursors are equivalent.
*/
CINDEX_LINKAGE unsigned clang_equalCursors(CXCursor, CXCursor);
-
+
/**
* \brief Retrieve the kind of the given cursor.
*/
@@ -607,21 +845,21 @@ CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind);
CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents an invalid
+ * \brief Determine whether the given cursor kind represents an invalid
* cursor.
- */
+ */
CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
/**
- * \brief Determine whether the given cursor kind represents a translation
- * unit.
+ * \brief Determine whether the given cursor kind represents a translation
+ * unit.
*/
CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
-
+
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_CURSOR_SOURCE Mapping between cursors and source code
*
@@ -632,16 +870,16 @@ CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
*
* @{
*/
-
+
/**
* \brief Map a source location to the cursor that describes the entity at that
* location in the source code.
*
* clang_getCursor() maps an arbitrary source location within a translation
* unit down to the most specific cursor that describes the entity at that
- * location. For example, given an expression \c x + y, invoking
+ * location. For example, given an expression \c x + y, invoking
* clang_getCursor() with a source location pointing to "x" will return the
- * cursor for "x"; similarly for "y". If the cursor points anywhere between
+ * cursor for "x"; similarly for "y". If the cursor points anywhere between
* "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
* will return a cursor referring to the "+" expression.
*
@@ -649,15 +887,15 @@ CINDEX_LINKAGE unsigned clang_isTranslationUnit(enum CXCursorKind);
* a NULL cursor if no such entity can be found.
*/
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
-
+
/**
* \brief Retrieve the physical location of the source constructor referenced
* by the given cursor.
*
* The location of a declaration is typically the location of the name of that
- * declaration, where the name of that declaration would occur if it is
- * unnamed, or some keyword that introduces that particular declaration.
- * The location of a reference is where that reference occurs within the
+ * declaration, where the name of that declaration would occur if it is
+ * unnamed, or some keyword that introduces that particular declaration.
+ * The location of a reference is where that reference occurs within the
* source code.
*/
CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
@@ -668,7 +906,7 @@ CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
*
* The extent of a cursor starts with the file/line/column pointing at the
* first character within the source construct that the cursor refers to and
- * ends with the last character withinin that source construct. For a
+ * ends with the last character withinin that source construct. For a
* declaration, the extent covers the declaration itself. For a reference,
* the extent covers the location of the reference (e.g., where the referenced
* entity was actually used).
@@ -678,7 +916,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors
*
@@ -687,7 +925,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
*
* @{
*/
-
+
/**
* \brief Describes how the traversal of the children of a particular
* cursor should proceed after visiting a particular child cursor.
@@ -697,10 +935,10 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
*/
enum CXChildVisitResult {
/**
- * \brief Terminates the cursor traversal.
+ * \brief Terminates the cursor traversal.
*/
CXChildVisit_Break,
- /**
+ /**
* \brief Continues the cursor traversal with the next sibling of
* the cursor just visited, without visiting its children.
*/
@@ -724,8 +962,8 @@ enum CXChildVisitResult {
* The visitor should return one of the \c CXChildVisitResult values
* to direct clang_visitCursorChildren().
*/
-typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
- CXCursor parent,
+typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
+ CXCursor parent,
CXClientData client_data);
/**
@@ -737,10 +975,8 @@ typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
* \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if
* the visitor returns \c CXChildVisit_Break.
*
- * \param tu the translation unit into which the cursor refers.
- *
* \param parent the cursor whose child may be visited. All kinds of
- * cursors can be visited, including invalid visitors (which, by
+ * cursors can be visited, including invalid cursors (which, by
* definition, have no children).
*
* \param visitor the visitor function that will be invoked for each
@@ -752,25 +988,25 @@ typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
* \returns a non-zero value if the traversal was terminated
* prematurely by the visitor returning \c CXChildVisit_Break.
*/
-CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
+CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent,
CXCursorVisitor visitor,
CXClientData client_data);
-
+
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_CURSOR_XREF Cross-referencing in the AST
*
- * These routines provide the ability to determine references within and
+ * These routines provide the ability to determine references within and
* across translation units, by providing the names of the entities referenced
* by cursors, follow reference cursors to the declarations they reference,
* and associate declarations with their definitions.
*
* @{
*/
-
+
/**
* \brief Retrieve a Unified Symbol Resolution (USR) for the entity referenced
* by the given cursor.
@@ -792,14 +1028,14 @@ CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor);
*
* Reference cursors refer to other entities in the AST. For example, an
* Objective-C superclass reference cursor refers to an Objective-C class.
- * This function produces the cursor for the Objective-C class from the
+ * This function produces the cursor for the Objective-C class from the
* cursor for the superclass reference. If the input cursor is a declaration or
* definition, it returns that declaration or definition unchanged.
- * Othewise, returns the NULL cursor.
+ * Otherwise, returns the NULL cursor.
*/
CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor);
-/**
+/**
* \brief For a cursor that is either a reference to or a declaration
* of some entity, retrieve a cursor that describes the definition of
* that entity.
@@ -829,12 +1065,148 @@ CINDEX_LINKAGE CXCursor clang_getCursorReferenced(CXCursor);
*/
CINDEX_LINKAGE CXCursor clang_getCursorDefinition(CXCursor);
-/**
+/**
* \brief Determine whether the declaration pointed to by this cursor
* is also a definition of that entity.
*/
CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_LEX Token extraction and manipulation
+ *
+ * The routines in this group provide access to the tokens within a
+ * translation unit, along with a semantic mapping of those tokens to
+ * their corresponding cursors.
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes a kind of token.
+ */
+typedef enum CXTokenKind {
+ /**
+ * \brief A token that contains some kind of punctuation.
+ */
+ CXToken_Punctuation,
+
+ /**
+ * \brief A language keyword.
+ */
+ CXToken_Keyword,
+
+ /**
+ * \brief An identifier (that is not a keyword).
+ */
+ CXToken_Identifier,
+
+ /**
+ * \brief A numeric, string, or character literal.
+ */
+ CXToken_Literal,
+
+ /**
+ * \brief A comment.
+ */
+ CXToken_Comment
+} CXTokenKind;
+
+/**
+ * \brief Describes a single preprocessing token.
+ */
+typedef struct {
+ unsigned int_data[4];
+ void *ptr_data;
+} CXToken;
+
+/**
+ * \brief Determine the kind of the given token.
+ */
+CINDEX_LINKAGE CXTokenKind clang_getTokenKind(CXToken);
+
+/**
+ * \brief Determine the spelling of the given token.
+ *
+ * The spelling of a token is the textual representation of that token, e.g.,
+ * the text of an identifier or keyword.
+ */
+CINDEX_LINKAGE CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
+
+/**
+ * \brief Retrieve the source location of the given token.
+ */
+CINDEX_LINKAGE CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
+ CXToken);
+
+/**
+ * \brief Retrieve a source range that covers the given token.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken);
+
+/**
+ * \brief Tokenize the source code described by the given range into raw
+ * lexical tokens.
+ *
+ * \param TU the translation unit whose text is being tokenized.
+ *
+ * \param Range the source range in which text should be tokenized. All of the
+ * tokens produced by tokenization will fall within this source range,
+ *
+ * \param Tokens this pointer will be set to point to the array of tokens
+ * that occur within the given source range. The returned pointer must be
+ * freed with clang_disposeTokens() before the translation unit is destroyed.
+ *
+ * \param NumTokens will be set to the number of tokens in the \c *Tokens
+ * array.
+ *
+ */
+CINDEX_LINKAGE void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
+ CXToken **Tokens, unsigned *NumTokens);
+
+/**
+ * \brief Annotate the given set of tokens by providing cursors for each token
+ * that can be mapped to a specific entity within the abstract syntax tree.
+ *
+ * This token-annotation routine is equivalent to invoking
+ * clang_getCursor() for the source locations of each of the
+ * tokens. The cursors provided are filtered, so that only those
+ * cursors that have a direct correspondence to the token are
+ * accepted. For example, given a function call \c f(x),
+ * clang_getCursor() would provide the following cursors:
+ *
+ * * when the cursor is over the 'f', a DeclRefExpr cursor referring to 'f'.
+ * * when the cursor is over the '(' or the ')', a CallExpr referring to 'f'.
+ * * when the cursor is over the 'x', a DeclRefExpr cursor referring to 'x'.
+ *
+ * Only the first and last of these cursors will occur within the
+ * annotate, since the tokens "f" and "x' directly refer to a function
+ * and a variable, respectively, but the parentheses are just a small
+ * part of the full syntax of the function call expression, which is
+ * not provided as an annotation.
+ *
+ * \param TU the translation unit that owns the given tokens.
+ *
+ * \param Tokens the set of tokens to annotate.
+ *
+ * \param NumTokens the number of tokens in \p Tokens.
+ *
+ * \param Cursors an array of \p NumTokens cursors, whose contents will be
+ * replaced with the cursors corresponding to each token.
+ */
+CINDEX_LINKAGE void clang_annotateTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors);
+
+/**
+ * \brief Free the given set of tokens.
+ */
+CINDEX_LINKAGE void clang_disposeTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens);
+
/**
* @}
*/
@@ -847,11 +1219,11 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
*
* @{
*/
-
+
/* for debug/testing */
-CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
-CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
- const char **startBuf,
+CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
+CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
+ const char **startBuf,
const char **endBuf,
unsigned *startLine,
unsigned *startColumn,
@@ -861,7 +1233,7 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_CODE_COMPLET Code completion
*
@@ -873,7 +1245,7 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
*
* @{
*/
-
+
/**
* \brief A semantic string that describes a code-completion result.
*
@@ -885,18 +1257,18 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
* the name of the entity being referenced, whether the text chunk is part of
* the template, or whether it is a "placeholder" that the user should replace
* with actual code,of a specific kind. See \c CXCompletionChunkKind for a
- * description of the different kinds of chunks.
+ * description of the different kinds of chunks.
*/
typedef void *CXCompletionString;
-
+
/**
* \brief A single result of code completion.
*/
typedef struct {
/**
- * \brief The kind of entity that this completion refers to.
+ * \brief The kind of entity that this completion refers to.
*
- * The cursor kind will be a macro, keyword, or a declaration (one of the
+ * The cursor kind will be a macro, keyword, or a declaration (one of the
* *Decl cursor kinds), describing the entity that the completion is
* referring to.
*
@@ -904,8 +1276,8 @@ typedef struct {
* the client to extract additional information from declaration.
*/
enum CXCursorKind CursorKind;
-
- /**
+
+ /**
* \brief The code-completion string that describes how to insert this
* code-completion result into the editing buffer.
*/
@@ -915,8 +1287,8 @@ typedef struct {
/**
* \brief Describes a single piece of text within a code-completion string.
*
- * Each "chunk" within a code-completion string (\c CXCompletionString) is
- * either a piece of text with a specific "kind" that describes how that text
+ * Each "chunk" within a code-completion string (\c CXCompletionString) is
+ * either a piece of text with a specific "kind" that describes how that text
* should be interpreted by the client or is another completion string.
*/
enum CXCompletionChunkKind {
@@ -925,7 +1297,7 @@ enum CXCompletionChunkKind {
* could be a part of the template (but is not required).
*
* The Optional chunk is the only kind of chunk that has a code-completion
- * string for its representation, which is accessible via
+ * string for its representation, which is accessible via
* \c clang_getCompletionChunkCompletionString(). The code-completion string
* describes an additional part of the template that is completely optional.
* For example, optional chunks can be used to describe the placeholders for
@@ -956,10 +1328,10 @@ enum CXCompletionChunkKind {
CXCompletionChunk_Optional,
/**
* \brief Text that a user would be expected to type to get this
- * code-completion result.
+ * code-completion result.
*
- * There will be exactly one "typed text" chunk in a semantic string, which
- * will typically provide the spelling of a keyword or the name of a
+ * There will be exactly one "typed text" chunk in a semantic string, which
+ * will typically provide the spelling of a keyword or the name of a
* declaration that could be used at the current code point. Clients are
* expected to filter the code-completion results based on the text in this
* chunk.
@@ -987,7 +1359,7 @@ enum CXCompletionChunkKind {
/**
* \brief Informative text that should be displayed but never inserted as
* part of the template.
- *
+ *
* An "informative" chunk contains annotations that can be displayed to
* help the user decide whether a particular code-completion result is the
* right option, but which is not part of the actual template to be inserted
@@ -1010,7 +1382,7 @@ enum CXCompletionChunkKind {
* "(", the code-completion string will contain a "current parameter" chunk
* for "int x", indicating that the current argument will initialize that
* parameter. After typing further, to \c add(17, (where the code-completion
- * point is after the ","), the code-completion string will contain a
+ * point is after the ","), the code-completion string will contain a
* "current paremeter" chunk to "int y".
*/
CXCompletionChunk_CurrentParameter,
@@ -1053,10 +1425,10 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_Comma,
/**
- * \brief Text that specifies the result type of a given result.
+ * \brief Text that specifies the result type of a given result.
*
* This special kind of informative chunk is not meant to be inserted into
- * the text buffer. Rather, it is meant to illustrate the type that an
+ * the text buffer. Rather, it is meant to illustrate the type that an
* expression using the given completion string would have.
*/
CXCompletionChunk_ResultType,
@@ -1082,7 +1454,7 @@ enum CXCompletionChunkKind {
*/
CXCompletionChunk_VerticalSpace
};
-
+
/**
* \brief Determine the kind of a particular chunk within a completion string.
*
@@ -1092,12 +1464,12 @@ enum CXCompletionChunkKind {
*
* \returns the kind of the chunk at the index \c chunk_number.
*/
-CINDEX_LINKAGE enum CXCompletionChunkKind
+CINDEX_LINKAGE enum CXCompletionChunkKind
clang_getCompletionChunkKind(CXCompletionString completion_string,
unsigned chunk_number);
-
+
/**
- * \brief Retrieve the text associated with a particular chunk within a
+ * \brief Retrieve the text associated with a particular chunk within a
* completion string.
*
* \param completion_string the completion string to query.
@@ -1111,7 +1483,7 @@ clang_getCompletionChunkText(CXCompletionString completion_string,
unsigned chunk_number);
/**
- * \brief Retrieve the completion string associated with a particular chunk
+ * \brief Retrieve the completion string associated with a particular chunk
* within a completion string.
*
* \param completion_string the completion string to query.
@@ -1125,7 +1497,7 @@ clang_getCompletionChunkText(CXCompletionString completion_string,
CINDEX_LINKAGE CXCompletionString
clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
unsigned chunk_number);
-
+
/**
* \brief Retrieve the number of chunks in the given code-completion string.
*/
@@ -1136,7 +1508,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
* \brief Contains the results of code-completion.
*
* This data structure contains the results of code completion, as
- * produced by \c clang_codeComplete. Its contents must be freed by
+ * produced by \c clang_codeComplete. Its contents must be freed by
* \c clang_disposeCodeCompleteResults.
*/
typedef struct {
@@ -1162,12 +1534,12 @@ typedef struct {
* performing syntax checking up to the location where code-completion has
* been requested. At that point, a special code-completion token is passed
* to the parser, which recognizes this token and determines, based on the
- * current location in the C/Objective-C/C++ grammar and the state of
+ * current location in the C/Objective-C/C++ grammar and the state of
* semantic analysis, what completions to provide. These completions are
* returned via a new \c CXCodeCompleteResults structure.
*
* Code completion itself is meant to be triggered by the client when the
- * user types punctuation characters or whitespace, at which point the
+ * user types punctuation characters or whitespace, at which point the
* code-completion location will coincide with the cursor. For example, if \c p
* is a pointer, code-completion might be triggered after the "-" and then
* after the ">" in \c p->. When the code-completion location is afer the ">",
@@ -1196,9 +1568,9 @@ typedef struct {
* \p command_line_args.
*
* \param command_line_args the command-line arguments to pass to the Clang
- * compiler to build the given source file. This should include all of the
+ * compiler to build the given source file. This should include all of the
* necessary include paths, language-dialect switches, precompiled header
- * includes, etc., but should not include any information specific to
+ * includes, etc., but should not include any information specific to
* code completion.
*
* \param num_unsaved_files the number of unsaved file entries in \p
@@ -1210,59 +1582,104 @@ typedef struct {
*
* \param complete_filename the name of the source file where code completion
* should be performed. In many cases, this name will be the same as the
- * source filename. However, the completion filename may also be a file
- * included by the source file, which is required when producing
+ * source filename. However, the completion filename may also be a file
+ * included by the source file, which is required when producing
* code-completion results for a header.
*
* \param complete_line the line at which code-completion should occur.
*
- * \param complete_column the column at which code-completion should occur.
+ * \param complete_column the column at which code-completion should occur.
* Note that the column should point just after the syntactic construct that
* initiated code completion, and not in the middle of a lexical token.
*
+ * \param diag_callback callback function that will receive any diagnostics
+ * emitted while processing this source file. If NULL, diagnostics will be
+ * suppressed.
+ *
+ * \param diag_client_data client data that will be passed to the diagnostic
+ * callback function.
+ *
* \returns if successful, a new CXCodeCompleteResults structure
* containing code-completion results, which should eventually be
* freed with \c clang_disposeCodeCompleteResults(). If code
* completion fails, returns NULL.
*/
-CINDEX_LINKAGE
-CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
+CINDEX_LINKAGE
+CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *source_filename,
- int num_command_line_args,
+ int num_command_line_args,
const char **command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
const char *complete_filename,
unsigned complete_line,
- unsigned complete_column);
-
+ unsigned complete_column,
+ CXDiagnosticCallback diag_callback,
+ CXClientData diag_client_data);
+
/**
* \brief Free the given set of code-completion results.
*/
-CINDEX_LINKAGE
+CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
-
+
/**
* @}
*/
-
-
+
+
/**
* \defgroup CINDEX_MISC Miscellaneous utility functions
*
* @{
*/
-
-CINDEX_LINKAGE const char *clang_getClangVersion();
+
+/**
+ * \brief Return a version string, suitable for showing to a user, but not
+ * intended to be parsed (the format is not guaranteed to be stable).
+ */
+CINDEX_LINKAGE CXString clang_getClangVersion();
+
+/**
+ * \brief Return a version string, suitable for showing to a user, but not
+ * intended to be parsed (the format is not guaranteed to be stable).
+ */
+
+
+ /**
+ * \brief Visitor invoked for each file in a translation unit
+ * (used with clang_getInclusions()).
+ *
+ * This visitor function will be invoked by clang_getInclusions() for each
+ * file included (either at the top-level or by #include directives) within
+ * a translation unit. The first argument is the file being included, and
+ * the second and third arguments provide the inclusion stack. The
+ * array is sorted in order of immediate inclusion. For example,
+ * the first element refers to the location that included 'included_file'.
+ */
+typedef void (*CXInclusionVisitor)(CXFile included_file,
+ CXSourceLocation* inclusion_stack,
+ unsigned include_len,
+ CXClientData client_data);
+
+/**
+ * \brief Visit the set of preprocessor inclusions in a translation unit.
+ * The visitor function is called with the provided data for every included
+ * file. This does not include headers included by the PCH file (unless one
+ * is inspecting the inclusions in the PCH file itself).
+ */
+CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu,
+ CXInclusionVisitor visitor,
+ CXClientData client_data);
/**
* @}
*/
-
+
/**
* @}
*/
-
+
#ifdef __cplusplus
}
#endif
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index e5429bec143..2ed9fd70801 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -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
@@ -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 &Protocols);
+ llvm::SmallPtrSet &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 SDMs;
+ friend class DeclContext;
+ void *CreateStoredDeclsMap();
+ void ReleaseDeclContextMaps();
};
/// @brief Utility function for constructing a nullary selector.
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index abd36f7e5f0..2d314913469 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -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 &Output,
+ void *Cookie);
} // end namespace clang
#endif
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
new file mode 100644
index 00000000000..f5f11ca8366
--- /dev/null
+++ b/include/clang/AST/ASTImporter.h
@@ -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 > 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 ImportedTypes;
+
+ /// \brief Mapping from the already-imported declarations in the "from"
+ /// context to the corresponding declarations in the "to" context.
+ llvm::DenseMap ImportedDecls;
+
+ /// \brief Mapping from the already-imported statements in the "from"
+ /// context to the corresponding statements in the "to" context.
+ llvm::DenseMap ImportedStmts;
+
+ /// \brief Mapping from the already-imported FileIDs in the "from" source
+ /// manager to the corresponding FileIDs in the "to" source manager.
+ llvm::DenseMap ImportedFileIDs;
+
+ /// \brief Imported, anonymous tag declarations that are missing their
+ /// corresponding typedefs.
+ llvm::SmallVector 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
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 03ab0f07020..37225907c6d 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -18,7 +18,6 @@
#include "llvm/ADT/StringRef.h"
#include
#include
-#include
#include
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
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 1491b1edbba..79a3022ee01 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -161,7 +161,8 @@ class CXXBasePaths {
void ComputeDeclsFound();
public:
- typedef std::list::const_iterator paths_iterator;
+ typedef std::list::iterator paths_iterator;
+ typedef std::list::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; }
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 6d52b2b2bc9..07442896dc4 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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(const_cast(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(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(const_cast(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(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(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(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(Ctx) || isa(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();
@@ -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(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(Ctx) || isa(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(const_cast(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(getDeclContext());
}
+
+ RecordDecl *getParent() {
+ return cast(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(const_cast(D));
@@ -1594,8 +1633,6 @@ public:
static TagDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast(const_cast(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(TagDecl::getDefinition(C));
+ RecordDecl* getDefinition() const {
+ return cast_or_null(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(const_cast(D));
}
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 775bce2a15f..a407a162774 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -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 ::value>
+struct cast_convert_decl_context {
+ static const ToTy *doit(const DeclContext *Val) {
+ return static_cast(Decl::castFromDeclContext(Val));
+ }
+
+ static ToTy *doit(DeclContext *Val) {
+ return static_cast(Decl::castFromDeclContext(Val));
+ }
+};
+
+// Specialization selected when ToTy is a known subclass of DeclContext.
+template
+struct cast_convert_decl_context {
+ static const ToTy *doit(const DeclContext *Val) {
+ return static_cast(Val);
+ }
+
+ static ToTy *doit(DeclContext *Val) {
+ return static_cast(Val);
+ }
+};
+
+
} // end clang.
namespace llvm {
-/// Implement a isa_impl_wrap specialization to check whether a DeclContext is
-/// a specific Decl.
+/// isa(DeclContext*)
template
struct isa_impl_wrap {
static bool doit(const ::clang::DeclContext &Val) {
- return ToTy::classof(::clang::Decl::castFromDeclContext(&Val));
+ return ToTy::classofKind(Val.getDeclKind());
}
};
template
@@ -1038,6 +1065,34 @@ struct isa_impl_wrap
: public isa_impl_wrap {};
+/// cast(DeclContext*)
+template
+struct cast_convert_val {
+ static const ToTy &doit(const ::clang::DeclContext &Val) {
+ return *::clang::cast_convert_decl_context::doit(&Val);
+ }
+};
+template
+struct cast_convert_val {
+ static ToTy &doit(::clang::DeclContext &Val) {
+ return *::clang::cast_convert_decl_context::doit(&Val);
+ }
+};
+template
+struct cast_convert_val {
+ static const ToTy *doit(const ::clang::DeclContext *Val) {
+ return ::clang::cast_convert_decl_context::doit(Val);
+ }
+};
+template
+struct cast_convert_val {
+ static ToTy *doit(::clang::DeclContext *Val) {
+ return ::clang::cast_convert_decl_context::doit(Val);
+ }
+};
+
/// Implement cast_convert_val for Decl -> DeclContext conversions.
template
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
-struct cast_convert_val {
- static ToTy &doit(const ::clang::DeclContext &Val) {
- return *reinterpret_cast(ToTy::castFromDeclContext(&Val));
- }
-};
-template
-struct cast_convert_val
- : public cast_convert_val {};
-
-template
-struct cast_convert_val {
- static ToTy *doit(const ::clang::DeclContext *Val) {
- return reinterpret_cast(ToTy::castFromDeclContext(Val));
- }
-};
-template
-struct cast_convert_val
- : public cast_convert_val {};
-
} // end namespace llvm
#endif
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 73ebf52d383..0978c6da9d6 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -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(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(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(getTypeForDecl())->isBeingDefined()) &&
- "getConversionFunctions() called on incomplete type");
- return &Conversions;
+ return &data().Conversions;
}
const UnresolvedSetImpl *getConversionFunctions() const {
- assert((this->isDefinition() ||
- cast(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 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(); }
@@ -1046,32 +1081,16 @@ public:
SourceRange getSourceRange() const;
FieldDecl *getAnonUnionMember() const {
- return CtorOrAnonUnion.dyn_cast();
+ return AnonUnionMember;
}
void setAnonUnionMember(FieldDecl *anonMember) {
- CtorOrAnonUnion = anonMember;
- }
-
- const CXXConstructorDecl *getConstructor() const {
- return CtorOrAnonUnion.dyn_cast();
+ 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(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(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(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(const_cast(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(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
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 0fb0db13bb5..e562d352e07 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -193,6 +193,9 @@ public:
ImplementationControl impControl = None);
virtual ObjCMethodDecl *getCanonicalDecl();
+ const ObjCMethodDecl *getCanonicalDecl() const {
+ return const_cast(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(const_cast(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(const_cast(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
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index d8b004a049c..ced174716c7 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -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; }
};
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 59d7e439e57..2254724410d 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -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
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 25278176716..114a19800f5 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -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(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;
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 6ce95ac5227..e4bc4b74643 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -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(SubExpr); }
+ Expr *getSubExpr() { return cast(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 find(Expr *E) {
+ assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
+
+ bool op = false;
+ E = E->IgnoreParens();
+ if (isa(E))
+ op = true, E = cast(E)->getSubExpr()->IgnoreParens();
+ return llvm::PointerIntPair(cast(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.
+ bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below
+
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast(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(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(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(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(this + 1);
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const {
- return const_cast(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(Base);
}
+ const Expr *getBase() const {
+ assert(!isImplicitAccess());
+ return cast(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.
- 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(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(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(this))
+ return cast(this)->getExplicitTemplateArgs();
+ else
+ return cast(this)->getExplicitTemplateArgs();
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 0b0cd64ad72..df39b535eb3 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -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
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index d058f838a00..94caa6faad6 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -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 Names;
- llvm::SmallVector Constraints;
- llvm::SmallVector 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 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(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
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 09ea4ca2101..4e87c2701c2 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -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 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(this + 1);
+ return Stmts[NumHandlers]->getLocEnd();
+ }
- CompoundStmt *getTryBlock() { return llvm::cast(Stmts[0]); }
+ CompoundStmt *getTryBlock() {
+ Stmt **Stmts = reinterpret_cast(this + 1);
+ return llvm::cast(Stmts[0]);
+ }
const CompoundStmt *getTryBlock() const {
+ Stmt const * const*Stmts = reinterpret_cast(this + 1);
return llvm::cast(Stmts[0]);
}
- unsigned getNumHandlers() const { return Stmts.size() - 1; }
+ unsigned getNumHandlers() const { return NumHandlers; }
CXXCatchStmt *getHandler(unsigned i) {
+ Stmt **Stmts = reinterpret_cast(this + 1);
return llvm::cast(Stmts[i + 1]);
}
const CXXCatchStmt *getHandler(unsigned i) const {
+ Stmt const * const*Stmts = reinterpret_cast(this + 1);
return llvm::cast(Stmts[i + 1]);
}
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 7102336180c..ec6149e55f1 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -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
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 3a525507dad..4986f08ac12 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -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"
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index b7b60df5acb..40e50988e6d 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -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(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(D)) {
assert(!isa(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(D), QualType()) { }
+ explicit RecordType(const RecordDecl *D)
+ : TagType(Record, reinterpret_cast(D), QualType()) { }
explicit RecordType(TypeClass TC, RecordDecl *D)
- : TagType(TC, reinterpret_cast(D), QualType()) { }
+ : TagType(TC, reinterpret_cast(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(D), QualType()) { }
+ explicit EnumType(const EnumDecl *D)
+ : TagType(Enum, reinterpret_cast(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(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 (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;
}
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 575011a8724..9cf2cb7bd77 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -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)
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index 055d1526467..9c59229e313 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/include/clang/AST/UnresolvedSet.h
@@ -16,7 +16,6 @@
#define LLVM_CLANG_AST_UNRESOLVEDSET_H
#include
-#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(uintptr_t(AS) |
+ reinterpret_cast(D));
+ }
+
+ operator NamedDecl*() const { return getDecl(); }
+ NamedDecl *operator->() const { return getDecl(); }
+};
+}
+
+// Take a moment to tell SmallVector that this is POD.
+namespace llvm {
+template struct isPodLike;
+template<> struct isPodLike {
+ 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 DeclEntry;
- typedef llvm::SmallVectorImpl DeclsTy;
+private:
+ typedef llvm::SmallVectorImpl DeclsTy;
typedef DeclsTy::iterator IteratorTy;
IteratorTy ir;
@@ -47,8 +92,8 @@ public:
typedef NamedDecl *reference;
typedef std::iterator_traits::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 class UnresolvedSet :
public UnresolvedSetImpl {
- llvm::SmallVector Decls;
+ llvm::SmallVector Decls;
};
diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h
new file mode 100644
index 00000000000..a4ad0b70370
--- /dev/null
+++ b/include/clang/Analysis/Analyses/PrintfFormatString.h
@@ -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
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 2b367b7e37f..cd771acb06a 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -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
diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
similarity index 89%
rename from include/clang/Analysis/PathSensitive/AnalysisContext.h
rename to include/clang/Analysis/AnalysisContext.h
index c82bb962fd1..ea4f5b20669 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -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 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() ?
- Data.get() : 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:
diff --git a/include/clang/Analysis/Support/Optional.h b/include/clang/Analysis/Support/Optional.h
index 40f38be020a..a4e6d519a04 100644
--- a/include/clang/Analysis/Support/Optional.h
+++ b/include/clang/Analysis/Support/Optional.h
@@ -20,19 +20,27 @@ namespace clang {
template
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; }
};
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 08945635e6c..3251ec4b1f9 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -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
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index c5d6d7c7131..d2516f8695b 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -23,16 +23,19 @@
namespace llvm {
template 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 &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
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index f075aaaf422..b6c2b13895d 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -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">;
}
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 7e14a329dca..66f84dbbbab 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -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">;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 8cdf85082b1..dc5ccfdf520 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -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 ;">;
+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">;
}
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 66a841a8afa..79147eac5f3 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -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">;
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 03aad860635..82f9eca1296 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -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]>;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index c6d06052528..bc26c3b0dad 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 8d75d2e2572..19b242e86b6 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -85,7 +85,11 @@ def warn_unused_variable : Warning<"unused variable %0">,
InGroup, 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, DefaultIgnore;
+
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
InGroup, 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>, 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;
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;
def warn_printf_too_many_data_args : Warning<
- "more data arguments than '%%' conversions">, InGroup;
+ "more data arguments than format specifiers">, InGroup;
def warn_printf_invalid_conversion : Warning<
- "invalid conversion '%0'">, InGroup;
+ "invalid conversion specifier '%0'">, InGroup;
+def warn_printf_incomplete_specifier : Warning<
+ "incomplete format specifier">, InGroup;
def warn_printf_missing_format_string : Warning<
"format string missing">, InGroup;
+def warn_printf_conversion_argument_type_mismatch : Warning<
+ "conversion specifies type %0 but the argument has type %1">,
+ InGroup;
def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">,
InGroup;
@@ -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;
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;
-
+def warn_printf_nonsensical_precision: Warning<
+ "precision used in '%0' conversion specifier (where it has no meaning)">,
+ InGroup;
+def warn_printf_nonsensical_flag: Warning<
+ "flag '%0' results in undefined behavior in '%1' conversion specifier">,
+ InGroup;
+
// 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 >;
+def not_in_enum : Warning<"case value not in enumerated type %0">,
+ InGroup >;
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">;
+
}
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 2b6092dea30..d909f83e74d 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -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; }
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
new file mode 100644
index 00000000000..de0de348d35
--- /dev/null
+++ b/include/clang/Basic/Linkage.h
@@ -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
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index 0d970123f74..873aaeecb6b 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -1,4 +1,4 @@
-//===--- PartialDiagnostic.h - Diagnostic "closures" ----------------------===//
+//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index b4cf959dc55..15ece685104 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -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");
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 4cace86dd18..9e54762add7 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -77,6 +77,7 @@ namespace clang {
AS_private,
AS_none
};
-}
+
+} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 97e0495bfbe..bc2cf198c3f 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.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 "";
}
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index bb022f11759..522ac13b4e3 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -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)
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index 4710b6b608e..2728637ba49 100644
--- a/include/clang/Basic/Version.h
+++ b/include/clang/Basic/Version.h
@@ -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
diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h
similarity index 97%
rename from include/clang/Analysis/PathSensitive/BugReporter.h
rename to include/clang/Checker/BugReporter/BugReporter.h
index 6f6681a3629..6c41668ccec 100644
--- a/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/include/clang/Checker/BugReporter/BugReporter.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
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Checker/BugReporter/BugType.h
similarity index 97%
rename from include/clang/Analysis/PathSensitive/BugType.h
rename to include/clang/Checker/BugReporter/BugType.h
index b75a8189e54..4f1523a5440 100644
--- a/include/clang/Analysis/PathSensitive/BugType.h
+++ b/include/clang/Checker/BugReporter/BugType.h
@@ -14,7 +14,6 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
-#include "clang/Analysis/PathSensitive/BugReporter.h"
#include
#include
diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Checker/BugReporter/PathDiagnostic.h
similarity index 100%
rename from include/clang/Analysis/PathDiagnostic.h
rename to include/clang/Checker/BugReporter/PathDiagnostic.h
diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Checker/Checkers/DereferenceChecker.h
similarity index 100%
rename from include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h
rename to include/clang/Checker/Checkers/DereferenceChecker.h
diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Checker/Checkers/LocalCheckers.h
similarity index 93%
rename from include/clang/Analysis/LocalCheckers.h
rename to include/clang/Checker/Checkers/LocalCheckers.h
index 9c343e07864..4a9e381a7c1 100644
--- a/include/clang/Analysis/LocalCheckers.h
+++ b/include/clang/Checker/Checkers/LocalCheckers.h
@@ -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);
diff --git a/include/clang/Checker/DomainSpecific/CocoaConventions.h b/include/clang/Checker/DomainSpecific/CocoaConventions.h
new file mode 100644
index 00000000000..ee3d648b860
--- /dev/null
+++ b/include/clang/Checker/DomainSpecific/CocoaConventions.h
@@ -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
diff --git a/include/clang/Analysis/ManagerRegistry.h b/include/clang/Checker/ManagerRegistry.h
similarity index 97%
rename from include/clang/Analysis/ManagerRegistry.h
rename to include/clang/Checker/ManagerRegistry.h
index 972993855c2..ebfd28e1093 100644
--- a/include/clang/Analysis/ManagerRegistry.h
+++ b/include/clang/Checker/ManagerRegistry.h
@@ -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 {
diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h
similarity index 96%
rename from include/clang/Analysis/PathSensitive/AnalysisManager.h
rename to include/clang/Checker/PathSensitive/AnalysisManager.h
index 8288864f2b6..fdf52a7dc77 100644
--- a/include/clang/Analysis/PathSensitive/AnalysisManager.h
+++ b/include/clang/Checker/PathSensitive/AnalysisManager.h
@@ -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 {
diff --git a/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Checker/PathSensitive/BasicValueFactory.h
similarity index 92%
rename from include/clang/Analysis/PathSensitive/BasicValueFactory.h
rename to include/clang/Checker/PathSensitive/BasicValueFactory.h
index 12f0ce2d50b..2f0b6c2a034 100644
--- a/include/clang/Analysis/PathSensitive/BasicValueFactory.h
+++ b/include/clang/Checker/PathSensitive/BasicValueFactory.h
@@ -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 Vals);
- const LazyCompoundValData *getLazyCompoundValData(const GRState *state,
+ const LazyCompoundValData *getLazyCompoundValData(const void *store,
const TypedRegion *region);
llvm::ImmutableList getEmptySValList() {
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h
similarity index 98%
rename from include/clang/Analysis/PathSensitive/Checker.h
rename to include/clang/Checker/PathSensitive/Checker.h
index 924a8b11b09..d498044b82c 100644
--- a/include/clang/Analysis/PathSensitive/Checker.h
+++ b/include/clang/Checker/PathSensitive/Checker.h
@@ -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"
diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Checker/PathSensitive/CheckerVisitor.def
similarity index 97%
rename from include/clang/Analysis/PathSensitive/CheckerVisitor.def
rename to include/clang/Checker/PathSensitive/CheckerVisitor.def
index 7ec27efe519..2edc4a37b7e 100644
--- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def
+++ b/include/clang/Checker/PathSensitive/CheckerVisitor.def
@@ -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)
diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Checker/PathSensitive/CheckerVisitor.h
similarity index 86%
rename from include/clang/Analysis/PathSensitive/CheckerVisitor.h
rename to include/clang/Checker/PathSensitive/CheckerVisitor.h
index 37ec8def50b..72f0ae1375e 100644
--- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h
+++ b/include/clang/Checker/PathSensitive/CheckerVisitor.h
@@ -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(this)->PreVisitCastExpr(C,
static_cast(S));
@@ -57,7 +56,7 @@ public:
case Stmt::NAME ## Class:\
static_cast(this)->PreVisit ## NAME(C,static_cast(S));\
break;
-#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
+#include "clang/Checker/PathSensitive/CheckerVisitor.def"
}
}
@@ -76,24 +75,26 @@ case Stmt::NAME ## Class:\
static_cast(this)->\
PostVisit ## NAME(C,static_cast(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(this)->PreVisitStmt(C, E);
+ }
#define PREVISIT(NAME, FALLBACK) \
void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\
- PreVisit ## FALLBACK(C, S);\
+ static_cast(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(this)->PostVisit ## FALLBACK(C, S);\
}
-#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
+#include "clang/Checker/PathSensitive/CheckerVisitor.def"
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/ConstraintManager.h b/include/clang/Checker/PathSensitive/ConstraintManager.h
similarity index 98%
rename from include/clang/Analysis/PathSensitive/ConstraintManager.h
rename to include/clang/Checker/PathSensitive/ConstraintManager.h
index c8292802ae9..ce7d1b38171 100644
--- a/include/clang/Analysis/PathSensitive/ConstraintManager.h
+++ b/include/clang/Checker/PathSensitive/ConstraintManager.h
@@ -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;
diff --git a/include/clang/Analysis/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h
similarity index 96%
rename from include/clang/Analysis/PathSensitive/Environment.h
rename to include/clang/Checker/PathSensitive/Environment.h
index 6d5c5678e59..0852c31faeb 100644
--- a/include/clang/Analysis/PathSensitive/Environment.h
+++ b/include/clang/Checker/PathSensitive/Environment.h
@@ -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"
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Checker/PathSensitive/ExplodedGraph.h
similarity index 99%
rename from include/clang/Analysis/PathSensitive/ExplodedGraph.h
rename to include/clang/Checker/PathSensitive/ExplodedGraph.h
index fb5e1b8a415..d6c4436c594 100644
--- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h
+++ b/include/clang/Checker/PathSensitive/ExplodedGraph.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"
diff --git a/include/clang/Analysis/PathSensitive/GRAuditor.h b/include/clang/Checker/PathSensitive/GRAuditor.h
similarity index 100%
rename from include/clang/Analysis/PathSensitive/GRAuditor.h
rename to include/clang/Checker/PathSensitive/GRAuditor.h
diff --git a/include/clang/Analysis/PathSensitive/GRBlockCounter.h b/include/clang/Checker/PathSensitive/GRBlockCounter.h
similarity index 100%
rename from include/clang/Analysis/PathSensitive/GRBlockCounter.h
rename to include/clang/Checker/PathSensitive/GRBlockCounter.h
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
similarity index 97%
rename from include/clang/Analysis/PathSensitive/GRCoreEngine.h
rename to include/clang/Checker/PathSensitive/GRCoreEngine.h
index 74f7a147b84..6da45815f99 100644
--- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.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 {
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
similarity index 94%
rename from include/clang/Analysis/PathSensitive/GRExprEngine.h
rename to include/clang/Checker/PathSensitive/GRExprEngine.h
index df90ad9f7f0..90a2cd55972 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -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);
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h b/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h
similarity index 97%
rename from include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
rename to include/clang/Checker/PathSensitive/GRExprEngineBuilders.h
index 60db406cd13..5503412f7e4 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngineBuilders.h
@@ -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 {
diff --git a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h
similarity index 90%
rename from include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
rename to include/clang/Checker/PathSensitive/GRSimpleAPICheck.h
index 978ff0889e6..383463b822c 100644
--- a/include/clang/Analysis/PathSensitive/GRSimpleAPICheck.h
+++ b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h
@@ -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 {
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h
similarity index 96%
rename from include/clang/Analysis/PathSensitive/GRState.h
rename to include/clang/Checker/PathSensitive/GRState.h
index 11cdac0e96d..4e44697a272 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Checker/PathSensitive/GRState.h
@@ -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 {
diff --git a/include/clang/Analysis/PathSensitive/GRStateTrait.h b/include/clang/Checker/PathSensitive/GRStateTrait.h
similarity index 100%
rename from include/clang/Analysis/PathSensitive/GRStateTrait.h
rename to include/clang/Checker/PathSensitive/GRStateTrait.h
diff --git a/include/clang/Analysis/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h
similarity index 98%
rename from include/clang/Analysis/PathSensitive/GRSubEngine.h
rename to include/clang/Checker/PathSensitive/GRSubEngine.h
index 5b383fae9bd..ce57c2c68b4 100644
--- a/include/clang/Analysis/PathSensitive/GRSubEngine.h
+++ b/include/clang/Checker/PathSensitive/GRSubEngine.h
@@ -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 {
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
similarity index 94%
rename from include/clang/Analysis/PathSensitive/GRTransferFuncs.h
rename to include/clang/Checker/PathSensitive/GRTransferFuncs.h
index b058460a493..04634effd58 100644
--- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
@@ -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
namespace clang {
diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Checker/PathSensitive/GRWorkList.h
similarity index 97%
rename from include/clang/Analysis/PathSensitive/GRWorkList.h
rename to include/clang/Checker/PathSensitive/GRWorkList.h
index 857fa316911..b8f90fa1eea 100644
--- a/include/clang/Analysis/PathSensitive/GRWorkList.h
+++ b/include/clang/Checker/PathSensitive/GRWorkList.h
@@ -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
namespace clang {
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h
similarity index 98%
rename from include/clang/Analysis/PathSensitive/MemRegion.h
rename to include/clang/Checker/PathSensitive/MemRegion.h
index 3bcedbefd65..12bc0b79568 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Checker/PathSensitive/MemRegion.h
@@ -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 {
+class RegionRawOffset {
private:
friend class ElementRegion;
+ const MemRegion *Region;
+ int64_t Offset;
+
RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
- : std::pair(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;
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h
similarity index 99%
rename from include/clang/Analysis/PathSensitive/SVals.h
rename to include/clang/Checker/PathSensitive/SVals.h
index 9206817989d..65a8a2c01df 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/include/clang/Checker/PathSensitive/SVals.h
@@ -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(Data);
}
- const GRState *getState() const;
+ const void *getStore() const;
const TypedRegion *getRegion() const;
static bool classof(const SVal *V) {
diff --git a/include/clang/Analysis/PathSensitive/SValuator.h b/include/clang/Checker/PathSensitive/SValuator.h
similarity index 66%
rename from include/clang/Analysis/PathSensitive/SValuator.h
rename to include/clang/Checker/PathSensitive/SValuator.h
index 4a4b502c627..9beb8cb0866 100644
--- a/include/clang/Analysis/PathSensitive/SValuator.h
+++ b/include/clang/Checker/PathSensitive/SValuator.h
@@ -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
- class GenericCastResult : public std::pair {
- public:
- const GRState *getState() const { return this->first; }
- T getSVal() const { return this->second; }
- GenericCastResult(const GRState *s, T v)
- : std::pair(s, v) {}
- };
+ SVal EvalCast(SVal V, QualType castTy, QualType originalType);
- class CastResult : public GenericCastResult {
- public:
- CastResult(const GRState *s, SVal v) : GenericCastResult(s, v) {}
- };
-
- class DefinedOrUnknownCastResult :
- public GenericCastResult {
- public:
- DefinedOrUnknownCastResult(const GRState *s, DefinedOrUnknownSVal v)
- : GenericCastResult(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;
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h
similarity index 75%
rename from include/clang/Analysis/PathSensitive/Store.h
rename to include/clang/Checker/PathSensitive/Store.h
index 5606df0014f..c660e7b7fee 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Checker/PathSensitive/Store.h
@@ -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& 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 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
diff --git a/include/clang/Checker/PathSensitive/SummaryManager.h b/include/clang/Checker/PathSensitive/SummaryManager.h
new file mode 100644
index 00000000000..fd23189491b
--- /dev/null
+++ b/include/clang/Checker/PathSensitive/SummaryManager.h
@@ -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
+class SummaryManager : SummaryManagerImpl {
+
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h
similarity index 100%
rename from include/clang/Analysis/PathSensitive/SymbolManager.h
rename to include/clang/Checker/PathSensitive/SymbolManager.h
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h
similarity index 94%
rename from include/clang/Analysis/PathSensitive/ValueManager.h
rename to include/clang/Checker/PathSensitive/ValueManager.h
index 9cec3c421fb..ea3af57ed3e 100644
--- a/include/clang/Analysis/PathSensitive/ValueManager.h
+++ b/include/clang/Checker/PathSensitive/ValueManager.h
@@ -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() {
diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h
index 8682715ce55..e1d4ad1b1cc 100644
--- a/include/clang/CodeGen/CodeGenOptions.h
+++ b/include/clang/CodeGen/CodeGenOptions.h
@@ -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;
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 2511dfb7677..047363ea597 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -38,19 +38,21 @@ def analysis_CFGView : Flag<"-cfg-view">,
HelpText<"View Control-Flow Graphs using GraphViz">;
def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">,
HelpText<"Print results of live variable analysis">;
-def analysis_SecuritySyntacticChecks : Flag<"-warn-security-syntactic">,
+def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">,
+ HelpText<"Check code for LLVM codebase conventions (domain-specific)">;
+def analysis_SecuritySyntacticChecks : Flag<"-analyzer-check-security-syntactic">,
HelpText<"Perform quick security checks that require no data flow">;
-def analysis_WarnDeadStores : Flag<"-warn-dead-stores">,
+def analysis_WarnDeadStores : Flag<"-analyzer-check-dead-stores">,
HelpText<"Warn about stores to dead variables">;
def analysis_WarnUninitVals : Flag<"-warn-uninit-values">,
HelpText<"Warn about uses of uninitialized variables">;
-def analysis_WarnObjCMethSigs : Flag<"-warn-objc-methodsigs">,
+def analysis_WarnObjCMethSigs : Flag<"-analyzer-check-objc-methodsigs">,
HelpText<"Warn about Objective-C method signatures with type incompatibilities">;
-def analysis_WarnObjCDealloc : Flag<"-warn-objc-missing-dealloc">,
+def analysis_WarnObjCDealloc : Flag<"-analyzer-check-objc-missing-dealloc">,
HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">;
-def analysis_WarnObjCUnusedIvars : Flag<"-warn-objc-unused-ivars">,
+def analysis_WarnObjCUnusedIvars : Flag<"-analyzer-check-objc-unused-ivars">,
HelpText<"Warn about private ivars that are never used">;
-def analysis_CheckerCFRef : Flag<"-checker-cfref">,
+def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">,
HelpText<"Run the [Core] Foundation reference count checker">;
def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
@@ -102,6 +104,8 @@ def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">,
def disable_llvm_optzns : Flag<"-disable-llvm-optzns">,
HelpText<"Don't run LLVM optimization passes">;
+def disable_llvm_verifier : Flag<"-disable-llvm-verifier">,
+ HelpText<"Don't run the LLVM IR verifier pass">;
def disable_red_zone : Flag<"-disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def dwarf_debug_flags : Separate<"-dwarf-debug-flags">,
@@ -115,6 +119,10 @@ def no_implicit_float : Flag<"-no-implicit-float">,
HelpText<"Don't generate implicit floating point instructions (x86-only)">;
def fno_merge_all_constants : Flag<"-fno-merge-all-constants">,
HelpText<"Disallow merging of constants.">;
+def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">,
+ HelpText<"Do not emit code to make initialization of local statics thread safe">;
+def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">,
+ HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">;
def masm_verbose : Flag<"-masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<"-mcode-model">,
@@ -165,6 +173,7 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">,
HelpText<"Do not include source line and caret with diagnostics">;
def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
HelpText<"Do not include fixit information in diagnostics">;
+def fdiagnostics_binary : Flag<"-fdiagnostics-binary">;
def w : Flag<"-w">, HelpText<"Suppress all warnings">;
def pedantic : Flag<"-pedantic">;
def pedantic_errors : Flag<"-pedantic-errors">;
@@ -197,6 +206,9 @@ def verify : Flag<"-verify">,
// CompilerInvocation out of a driver-derived argument vector.
def cc1 : Flag<"-cc1">;
+def ast_merge : Separate<"-ast-merge">,
+ MetaVarName<"">,
+ HelpText<"Merge the given AST file into the translation unit being compiled.">;
def code_completion_at : Separate<"-code-completion-at">,
MetaVarName<"::">,
HelpText<"Dump code-completion information at a location">;
@@ -280,6 +292,8 @@ def emit_llvm_bc : Flag<"-emit-llvm-bc">,
HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
def emit_llvm_only : Flag<"-emit-llvm-only">,
HelpText<"Build ASTs and convert to LLVM, discarding output">;
+def emit_obj : Flag<"-emit-obj">,
+ HelpText<"Emit native object files">;
def rewrite_test : Flag<"-rewrite-test">,
HelpText<"Rewriter playground">;
def rewrite_objc : Flag<"-rewrite-objc">,
@@ -319,6 +333,8 @@ def fblocks : Flag<"-fblocks">,
def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
def fexceptions : Flag<"-fexceptions">,
HelpText<"Enable support for exception handling">;
+def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
+ HelpText<"Use SjLj style exceptions">;
def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fgnu_runtime : Flag<"-fgnu-runtime">,
@@ -346,10 +362,14 @@ def fobjc_gc : Flag<"-fobjc-gc">,
HelpText<"Enable Objective-C garbage collection">;
def fobjc_gc_only : Flag<"-fobjc-gc-only">,
HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">,
+ HelpText<"Use legacy dispatch with the Objective-C non-fragile ABI">;
def print_ivar_layout : Flag<"-print-ivar-layout">,
HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
HelpText<"enable objective-c's nonfragile abi">;
+def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">,
+ HelpText<"enable objective-c's enhanced nonfragile abi">;
def ftrapv : Flag<"-ftrapv">,
HelpText<"Trap on integer overflow">;
def pic_level : Separate<"-pic-level">,
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 3186471ce61..64f88ed9831 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -77,32 +77,36 @@ public:
/// Information about the host which can be overriden by the user.
std::string HostBits, HostMachine, HostSystem, HostRelease;
- /// Whether the driver should follow g++ like behavior.
- bool CCCIsCXX : 1;
-
- /// Echo commands while executing (in -v style).
- bool CCCEcho : 1;
-
- /// Only print tool bindings, don't build any jobs.
- bool CCCPrintBindings : 1;
-
/// Name to use when calling the generic gcc.
std::string CCCGenericGCCName;
+ /// Whether the driver should follow g++ like behavior.
+ unsigned CCCIsCXX : 1;
+
+ /// Echo commands while executing (in -v style).
+ unsigned CCCEcho : 1;
+
+ /// Only print tool bindings, don't build any jobs.
+ unsigned CCCPrintBindings : 1;
+
private:
+ /// Whether to check that input files exist when constructing compilation
+ /// jobs.
+ unsigned CheckInputsExist : 1;
+
/// Use the clang compiler where possible.
- bool CCCUseClang : 1;
+ unsigned CCCUseClang : 1;
/// Use clang for handling C++ and Objective-C++ inputs.
- bool CCCUseClangCXX : 1;
+ unsigned CCCUseClangCXX : 1;
/// Use clang as a preprocessor (clang's preprocessor will still be
/// used where an integrated CPP would).
- bool CCCUseClangCPP : 1;
+ unsigned CCCUseClangCPP : 1;
public:
/// Use lazy precompiled headers for PCH support.
- bool CCCUsePCH;
+ unsigned CCCUsePCH : 1;
private:
/// Only use clang for the given architectures (only used when
@@ -129,6 +133,10 @@ public:
const Diagnostic &getDiags() const { return Diags; }
+ bool getCheckInputsExist() const { return CheckInputsExist; }
+
+ void setCheckInputsExist(bool Value) { CheckInputsExist = Value; }
+
/// @}
/// @name Primary Functionality
/// @{
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 955d98e4e91..4693e5c1433 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -252,6 +252,7 @@ def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group, Group;
def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group;
def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group;
+def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group, Flags<[HelpHidden]>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group;
@@ -302,6 +303,7 @@ def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group, Group;
def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group;
def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group;
+def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group;
def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group;
def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group;
def fno_rtti : Flag<"-fno-rtti">, Group;
@@ -309,6 +311,7 @@ def fno_show_column : Flag<"-fno-show-column">, Group;
def fno_show_source_location : Flag<"-fno-show-source-location">, Group;
def fno_stack_protector : Flag<"-fno-stack-protector">, Group;
def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group;
+def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group;
def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group;
def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group;
def fno_working_directory : Flag<"-fno-working-directory">, Group;
@@ -317,8 +320,10 @@ def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group;
def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group;
def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group;
def fobjc_gc : Flag<"-fobjc-gc">, Group;
+def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group;
def fobjc_new_property : Flag<"-fobjc-new-property">, Group