[patch] Knowing if "static" was written or not

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[patch] Knowing if "static" was written or not

Paolo Bolzoni
The enclosed patch allows to differentiate between those functions and
variables explicitly marked with the keyword static and those functions
or variables that are marked static for semantic reason.

As an example for the C language, the definition of function f below is
static even though the static keyword does not appear:

static void f(void);
void f(void) {} /* this one */


As for C++, here we have an example of a static variable where the static
keyword does not appear:

struct A {
  static int a;
};
int A::a = -1; /* this one */


Currently there seems to be no way to distinguish between a function
that is static because the keyword static is there or because a previous
declaration was marked as static. My patch added few member functions to
FunctionDecl in order to allow making such a distinction.

It is already possible to detect the difference in the variables, but for
sake of clearness I also put a similar member function in VarDecl.

Paolo Bolzoni

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

patch_clang.tar.gz (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

[patch] Knowing if "static" was written or not

Paolo Bolzoni-2
The enclosed patch allows to differentiate between those functions and
variables explicitly marked with the keyword static and those functions
or variables that are marked static for semantic reason.

As an example for the C language, the definition of function f below is
static even though the static keyword does not appear:

static void f(void);
void f(void) {} /* this one */


As for C++, here we have an example of a static variable where the static
keyword does not appear:

struct A {
 static int a;
};
int A::a = -1; /* this one */


Currently there seems to be no way to distinguish between a function
that is static because the keyword static is there or because a previous
declaration was marked as static. My patch added few member functions to
FunctionDecl in order to allow making such a distinction.

It is already possible to detect the difference in the variables, but for
sake of clearness I also put a similar member function in VarDecl.

Paolo Bolzoni

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

patch_clang.tar.gz (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [patch] Knowing if "static" was written or not

Douglas Gregor

On Feb 8, 2010, at 12:25 AM, Paolo Bolzoni wrote:

> The enclosed patch allows to differentiate between those functions and
> variables explicitly marked with the keyword static and those functions
> or variables that are marked static for semantic reason.
>
> As an example for the C language, the definition of function f below is
> static even though the static keyword does not appear:
>
> static void f(void);
> void f(void) {} /* this one */

That makes sense.

> As for C++, here we have an example of a static variable where the static
> keyword does not appear:
>
> struct A {
>  static int a;
> };
> int A::a = -1; /* this one */

Well, in this case you aren't allowed to write 'static', so we don't actually need to pass down the 'is static as written' bit in CXXMethodDecl and friends. For example, this isn't necessary:

===================================================================
--- include/clang/AST/DeclCXX.h (revision 95203)
+++ include/clang/AST/DeclCXX.h (working copy)
@@ -844,16 +844,17 @@
 protected:
   CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
                 DeclarationName N, QualType T, TypeSourceInfo *TInfo,
-                bool isStatic, bool isInline)
+                bool isStatic, bool isInline, bool isStaticAsWritten)
     : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None),-                   isInline) {}
+                   isInline, isStaticAsWritten) {}
 
 public:
   static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
                               SourceLocation L, DeclarationName N,
                               QualType T, TypeSourceInfo *TInfo,
                               bool isStatic = false,
-                              bool isInline = false);
+                              bool isInline = false,
+                              bool isStaticAsWritten = false);

And CXXConversionDecl, CXXConstructorDecl, and CXXDestructorDecl nodes will never need "static as written" bits, because they can never be static.

> Currently there seems to be no way to distinguish between a function
> that is static because the keyword static is there or because a previous
> declaration was marked as static. My patch added few member functions to
> FunctionDecl in order to allow making such a distinction.
>
> It is already possible to detect the difference in the variables, but for
> sake of clearness I also put a similar member function in VarDecl.


I'm curious about why you're focusing on whether "static" was written explicitly rather than tackling the general problem of "what storage specifier was actually written?". For example, one could have:

        static int i;
        extern int i;

where the semantic storage specifier of the second "i" is "static" but the storage specifier as written is "extern". Wouldn't it be more valuable to add, to both FunctionDecl and VarDecl, a

        StorageClass getStorageClassAsWritten() const;

?

One last comment...

Index: include/clang/Parse/DeclSpec.h
===================================================================
--- include/clang/Parse/DeclSpec.h      (revision 95203)
+++ include/clang/Parse/DeclSpec.h      (working copy)
@@ -200,6 +200,7 @@
   SourceLocation FriendLoc, ConstexprLoc;
 
   WrittenBuiltinSpecs writtenBS;
+  bool SCS_static_specified : 1;
   void SaveWrittenBuiltinSpecs();
 
   DeclSpec(const DeclSpec&);       // DO NOT IMPLEMENT
@@ -224,7 +225,8 @@
       AttrList(0),
       ProtocolQualifiers(0),
       NumProtocolQualifiers(0),
-      ProtocolLocs(0) {
+      ProtocolLocs(0),
+      SCS_static_specified(false) {
   }
   ~DeclSpec() {
     delete AttrList;
@@ -238,6 +240,11 @@
   SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
   SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
 
+  bool isStaticSpecified() const { return SCS_static_specified; }
+  SourceLocation getStaticSpecLoc() const { return isStaticSpecified()
+                                            ? StorageClassSpecLoc
+                                            : SourceLocation(); }
+
   void ClearStorageClassSpecs() {
     StorageClassSpec     = DeclSpec::SCS_unspecified;
     SCS_thread_specified = false;

I don't understand why this is needed. The DeclSpec will only have a single storage specifier; the one that was written in the source, along with the location of that storage specifier. It's only when we get into merging function or variable declarations that we change the effective storage class on the AST (but not in the DeclSpec).

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [patch] Knowing if "static" was written or not

Paolo Bolzoni
I followed the hints by Douglas and re-made the patch.  I added
getStorageClassAsWritten() in both FunctionDecl and VarDecl. Details about
the fixes wrt previous patch follow.

pb


On Feb 8, 2010, at 12:25 AM, Paolo Bolzoni wrote:

>> The enclosed patch allows to differentiate between those functions and
>> variables explicitly marked with the keyword static and those functions
>> or variables that are marked static for semantic reason.
>> [...]
>> Currently there seems to be no way to distinguish between a function
>> that is static because the keyword static is there or because a previous
>> declaration was marked as static. My patch added few member functions to
>> FunctionDecl in order to allow making such a distinction.
>>
>> It is already possible to detect the difference in the variables, but for
>> sake of clearness I also put a similar member function in VarDecl.
>
>I'm curious about why you're focusing on whether "static" was written explicitly rather than tackling the general problem of "what storage specifier was actually written?". For example, one could have:
>
>       static int i;
>       extern int i;
>
>where the semantic storage specifier of the second "i" is "static" but the storage specifier as written is "extern". Wouldn't it be more valuable to add, to both FunctionDecl and VarDecl, a
>
>       StorageClass getStorageClassAsWritten() const;
>
>?
It is indeed more valuable, I just did not thought about this case.

>> As for C++, here we have an example of a static variable where the static
>> keyword does not appear:
>>
>> struct A {
>>  static int a;
>> };
>> int A::a = -1; /* this one */
>
>Well, in this case you aren't allowed to write 'static', so we don't actually need to pass down the 'is static as written' bit in CXXMethodDecl and friends. For example, this isn't necessary:
>
>[old patch piece omitted]
>
>And CXXConversionDecl, CXXConstructorDecl, and CXXDestructorDecl nodes will never need "static as written" bits, because they can never be static.
Even though getStorageClassAsWritten() will never return 'static' on a
correct program, it might return 'extern', since it is possible to do
something such as the following:

struct A {
   operator void*();
};
extern A::operator void*() { return 0; }

>One last comment...
>
>Index: include/clang/Parse/DeclSpec.h
>===================================================================
>--- include/clang/Parse/DeclSpec.h      (revision 95203)
>+++ include/clang/Parse/DeclSpec.h      (working copy)
>[...]
>@@ -238,6 +240,11 @@
>[...]
>+  bool isStaticSpecified() const { return SCS_static_specified; }
>+  SourceLocation getStaticSpecLoc() const { return isStaticSpecified()
>+                                            ? StorageClassSpecLoc
>+                                            : SourceLocation(); }
>+
>[...]
>
>I don't understand why this is needed. The DeclSpec will only have a single storage specifier; the one that was written in the source, along with the location of that storage specifier. It's only when we get into merging function or variable declarations that we change the effective storage class on the AST (but not in the DeclSpec).
>
You are right, I misunderstood a few details in DeclSpec.
Now this should be corrected.

pb

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

patch.tar.gz (12K) Download Attachment