Browse Source

cppparser: Properly record C++11 attributes

rdb 3 years ago
parent
commit
dd262c6715
32 changed files with 1676 additions and 1257 deletions
  1. 2 0
      dtool/src/cppparser/CMakeLists.txt
  2. 5 0
      dtool/src/cppparser/cppArrayType.cxx
  3. 196 0
      dtool/src/cppparser/cppAttributeList.cxx
  4. 65 0
      dtool/src/cppparser/cppAttributeList.h
  5. 916 952
      dtool/src/cppparser/cppBison.cxx.prebuilt
  6. 6 3
      dtool/src/cppparser/cppBison.h.prebuilt
  7. 256 203
      dtool/src/cppparser/cppBison.yxx
  8. 2 0
      dtool/src/cppparser/cppBisonDefs.h
  9. 4 0
      dtool/src/cppparser/cppClosureType.cxx
  10. 22 3
      dtool/src/cppparser/cppDeclaration.cxx
  11. 8 3
      dtool/src/cppparser/cppDeclaration.h
  12. 23 12
      dtool/src/cppparser/cppEnumType.cxx
  13. 6 3
      dtool/src/cppparser/cppEnumType.h
  14. 5 1
      dtool/src/cppparser/cppExtensionType.cxx
  15. 1 1
      dtool/src/cppparser/cppExtensionType.h
  16. 20 9
      dtool/src/cppparser/cppFunctionType.cxx
  17. 8 0
      dtool/src/cppparser/cppIdentifier.cxx
  18. 2 0
      dtool/src/cppparser/cppIdentifier.h
  19. 11 15
      dtool/src/cppparser/cppInstance.cxx
  20. 1 1
      dtool/src/cppparser/cppInstance.h
  21. 40 16
      dtool/src/cppparser/cppInstanceIdentifier.cxx
  22. 22 8
      dtool/src/cppparser/cppInstanceIdentifier.h
  23. 12 6
      dtool/src/cppparser/cppNamespace.cxx
  24. 1 1
      dtool/src/cppparser/cppNamespace.h
  25. 6 0
      dtool/src/cppparser/cppPointerType.cxx
  26. 9 6
      dtool/src/cppparser/cppReferenceType.cxx
  27. 9 5
      dtool/src/cppparser/cppStructType.cxx
  28. 2 1
      dtool/src/cppparser/cppStructType.h
  29. 13 2
      dtool/src/cppparser/cppTypedefType.cxx
  30. 2 1
      dtool/src/cppparser/cppTypedefType.h
  31. 1 1
      dtool/src/cppparser/p3cppParser_composite1.cxx
  32. 0 4
      dtool/src/parser-inc/stdtypedefs.h

+ 2 - 0
dtool/src/cppparser/CMakeLists.txt

@@ -1,4 +1,5 @@
 set(P3CPPPARSER_HEADERS
+  cppAttributeList.h
   cppArrayType.h cppBison.yxx cppBisonDefs.h
   cppClassTemplateParameter.h cppCommentBlock.h
   cppClosureType.h cppConstType.h
@@ -17,6 +18,7 @@ set(P3CPPPARSER_HEADERS
 )
 
 set(P3CPPPARSER_SOURCES
+  cppAttributeList.cxx
   cppArrayType.cxx ${CMAKE_CURRENT_BINARY_DIR}/cppBison.cxx
   cppClassTemplateParameter.cxx
   cppCommentBlock.cxx cppClosureType.cxx cppConstType.cxx cppDeclaration.cxx

+ 5 - 0
dtool/src/cppparser/cppArrayType.cxx

@@ -189,6 +189,11 @@ output_instance(std::ostream &out, int indent_level, CPPScope *scope,
     brackets << *_bounds;
   }
   brackets << "]";
+
+  if (!_attributes.is_empty()) {
+    brackets << " " << _attributes;
+  }
+
   std::string bracketsstr = brackets.str();
 
   _element_type->output_instance(out, indent_level, scope, complete,

+ 196 - 0
dtool/src/cppparser/cppAttributeList.cxx

@@ -0,0 +1,196 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file cppAttributeList.cxx
+ * @author rdb
+ * @date 2022-10-23
+ */
+
+#include "cppAttributeList.h"
+#include "cppExpression.h"
+#include "cppIdentifier.h"
+#include "cppType.h"
+
+/**
+ * Returns true if no attributes have been defined.
+ */
+bool CPPAttributeList::
+is_empty() const {
+  return _attributes.empty() && _alignas == nullptr;
+}
+
+/**
+ * Returns true if the attribute list has an attribute with the given name.
+ */
+bool CPPAttributeList::
+has_attribute(const std::string &name) const {
+  for (const Attribute &attr : _attributes) {
+    if (attr._ident->get_fully_scoped_name() == name) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ *
+ */
+bool CPPAttributeList::
+operator == (const CPPAttributeList &other) const {
+  if (_attributes.size() != other._attributes.size()) {
+    return false;
+  }
+  if ((_alignas != nullptr) != (other._alignas != nullptr)) {
+    return false;
+  }
+  if (_alignas != nullptr && *_alignas != *other._alignas) {
+    return false;
+  }
+  for (size_t i = 0; i < _attributes.size(); ++i) {
+    if (_attributes[i]._ident != other._attributes[i]._ident) {
+      return false;
+    }
+    if (_attributes[i]._reason != other._attributes[i]._reason) {
+      return false;
+    }
+  }
+  return true;
+}
+
+/**
+ *
+ */
+bool CPPAttributeList::
+operator != (const CPPAttributeList &other) const {
+  return !(*this == other);
+}
+
+/**
+ *
+ */
+bool CPPAttributeList::
+operator < (const CPPAttributeList &other) const {
+  if (_attributes.size() != other._attributes.size()) {
+    return _attributes.size() < other._attributes.size();
+  }
+  if ((_alignas != nullptr) != (other._alignas != nullptr)) {
+    return _alignas == nullptr;
+  }
+  if (_alignas != nullptr && *_alignas != *other._alignas) {
+    return *_alignas < *other._alignas;
+  }
+  for (size_t i = 0; i < _attributes.size(); ++i) {
+    if (_attributes[i]._ident != other._attributes[i]._ident) {
+      return _attributes[i]._ident < other._attributes[i]._ident;
+    }
+    if (_attributes[i]._reason != other._attributes[i]._reason) {
+      return _attributes[i]._reason < other._attributes[i]._reason;
+    }
+  }
+  return false;
+}
+
+/**
+ * Adds an attribute.
+ */
+void CPPAttributeList::
+add_attribute(CPPIdentifier *ident) {
+  _attributes.push_back({ident});
+}
+
+/**
+ * Adds an attribute.
+ */
+void CPPAttributeList::
+add_attribute(CPPIdentifier *ident, std::string reason) {
+  _attributes.push_back({ident, std::move(reason)});
+}
+
+/**
+ * Adds an alignas specifier.
+ */
+void CPPAttributeList::
+add_alignas(int size) {
+  if (_alignas == nullptr || size >= _alignas->evaluate().as_integer()) {
+    _alignas = new CPPExpression(size);
+  }
+}
+
+/**
+ * Adds an alignas specifier.
+ */
+void CPPAttributeList::
+add_alignas(CPPType *type) {
+  CPPExpression expr = CPPExpression::alignof_func(type);
+  if (_alignas == nullptr || expr.evaluate().as_integer() > _alignas->evaluate().as_integer()) {
+    _alignas = new CPPExpression(expr);
+  }
+}
+
+/**
+ * Adds an alignas specifier.
+ */
+void CPPAttributeList::
+add_alignas(CPPExpression *expr) {
+  if (_alignas == nullptr || expr->evaluate().as_integer() > _alignas->evaluate().as_integer()) {
+    _alignas = expr;
+  }
+}
+
+/**
+ * Merges the other list into this one.
+ */
+void CPPAttributeList::
+add_attributes_from(const CPPAttributeList &other) {
+  for (const Attribute &attr : other._attributes) {
+    _attributes.push_back(attr);
+  }
+
+  if (other._alignas != nullptr) {
+    add_alignas(other._alignas);
+  }
+}
+
+/**
+ *
+ */
+void CPPAttributeList::
+output(std::ostream &out, CPPScope *scope) const {
+  Attributes::const_iterator it = _attributes.begin();
+  if (it != _attributes.end()) {
+    out << "[[";
+    (*it)._ident->output(out, scope);
+    if (!(*it)._reason.empty()) {
+      out << "(" << (*it)._reason << ")";
+    }
+
+    for (++it; it != _attributes.end(); ++it) {
+      out << ", ";
+      (*it)._ident->output(out, scope);
+      if (!(*it)._reason.empty()) {
+        out << "(" << (*it)._reason << ")";
+      }
+    }
+
+    out << "]]";
+
+    if (_alignas != nullptr) {
+      out << " ";
+    }
+  }
+
+  if (_alignas != nullptr) {
+    out << "alignas(";
+    if (_alignas->_type == CPPExpression::T_alignof) {
+      _alignas->_u._typecast._to->output(out, 0, scope, false);
+    } else {
+      _alignas->output(out, 0, scope, false);
+    }
+    out << ")";
+  }
+}

+ 65 - 0
dtool/src/cppparser/cppAttributeList.h

@@ -0,0 +1,65 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file cppAttributeList.h
+ * @author rdb
+ * @date 2022-10-23
+ */
+
+#ifndef CPPATTRIBUTELIST_H
+#define CPPATTRIBUTELIST_H
+
+#include "dtoolbase.h"
+
+#include <vector>
+
+class CPPExpression;
+class CPPIdentifier;
+class CPPScope;
+class CPPType;
+
+/**
+ * A list of square-bracket attributes and/or alignas specifiers.
+ */
+class CPPAttributeList {
+public:
+  bool is_empty() const;
+  bool has_attribute(const std::string &name) const;
+
+  bool operator == (const CPPAttributeList &other) const;
+  bool operator != (const CPPAttributeList &other) const;
+  bool operator < (const CPPAttributeList &other) const;
+
+  void add_attribute(CPPIdentifier *ident);
+  void add_attribute(CPPIdentifier *ident, std::string reason);
+
+  void add_alignas(int size);
+  void add_alignas(CPPType *type);
+  void add_alignas(CPPExpression *expr);
+
+  void add_attributes_from(const CPPAttributeList &other);
+
+  struct Attribute {
+    CPPIdentifier *_ident;
+    std::string _reason;
+  };
+
+  typedef std::vector<Attribute> Attributes;
+  Attributes _attributes;
+  CPPExpression *_alignas = nullptr;
+
+  void output(std::ostream &out, CPPScope *scope) const;
+};
+
+inline std::ostream &
+operator << (std::ostream &out, const CPPAttributeList &alist) {
+  alist.output(out, nullptr);
+  return out;
+}
+
+#endif

File diff suppressed because it is too large
+ 916 - 952
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 6 - 3
dtool/src/cppparser/cppBison.h.prebuilt

@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.7.3.  */
+/* A Bison parser, made by GNU Bison 3.8.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
    Inc.
 
    This program is free software: you can redistribute it and/or modify
@@ -16,7 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -208,6 +208,7 @@ extern int cppyydebug;
   typedef enum yytokentype yytoken_kind_t;
 #endif
 /* Token kinds.  */
+#define YYEMPTY -2
 #define YYEOF 0
 #define YYerror 256
 #define YYUNDEF 257
@@ -380,6 +381,8 @@ struct YYLTYPE
 
 
 
+
 int cppyyparse (void);
 
+
 #endif /* !YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED  */

File diff suppressed because it is too large
+ 256 - 203
dtool/src/cppparser/cppBison.yxx


+ 2 - 0
dtool/src/cppparser/cppBisonDefs.h

@@ -23,6 +23,7 @@
 
 #include <string>
 
+#include "cppAttributeList.h"
 #include "cppClosureType.h"
 #include "cppExtensionType.h"
 #include "cppFile.h"
@@ -65,6 +66,7 @@ extern CPPPreprocessor *current_lexer;
 class cppyystype {
 public:
   std::string str;
+  CPPAttributeList attr_list;
   union {
     unsigned long long integer;
     long double real;

+ 4 - 0
dtool/src/cppparser/cppClosureType.cxx

@@ -152,6 +152,10 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
     out << " noexcept";
   }
 
+  if (!_attributes.is_empty()) {
+    out << " " << _attributes;
+  }
+
   if (_return_type != nullptr) {
     out << " -> ";
     _return_type->output(out, indent_level, scope, false);

+ 22 - 3
dtool/src/cppparser/cppDeclaration.cxx

@@ -18,8 +18,9 @@
  *
  */
 CPPDeclaration::
-CPPDeclaration(const CPPFile &file) :
-  _file(file)
+CPPDeclaration(const CPPFile &file, CPPAttributeList attr) :
+  _file(file),
+  _attributes(std::move(attr))
 {
   _vis = V_unknown;
   _template_scope = nullptr;
@@ -34,7 +35,8 @@ CPPDeclaration(const CPPDeclaration &copy) :
   _vis(copy._vis),
   _template_scope(copy._template_scope),
   _file(copy._file),
-  _leading_comment(copy._leading_comment)
+  _leading_comment(copy._leading_comment),
+  _attributes(copy._attributes)
 {
 }
 
@@ -47,6 +49,7 @@ operator = (const CPPDeclaration &copy) {
   _template_scope = copy._template_scope;
   _file = copy._file;
   _leading_comment = copy._leading_comment;
+  _attributes = copy._attributes;
   return *this;
 }
 
@@ -135,6 +138,22 @@ substitute_decl(SubstDecl &subst, CPPScope *, CPPScope *) {
   return this;
 }
 
+/**
+ *
+ */
+void CPPDeclaration::
+output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  out << _attributes;
+}
+
+/**
+ *
+ */
+CPPDeclaration::SubType CPPDeclaration::
+get_subtype() const {
+  return ST_empty;
+}
+
 /**
  *
  */

+ 8 - 3
dtool/src/cppparser/cppDeclaration.h

@@ -19,6 +19,7 @@
 #include "cppVisibility.h"
 #include "cppFile.h"
 #include "cppCommentBlock.h"
+#include "cppAttributeList.h"
 
 #include <string>
 #include <vector>
@@ -59,6 +60,9 @@ class CPPPreprocessor;
 class CPPDeclaration {
 public:
   enum SubType {
+    // Empty declaration
+    ST_empty,
+
     // Subtypes of CPPDeclaration
     ST_instance,
     ST_type_declaration,
@@ -87,7 +91,7 @@ public:
     ST_closure,
   };
 
-  CPPDeclaration(const CPPFile &file);
+  CPPDeclaration(const CPPFile &file, CPPAttributeList attr = CPPAttributeList());
   CPPDeclaration(const CPPDeclaration &copy);
   virtual ~CPPDeclaration() {};
 
@@ -114,9 +118,9 @@ public:
   Instantiations _instantiations;
 
   virtual void output(std::ostream &out, int indent_level, CPPScope *scope,
-                      bool complete) const=0;
+                      bool complete) const;
 
-  virtual SubType get_subtype() const=0;
+  virtual SubType get_subtype() const;
 
   virtual CPPInstance *as_instance();
   virtual CPPClassTemplateParameter *as_class_template_parameter();
@@ -216,6 +220,7 @@ public:
   CPPTemplateScope *_template_scope;
   CPPFile _file;
   CPPCommentBlock *_leading_comment;
+  CPPAttributeList _attributes;
 
 protected:
   virtual bool is_equal(const CPPDeclaration *other) const;

+ 23 - 12
dtool/src/cppparser/cppEnumType.cxx

@@ -26,8 +26,8 @@
  */
 CPPEnumType::
 CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
-            CPPScope *scope, const CPPFile &file) :
-  CPPExtensionType(type, ident, current_scope, file),
+            CPPScope *scope, const CPPFile &file, CPPAttributeList attr) :
+  CPPExtensionType(type, ident, current_scope, file, std::move(attr)),
   _scope(scope),
   _element_type(nullptr),
   _last_value(nullptr)
@@ -44,8 +44,9 @@ CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
  */
 CPPEnumType::
 CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
-            CPPScope *current_scope, CPPScope *scope, const CPPFile &file) :
-  CPPExtensionType(type, ident, current_scope, file),
+            CPPScope *current_scope, CPPScope *scope, const CPPFile &file,
+            CPPAttributeList attr) :
+  CPPExtensionType(type, ident, current_scope, file, std::move(attr)),
   _scope(scope),
   _element_type(element_type),
   _last_value(nullptr)
@@ -89,7 +90,9 @@ get_underlying_type() {
  *
  */
 CPPInstance *CPPEnumType::
-add_element(const std::string &name, CPPExpression *value, CPPPreprocessor *preprocessor, const cppyyltype &pos) {
+add_element(const std::string &name, CPPExpression *value,
+            CPPPreprocessor *preprocessor, const cppyyltype &pos,
+            CPPAttributeList attr) {
   CPPIdentifier *ident = new CPPIdentifier(name);
   ident->_native_scope = _parent_scope;
 
@@ -102,6 +105,7 @@ add_element(const std::string &name, CPPExpression *value, CPPPreprocessor *prep
     inst = new CPPInstance(this, ident);
   }
   inst->_storage_class |= CPPInstance::SC_constexpr;
+  inst->_attributes = std::move(attr);
   _elements.push_back(inst);
 
   if (value == nullptr) {
@@ -269,9 +273,12 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
       out << _type << " ";
     }
     out << _ident->get_local_name(scope);
-
-  } else {
+  }
+  else {
     out << _type;
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
     if (_ident != nullptr) {
       out << " " << _ident->get_local_name(scope);
     }
@@ -280,11 +287,15 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
     }
 
     out << " {\n";
-    Elements::const_iterator ei;
-    for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
-      indent(out, indent_level + 2) << (*ei)->get_local_name();
-      if ((*ei)->_initializer != nullptr) {
-        out << " = " << *(*ei)->_initializer;
+    for (CPPInstance *element : _elements) {
+      indent(out, indent_level + 2) << element->get_local_name();
+
+      if (!element->_attributes.is_empty()) {
+        out << " " << element->_attributes;
+      }
+
+      if (element->_initializer != nullptr) {
+        out << " = " << *element->_initializer;
       }
       out << ",\n";
     }

+ 6 - 3
dtool/src/cppparser/cppEnumType.h

@@ -32,15 +32,18 @@ class CPPScope;
 class CPPEnumType : public CPPExtensionType {
 public:
   CPPEnumType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
-              CPPScope *scope, const CPPFile &file);
+              CPPScope *scope, const CPPFile &file,
+              CPPAttributeList attr = CPPAttributeList());
   CPPEnumType(Type type, CPPIdentifier *ident, CPPType *element_type,
-              CPPScope *current_scope, CPPScope *scope, const CPPFile &file);
+              CPPScope *current_scope, CPPScope *scope, const CPPFile &file,
+              CPPAttributeList attr = CPPAttributeList());
 
   bool is_scoped() const;
   CPPType *get_underlying_type();
 
   CPPInstance *add_element(const std::string &name, CPPExpression *value,
-                           CPPPreprocessor *preprocessor, const cppyyltype &pos);
+                           CPPPreprocessor *preprocessor, const cppyyltype &pos,
+                           CPPAttributeList attr = CPPAttributeList());
 
   virtual bool is_incomplete() const;
 

+ 5 - 1
dtool/src/cppparser/cppExtensionType.cxx

@@ -23,7 +23,7 @@
 CPPExtensionType::
 CPPExtensionType(CPPExtensionType::Type type,
                  CPPIdentifier *ident, CPPScope *current_scope,
-                 const CPPFile &file) :
+                 const CPPFile &file, CPPAttributeList attr) :
   CPPType(file),
   _type(type), _ident(ident),
   _alignment(nullptr)
@@ -31,6 +31,7 @@ CPPExtensionType(CPPExtensionType::Type type,
   if (_ident != nullptr) {
     _ident->_native_scope = current_scope;
   }
+  _attributes = std::move(attr);
 }
 
 /**
@@ -215,6 +216,9 @@ output(std::ostream &out, int, CPPScope *scope, bool complete) const {
     if (complete || cppparser_output_class_keyword) {
       out << _type << " ";
     }
+    if (complete && !_attributes.is_empty()) {
+      out << _attributes << " ";
+    }
     out << _ident->get_local_name(scope);
 
   } else if (!_typedefs.empty()) {

+ 1 - 1
dtool/src/cppparser/cppExtensionType.h

@@ -39,7 +39,7 @@ public:
   };
 
   CPPExtensionType(Type type, CPPIdentifier *ident, CPPScope *current_scope,
-                   const CPPFile &file);
+                   const CPPFile &file, CPPAttributeList attr = CPPAttributeList());
 
   virtual std::string get_simple_name() const;
   virtual std::string get_local_name(CPPScope *scope = nullptr) const;

+ 20 - 9
dtool/src/cppparser/cppFunctionType.cxx

@@ -224,10 +224,13 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
     if (_flags & F_override) {
       out << " override";
     }
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
     out << " -> ";
     _return_type->output(out, indent_level, scope, false);
-
-  } else {
+  }
+  else {
     _return_type->output(out, indent_level, scope, complete);
     out << "(";
     _parameters->output(out, scope, true, num_default_parameters);
@@ -244,6 +247,9 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
     if (_flags & F_override) {
       out << " override";
     }
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
   }
 }
 
@@ -278,8 +284,8 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
   if (_flags & (F_constructor | F_destructor)) {
     // No return type for constructors and destructors.
     out << prename << name << str;
-
-  } else if (_flags & F_trailing_return_type) {
+  }
+  else if (_flags & F_trailing_return_type) {
     // It was declared using trailing return type, so let's format it that
     // way.
     out << "auto ";
@@ -291,12 +297,13 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
     }
 
     out << str;
-
-  } else if (_flags & F_operator_typecast) {
+  }
+  else if (_flags & F_operator_typecast) {
     out << "operator ";
-    _return_type->output_instance(out, indent_level, scope, complete, "", prename + str);
-
-  } else {
+    _return_type->output_instance(out, indent_level, scope, complete,
+                                  "", prename + str);
+  }
+  else {
     if (prename.empty()) {
       _return_type->output_instance(out, indent_level, scope, complete,
                                     "", prename + name + str);
@@ -322,6 +329,10 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
     out << " override";
   }
 
+  if (!_attributes.is_empty()) {
+    out << " " << _attributes;
+  }
+
   if (_flags & F_trailing_return_type) {
     out << " -> ";
     _return_type->output(out, indent_level, scope, false);

+ 8 - 0
dtool/src/cppparser/cppIdentifier.cxx

@@ -84,6 +84,14 @@ add_name(const CPPNameComponent &name) {
   _names.push_back(name);
 }
 
+/**
+ *
+ */
+void CPPIdentifier::
+prepend(CPPIdentifier *ident) {
+  _names.insert(_names.begin(), ident->_names.begin(), ident->_names.end());
+}
+
 /**
  *
  */

+ 2 - 0
dtool/src/cppparser/cppIdentifier.h

@@ -41,6 +41,8 @@ public:
   void add_name(const std::string &name);
   void add_name(const CPPNameComponent &name);
 
+  void prepend(CPPIdentifier *ident);
+
   bool operator == (const CPPIdentifier &other) const;
   bool operator != (const CPPIdentifier &other) const;
   bool operator < (const CPPIdentifier &other) const;

+ 11 - 15
dtool/src/cppparser/cppInstance.cxx

@@ -37,7 +37,6 @@ CPPInstance(CPPType *type, const string &name, int storage_class) :
   _type(type),
   _ident(new CPPIdentifier(name)),
   _storage_class(storage_class),
-  _alignment(nullptr),
   _bit_width(-1)
 {
   _initializer = nullptr;
@@ -52,7 +51,6 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
   _type(type),
   _ident(ident),
   _storage_class(storage_class),
-  _alignment(nullptr),
   _bit_width(-1)
 {
   _initializer = nullptr;
@@ -66,11 +64,11 @@ CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
 CPPInstance::
 CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
             const CPPFile &file) :
-  CPPDeclaration(file),
-  _alignment(nullptr)
+  CPPDeclaration(file)
 {
   _type = ii->unroll_type(type);
   _ident = ii->_ident;
+  _attributes = ii->_attributes;
   ii->_ident = nullptr;
   _storage_class = storage_class;
   _initializer = nullptr;
@@ -111,7 +109,6 @@ CPPInstance(const CPPInstance &copy) :
   _ident(copy._ident),
   _initializer(copy._initializer),
   _storage_class(copy._storage_class),
-  _alignment(copy._alignment),
   _bit_width(copy._bit_width)
 {
   assert(_type != nullptr);
@@ -156,7 +153,7 @@ operator == (const CPPInstance &other) const {
   if (_storage_class != other._storage_class) {
     return false;
   }
-  if (_alignment != other._alignment) {
+  if (_attributes != other._attributes) {
     return false;
   }
 
@@ -200,8 +197,8 @@ operator < (const CPPInstance &other) const {
   if (_storage_class != other._storage_class) {
     return _storage_class < other._storage_class;
   }
-  if (_alignment != other._alignment) {
-    return _alignment < other._alignment;
+  if (_attributes != other._attributes) {
+    return _attributes < other._attributes;
   }
 
   // We *do* care about the identifier.  We need to differentiate types of
@@ -264,7 +261,7 @@ set_initializer(CPPExpression *initializer) {
  */
 void CPPInstance::
 set_alignment(int align) {
-  _alignment = new CPPExpression(align);
+  _attributes.add_alignas(align);
 }
 
 /**
@@ -274,7 +271,7 @@ set_alignment(int align) {
  */
 void CPPInstance::
 set_alignment(CPPExpression *const_expr) {
-  _alignment = const_expr;
+  _attributes.add_alignas(const_expr);
 }
 
 /**
@@ -544,8 +541,8 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete,
     indent(out, indent_level);
   }
 
-  if (_alignment != nullptr) {
-    out << "alignas(" << *_alignment << ") ";
+  if (!_attributes.is_empty()) {
+    out << _attributes << " ";
   }
 
   if (_storage_class & SC_static) {
@@ -600,8 +597,8 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete,
     _type->as_function_type()->
       output_instance(out, indent_level, scope, complete, "", name,
                       num_default_parameters);
-
-  } else {
+  }
+  else {
     _type->output_instance(out, indent_level, scope, complete, "", name);
   }
 
@@ -623,7 +620,6 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete,
   }
 }
 
-
 /**
  *
  */

+ 1 - 1
dtool/src/cppparser/cppInstance.h

@@ -19,6 +19,7 @@
 #include "cppDeclaration.h"
 #include "cppType.h"
 #include "cppTemplateParameterList.h"
+#include "cppAttributeList.h"
 
 class CPPInstanceIdentifier;
 class CPPIdentifier;
@@ -127,7 +128,6 @@ public:
   CPPExpression *_initializer;
 
   int _storage_class;
-  CPPExpression *_alignment;
   int _bit_width;
 
 private:

+ 40 - 16
dtool/src/cppparser/cppInstanceIdentifier.cxx

@@ -25,20 +25,22 @@
  *
  */
 CPPInstanceIdentifier::Modifier::
-Modifier(CPPInstanceIdentifierType type) :
+Modifier(CPPInstanceIdentifierType type, CPPAttributeList attr) :
   _type(type),
   _func_params(nullptr),
   _func_flags(0),
   _scoping(nullptr),
-  _expr(nullptr) {
+  _expr(nullptr),
+  _attributes(std::move(attr)) {
 }
 
 /**
  *
  */
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
-func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
-  Modifier mod(IIT_func);
+func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type,
+          CPPAttributeList attr) {
+  Modifier mod(IIT_func, std::move(attr));
   mod._func_params = params;
   mod._func_flags = flags;
   mod._trailing_return_type = trailing_return_type;
@@ -49,8 +51,8 @@ func_type(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
  *
  */
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
-array_type(CPPExpression *expr) {
-  Modifier mod(IIT_array);
+array_type(CPPExpression *expr, CPPAttributeList attr) {
+  Modifier mod(IIT_array, std::move(attr));
   mod._expr = expr;
   return mod;
 }
@@ -59,8 +61,8 @@ array_type(CPPExpression *expr) {
  *
  */
 CPPInstanceIdentifier::Modifier CPPInstanceIdentifier::Modifier::
-scoped_pointer_type(CPPIdentifier *scoping) {
-  Modifier mod(IIT_scoped_pointer);
+scoped_pointer_type(CPPIdentifier *scoping, CPPAttributeList attr) {
+  Modifier mod(IIT_scoped_pointer, std::move(attr));
   mod._scoping = scoping;
   return mod;
 }
@@ -86,6 +88,17 @@ CPPInstanceIdentifier(CPPIdentifier *ident) :
   _packed(false) {
 }
 
+/**
+ *
+ */
+CPPInstanceIdentifier::
+CPPInstanceIdentifier(CPPIdentifier *ident, CPPAttributeList attributes) :
+  _ident(ident),
+  _attributes(std::move(attributes)),
+  _bit_width(nullptr),
+  _packed(false) {
+}
+
 /**
  * Unrolls the list of type punctuation on either side of the identifier to
  * determine the actual type represented by the identifier, given the
@@ -103,15 +116,16 @@ unroll_type(CPPType *start_type) {
  *
  */
 void CPPInstanceIdentifier::
-add_modifier(CPPInstanceIdentifierType type) {
-  _modifiers.push_back(Modifier(type));
+add_modifier(CPPInstanceIdentifierType type, CPPAttributeList attr) {
+  _modifiers.push_back(Modifier(type, std::move(attr)));
 }
 
 /**
  *
  */
 void CPPInstanceIdentifier::
-add_func_modifier(CPPParameterList *params, int flags, CPPType *trailing_return_type) {
+add_func_modifier(CPPParameterList *params, int flags,
+                  CPPType *trailing_return_type, CPPAttributeList attr) {
   // As a special hack, if we added a parameter list to an operator function,
   // check if the parameter list is empty.  If it is, this is really a unary
   // operator, so set the unary_op flag.  Operators () and [] are never
@@ -134,22 +148,22 @@ add_func_modifier(CPPParameterList *params, int flags, CPPType *trailing_return_
     flags |= CPPFunctionType::F_trailing_return_type;
   }
 
-  _modifiers.push_back(Modifier::func_type(params, flags, trailing_return_type));
+  _modifiers.push_back(Modifier::func_type(params, flags, trailing_return_type, std::move(attr)));
 }
 
 /**
  *
  */
 void CPPInstanceIdentifier::
-add_scoped_pointer_modifier(CPPIdentifier *scoping) {
-  _modifiers.push_back(Modifier::scoped_pointer_type(scoping));
+add_scoped_pointer_modifier(CPPIdentifier *scoping, CPPAttributeList attr) {
+  _modifiers.push_back(Modifier::scoped_pointer_type(scoping, std::move(attr)));
 }
 
 /**
  *
  */
 void CPPInstanceIdentifier::
-add_array_modifier(CPPExpression *expr) {
+add_array_modifier(CPPExpression *expr, CPPAttributeList attr) {
   // Special case for operator new[] and delete[].  We're not really adding an
   // array modifier to them, but appending [] to the identifier.  This is to
   // work around a parser ambiguity.
@@ -158,7 +172,7 @@ add_array_modifier(CPPExpression *expr) {
 
     _ident->_names.back().append_name("[]");
   } else {
-    _modifiers.push_back(Modifier::array_type(expr));
+    _modifiers.push_back(Modifier::array_type(expr, std::move(attr)));
   }
 }
 
@@ -187,6 +201,14 @@ add_trailing_return_type(CPPType *type) {
   std::cerr << "trailing return type can only be added to a function\n";
 }
 
+/**
+ * Add attributes to the instance (not the type).
+ */
+void CPPInstanceIdentifier::
+add_attributes(const CPPAttributeList &attributes) {
+  _attributes.add_attributes_from(attributes);
+}
+
 /**
  * Returns the initializer parameter list that was set for this particular
  * instance, e.g.  if the instance were:
@@ -316,5 +338,7 @@ r_unroll_type(CPPType *start_type,
     abort();
   }
 
+  result->_attributes = mod._attributes;
+
   return CPPType::new_type(result);
 }

+ 22 - 8
dtool/src/cppparser/cppInstanceIdentifier.h

@@ -15,6 +15,7 @@
 #define CPPINSTANCEIDENTIFIER_H
 
 #include "dtoolbase.h"
+#include "cppAttributeList.h"
 
 #include <vector>
 #include <string>
@@ -48,18 +49,25 @@ enum CPPInstanceIdentifierType {
 class CPPInstanceIdentifier {
 public:
   CPPInstanceIdentifier(CPPIdentifier *ident);
+  CPPInstanceIdentifier(CPPIdentifier *ident, CPPAttributeList attributes);
 
   CPPType *unroll_type(CPPType *start_type);
 
-  void add_modifier(CPPInstanceIdentifierType type);
+  void add_modifier(CPPInstanceIdentifierType type,
+                    CPPAttributeList attr = CPPAttributeList());
   void add_func_modifier(CPPParameterList *params, int flags,
-                         CPPType *trailing_return_type = nullptr);
-  void add_scoped_pointer_modifier(CPPIdentifier *scoping);
-  void add_array_modifier(CPPExpression *expr);
+                         CPPType *trailing_return_type = nullptr,
+                         CPPAttributeList attr = CPPAttributeList());
+  void add_scoped_pointer_modifier(CPPIdentifier *scoping,
+                                   CPPAttributeList attr = CPPAttributeList());
+  void add_array_modifier(CPPExpression *expr,
+                          CPPAttributeList attr = CPPAttributeList());
   void add_initializer_modifier(CPPParameterList *params);
 
   void add_trailing_return_type(CPPType *type);
 
+  void add_attributes(const CPPAttributeList &attributes);
+
   CPPParameterList *get_initializer() const;
 
   CPPScope *get_scope(CPPScope *current_scope, CPPScope *global_scope,
@@ -69,11 +77,14 @@ public:
 
   class Modifier {
   public:
-    Modifier(CPPInstanceIdentifierType type);
+    Modifier(CPPInstanceIdentifierType type,
+             CPPAttributeList attr = CPPAttributeList());
     static Modifier func_type(CPPParameterList *params, int flags,
-                              CPPType *trailing_return_type);
-    static Modifier array_type(CPPExpression *expr);
-    static Modifier scoped_pointer_type(CPPIdentifier *scoping);
+                              CPPType *trailing_return_type,
+                              CPPAttributeList attr);
+    static Modifier array_type(CPPExpression *expr, CPPAttributeList attr);
+    static Modifier scoped_pointer_type(CPPIdentifier *scoping,
+                                        CPPAttributeList attr);
     static Modifier initializer_type(CPPParameterList *params);
 
     CPPInstanceIdentifierType _type;
@@ -82,10 +93,13 @@ public:
     CPPIdentifier *_scoping;
     CPPExpression *_expr;
     CPPType *_trailing_return_type;
+    CPPAttributeList _attributes;
   };
   typedef std::vector<Modifier> Modifiers;
   Modifiers _modifiers;
 
+  CPPAttributeList _attributes;
+
   // If not null, indicates a bitfield
   CPPExpression *_bit_width;
 

+ 12 - 6
dtool/src/cppparser/cppNamespace.cxx

@@ -20,8 +20,9 @@
  *
  */
 CPPNamespace::
-CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file) :
-  CPPDeclaration(file),
+CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file,
+             CPPAttributeList attr) :
+  CPPDeclaration(file, std::move(attr)),
   _is_inline(false),
   _ident(ident),
   _scope(scope)
@@ -77,15 +78,20 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
   if (_is_inline) {
     out << "inline ";
   }
+  out << "namespace ";
+
   if (!complete && _ident != nullptr) {
     // If we have a name, use it.
     out << "namespace " << _ident->get_local_name(scope);
-
-  } else {
+  }
+  else {
+    if (!_attributes.is_empty()) {
+      out << _attributes << " ";
+    }
     if (_ident != nullptr) {
-      out << "namespace " << _ident->get_local_name(scope) << " {\n";
+      out << _ident->get_local_name(scope) << " {\n";
     } else {
-      out << "namespace {\n";
+      out << "{\n";
     }
 
     _scope->write(out, indent_level + 2, _scope);

+ 1 - 1
dtool/src/cppparser/cppNamespace.h

@@ -27,7 +27,7 @@ class CPPScope;
 class CPPNamespace : public CPPDeclaration {
 public:
   CPPNamespace(CPPIdentifier *ident, CPPScope *scope,
-               const CPPFile &file);
+               const CPPFile &file, CPPAttributeList attr = CPPAttributeList());
 
   std::string get_simple_name() const;
   std::string get_local_name(CPPScope *scope = nullptr) const;

+ 6 - 0
dtool/src/cppparser/cppPointerType.cxx

@@ -247,6 +247,12 @@ output_instance(std::ostream &out, int indent_level, CPPScope *scope,
     star = ftype->_class_owner->get_fully_scoped_name() + "::*";
   }
 
+  if (!_attributes.is_empty()) {
+    std::ostringstream strm;
+    strm << star << _attributes << " ";
+    star = strm.str();
+  }
+
   _pointing_at->output_instance(out, indent_level, scope, complete,
                                 star + prename, name);
 }

+ 9 - 6
dtool/src/cppparser/cppReferenceType.cxx

@@ -228,13 +228,16 @@ output_instance(std::ostream &out, int indent_level, CPPScope *scope,
                 bool complete, const std::string &prename,
                 const std::string &name) const {
 
-  if (_value_category == VC_rvalue) {
-    _pointing_at->output_instance(out, indent_level, scope, complete,
-                                  "&&" + prename, name);
-  } else {
-    _pointing_at->output_instance(out, indent_level, scope, complete,
-                                  "&" + prename, name);
+  std::string prefix((_value_category == VC_rvalue) ? "&&" : "&");
+
+  if (!_attributes.is_empty()) {
+    std::ostringstream strm;
+    strm << prefix << _attributes << " ";
+    prefix = strm.str();
   }
+
+  _pointing_at->output_instance(out, indent_level, scope, complete,
+                                prefix + prename, name);
 }
 
 /**

+ 9 - 5
dtool/src/cppparser/cppStructType.cxx

@@ -41,8 +41,8 @@ output(std::ostream &out) const {
 CPPStructType::
 CPPStructType(CPPStructType::Type type, CPPIdentifier *ident,
               CPPScope *current_scope, CPPScope *scope,
-              const CPPFile &file) :
-  CPPExtensionType(type, ident, current_scope, file),
+              const CPPFile &file, CPPAttributeList attr) :
+  CPPExtensionType(type, ident, current_scope, file, std::move(attr)),
   _scope(scope),
   _final(false)
 {
@@ -1261,10 +1261,14 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
       get_template_scope()->_parameters.write_formal(out, scope);
       indent(out, indent_level);
     }
+    out << _type;
+
+    if (!_attributes.is_empty()) {
+      out << " " << _attributes;
+    }
+
     if (_ident != nullptr) {
-      out << _type << " " << _ident->get_local_name(scope);
-    } else {
-      out << _type;
+      out << " " << _ident->get_local_name(scope);
     }
 
     if (_final) {

+ 2 - 1
dtool/src/cppparser/cppStructType.h

@@ -35,7 +35,8 @@ public:
   CPPStructType(Type type, CPPIdentifier *ident,
                 CPPScope *current_scope,
                 CPPScope *scope,
-                const CPPFile &file);
+                const CPPFile &file,
+                CPPAttributeList attr = CPPAttributeList());
   CPPStructType(const CPPStructType &copy);
   void operator = (const CPPStructType &copy);
 

+ 13 - 2
dtool/src/cppparser/cppTypedefType.cxx

@@ -43,7 +43,8 @@ CPPTypedefType(CPPType *type, const string &name, CPPScope *current_scope) :
  *
  */
 CPPTypedefType::
-CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
+CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope,
+               CPPAttributeList attr) :
   CPPType(CPPFile()),
   _type(type),
   _ident(ident),
@@ -53,6 +54,8 @@ CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope) :
     _ident->_native_scope = current_scope;
   }
   _subst_decl_recursive_protect = false;
+
+  _attributes = std::move(attr);
 }
 
 /**
@@ -69,6 +72,7 @@ CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
   assert(ii != nullptr);
   _type = ii->unroll_type(type);
   _ident = ii->_ident;
+  _attributes = std::move(ii->_attributes);
   ii->_ident = nullptr;
   delete ii;
 
@@ -388,9 +392,16 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool complete) cons
         get_template_scope()->_parameters.write_formal(out, scope);
         indent(out, indent_level);
       }
-      out << "using " << name << " = ";
+      out << "using " << name;
+      if (!_attributes.is_empty()) {
+        out << " " << _attributes;
+      }
+      out << " = ";
       _type->output(out, 0, scope, false);
     } else {
+      if (!_attributes.is_empty()) {
+        out << _attributes << " ";
+      }
       out << "typedef ";
       _type->output_instance(out, indent_level, scope, false, "", name);
     }

+ 2 - 1
dtool/src/cppparser/cppTypedefType.h

@@ -28,7 +28,8 @@ class CPPInstanceIdentifier;
 class CPPTypedefType : public CPPType {
 public:
   CPPTypedefType(CPPType *type, const std::string &name, CPPScope *current_scope);
-  CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope);
+  CPPTypedefType(CPPType *type, CPPIdentifier *ident, CPPScope *current_scope,
+                 CPPAttributeList attr = CPPAttributeList());
   CPPTypedefType(CPPType *type, CPPInstanceIdentifier *ii,
                  CPPScope *current_scope, const CPPFile &file);
 

+ 1 - 1
dtool/src/cppparser/p3cppParser_composite1.cxx

@@ -1,4 +1,4 @@
-
+#include "cppAttributeList.cxx"
 #include "cppFunctionType.cxx"
 #include "cppGlobals.cxx"
 #include "cppCommentBlock.cxx"

+ 0 - 4
dtool/src/parser-inc/stdtypedefs.h

@@ -47,8 +47,4 @@ namespace std {
   typedef decltype(nullptr) nullptr_t;
 }
 
-// One day, we might extend interrogate to be able to parse this,
-// but we currently don't need it.
-#define alignas(x)
-
 #endif

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